diff options
Diffstat (limited to 'src/dm')
77 files changed, 27954 insertions, 0 deletions
diff --git a/src/dm/EASTL_new.cpp b/src/dm/EASTL_new.cpp new file mode 100644 index 0000000..1ca308e --- /dev/null +++ b/src/dm/EASTL_new.cpp @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "EASTL/allocator.h" + +void *operator new[](size_t size, const char *, int, unsigned, const char *, int) +{ + return malloc(size); +} + +void *operator new[](size_t size, size_t, size_t, const char *, int, unsigned, const char *, int) +{ + return malloc(size); +} diff --git a/src/dm/Qt3DSDMPrefix.h b/src/dm/Qt3DSDMPrefix.h new file mode 100644 index 0000000..4164d64 --- /dev/null +++ b/src/dm/Qt3DSDMPrefix.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ + +#ifdef __cplusplus +#pragma once + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT \ + 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +// TODO: reference additional headers your program requires here +#if defined(WIN32) && defined(MSVC) +#pragma warning(push) +#pragma warning(disable : 4100) +#pragma warning(disable : 4512) +#pragma warning(disable : 4702) +#pragma warning(disable : 4996) +#endif + +// std includes +#include <map> +#include <vector> +#include <string> +#include <exception> +#include <set> +#include <iostream> +#include <sstream> +#include <fstream> +#include <memory> +#include <functional> + +// Project includes +#include "StandardExtensions.h" + +namespace qt3dsdm { +using std::ref; +using std::get; +using std::bind; +using std::tuple; +using std::static_pointer_cast; +using std::make_pair; +using std::equal_to; +using std::vector; +using std::make_tuple; +using std::function; +using std::shared_ptr; +using std::make_shared; +} +#if defined(WIN32) && defined(MSVC) +#pragma warning(pop) +#endif +#endif diff --git a/src/dm/dm.pro b/src/dm/dm.pro new file mode 100644 index 0000000..2e57f30 --- /dev/null +++ b/src/dm/dm.pro @@ -0,0 +1,58 @@ +TEMPLATE = lib +TARGET = QT3DSDM +CONFIG += staticlib +include(../commoninclude.pri) + +DEFINES += QT3DS_AUTHORING _AFXDLL PCRE_STATIC _UNICODE + +linux { + DEFINES += QT3DSDM_META_DATA_NO_SIGNALS +} + +INCLUDEPATH += \ + \ + systems \ + systems/cores \ + ../system \ + ../foundation \ + ../runtimerender \ + ../datamodel \ + ../render \ + ../3rdparty/EASTL/UnknownVersion/include \ + ../3rdparty/color \ + +PRECOMPILED_HEADER = Qt3DSDMPrefix.h + +SOURCES += \ + EASTL_new.cpp \ + systems/ActionSystem.cpp \ + systems/SignalsImpl.cpp \ + systems/SlideSystem.cpp \ + systems/StudioAnimationSystem.cpp \ + systems/StudioCoreSystem.cpp \ + systems/StudioFullSystem.cpp \ + systems/StudioPropertySystem.cpp \ + systems/Qt3DSDMComposerTypeDefinitions.cpp \ + systems/Qt3DSDMGuides.cpp \ + systems/Qt3DSDMMetaData.cpp \ + systems/Qt3DSDMSignalSystem.cpp \ + systems/Qt3DSDMStringTable.cpp \ + systems/Qt3DSDMValue.cpp \ + systems/Qt3DSDMXML.cpp \ + systems/cores/ActionCoreProducer.cpp \ + systems/cores/AnimationCoreProducer.cpp \ + systems/cores/DataCoreProducer.cpp \ + systems/cores/SimpleActionCore.cpp \ + systems/cores/SimpleAnimationCore.cpp \ + systems/cores/SimpleDataCore.cpp \ + systems/cores/SimpleSlideCore.cpp \ + systems/cores/SimpleSlideGraphCore.cpp \ + systems/cores/SlideCoreProducer.cpp \ + systems/cores/SlideGraphCoreProducer.cpp \ + +HEADERS += \ + systems/Qt3DSDMDataTypes.h \ + systems/Qt3DSDMMetaDataTypes.h \ + systems/Qt3DSDMMetaDataValue.h \ + systems/Qt3DSDMMetaData.h \ + systems/Qt3DSDMWStrOpsImpl.h diff --git a/src/dm/systems/ActionSystem.cpp b/src/dm/systems/ActionSystem.cpp new file mode 100644 index 0000000..fbd2593 --- /dev/null +++ b/src/dm/systems/ActionSystem.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "ActionSystem.h" + +using namespace std; + +namespace qt3dsdm { + +CActionSystem::CActionSystem(TDataCorePtr inDataCore, TSlideCorePtr inSlideCore, + TSlideGraphCorePtr inSlideGraphCore, TActionCorePtr inActionCore, + TSlideSystemPtr inSlideSystem, Qt3DSDMInstanceHandle inActionInstance, + Qt3DSDMPropertyHandle inActionEyeball) + : m_DataCore(inDataCore) + , m_SlideCore(inSlideCore) + , m_SlideGraphCore(inSlideGraphCore) + , m_ActionCore(inActionCore) + , m_SlideSystem(inSlideSystem) + , m_ActionInstance(inActionInstance) + , m_ActionEyeball(inActionEyeball) +{ + m_Signaller = CreateActionSystemSignaller(); +} + +Qt3DSDMActionHandle CActionSystem::CreateAction(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner, + SLong4 inTriggerTargetObjects) +{ + Q_ASSERT(inSlide.Valid() && inOwner.Valid()); + + // Create Action instance handle that derives from Action instance + Qt3DSDMInstanceHandle theActionInstance = m_DataCore->CreateInstance(); + m_DataCore->DeriveInstance(theActionInstance, m_ActionInstance); + + // Associate Action instance handle with Slide + m_SlideSystem->AssociateInstanceWithSlide(inSlide, theActionInstance); + + // Unlink the eyeball property because Action can be eyeballed-on/off per-slide + m_SlideSystem->UnlinkProperty(theActionInstance, m_ActionEyeball); + + // Create the Action handle + Qt3DSDMActionHandle retval = + m_ActionCore->CreateAction(theActionInstance, inSlide, inOwner, inTriggerTargetObjects); + + GetSignalSender()->SendActionCreated(retval, inSlide, inOwner); + return retval; +} + +void CActionSystem::DeleteAction(Qt3DSDMActionHandle inAction) +{ + Qt3DSDMInstanceHandle theActionInstance; + SActionInfo theActionInfo = m_ActionCore->GetActionInfo(inAction); + m_ActionCore->DeleteAction(inAction, theActionInstance); + m_DataCore->DeleteInstance(theActionInstance); + GetSignalSender()->SendActionDeleted(inAction, theActionInfo.m_Slide, theActionInfo.m_Owner); +} + +void CActionSystem::GetActions(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const +{ + // Get all actions that exist in inSlide + m_ActionCore->GetActions(inSlide, inOwner, outActions); + + // if inSlide is not master, get all actions that exist in master slide + Qt3DSDMSlideHandle theMaster = m_SlideSystem->GetMasterSlide(inSlide); + if (theMaster != inSlide) { + TActionHandleList theMasterActions; + m_ActionCore->GetActions(theMaster, inOwner, theMasterActions); + outActions.insert(outActions.end(), theMasterActions.begin(), theMasterActions.end()); + sort(outActions.begin(), outActions.end()); + } +} + +bool CActionSystem::GetActionEyeballValue(Qt3DSDMSlideHandle inActiveSlide, + Qt3DSDMActionHandle inAction) const +{ + SValue theValue; + Qt3DSDMInstanceHandle theInstance = m_ActionCore->GetActionInstance(inAction); + // Get the eyeball property value from SlideCore. There is no animation on eyeball so we can + // query SlideCore directly. + m_SlideCore->GetInstancePropertyValue(inActiveSlide, theInstance, m_ActionEyeball, theValue); + if (m_SlideCore->IsSlide(inActiveSlide)) + return qt3dsdm::get<bool>(theValue); + return false; +} + +void CActionSystem::SetActionEyeballValue(Qt3DSDMSlideHandle inActiveSlide, + Qt3DSDMActionHandle inAction, bool inValue) +{ + Qt3DSDMInstanceHandle theInstance = m_ActionCore->GetActionInstance(inAction); + // Set the eyeball property value to SlideCore. + m_SlideCore->ForceSetInstancePropertyValue(inActiveSlide, theInstance, m_ActionEyeball, + inValue); +} + +IActionSystemSignalProvider *CActionSystem::GetSignalProvider() +{ + return dynamic_cast<IActionSystemSignalProvider *>(m_Signaller.get()); +} + +IActionSystemSignalSender *CActionSystem::GetSignalSender() +{ + return dynamic_cast<IActionSystemSignalSender *>(m_Signaller.get()); +} +} diff --git a/src/dm/systems/ActionSystem.h b/src/dm/systems/ActionSystem.h new file mode 100644 index 0000000..fea9894 --- /dev/null +++ b/src/dm/systems/ActionSystem.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef ACTIONSYSTEMH +#define ACTIONSYSTEMH +#include "Qt3DSDMActionSystem.h" +#include "Qt3DSDMActionCore.h" +#include "Qt3DSDMDataCore.h" +#include "Qt3DSDMSlideCore.h" +#include "Qt3DSDMSlideGraphCore.h" +#include "Qt3DSDMSlides.h" +#include "Qt3DSDMTransactions.h" +#include "SignalsImpl.h" + +namespace qt3dsdm { + +class CActionSystem : public IActionSystem +{ + TDataCorePtr m_DataCore; + TSlideCorePtr m_SlideCore; + TSlideGraphCorePtr m_SlideGraphCore; + TActionCorePtr m_ActionCore; + + TSlideSystemPtr m_SlideSystem; + + Qt3DSDMInstanceHandle m_ActionInstance; + Qt3DSDMPropertyHandle m_ActionEyeball; + + std::shared_ptr<ISignalItem> m_Signaller; + +public: + CActionSystem(TDataCorePtr inDataCore, TSlideCorePtr inSlideCore, + TSlideGraphCorePtr inSlideGraphCore, TActionCorePtr inActionCore, + TSlideSystemPtr inSlideSystem, Qt3DSDMInstanceHandle inActionInstance, + Qt3DSDMPropertyHandle inActionEyeball); + + Qt3DSDMActionHandle CreateAction(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + SLong4 inTriggerTargetObjects) override; + void DeleteAction(Qt3DSDMActionHandle inAction) override; + void GetActions(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const override; + + bool GetActionEyeballValue(Qt3DSDMSlideHandle inActiveSlide, + Qt3DSDMActionHandle inAction) const override; + void SetActionEyeballValue(Qt3DSDMSlideHandle inActiveSlide, Qt3DSDMActionHandle inAction, + bool inValue) override; + + virtual IActionSystemSignalProvider *GetSignalProvider(); + +private: + virtual IActionSystemSignalSender *GetSignalSender(); + + CActionSystem(const CActionSystem&) = delete; + CActionSystem& operator=(const CActionSystem&) = delete; +}; +} + +#endif diff --git a/src/dm/systems/HandleSystemBase.h b/src/dm/systems/HandleSystemBase.h new file mode 100644 index 0000000..cb8e0f6 --- /dev/null +++ b/src/dm/systems/HandleSystemBase.h @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef HANDLESYSTEMIMPLH +#define HANDLESYSTEMIMPLH + +#include <unordered_map> + +namespace qt3dsdm { + +class CHandleObject +{ +public: + // Type of CHandleObject + // Each subclass needs to specify what type it is + // This is used to avoid dynamic_cast (RTTI) which is expensive + enum EHandleObjectType { + EHandleObjectTypeUnknown = 0, + EHandleObjectTypeCDataModelInstance, + EHandleObjectTypeCDataModelPropertyDefinitionObject, + EHandleObjectTypeSAnimationTrack, + EHandleObjectTypeSKeyframe, + EHandleObjectTypeSSlide, + EHandleObjectTypeSSlideGraph, + EHandleObjectTypeAction, + EHandleObjectTypeActionHandlerArgument, + EHandleObjectTypeCustomProperty, + EHandleObjectTypeEvent, + EHandleObjectTypeCustomHandler, + EHandleObjectTypeHandlerParam, + EHandleObjectTypeEnd, + }; + + CHandleObject(int inHandle = 0) + : m_Handle(inHandle) + { + } + virtual ~CHandleObject() {} + + virtual EHandleObjectType GetType() = 0; + + int m_Handle; + +private: //noncopyable + CHandleObject(const CHandleObject&) = delete; + CHandleObject& operator=(const CHandleObject&) = delete; + +}; + +typedef std::shared_ptr<CHandleObject> THandleObjectPtr; + +// Note that maps don't need to copy their objects. +typedef std::unordered_map<int, THandleObjectPtr> THandleObjectMap; +typedef std::pair<int, THandleObjectPtr> THandleObjectPair; + +class IHandleBase +{ +public: + /** + * Check whether a given handle exists + */ + virtual bool HandleValid(int inHandle) const = 0; +}; + +struct CHandleBase : public IHandleBase +{ + THandleObjectMap m_Objects; + int m_NextId; + + CHandleBase() + : m_NextId(1) + { + } + CHandleBase(const CHandleBase &inOther) + : m_Objects(inOther.m_Objects) + , m_NextId(inOther.m_NextId) + { + } + + CHandleBase &operator=(const CHandleBase &inOther) + { + m_Objects = inOther.m_Objects; + m_NextId = inOther.m_NextId; + return *this; + } + + // IHandleBase + bool HandleValid(int inHandle) const override + { + return m_Objects.find(inHandle) != m_Objects.end(); + } + + template <typename T> + static inline bool HandleObjectValid(int inHandle, const THandleObjectMap &inMap) + { + THandleObjectMap::const_iterator theIter = inMap.find(inHandle); + if (theIter != inMap.end()) { + if (theIter->second->GetType() == T::s_Type) + return true; + } + return false; + } + + template <typename T> + static inline const T *GetHandleObject(int inHandle, const THandleObjectMap &inMap) + { + THandleObjectMap::const_iterator theIter = inMap.find(inHandle); + if (theIter != inMap.end()) { + if (theIter->second->GetType() == T::s_Type) + return static_cast<const T *>(theIter->second.get()); + } + return NULL; + } + + template <typename ObjectType, typename HandleType> + static inline void MaybeAddObject(const std::pair<int, THandleObjectPtr> &inItem, + std::vector<HandleType> &outHandles) + { + if (inItem.second->GetType() == ObjectType::s_Type) + outHandles.push_back(HandleType(inItem.first)); + } + + static void EraseHandle(int inHandle, THandleObjectMap &inObjects) + { + THandleObjectMap::iterator theFind = inObjects.find(inHandle); + if (theFind != inObjects.end()) + inObjects.erase(theFind); + } + + // Return the next unused id. There are no guarantees whether positive or negative; what this + // will + // guarantee is that it isn't currently used in the object map and it is non-zero. + int GetNextId() + { + do { + ++m_NextId; + } while (m_Objects.find(m_NextId) != m_Objects.end()); + return m_NextId; + } +}; +} + +#endif diff --git a/src/dm/systems/HandleSystemTransactions.h b/src/dm/systems/HandleSystemTransactions.h new file mode 100644 index 0000000..9d77884 --- /dev/null +++ b/src/dm/systems/HandleSystemTransactions.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef HANDLESYSTEMTRANSACTIONSH +#define HANDLESYSTEMTRANSACTIONSH +#include "HandleSystemBase.h" +#include "Qt3DSDMTransactions.h" + +namespace qt3dsdm { +inline void InsertItemInMap(THandleObjectMap &inObjects, + const std::pair<int, THandleObjectPtr> &inItem) +{ + inObjects.insert(inItem); +} +inline void HandleCreateTransaction(const char *inFile, int inLine, int inHandle, + THandleObjectMap &inObjects, + TTransactionConsumerPtr &inConsumer) +{ + std::pair<int, THandleObjectPtr> theEntry = *inObjects.find(inHandle); + std::function<void()> doOp(std::bind(InsertItemInMap, std::ref(inObjects), theEntry)); + std::function<void()> undoOp( + std::bind(CHandleBase::EraseHandle, inHandle, std::ref(inObjects))); + TTransactionPtr theTransaction(DoCreateGenericTransaction(inFile, inLine, doOp, undoOp)); + inConsumer->OnTransaction(theTransaction); +} + +inline void HandleDeleteTransaction(const char *inFile, int inLine, int inHandle, + THandleObjectMap &inObjects, + TTransactionConsumerPtr &inConsumer) +{ + using namespace std; + pair<int, THandleObjectPtr> theEntry = *inObjects.find(inHandle); + TTransactionPtr theTransaction(DoCreateGenericTransaction( + inFile, inLine, std::bind(CHandleBase::EraseHandle, inHandle, std::ref(inObjects)), + std::bind(InsertItemInMap, std::ref(inObjects), theEntry))); + inConsumer->OnTransaction(theTransaction); +} + +inline void DoCreateHandleCreateTransaction(const char *inFile, int inLine, + TTransactionConsumerPtr inConsumer, int inHandle, + THandleObjectMap &inObjects) +{ + RunWithConsumer(inConsumer, std::bind(HandleCreateTransaction, inFile, inLine, inHandle, + std::ref(inObjects), std::placeholders::_1)); +} + +#define CREATE_HANDLE_CREATE_TRANSACTION(inConsumer, inHandle, inObjects) \ + DoCreateHandleCreateTransaction(__FILE__, __LINE__, inConsumer, inHandle, inObjects); + +inline void DoCreateHandleDeleteTransaction(const char *inFile, int inLine, + TTransactionConsumerPtr inConsumer, int inHandle, + THandleObjectMap &inObjects) +{ + RunWithConsumer(inConsumer, std::bind(HandleDeleteTransaction, inFile, inLine, inHandle, + std::ref(inObjects), std::placeholders::_1)); +} + +#define CREATE_HANDLE_DELETE_TRANSACTION(inConsumer, inHandle, inObjects) \ + DoCreateHandleDeleteTransaction(__FILE__, __LINE__, inConsumer, inHandle, inObjects); +} + +#endif diff --git a/src/dm/systems/Qt3DSDMActionCore.h b/src/dm/systems/Qt3DSDMActionCore.h new file mode 100644 index 0000000..a920146 --- /dev/null +++ b/src/dm/systems/Qt3DSDMActionCore.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_ACTION_CORE_H +#define QT3DSDM_ACTION_CORE_H + +#include "Qt3DSDMHandles.h" +#include "HandleSystemBase.h" +#include "Qt3DSDMActionInfo.h" + +namespace qt3dsdm { +const long REFERENCED_AS_OWNER = 0x01; +const long REFERENCED_AS_TRIGGER = 0x02; +const long REFERENCED_AS_TARGET = 0x04; +class IStringTable; + +/** + * ActionCore + */ +class IActionCore : public IHandleBase +{ +public: + virtual ~IActionCore() {} + + virtual TStringTablePtr GetStringTablePtr() const = 0; + virtual IStringTable &GetStringTable() const = 0; + // Action + virtual Qt3DSDMActionHandle CreateAction(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + SLong4 inTriggerTargetObjects) = 0; + virtual void DeleteAction(Qt3DSDMActionHandle inAction, Qt3DSDMInstanceHandle &outInstance) = 0; + virtual const SActionInfo &GetActionInfo(Qt3DSDMActionHandle inAction) const = 0; + virtual void GetActions(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const = 0; + virtual void GetActions(Qt3DSDMSlideHandle inSlide, TActionHandleList &outActions) const = 0; + virtual void GetActions(Qt3DSDMInstanceHandle inOwner, TActionHandleList &outActions) const = 0; + virtual void GetActions(TActionHandleList &outActions) const = 0; + + // Return the instance that was allocated for this action. + virtual Qt3DSDMInstanceHandle GetActionInstance(Qt3DSDMActionHandle inAction) const = 0; + // Reverse lookup into the action system so you can match actions to instances. + virtual Qt3DSDMActionHandle GetActionByInstance(Qt3DSDMInstanceHandle inActionInstance) const = 0; + + // Action Properties + virtual void SetTriggerObject(Qt3DSDMActionHandle inAction, + const SObjectRefType &inTriggerObject) = 0; + virtual void SetTargetObject(Qt3DSDMActionHandle inAction, + const SObjectRefType &inTargetObject) = 0; + virtual void SetEvent(Qt3DSDMActionHandle inAction, const wstring &inEventName) = 0; + virtual void SetHandler(Qt3DSDMActionHandle inAction, const wstring &inHandlerName) = 0; + + // Handler Argument + virtual Qt3DSDMHandlerArgHandle AddHandlerArgument(Qt3DSDMActionHandle inAction, + const TCharStr &inName, + HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) = 0; + virtual void RemoveHandlerArgument(Qt3DSDMHandlerArgHandle inHandlerArgument) = 0; + virtual const SHandlerArgumentInfo & + GetHandlerArgumentInfo(Qt3DSDMHandlerArgHandle inHandlerArgument) const = 0; + virtual void GetHandlerArguments(Qt3DSDMActionHandle inAction, + THandlerArgHandleList &outHandlerArguments) const = 0; + + // Handler Argument Properties + virtual void GetHandlerArgumentValue(Qt3DSDMHandlerArgHandle inHandlerArgument, + SValue &outValue) const = 0; + virtual void SetHandlerArgumentValue(Qt3DSDMHandlerArgHandle inHandlerArgument, + const SValue &inValue) = 0; +}; + +typedef std::shared_ptr<IActionCore> TActionCorePtr; +} + +#endif diff --git a/src/dm/systems/Qt3DSDMActionInfo.h b/src/dm/systems/Qt3DSDMActionInfo.h new file mode 100644 index 0000000..40fd964 --- /dev/null +++ b/src/dm/systems/Qt3DSDMActionInfo.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_ACTION_INFO_H +#define QT3DSDM_ACTION_INFO_H + +#include "Qt3DSDMDataTypes.h" +#include "Qt3DSDMMetaDataTypes.h" + +namespace qt3dsdm { +using std::wstring; +struct SActionInfo +{ + // InstanceHandle corresponding to this action (to store other properties not listed here) + Qt3DSDMInstanceHandle m_Instance; + + // Where the action is added to + Qt3DSDMSlideHandle m_Slide; // the slide that the action is added to + Qt3DSDMInstanceHandle + m_Owner; // the object that the action is added to (the owner of the action) + + // Trigger object + SObjectRefType m_TriggerObject; // trigger object + wstring m_Event; // the list of applicable events is based on object type and stored, by type, + // in metadata + + // Target object + SObjectRefType m_TargetObject; // target object + wstring m_Handler; // the list of applicable action handlers is loaded from metadata xml file + // and based on object type + THandlerArgHandleList m_HandlerArgs; // the list of applicable action arguments is dependent on + // the handler and loaded from the metadata xml file. + + SActionInfo() {} + + SActionInfo(Qt3DSDMInstanceHandle inInstance, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) + : m_Instance(inInstance) + , m_Slide(inSlide) + , m_Owner(inOwner) + { + } +}; + +struct SHandlerArgumentInfo +{ + Qt3DSDMActionHandle m_Action; // Action that owns this Action Argument + TCharStr m_Name; // Name of the Action Argument + HandlerArgumentType::Value m_ArgType; // m_ArgType will override m_ValueType + DataModelDataType::Value m_ValueType; // m_ValueType is ignored if ArgType is specified + SValue m_Value; // Value of the Action Argument + + SHandlerArgumentInfo() + : m_ArgType(HandlerArgumentType::None) + , m_ValueType(DataModelDataType::None) + { + } + + SHandlerArgumentInfo(Qt3DSDMActionHandle inAction, const TCharStr &inName, + HandlerArgumentType::Value inArgType, DataModelDataType::Value inValueType) + : m_Action(inAction) + , m_Name(inName) + , m_ArgType(inArgType) + , m_ValueType(inValueType) + { + } +}; +} + +#endif diff --git a/src/dm/systems/Qt3DSDMActionSystem.h b/src/dm/systems/Qt3DSDMActionSystem.h new file mode 100644 index 0000000..8713729 --- /dev/null +++ b/src/dm/systems/Qt3DSDMActionSystem.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_ACTION_SYSTEM_H +#define QT3DSDM_ACTION_SYSTEM_H +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMActionCore.h" + +namespace qt3dsdm { +/** + * ActionSystem acts as a wrapper or helper around ActionCore. ActionSystem will call + * ActionCore and perform other necessary setups. It also has the knowledge of other + * system or core so there are some synchronization being done here. + * + * When in doubts which one to use (ActionSystem or ActionCore), always use ActionSystem + */ +class IActionSystem +{ +public: + virtual ~IActionSystem() {} + + // CreateAction will create Action's InstanceHandle and Action's ActionHandle and do some + // necessary setup + virtual Qt3DSDMActionHandle CreateAction(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + SLong4 inTriggerTargetObjects) = 0; + // DeleteAction will delete both Action's ActionHandle and Action's InstanceHandle + virtual void DeleteAction(Qt3DSDMActionHandle inAction) = 0; + // Return all actions that belong to a certain instance in a certain slide + the master slide + virtual void GetActions(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const = 0; + + // Get/set action eyeball property value + virtual bool GetActionEyeballValue(Qt3DSDMSlideHandle inActiveSlide, + Qt3DSDMActionHandle inAction) const = 0; + virtual void SetActionEyeballValue(Qt3DSDMSlideHandle inActiveSlide, Qt3DSDMActionHandle inAction, + bool inValue) = 0; +}; + +typedef std::shared_ptr<IActionSystem> TActionSystemPtr; +} + +#endif diff --git a/src/dm/systems/Qt3DSDMAnimation.h b/src/dm/systems/Qt3DSDMAnimation.h new file mode 100644 index 0000000..457b042 --- /dev/null +++ b/src/dm/systems/Qt3DSDMAnimation.h @@ -0,0 +1,841 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 QT3DSDM_ANIMATION_H +#define QT3DSDM_ANIMATION_H + +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMDataTypes.h" +#include "Qt3DSDMValue.h" + +namespace qt3dsdm { + +struct SLinearKeyframe +{ + float m_KeyframeSeconds; + float m_KeyframeValue; +}; + +struct SBezierKeyframe : public SLinearKeyframe +{ + float m_InTangentTime; // time + float m_InTangentValue; // value offset + float m_OutTangentTime; // time offset in seconds + float m_OutTangentValue; // value offset +}; + +typedef std::vector<SBezierKeyframe> TBezierKeyframeList; + +/** + * Ease in/out are parameters that affect the bezier evaluation. + * Ease in/out at 100 means that the control values are at the end points thus creating + * a gradual deceleration. Ease in/out at 0 means that interpolation is linear, the + * control points are at 1/3 and 2/3's the distance to the next value. + * Ease in/out go from 0.f to 100.0f + */ +struct SEaseInEaseOutKeyframe : public SLinearKeyframe +{ + float m_EaseIn; + float m_EaseOut; +}; + +} // namespace qt3dsdm + +namespace qt3ds { +namespace foundation { + // Disable calling destructor of these pod types + template <> + struct DestructTraits<qt3dsdm::SEaseInEaseOutKeyframe> + { + void destruct(qt3dsdm::SEaseInEaseOutKeyframe &) {} + }; + template <> + struct DestructTraits<qt3dsdm::SBezierKeyframe> + { + void destruct(qt3dsdm::SBezierKeyframe &) {} + }; + template <> + struct DestructTraits<qt3dsdm::SLinearKeyframe> + { + void destruct(qt3dsdm::SLinearKeyframe &) {} + }; +} +} + +namespace qt3dsdm { + +enum EAnimationType { + EAnimationTypeNone = 0, + EAnimationTypeLinear, + EAnimationTypeBezier, + EAnimationTypeEaseInOut, +}; + +template <typename TDataType> +struct SAnimationTypeTraits +{ +}; + +template <> +struct SAnimationTypeTraits<SBezierKeyframe> +{ + EAnimationType getType() { return EAnimationTypeBezier; } +}; +template <> +struct SAnimationTypeTraits<SLinearKeyframe> +{ + EAnimationType getType() { return EAnimationTypeLinear; } +}; +template <> +struct SAnimationTypeTraits<SEaseInEaseOutKeyframe> +{ + EAnimationType getType() { return EAnimationTypeEaseInOut; } +}; + +struct SKeyframeUnionTraits +{ + typedef EAnimationType TIdType; + enum { + TBufferSize = sizeof(SBezierKeyframe), + }; + static TIdType getNoDataId() { return EAnimationTypeNone; } + template <typename TDataType> + static TIdType getType() + { + return SAnimationTypeTraits<TDataType>().getType(); + } + + template <typename TRetType, typename TVisitorType> + static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor) + { + switch (inType) { + case EAnimationTypeBezier: + return inVisitor(*reinterpret_cast<SBezierKeyframe *>(inData)); + case EAnimationTypeLinear: + return inVisitor(*reinterpret_cast<SLinearKeyframe *>(inData)); + case EAnimationTypeEaseInOut: + return inVisitor(*reinterpret_cast<SEaseInEaseOutKeyframe *>(inData)); + default: + QT3DS_ASSERT(false); + case EAnimationTypeNone: + return inVisitor(); + } + } + + template <typename TRetType, typename TVisitorType> + static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor) + { + switch (inType) { + case EAnimationTypeBezier: + return inVisitor(*reinterpret_cast<const SBezierKeyframe *>(inData)); + case EAnimationTypeLinear: + return inVisitor(*reinterpret_cast<const SLinearKeyframe *>(inData)); + case EAnimationTypeEaseInOut: + return inVisitor(*reinterpret_cast<const SEaseInEaseOutKeyframe *>(inData)); + default: + QT3DS_ASSERT(false); + case EAnimationTypeNone: + return inVisitor(); + } + } +}; + +typedef qt3ds::foundation:: + DiscriminatedUnion<qt3ds::foundation:: + DiscriminatedUnionGenericBase<SKeyframeUnionTraits, + SKeyframeUnionTraits::TBufferSize>, + SKeyframeUnionTraits::TBufferSize> + TKeyframe; + +template <> +struct Qt3DSDMGetter<TKeyframe> +{ + template <typename TRetType> + TRetType doGet(const TKeyframe &inValue) + { + return inValue.getData<TRetType>(); + } +}; + +typedef std::vector<TKeyframe> TKeyframeList; + +struct SAnimationInfo +{ + Qt3DSDMSlideHandle m_Slide; + Qt3DSDMInstanceHandle m_Instance; + Qt3DSDMPropertyHandle m_Property; + size_t m_Index; + EAnimationType m_AnimationType; + // Use the existing value for the value of the first keyframe. + // Not reflected in studio at this time, purely a runtime problem. + // Defaults to false + bool m_DynamicFirstKeyframe; + bool m_ArtistEdited; + SAnimationInfo() + : m_Index(0) + , m_AnimationType(EAnimationTypeLinear) + , m_DynamicFirstKeyframe(false) + // Animations are assumed to be artist edited. + // And any change will force this flag to true. + , m_ArtistEdited(true) + + { + } + SAnimationInfo(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, EAnimationType inAnimationType, + bool inDynamicFirstKeyframe, bool inArtistEdited) + : m_Slide(inSlide) + , m_Instance(inInstance) + , m_Property(inProperty) + , m_Index(inIndex) + , m_AnimationType(inAnimationType) + , m_DynamicFirstKeyframe(inDynamicFirstKeyframe) + , m_ArtistEdited(inArtistEdited) + { + } +}; + +typedef std::pair<SAnimationInfo, TKeyframeList> TAnimationKeyframesPair; +typedef std::vector<TAnimationKeyframesPair> TAnimationKeyframesPairList; +typedef std::vector<SAnimationInfo> TAnimationInfoList; + +/** + * Pure animation core. Not wrapped in any niceties. + */ +class IAnimationCore +{ +public: + virtual ~IAnimationCore() {} + virtual Qt3DSDMAnimationHandle CreateAnimation(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType, + bool inFirstKeyframeDynamic) = 0; + virtual void DeleteAnimation(Qt3DSDMAnimationHandle inAnimation) = 0; + virtual Qt3DSDMAnimationHandle GetAnimation(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + size_t inIndex) const = 0; + virtual SAnimationInfo GetAnimationInfo(Qt3DSDMAnimationHandle inAnimation) const = 0; + virtual void GetAnimations(TAnimationHandleList &outAnimations) const = 0; + virtual void GetAnimations(TAnimationInfoList &outAnimations, + Qt3DSDMSlideHandle inMaster = Qt3DSDMSlideHandle(), + Qt3DSDMSlideHandle inSlide = Qt3DSDMSlideHandle()) const = 0; + + virtual void GetSpecificInstanceAnimations(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + TAnimationHandleList &outAnimations) = 0; + + virtual void SetFirstKeyframeDynamic(Qt3DSDMAnimationHandle inAnimation, bool inValue) = 0; + + // keyframe manipulation + virtual Qt3DSDMKeyframeHandle InsertKeyframe(Qt3DSDMAnimationHandle inAnimation, + const TKeyframe &inKeyframe) = 0; + virtual void EraseKeyframe(Qt3DSDMKeyframeHandle inKeyframe) = 0; + virtual void DeleteAllKeyframes(Qt3DSDMAnimationHandle inAnimation) = 0; + + // All of these mutators will force the artist edited property + // of the animation to true. + virtual Qt3DSDMAnimationHandle + GetAnimationForKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const = 0; + virtual TKeyframe GetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe) const = 0; + virtual void SetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData) = 0; + virtual void GetKeyframes(Qt3DSDMAnimationHandle inAnimation, + TKeyframeHandleList &outKeyframes) const = 0; + virtual size_t GetKeyframeCount(Qt3DSDMAnimationHandle inAnimation) const = 0; + virtual bool IsFirstKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const = 0; + + virtual void OffsetAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + long inOffset) = 0; + + // Direct mutators of the artist edited feature of animations + virtual void SetIsArtistEdited(Qt3DSDMAnimationHandle inAnimation, bool inEdited = true) = 0; + virtual bool IsArtistEdited(Qt3DSDMAnimationHandle inAnimation) const = 0; + + // Animation Evaluation. + virtual float EvaluateAnimation(Qt3DSDMAnimationHandle inAnimation, float inSeconds) const = 0; + + virtual bool KeyframeValid(Qt3DSDMKeyframeHandle inKeyframe) const = 0; + virtual bool AnimationValid(Qt3DSDMAnimationHandle inAnimation) const = 0; + + virtual void CopyAnimations(Qt3DSDMSlideHandle inSourceSlide, + Qt3DSDMInstanceHandle inSourceInstance, + Qt3DSDMSlideHandle inDestSlide, + Qt3DSDMInstanceHandle inDestInstance) = 0; +}; + +typedef std::shared_ptr<IAnimationCore> TAnimationCorePtr; + +struct SGetOrSetKeyframeInfo +{ + float m_Value = 0.0; + float m_EaseIn = -1.f; + float m_EaseOut = -1.f; + bool m_AnimationTrackIsDynamic = false; + + SGetOrSetKeyframeInfo(float inValue, float inEaseIn = -1.f, float inEaseOut = -1.f, + bool inDynamic = false) + : m_Value(inValue) + , m_EaseIn(inEaseIn) + , m_EaseOut(inEaseOut) + , m_AnimationTrackIsDynamic(inDynamic) + { + } + SGetOrSetKeyframeInfo() = default; + +}; +/** + * Interface from studio into the animation system that speaks + * a language near to that of studio. Public interface. + */ +class IStudioAnimationSystem +{ +public: + virtual ~IStudioAnimationSystem() {} + + /** + * When auto-keyframing is on, all calls to setinstancepropertyvalue will + * case a keyframe to be set if the instance is a member of a slide graph. + */ + virtual void SetAutoKeyframe(bool inAutoKeyframe) = 0; + /** + * Returns true when auto keyframing is set. + */ + virtual bool GetAutoKeyframe() const = 0; + /** + * Create animation on the property on this instance. If the property was animated and had + *keyframes previously, + * this function will also set the keyframes accordingly. + */ + virtual void Animate(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) = 0; + /** + * Delete animation on the property on this instance + */ + virtual void Deanimate(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) = 0; + /** + * Set a keyframe on this property. Uses the current time of the slide graph. + * If the keyframe is within a given time distance of another, this function will simply change + * the keyframed value of the other property to match the current value of this property. + */ + virtual void KeyframeProperty(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + bool inDoDiffValue) = 0; + /** + * Set the value of a existing a keyframe or create a new one, on this property, at the given + *time. + * If ease in or ease out are unset then the keyframe gets the default ease in or out. + */ + virtual void SetOrCreateKeyframe(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, float inTimeInSeconds, + SGetOrSetKeyframeInfo *inKeyframeInfo, size_t inNumInfos) = 0; + /** + * Return the animation that is currently controlling this property. This function will return + * an invalid handle value if there is currently no animation controlling this property. + */ + virtual Qt3DSDMAnimationHandle GetControllingAnimation(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + size_t inIndex) const = 0; + + /** + * Return true if the given property is animatable. You can begin animation by calling + *KeyframeProperty *or* + * by setting auto keyframe to on and setting a property value through the + *IInstancePropertyCore system. + */ + virtual bool IsPropertyAnimatable(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const = 0; + + /** + * Return true if the given property is animated. Currently, either 0 or ALL channels are + *animated. Hence, checking for index = 0 suffices. + * And if that changes, this function can be updated accordingly. + */ + virtual bool IsPropertyAnimated(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const = 0; + + /** + * Specify if new keyframes should be created with smooth ( ie Ease In/Out values = 100 ) or + *linear ( Ease In/Out values = 0 ) + */ + virtual void SetInterpolation(bool inSmooth) = 0; + + /** + * Get an instance property value. Will override outValue only if the slide, instance, + *property is animated. + */ + virtual bool GetAnimatedInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const = 0; + /** + * Set an instance property value. Will return true in the cases where + * the property is actually animated. May only set local values, or may auto set a keyframed + *value. + */ + virtual bool SetAnimatedInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) = 0; + + typedef std::function<void(Qt3DSDMInstanceHandle instance)> TRefreshCallbackFunc; + virtual void setRefreshCallback(TRefreshCallbackFunc func) = 0; +}; + +typedef std::shared_ptr<IStudioAnimationSystem> TStudioAnimationSystemPtr; + +inline SLinearKeyframe CreateLinearKeyframe(float inSeconds, float inValue) +{ + SLinearKeyframe retval = { inSeconds, inValue }; + return retval; +} + +inline SBezierKeyframe CreateBezierKeyframe(float inSeconds, float inValue, float inInTangentTime, + float inInTangentValue, float inOutTangentTime, + float inOutTangentValue) +{ + SBezierKeyframe theBezierKeyframe; + theBezierKeyframe.m_KeyframeSeconds = inSeconds; + theBezierKeyframe.m_KeyframeValue = inValue; + theBezierKeyframe.m_InTangentTime = inInTangentTime; + theBezierKeyframe.m_InTangentValue = inInTangentValue; + theBezierKeyframe.m_OutTangentTime = inOutTangentTime; + theBezierKeyframe.m_OutTangentValue = inOutTangentValue; + return theBezierKeyframe; +} + +inline SEaseInEaseOutKeyframe CreateEaseInEaseOutKeyframe(float inSeconds, float inValue, + float inEaseIn, float inEaseOut) +{ + SEaseInEaseOutKeyframe retval; + retval.m_KeyframeSeconds = inSeconds; + retval.m_KeyframeValue = inValue; + retval.m_EaseIn = inEaseIn; + retval.m_EaseOut = inEaseOut; + return retval; +} + +inline SAnimationInfo CreateAnimationInfo(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType, + bool inFirstKeyframeDynamic, bool inArtistEdited) +{ + SAnimationInfo retval(inSlide, inInstance, inProperty, inIndex, inAnimationType, + inFirstKeyframeDynamic, inArtistEdited); + return retval; +} + +struct SKeyframeValueVisitor +{ + float operator()(const SLinearKeyframe &inKeyframe) const { return inKeyframe.m_KeyframeValue; } + float operator()(const SBezierKeyframe &inKeyframe) const { return inKeyframe.m_KeyframeValue; } + float operator()(const SEaseInEaseOutKeyframe &inKeyframe) const + { + return inKeyframe.m_KeyframeValue; + } + float operator()() + { + QT3DS_ASSERT(false); + return 0.0f; + } +}; + +inline float KeyframeValueValue(const TKeyframe &inKeyframe) +{ + return inKeyframe.visit<float>(SKeyframeValueVisitor()); +} + +struct SKeyframeTimeAnalyzer +{ + float operator()(const SLinearKeyframe &inValue) const { return inValue.m_KeyframeSeconds; } + float operator()(const SBezierKeyframe &inValue) const { return inValue.m_KeyframeSeconds; } + float operator()(const SEaseInEaseOutKeyframe &inValue) const + { + return inValue.m_KeyframeSeconds; + } + float operator()() + { + QT3DS_ASSERT(false); + return 0.0f; + } +}; + +inline float KeyframeTime(const TKeyframe &inValue) +{ + return inValue.visit<float>(SKeyframeTimeAnalyzer()); +} + +inline EAnimationType GetKeyframeType(const TKeyframe &inKeyframe) +{ + return inKeyframe.getType(); +} + +struct SAnimatableArityVisitor +{ + std::tuple<bool, size_t> operator()(bool) const + { + return std::tuple<bool, size_t>(true, 1); + } + std::tuple<bool, size_t> operator()(long) const + { + return std::tuple<bool, size_t>(true, 1); + } + std::tuple<bool, size_t> operator()(float) const + { + return std::tuple<bool, size_t>(true, 1); + } + std::tuple<bool, size_t> operator()(const SFloat2 &) const + { + return std::tuple<bool, size_t>(true, 2); + } + std::tuple<bool, size_t> operator()(const SFloat3 &) const + { + return std::tuple<bool, size_t>(true, 3); + } + std::tuple<bool, size_t> operator()(const SFloat4 &) const + { + return std::tuple<bool, size_t>(true, 4); + } + template <typename TDataType> + std::tuple<bool, size_t> operator()(const TDataType &) const + { + return std::tuple<bool, size_t>(false, 0); + } + std::tuple<bool, size_t> operator()() + { + QT3DS_ASSERT(false); + return std::tuple<bool, size_t>(false, 0); + } +}; + +inline std::tuple<bool, size_t> GetVariantAnimatableAndArity(const SValue &inValue) +{ + return inValue.visit<std::tuple<bool, size_t>>(SAnimatableArityVisitor()); +} + +inline std::tuple<bool, size_t> GetDatatypeAnimatableAndArity(DataModelDataType::Value inDataType) +{ + switch (inDataType) { + case DataModelDataType::Long: + case DataModelDataType::Float: + return std::make_tuple(true, 1); + + case DataModelDataType::Float2: + return std::make_tuple(true, 2); + + case DataModelDataType::Float3: + return std::make_tuple(true, 3); + + case DataModelDataType::Float4: + return std::make_tuple(true, 4); + + default: + return std::make_tuple(false, 0); + } +} + +template <typename TDataType> +inline TDataType SetFloatValue(float inValue, size_t inIndex, const TDataType &inDataType) +{ + TDataType retval(inDataType); + retval[inIndex] = inValue; + return retval; +} + +struct SAnimationApplier +{ + float m_Value; + size_t m_Index; + SValue operator()(const bool &) { return m_Value > 0.5f; } + SValue operator()(const qt3ds::QT3DSI32 &) { return static_cast<qt3ds::QT3DSI32>(m_Value + .5f); } + SValue operator()(const float &) { return m_Value; } + SValue operator()(const SFloat2 &inValue) { return SetFloatValue(m_Value, m_Index, inValue); } + SValue operator()(const SFloat3 &inValue) { return SetFloatValue(m_Value, m_Index, inValue); } + SValue operator()(const SFloat4 &inValue) { return SetFloatValue(m_Value, m_Index, inValue); } + template <typename TDataType> + SValue operator()(const TDataType &inValue) + { + return inValue; + } + SValue operator()() + { + QT3DS_ASSERT(false); + return SValue(); + } +}; + +inline void SetAnimationValue(float inValue, size_t inIndex, SValue &ioValue) +{ + using namespace std; + SAnimationApplier theApplier; + theApplier.m_Value = inValue; + theApplier.m_Index = inIndex; + ioValue = ioValue.visit<SValue>(theApplier); +} + +template <typename TDataType> +inline float GetFloatValue(const TDataType &inValue, size_t inIndex) +{ + return inValue[inIndex]; +} + +struct SAnimationGetter +{ + size_t m_Index; + float operator()(const bool &inValue) const { return inValue ? 1.f : 0.f; } + float operator()(const long &inValue) const { return static_cast<float>(inValue); } + float operator()(const float &inValue) const { return inValue; } + float operator()(const SFloat2 &inValue) const { return GetFloatValue(inValue, m_Index); } + float operator()(const SFloat3 &inValue) const { return GetFloatValue(inValue, m_Index); } + float operator()(const SFloat4 &inValue) const { return GetFloatValue(inValue, m_Index); } + template <typename TDataType> + float operator()(const TDataType & /*inValue*/) const + { + return 0.f; + } + float operator()() + { + QT3DS_ASSERT(false); + return 0.0f; + } +}; + +inline float GetAnimationValue(size_t inIndex, const SValue &ioValue) +{ + SAnimationGetter theGetter; + theGetter.m_Index = inIndex; + return ioValue.visit<float>(theGetter); +} + +struct SKeyframeTimeSetter +{ + float m_Seconds; + TKeyframe operator()(const SLinearKeyframe &inValue) const + { + return CreateLinearKeyframe(m_Seconds, inValue.m_KeyframeValue); + } + TKeyframe operator()(const SBezierKeyframe &inValue) const + { + return CreateBezierKeyframe(m_Seconds, inValue.m_KeyframeValue, inValue.m_InTangentTime, + inValue.m_InTangentValue, inValue.m_OutTangentTime, + inValue.m_OutTangentValue); + } + TKeyframe operator()(const SEaseInEaseOutKeyframe &inValue) const + { + return CreateEaseInEaseOutKeyframe(m_Seconds, inValue.m_KeyframeValue, inValue.m_EaseIn, + inValue.m_EaseOut); + } + TKeyframe operator()() + { + QT3DS_ASSERT(false); + return TKeyframe(); + } +}; + +inline TKeyframe SetKeyframeSeconds(const TKeyframe &inKeyframe, float inSeconds) +{ + SKeyframeTimeSetter theSetter; + theSetter.m_Seconds = inSeconds; + return inKeyframe.visit<TKeyframe>(theSetter); +} + +struct SKeyframeTimeGetter +{ + template <typename TKeyframeType> + float operator()(const TKeyframeType &inValue) const + { + return inValue.m_KeyframeSeconds; + } + float operator()() + { + QT3DS_ASSERT(false); + return 0.0f; + } +}; + +inline float GetKeyframeSeconds(const TKeyframe &inKeyframe) +{ + SKeyframeTimeGetter theGetter; + return inKeyframe.visit<float>(theGetter); +} + +struct SKeyframeValueSetter +{ + float m_Value; + TKeyframe operator()(const SLinearKeyframe &inValue) const + { + return CreateLinearKeyframe(inValue.m_KeyframeSeconds, m_Value); + } + TKeyframe operator()(const SBezierKeyframe &inValue) const + { + return CreateBezierKeyframe(inValue.m_KeyframeSeconds, m_Value, inValue.m_InTangentTime, + inValue.m_InTangentValue, inValue.m_OutTangentTime, + inValue.m_OutTangentValue); + } + TKeyframe operator()(const SEaseInEaseOutKeyframe &inValue) const + { + return CreateEaseInEaseOutKeyframe(inValue.m_KeyframeSeconds, m_Value, inValue.m_EaseIn, + inValue.m_EaseOut); + } + TKeyframe operator()() + { + QT3DS_ASSERT(false); + return TKeyframe(); + } +}; + +inline TKeyframe SetKeyframeValue(const TKeyframe &inKeyframe, float inValue) +{ + SKeyframeValueSetter theSetter; + theSetter.m_Value = inValue; + return inKeyframe.visit<TKeyframe>(theSetter); +} + +inline float AnimationClamp(float inLowerBound, float inUpperBound, float inValue) +{ + if (inValue < inLowerBound) + return inLowerBound; + if (inValue > inUpperBound) + return inUpperBound; + return inValue; +} + +inline SBezierKeyframe +CreateBezierKeyframeFromEaseInEaseOutKeyframe(float *inPreviousValue, + SEaseInEaseOutKeyframe inCurrent, float *inNextValue) +{ + float theValue = inCurrent.m_KeyframeValue; + float theSeconds = inCurrent.m_KeyframeSeconds; + float inSeconds = 0.f; + float inValue = 0.f; + float outSeconds = 0.f; + float outValue = 0.f; + if (inPreviousValue) { + float thePercent = 1.0f - AnimationClamp(0.0f, 1.0f, inCurrent.m_EaseIn / 100.f); + double theAmount = 1.0f - thePercent * .333333333334; + inValue = (float)(*inPreviousValue + + ((inCurrent.m_KeyframeValue - *inPreviousValue) * theAmount)); + } + if (inNextValue) { + float thePercent = 1.0f - AnimationClamp(0.0f, 1.0f, inCurrent.m_EaseOut / 100.f); + double theAmount = thePercent * .3333333333334; + outValue = (float)(inCurrent.m_KeyframeValue + + ((*inNextValue - inCurrent.m_KeyframeValue) * theAmount)); + } + return CreateBezierKeyframe(theSeconds, theValue, inSeconds, inValue, outSeconds, outValue); +} + +void CopyKeyframes(const IAnimationCore &inSourceAnimationCore, IAnimationCore &inDestAnimationCore, + Qt3DSDMAnimationHandle inDestAnimation, const TKeyframeHandleList &inKeyframes); + +Qt3DSDMAnimationHandle CopyAnimation(TAnimationCorePtr inSourceAnimationCore, + Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMSlideHandle inNewSlide, + Qt3DSDMInstanceHandle inNewInstance, + Qt3DSDMPropertyHandle inNewProperty, size_t inNewIndex); + +struct SEaseInGetter +{ + float operator()(const SLinearKeyframe &) const { return 0.f; } + float operator()(const SBezierKeyframe &) const { return 0.f; } + float operator()(const SEaseInEaseOutKeyframe &inValue) const { return inValue.m_EaseIn; } + float operator()() + { + QT3DS_ASSERT(false); + return 0.0f; + } +}; +struct SEaseOutGetter +{ + float operator()(const SLinearKeyframe &) const { return 0.f; } + float operator()(const SBezierKeyframe &) const { return 0.f; } + float operator()(const SEaseInEaseOutKeyframe &inValue) const { return inValue.m_EaseOut; } + float operator()() + { + QT3DS_ASSERT(false); + return 0.0f; + } +}; +inline void GetEaseInOutValues(const TKeyframe &inValue, float &outEaseIn, float &outEaseOut) +{ + SEaseInGetter theGetter; + outEaseIn = inValue.visit<float>(theGetter); + + SEaseOutGetter theEaseOutGetter; + outEaseOut = inValue.visit<float>(theEaseOutGetter); +} + +struct SEaseInSetter +{ + float m_Value; + TKeyframe operator()(SLinearKeyframe &inValue) const { return inValue; } + TKeyframe operator()(SBezierKeyframe &inValue) const { return inValue; } + TKeyframe operator()(SEaseInEaseOutKeyframe &inKeyframe) const + { + inKeyframe.m_EaseIn = m_Value; + return inKeyframe; + } + TKeyframe operator()() + { + QT3DS_ASSERT(false); + return TKeyframe(); + } +}; +struct SEaseOutSetter +{ + float m_Value; + TKeyframe operator()(SLinearKeyframe &inValue) const { return inValue; } + TKeyframe operator()(SBezierKeyframe &inValue) const { return inValue; } + TKeyframe operator()(SEaseInEaseOutKeyframe &inKeyframe) const + { + inKeyframe.m_EaseOut = m_Value; + return inKeyframe; + } + TKeyframe operator()() + { + QT3DS_ASSERT(false); + return TKeyframe(); + } +}; +inline TKeyframe SetEaseInOutValues(TKeyframe &inKeyframe, float inEaseIn, float inEaseOut) +{ + SEaseInSetter theSetter; + theSetter.m_Value = inEaseIn; + inKeyframe.visit<TKeyframe>(theSetter); + + SEaseOutSetter theEaseOutSetter; + theEaseOutSetter.m_Value = inEaseOut; + inKeyframe.visit<TKeyframe>(theEaseOutSetter); + + return inKeyframe; +} + +void GetKeyframesAsBezier(Qt3DSDMAnimationHandle inAnimation, const IAnimationCore &inAnimationCore, + TBezierKeyframeList &outKeyframes); +} + +#endif diff --git a/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp new file mode 100644 index 0000000..2bd8941 --- /dev/null +++ b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp @@ -0,0 +1,579 @@ +/**************************************************************************** +** +** Copyright (C) 2008 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "Qt3DSDMComposerTypeDefinitions.h" +#include <memory> +#include "Qt3DSDMDataCore.h" +#include "SimpleDataCore.h" +#include "DataCoreProducer.h" +#include "Qt3DSDMSlideCore.h" + +#include <QtGlobal> + +using namespace qt3dsdm; +using std::make_shared; +using std::shared_ptr; + +#ifdef _WIN32 +#pragma warning(disable : 4100) +#endif + +// SComposerTypePropertyDefinition constructors + +namespace { + +template <typename TDataType> +struct DataConstructor +{ + template <typename TInputType> + TDataType Construct(const TInputType &inInput) + { + return TDataType(inInput); + } +}; + +template <> +struct DataConstructor<SLong4> +{ + SLong4 Construct(int inValue) + { + unsigned long theValue((unsigned long)inValue); + return SLong4(theValue, theValue, theValue, theValue); + } +}; + +template <> +struct DataConstructor<TDataStrPtr> +{ + TDataStrPtr Construct(const wchar_t *inData) + { + if (IsTrivial(inData)) + return make_shared<CDataStr>(); + return make_shared<CDataStr>(inData); + } +}; +template <> +struct DataConstructor<SStringOrInt> +{ + SStringOrInt Construct(const wchar_t *inData) + { + if (IsTrivial(inData)) + return make_shared<CDataStr>(); + return make_shared<CDataStr>(inData); + } +}; +template <> +struct DataConstructor<SObjectRefType> +{ + SObjectRefType Construct(const wchar_t *) { return SObjectRefType(); } +}; +} + +#define QT3DS_WCHAR_T_Typed L"Typed" +#define QT3DS_WCHAR_T_Guided L"Guided" +#define QT3DS_WCHAR_T_Named L"Named" +#define QT3DS_WCHAR_T_SlideOwner L"SlideOwner" +#define QT3DS_WCHAR_T_Slide L"Slide" +#define QT3DS_WCHAR_T_Action L"Action" +#define QT3DS_WCHAR_T_Asset L"Asset" +#define QT3DS_WCHAR_T_Scene L"Scene" +#define QT3DS_WCHAR_T_Image L"Image" +#define QT3DS_WCHAR_T_Material L"Material" +#define QT3DS_WCHAR_T_Behavior L"Behavior" +#define QT3DS_WCHAR_T_Node L"Node" +#define QT3DS_WCHAR_T_Layer L"Layer" +#define QT3DS_WCHAR_T_Group L"Group" +#define QT3DS_WCHAR_T_Model L"Model" +#define QT3DS_WCHAR_T_Light L"Light" +#define QT3DS_WCHAR_T_Camera L"Camera" +#define QT3DS_WCHAR_T_Component L"Component" +#define QT3DS_WCHAR_T_Text L"Text" +#define QT3DS_WCHAR_T_Effect L"Effect" +#define QT3DS_WCHAR_T_RenderPlugin L"RenderPlugin" +#define QT3DS_WCHAR_T_MaterialBase L"MaterialBase" +#define QT3DS_WCHAR_T_CustomMaterial L"CustomMaterial" +#define QT3DS_WCHAR_T_ReferencedMaterial L"ReferencedMaterial" +#define QT3DS_WCHAR_T_Alias L"Alias" +#define QT3DS_WCHAR_T_Lightmaps L"Lightmaps" + +#define QT3DS_WCHAR_T_type L"type" +#define QT3DS_WCHAR_T_id L"id" +#define QT3DS_WCHAR_T_name L"name" +#define QT3DS_WCHAR_T_componentid L"componentid" +#define QT3DS_WCHAR_T_playmode L"playmode" +#define QT3DS_WCHAR_T_playthroughto L"playthroughto" +#define QT3DS_WCHAR_T_initialplaystate L"initialplaystate" +#define QT3DS_WCHAR_T_actioneyeball L"actioneyeball" +#define QT3DS_WCHAR_T_sourcepath L"sourcepath" +#define QT3DS_WCHAR_T_importid L"importid" +#define QT3DS_WCHAR_T_starttime L"starttime" +#define QT3DS_WCHAR_T_endtime L"endtime" +#define QT3DS_WCHAR_T_eyeball L"eyeball" +#define QT3DS_WCHAR_T_shy L"shy" +#define QT3DS_WCHAR_T_locked L"locked" +#define QT3DS_WCHAR_T_timebarcolor L"timebarcolor" +#define QT3DS_WCHAR_T_timebartext L"timebartext" +#define QT3DS_WCHAR_T_bgcolorenable L"bgcolorenable" +#define QT3DS_WCHAR_T_background L"background" +#define QT3DS_WCHAR_T_backgroundcolor L"backgroundcolor" +#define QT3DS_WCHAR_T_blendtype L"blendtype" +#define QT3DS_WCHAR_T_scaleu L"scaleu" +#define QT3DS_WCHAR_T_scalev L"scalev" +#define QT3DS_WCHAR_T_mappingmode L"mappingmode" +#define QT3DS_WCHAR_T_tilingmodehorz L"tilingmodehorz" +#define QT3DS_WCHAR_T_tilingmodevert L"tilingmodevert" +#define QT3DS_WCHAR_T_rotationuv L"rotationuv" +#define QT3DS_WCHAR_T_positionu L"positionu" +#define QT3DS_WCHAR_T_positionv L"positionv" +#define QT3DS_WCHAR_T_pivotu L"pivotu" +#define QT3DS_WCHAR_T_pivotv L"pivotv" +#define QT3DS_WCHAR_T_subpresentation L"subpresentation" +#define QT3DS_WCHAR_T_iblprobe L"iblprobe" +#define QT3DS_WCHAR_T_shaderlighting L"shaderlighting" +#define QT3DS_WCHAR_T_blendmode L"blendmode" +#define QT3DS_WCHAR_T_vertexcolors L"vertexcolors" +#define QT3DS_WCHAR_T_diffuse L"diffuse" +#define QT3DS_WCHAR_T_diffusemap L"diffusemap" +#define QT3DS_WCHAR_T_diffusemap2 L"diffusemap2" +#define QT3DS_WCHAR_T_diffusemap3 L"diffusemap3" +#define QT3DS_WCHAR_T_specularreflection L"specularreflection" +#define QT3DS_WCHAR_T_specularmap L"specularmap" +#define QT3DS_WCHAR_T_specularmodel L"specularmodel" +#define QT3DS_WCHAR_T_speculartint L"speculartint" +#define QT3DS_WCHAR_T_ior L"ior" +#define QT3DS_WCHAR_T_specularamount L"specularamount" +#define QT3DS_WCHAR_T_specularroughness L"specularroughness" +#define QT3DS_WCHAR_T_roughnessmap L"roughnessmap" +#define QT3DS_WCHAR_T_opacitymap L"opacitymap" +#define QT3DS_WCHAR_T_emissivepower L"emissivepower" +#define QT3DS_WCHAR_T_emissivecolor L"emissivecolor" +#define QT3DS_WCHAR_T_emissivemap L"emissivemap" +#define QT3DS_WCHAR_T_emissivemap2 L"emissivemap2" +#define QT3DS_WCHAR_T_normalmap L"normalmap" +#define QT3DS_WCHAR_T_normalstrength L"normalstrength" +#define QT3DS_WCHAR_T_position L"position" +#define QT3DS_WCHAR_T_rotation L"rotation" +#define QT3DS_WCHAR_T_scale L"scale" +#define QT3DS_WCHAR_T_pivot L"pivot" +#define QT3DS_WCHAR_T_opacity L"opacity" +#define QT3DS_WCHAR_T_rotationorder L"rotationorder" +#define QT3DS_WCHAR_T_orientation L"orientation" +#define QT3DS_WCHAR_T_progressiveaa L"progressiveaa" +#define QT3DS_WCHAR_T_multisampleaa L"multisampleaa" +#define QT3DS_WCHAR_T_disabledepthtest L"disabledepthtest" +#define QT3DS_WCHAR_T_disabledepthprepass L"disabledepthprepass" +#define QT3DS_WCHAR_T_layerwidth L"layerwidth" +#define QT3DS_WCHAR_T_layerheight L"layerheight" +#define QT3DS_WCHAR_T_lighttype L"lighttype" +#define QT3DS_WCHAR_T_lightdiffuse L"lightdiffuse" +#define QT3DS_WCHAR_T_lightspecular L"lightspecular" +#define QT3DS_WCHAR_T_lightambient L"lightambient" +#define QT3DS_WCHAR_T_brightness L"brightness" +#define QT3DS_WCHAR_T_linearfade L"linearfade" +#define QT3DS_WCHAR_T_expfade L"expfade" +#define QT3DS_WCHAR_T_areawidth L"areawidth" +#define QT3DS_WCHAR_T_areaheight L"areaheight" +#define QT3DS_WCHAR_T_castshadow L"castshadow" +#define QT3DS_WCHAR_T_shdwbias L"shdwbias" +#define QT3DS_WCHAR_T_shdwfactor L"shdwfactor" +#define QT3DS_WCHAR_T_shdwmapres L"shdwmapres" +#define QT3DS_WCHAR_T_shdwmapfar L"shdwmapfar" +#define QT3DS_WCHAR_T_shdwmapfov L"shdwmapfov" +#define QT3DS_WCHAR_T_shdwfilter L"shdwfilter" +#define QT3DS_WCHAR_T_orthographic L"orthographic" +#define QT3DS_WCHAR_T_fov L"fov" +#define QT3DS_WCHAR_T_fovhorizontal L"fovhorizontal" +#define QT3DS_WCHAR_T_clipnear L"clipnear" +#define QT3DS_WCHAR_T_clipfar L"clipfar" +#define QT3DS_WCHAR_T_lookatlock L"lookatlock" +#define QT3DS_WCHAR_T_lookatpoint L"lookatpoint" +#define QT3DS_WCHAR_T_textstring L"textstring" +#define QT3DS_WCHAR_T_textcolor L"textcolor" +#define QT3DS_WCHAR_T_font L"font" +#define QT3DS_WCHAR_T_size L"size" +#define QT3DS_WCHAR_T_horzalign L"horzalign" +#define QT3DS_WCHAR_T_vertalign L"vertalign" +#define QT3DS_WCHAR_T_leading L"leading" +#define QT3DS_WCHAR_T_tracking L"tracking" +#define QT3DS_WCHAR_T_dropshadow L"dropshadow" +#define QT3DS_WCHAR_T_dropshadowstrength L"dropshadowstrength" +#define QT3DS_WCHAR_T_dropshadowoffsetx L"dropshadowoffsetx" +#define QT3DS_WCHAR_T_dropshadowoffsety L"dropshadowoffsety" +#define QT3DS_WCHAR_T_wordwrap L"wordwrap" +#define QT3DS_WCHAR_T_boundingbox L"boundingbox" +#define QT3DS_WCHAR_T_elide L"elide" +#define QT3DS_WCHAR_T_enableacceleratedfont L"enableacceleratedfont" +#define QT3DS_WCHAR_T_importfile L"importfile" +#define QT3DS_WCHAR_T_fileid L"fileid" +#define QT3DS_WCHAR_T_size L"size" +#define QT3DS_WCHAR_T_location L"location" +#define QT3DS_WCHAR_T_boneid L"boneid" +#define QT3DS_WCHAR_T_poseroot L"poseroot" +#define QT3DS_WCHAR_T_ignoresparent L"ignoresparent" +#define QT3DS_WCHAR_T_shadowcaster L"shadowcaster" +#define QT3DS_WCHAR_T_tessellation L"tessellation" +#define QT3DS_WCHAR_T_edgetess L"edgetess" +#define QT3DS_WCHAR_T_innertess L"innertess" +#define QT3DS_WCHAR_T_scalemode L"scalemode" +#define QT3DS_WCHAR_T_scaleanchor L"scaleanchor" +#define QT3DS_WCHAR_T_horzfields L"horzfields" +#define QT3DS_WCHAR_T_left L"left" +#define QT3DS_WCHAR_T_leftunits L"leftunits" +#define QT3DS_WCHAR_T_width L"width" +#define QT3DS_WCHAR_T_widthunits L"widthunits" +#define QT3DS_WCHAR_T_right L"right" +#define QT3DS_WCHAR_T_rightunits L"rightunits" +#define QT3DS_WCHAR_T_vertfields L"vertfields" +#define QT3DS_WCHAR_T_top L"top" +#define QT3DS_WCHAR_T_topunits L"topunits" +#define QT3DS_WCHAR_T_height L"height" +#define QT3DS_WCHAR_T_heightunits L"heightunits" +#define QT3DS_WCHAR_T_bottom L"bottom" +#define QT3DS_WCHAR_T_bottomunits L"bottomunits" +#define QT3DS_WCHAR_T_aostrength L"aostrength" +#define QT3DS_WCHAR_T_aodistance L"aodistance" +#define QT3DS_WCHAR_T_aosoftness L"aosoftness" +#define QT3DS_WCHAR_T_aobias L"aobias" +#define QT3DS_WCHAR_T_aosamplerate L"aosamplerate" +#define QT3DS_WCHAR_T_aodither L"aodither" +#define QT3DS_WCHAR_T_shadowstrength L"shadowstrength" +#define QT3DS_WCHAR_T_shadowdist L"shadowdist" +#define QT3DS_WCHAR_T_shadowsoftness L"shadowsoftness" +#define QT3DS_WCHAR_T_shadowbias L"shadowbias" +#define QT3DS_WCHAR_T_source L"source" +#define QT3DS_WCHAR_T_referencedmaterial L"referencedmaterial" +#define QT3DS_WCHAR_T_lightprobe L"lightprobe" +#define QT3DS_WCHAR_T_probebright L"probebright" +#define QT3DS_WCHAR_T_fastibl L"fastibl" +#define QT3DS_WCHAR_T_probehorizon L"probehorizon" +#define QT3DS_WCHAR_T_probefov L"probefov" +#define QT3DS_WCHAR_T_lightprobe2 L"lightprobe2" +#define QT3DS_WCHAR_T_probe2fade L"probe2fade" +#define QT3DS_WCHAR_T_probe2window L"probe2window" +#define QT3DS_WCHAR_T_probe2pos L"probe2pos" +#define QT3DS_WCHAR_T_bumpmap L"bumpmap" +#define QT3DS_WCHAR_T_bumpamount L"bumpamount" +#define QT3DS_WCHAR_T_normalmap L"normalmap" +#define QT3DS_WCHAR_T_displacementmap L"displacementmap" +#define QT3DS_WCHAR_T_displaceamount L"displaceamount" +#define QT3DS_WCHAR_T_translucencymap L"translucencymap" +#define QT3DS_WCHAR_T_translucentfalloff L"translucentfalloff" +#define QT3DS_WCHAR_T_diffuselightwrap L"diffuselightwrap" +#define QT3DS_WCHAR_T_fresnelPower L"fresnelPower" +#define QT3DS_WCHAR_T_referencednode L"referencednode" +#define QT3DS_WCHAR_T_temporalaa L"temporalaa" +#define QT3DS_WCHAR_T_scope L"scope" +#define QT3DS_WCHAR_T_Path L"Path" +#define QT3DS_WCHAR_T_pathdata L"pathdata" +#define QT3DS_WCHAR_T_PathAnchorPoint L"PathAnchorPoint" +#define QT3DS_WCHAR_T_incomingangle L"incomingangle" +#define QT3DS_WCHAR_T_incomingdistance L"incomingdistance" +#define QT3DS_WCHAR_T_outgoingdistance L"outgoingdistance" +#define QT3DS_WCHAR_T_linearerror L"linearerror" +#define QT3DS_WCHAR_T_edgetessamount L"edgetessamount" +#define QT3DS_WCHAR_T_innertessamount L"innertessamount" +#define QT3DS_WCHAR_T_begincap L"begincap" +#define QT3DS_WCHAR_T_begincapoffset L"begincapoffset" +#define QT3DS_WCHAR_T_begincapopacity L"begincapopacity" +#define QT3DS_WCHAR_T_begincapwidth L"begincapwidth" +#define QT3DS_WCHAR_T_endcap L"endcap" +#define QT3DS_WCHAR_T_endcapoffset L"endcapoffset" +#define QT3DS_WCHAR_T_endcapopacity L"endcapopacity" +#define QT3DS_WCHAR_T_endcapwidth L"endcapwidth" +#define QT3DS_WCHAR_T_pathtype L"pathtype" +#define QT3DS_WCHAR_T_closed L"closed" +#define QT3DS_WCHAR_T_paintstyle L"paintstyle" +#define QT3DS_WCHAR_T_SubPath L"SubPath" +#define QT3DS_WCHAR_T_lightmapindirect L"lightmapindirect" +#define QT3DS_WCHAR_T_lightmapradiosity L"lightmapradiosity" +#define QT3DS_WCHAR_T_lightmapshadow L"lightmapshadow" +#define QT3DS_WCHAR_T_controlledproperty L"controlledproperty" +#define QT3DS_WCHAR_T_variants L"variants" + +const wchar_t *ComposerObjectTypes::Convert(ComposerObjectTypes::Enum inType) +{ + switch (inType) { +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \ + case name: \ + return QT3DS_WCHAR_T_##name; + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE + default: + break; + } + + QT3DS_ASSERT(false); + return L"Unknown"; +} + +ComposerObjectTypes::Enum ComposerObjectTypes::Convert(const wchar_t *inType) +{ + +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \ + if (AreEqual(QT3DS_WCHAR_T_##name, inType)) \ + return ComposerObjectTypes::name; + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE + + QT3DS_ASSERT(false); + return ComposerObjectTypes::Unknown; +} + +ComposerObjectTypes::Enum ComposerObjectTypes::Convert(const char8_t *inType) +{ + +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \ + if (AreEqual(#name, inType)) \ + return ComposerObjectTypes::name; + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE + + QT3DS_ASSERT(false); + return ComposerObjectTypes::Unknown; +} + +const wchar_t *ComposerPropertyNames::Convert(ComposerPropertyNames::Enum inType) +{ + switch (inType) { +#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, type, defaultValue) +#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) \ + case name: \ + return QT3DS_WCHAR_T_##name; +#define HANDLE_COMPOSER_PROPERTY(name, memberName, type, defaultValue) \ + HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) propmacro + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE +#undef HANDLE_COMPOSER_PROPERTY +#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT +#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE + default: + break; + } + QT3DS_ASSERT(false); + return L"Unknown"; +} + +ComposerPropertyNames::Enum ComposerPropertyNames::Convert(const wchar_t *inType) +{ +#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, type, defaultValue) +#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) \ + if (AreEqual(inType, QT3DS_WCHAR_T_##name)) \ + return name; +#define HANDLE_COMPOSER_PROPERTY(name, memberName, type, defaultValue) \ + HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) propmacro + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE +#undef HANDLE_COMPOSER_PROPERTY +#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT +#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE + QT3DS_ASSERT(false); + return ComposerPropertyNames::Unknown; +} + +const char8_t *ComposerPropertyNames::ConvertNarrow(ComposerPropertyNames::Enum inType) +{ + switch (inType) { +#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, type, defaultValue) +#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) \ + case name: \ + return #name; +#define HANDLE_COMPOSER_PROPERTY(name, memberName, type, defaultValue) \ + HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) propmacro + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE +#undef HANDLE_COMPOSER_PROPERTY +#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT +#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE + default: + break; + } + QT3DS_ASSERT(false); + return "Unknown"; +} + +ComposerPropertyNames::Enum ComposerPropertyNames::Convert(const char8_t *inType) +{ +#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, type, defaultValue) +#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) \ + if (AreEqual(inType, #name)) \ + return name; +#define HANDLE_COMPOSER_PROPERTY(name, memberName, type, defaultValue) \ + HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) propmacro + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE +#undef HANDLE_COMPOSER_PROPERTY +#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT +#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE + QT3DS_ASSERT(false); + return ComposerPropertyNames::Unknown; +} + +#define HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue) \ + , memberName(inCore, inInstance, DataConstructor<dtype>().Construct(defaultValue)) + +#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype) \ + , memberName(inCore, inInstance) + +#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, dtype, defaultValue) \ + HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue) + +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \ + SComposerTypePropertyDefinition<ComposerObjectTypes::name>::SComposerTypePropertyDefinition( \ + IDataCore &inCore, Qt3DSDMInstanceHandle inInstance) \ + : reserved(false) propmacro \ + { \ + Q_UNUSED(inCore); \ + Q_UNUSED(inInstance); \ + } +ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE +#undef HANDLE_COMPOSER_PROPERTY +#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT +#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE + +void ComposerTypeDefinitionsHelper::SetInstanceAsCanonical(IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + ComposerObjectTypes::Enum inObjectType) +{ + inMetaData.SetInstanceAsCanonical(inInstance, ComposerObjectTypes::Convert(inObjectType)); +} + +void ComposerTypeDefinitionsHelper::SetInstancePropertyValue(IDataCore &inDataCore, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const wchar_t *inPropValue) +{ + inDataCore.SetInstancePropertyValue(inInstance, inProperty, make_shared<CDataStr>(inPropValue)); +} + +void ComposerTypeDefinitionsHelper::DeriveInstance(IDataCore &inDataCore, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) +{ + inDataCore.DeriveInstance(inInstance, inParent); +} + +// Container object for all of the object definitions +SComposerObjectDefinitions::SComposerObjectDefinitions(IDataCore &inCore, IMetaData &inMetaData) + : m_Typed(inCore, inMetaData, inCore.CreateInstance()) + , m_Guided(inCore, inMetaData, inCore.CreateInstance()) + , m_Named(inCore, inMetaData, inCore.CreateInstance()) + , m_SlideOwner(inCore, inMetaData, inCore.CreateInstance()) + , m_Slide(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Named) + , m_Action(inCore, inMetaData, inCore.CreateInstance(), m_Typed) + , m_Asset(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Guided, m_Named) + , m_Scene(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset, m_SlideOwner) + , m_Image(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset) + , m_MaterialBase(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset) + , m_Lightmaps(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_MaterialBase) + , m_Material(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Lightmaps) + , m_CustomMaterial(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Lightmaps) + , m_ReferencedMaterial(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Lightmaps) + , m_Behavior(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset) + , m_Effect(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset) + , m_Node(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset) + , m_Layer(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node) + , m_Group(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node) + , m_Model(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node) + , m_Light(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node) + , m_Camera(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node) + , m_Component(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node, m_SlideOwner) + , m_Text(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node) + , m_RenderPlugin(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset) + , m_Alias(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node) + , m_Path(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node) + , m_PathAnchorPoint(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset) + , m_SubPath(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset) + , m_DataCore(inCore) +{ +} + +bool SComposerObjectDefinitions::IsA(Qt3DSDMInstanceHandle inInstance, + ComposerObjectTypes::Enum inType) +{ + if (m_DataCore.IsInstance(inInstance) == false) + return false; + + switch (inType) { +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \ + case ComposerObjectTypes::name: \ + return m_DataCore.IsInstanceOrDerivedFrom(inInstance, m_##name.m_Instance); + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE + default: + break; + } + + QT3DS_ASSERT(false); + return false; +} + +// Could easily return None, meaning we can't identify the object type. +// Checks the type of the first derivation parent, so this won't ever return +// SlideOwner, for instance. +ComposerObjectTypes::Enum SComposerObjectDefinitions::GetType(Qt3DSDMInstanceHandle inInstance) +{ + if (m_DataCore.IsInstance(inInstance) == false) + return ComposerObjectTypes::Unknown; + + Qt3DSDMInstanceHandle theTargetInstance = inInstance; + TInstanceHandleList theHandleList; + m_DataCore.GetInstanceParents(inInstance, theHandleList); + if (theHandleList.empty() == false) + theTargetInstance = theHandleList[0]; + +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \ + if (m_##name.m_Instance == theTargetInstance) \ + return ComposerObjectTypes::name; + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE + + return ComposerObjectTypes::Unknown; +} + +Qt3DSDMInstanceHandle +SComposerObjectDefinitions::GetInstanceForType(ComposerObjectTypes::Enum inType) +{ + switch (inType) { +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \ + case ComposerObjectTypes::name: \ + return m_##name.m_Instance; + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE + default: + break; + } + + QT3DS_ASSERT(false); + return 0; +} diff --git a/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h new file mode 100644 index 0000000..1a07940 --- /dev/null +++ b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h @@ -0,0 +1,956 @@ +/**************************************************************************** +** +** Copyright (C) 2008 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMDataTypes.h" +#include "foundation/Qt3DSOption.h" +#include "Qt3DSDMDataCore.h" +#include <utility> + +// Defines the minimal property model that UIComposer needs to +// run off of. +namespace qt3dsdm { +class IDataCore; +class IMetaData; +class ISlideCore; +class IPropertySystem; + +// Extensible macro definitions +// Enumerations *have* to be in derivation order +// else initialization of the SComposerObjectDefinitions class +// will fail catastrophically +// Specific type documentation is below +#define ITERATE_COMPOSER_OBJECT_TYPES \ + HANDLE_COMPOSER_OBJECT_TYPE(Typed, ITERATE_COMPOSER_TYPED_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Guided, ITERATE_COMPOSER_GUIDED_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Named, ITERATE_COMPOSER_NAMED_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(SlideOwner, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Slide, ITERATE_COMPOSER_SLIDE_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Action, ITERATE_COMPOSER_ACTION_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Asset, ITERATE_COMPOSER_ASSET_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Scene, ITERATE_COMPOSER_SCENE_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Image, ITERATE_COMPOSER_IMAGE_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(MaterialBase, ITERATE_COMPOSER_MATERIAL_BASE_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Lightmaps, ITERATE_COMPOSER_LIGHTMAP_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Material, ITERATE_COMPOSER_MATERIAL_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(CustomMaterial, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(ReferencedMaterial, \ + ITERATE_COMPOSER_REFERENCED_MATERIAL_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Behavior, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Effect, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Node, ITERATE_COMPOSER_NODE_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Layer, ITERATE_COMPOSER_LAYER_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Group, ITERATE_COMPOSER_GROUP_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Model, ITERATE_COMPOSER_MODEL_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Light, ITERATE_COMPOSER_LIGHT_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Camera, ITERATE_COMPOSER_CAMERA_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Component, ITERATE_COMPOSER_COMPONENT_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Text, ITERATE_COMPOSER_TEXT_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(RenderPlugin, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Alias, ITERATE_COMPOSER_ALIAS_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(Path, ITERATE_COMPOSER_PATH_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(PathAnchorPoint, ITERATE_COMPOSER_PATH_ANCHOR_POINT_PROPERTIES) \ + HANDLE_COMPOSER_OBJECT_TYPE(SubPath, ITERATE_COMPOSER_PATH_SUBPATH_PROPERTIES) + +#define ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES + +#define ITERATE_COMPOSER_TYPED_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(type, m_TypeProp, TDataStrPtr, L"Typed") + +#define ITERATE_COMPOSER_GUIDED_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(id, m_GuidProp, SLong4, 0) + +#define ITERATE_COMPOSER_NAMED_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(name, m_NameProp, TDataStrPtr, L"Unnamed") + +#define ITERATE_COMPOSER_ASSET_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(sourcepath, m_SourcePath, TDataStrPtr, L"") \ + HANDLE_COMPOSER_PROPERTY(importid, m_ImportId, TDataStrPtr, L"") \ + HANDLE_COMPOSER_PROPERTY(importfile, m_ImportFile, TDataStrPtr, L"") \ + HANDLE_COMPOSER_PROPERTY(fileid, m_FileId, TDataStrPtr, L"") \ + HANDLE_COMPOSER_PROPERTY(starttime, m_StartTime, qt3ds::QT3DSI32, 0) \ + HANDLE_COMPOSER_PROPERTY(endtime, m_EndTime, qt3ds::QT3DSI32, 10000) \ + HANDLE_COMPOSER_PROPERTY(eyeball, m_Eyeball, bool, true) \ + HANDLE_COMPOSER_PROPERTY(shy, m_Shy, bool, false) \ + HANDLE_COMPOSER_PROPERTY(locked, m_Locked, bool, false) \ + HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(timebarcolor, m_TimebarColor, SFloat4) \ + HANDLE_COMPOSER_PROPERTY(timebartext, m_TimebarText, TDataStrPtr, L"") \ + HANDLE_COMPOSER_PROPERTY(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_SCENE_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(bgcolorenable, m_BgColorEnable, bool, true) \ + HANDLE_COMPOSER_PROPERTY(backgroundcolor, m_BackgroundColor, SFloat4, SFloat4(0, 0, 0, 1)) \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_COMPONENT_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(variants, m_variants, TDataStrPtr, L"") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_NODE_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(position, m_Position, SFloat3, SFloat3(0, 0, 0)) \ + HANDLE_COMPOSER_PROPERTY(rotation, m_Rotation, SFloat3, SFloat3(0, 0, 0)) \ + HANDLE_COMPOSER_PROPERTY(scale, m_Scale, SFloat3, SFloat3(1, 1, 1)) \ + HANDLE_COMPOSER_PROPERTY(pivot, m_Pivot, SFloat3, SFloat3(0, 0, 0)) \ + HANDLE_COMPOSER_PROPERTY(opacity, m_Opacity, float, 100.f) \ + HANDLE_COMPOSER_PROPERTY(rotationorder, m_RotationOrder, TDataStrPtr, L"YXZ") \ + HANDLE_COMPOSER_PROPERTY(orientation, m_Orientation, TDataStrPtr, L"Left Handed") \ + HANDLE_COMPOSER_PROPERTY(boneid, m_BoneId, qt3ds::QT3DSI32, 0) \ + HANDLE_COMPOSER_PROPERTY(ignoresparent, m_IgnoresParent, bool, false) \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_MODEL_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(shadowcaster, m_ShadowCaster, bool, true) \ + HANDLE_COMPOSER_PROPERTY(poseroot, m_PoseRoot, qt3ds::QT3DSI32, -1) \ + HANDLE_COMPOSER_PROPERTY(tessellation, m_Tessellation, TDataStrPtr, L"None") \ + HANDLE_COMPOSER_PROPERTY(edgetess, m_EdgeTess, float, 1.0) \ + HANDLE_COMPOSER_PROPERTY(innertess, m_InnerTess, float, 1.0) \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(variants, m_variants, TDataStrPtr, L"") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_IMAGE_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(scaleu, m_RepeatU, float, 1.0f) \ + HANDLE_COMPOSER_PROPERTY(scalev, m_RepeatV, float, 1.0f) \ + HANDLE_COMPOSER_PROPERTY(mappingmode, m_TextureMapping, TDataStrPtr, L"UV Mapping") \ + HANDLE_COMPOSER_PROPERTY(tilingmodehorz, m_TilingU, TDataStrPtr, L"No Tiling") \ + HANDLE_COMPOSER_PROPERTY(tilingmodevert, m_TilingV, TDataStrPtr, L"No Tiling") \ + HANDLE_COMPOSER_PROPERTY(rotationuv, m_RotationUV, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(positionu, m_PositionU, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(positionv, m_PositionV, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(pivotu, m_PivotU, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(pivotv, m_PivotV, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(subpresentation, m_SubPresentation, TDataStrPtr, L"") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_LIGHTMAP_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(lightmapindirect, m_LightmapIndirect, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(lightmapradiosity, m_LightmapRadiosity, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(lightmapshadow, m_LightmapShadow, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_CUSTOM_MATERIAL_PROPERTIES \ + HANDLE_QT3DS_RENDER_PROPERTY(iblprobe, m_IblProbe, SLong4, 0) + +#define ITERATE_COMPOSER_MATERIAL_BASE_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(iblprobe, m_IblProbe, SLong4, 0) + +#define ITERATE_COMPOSER_MATERIAL_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(shaderlighting, m_ShaderLighting, TDataStrPtr, L"Vertex") \ + HANDLE_COMPOSER_PROPERTY(blendmode, m_BlendMode, TDataStrPtr, L"Normal") \ + HANDLE_COMPOSER_PROPERTY(diffuse, m_DiffuseColor, SFloat4, SFloat4(1, 1, 1, 1)) \ + HANDLE_COMPOSER_PROPERTY(diffusemap, m_DiffuseMap1, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(diffusemap2, m_DiffuseMap2, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(diffusemap3, m_DiffuseMap3, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(specularreflection, m_SpecularReflection, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(specularamount, m_SpecularAmount, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(specularroughness, m_SpecularRoughness, float, 50.f) \ + HANDLE_COMPOSER_PROPERTY(roughnessmap, m_RoughnessMap, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(opacity, m_Opacity, float, 100.f) \ + HANDLE_COMPOSER_PROPERTY(opacitymap, m_OpacityMap, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(emissivecolor, m_EmissiveColor, SFloat4, SFloat4(1, 1, 1, 1)) \ + HANDLE_COMPOSER_PROPERTY(emissivepower, m_EmissivePower, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(emissivemap, m_EmissiveMap, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(emissivemap2, m_EmissiveMap2, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(bumpmap, m_BumpMap, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(bumpamount, m_BumpAmount, float, 9.0f) \ + HANDLE_COMPOSER_PROPERTY(normalmap, m_NormalMap, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(displacementmap, m_DisplacementMap, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(displaceamount, m_DisplaceAmount, float, 0.5f) \ + HANDLE_COMPOSER_PROPERTY(translucencymap, m_TranslucencyMap, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(translucentfalloff, m_TranslucentFalloff, float, 1.f) \ + HANDLE_COMPOSER_PROPERTY(diffuselightwrap, m_DiffuseLightWrap, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(specularmap, m_SpecularMap, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(specularmodel, m_SpecularModel, TDataStrPtr, L"Default") \ + HANDLE_COMPOSER_PROPERTY(speculartint, m_SpecularTint, SFloat4, SFloat4(1, 1, 1, 1)) \ + HANDLE_COMPOSER_PROPERTY(ior, m_IOR, float, 0) \ + HANDLE_COMPOSER_PROPERTY(fresnelPower, m_FresnelPower, float, 0) \ + HANDLE_COMPOSER_PROPERTY(vertexcolors, m_VertexColors, bool, false) \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_REFERENCED_MATERIAL_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(referencedmaterial, m_ReferencedMaterial, SObjectRefType, L"") + +#define ITERATE_COMPOSER_LAYER_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(progressiveaa, m_ProgressiveAA, TDataStrPtr, L"None") \ + HANDLE_COMPOSER_PROPERTY(multisampleaa, m_MultisampleAA, TDataStrPtr, L"None") \ + HANDLE_COMPOSER_PROPERTY(temporalaa, m_TemporalAA, bool, false) \ + HANDLE_COMPOSER_PROPERTY(disabledepthtest, m_DisableDepthTest, bool, false) \ + HANDLE_COMPOSER_PROPERTY(disabledepthprepass, m_DisableDepthPrepass, bool, false) \ + HANDLE_COMPOSER_PROPERTY(background, m_Background, TDataStrPtr, L"Transparent") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(backgroundcolor, m_BackgroundColor, SFloat4, \ + SFloat4(0, 0, 0, 1)) \ + HANDLE_COMPOSER_PROPERTY(blendtype, m_BlendType, TDataStrPtr, L"Normal") \ + HANDLE_COMPOSER_PROPERTY(horzfields, m_HorizontalFieldValues, TDataStrPtr, L"Left/Width") \ + HANDLE_COMPOSER_PROPERTY(left, m_Left, float, 0) \ + HANDLE_COMPOSER_PROPERTY(leftunits, m_LeftUnits, TDataStrPtr, L"percent") \ + HANDLE_COMPOSER_PROPERTY(width, m_Width, float, 100.0f) \ + HANDLE_COMPOSER_PROPERTY(widthunits, m_WidthUnits, TDataStrPtr, L"percent") \ + HANDLE_COMPOSER_PROPERTY(right, m_Right, float, 0) \ + HANDLE_COMPOSER_PROPERTY(rightunits, m_RightUnits, TDataStrPtr, L"percent") \ + HANDLE_COMPOSER_PROPERTY(vertfields, m_VerticalFieldValues, TDataStrPtr, L"Top/Height") \ + HANDLE_COMPOSER_PROPERTY(top, m_Top, float, 0) \ + HANDLE_COMPOSER_PROPERTY(topunits, m_TopUnits, TDataStrPtr, L"percent") \ + HANDLE_COMPOSER_PROPERTY(height, m_Height, float, 100.0f) \ + HANDLE_COMPOSER_PROPERTY(heightunits, m_HeightUnits, TDataStrPtr, L"percent") \ + HANDLE_COMPOSER_PROPERTY(bottom, m_Bottom, float, 0) \ + HANDLE_COMPOSER_PROPERTY(bottomunits, m_BottomUnits, TDataStrPtr, L"percent") \ + HANDLE_COMPOSER_PROPERTY(aostrength, m_AoStrength, float, 0) \ + HANDLE_COMPOSER_PROPERTY(aodistance, m_AoDistance, float, 0) \ + HANDLE_COMPOSER_PROPERTY(aosoftness, m_AoSoftness, float, 0) \ + HANDLE_COMPOSER_PROPERTY(aobias, m_AoBias, float, 0) \ + HANDLE_COMPOSER_PROPERTY(aosamplerate, m_AoSamplerate, qt3ds::QT3DSI32, 1) \ + HANDLE_COMPOSER_PROPERTY(aodither, m_AoDither, bool, false) \ + HANDLE_COMPOSER_PROPERTY(shadowstrength, m_ShadowStrength, float, 0) \ + HANDLE_COMPOSER_PROPERTY(shadowdist, m_ShadowDist, float, 0) \ + HANDLE_COMPOSER_PROPERTY(shadowsoftness, m_ShadowSoftness, float, 0) \ + HANDLE_COMPOSER_PROPERTY(shadowbias, m_ShadowBias, float, 0) \ + HANDLE_COMPOSER_PROPERTY(lightprobe, m_LightProbe, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(probebright, m_ProbeBright, float, 100.0f) \ + HANDLE_COMPOSER_PROPERTY(fastibl, m_FastIbl, bool, true) \ + HANDLE_COMPOSER_PROPERTY(probehorizon, m_ProbeHorizon, float, -1) \ + HANDLE_COMPOSER_PROPERTY(probefov, m_ProbeFov, float, 180.0f) \ + HANDLE_COMPOSER_PROPERTY(lightprobe2, m_LightProbe2, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(probe2fade, m_Probe2Fade, float, 1) \ + HANDLE_COMPOSER_PROPERTY(probe2window, m_Probe2Window, float, 1) \ + HANDLE_COMPOSER_PROPERTY(probe2pos, m_Probe2Pos, float, 0.5f) \ + HANDLE_COMPOSER_PROPERTY(variants, m_variants, TDataStrPtr, L"") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_GROUP_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(variants, m_variants, TDataStrPtr, L"") \ + +#define ITERATE_COMPOSER_LIGHT_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(lighttype, m_LightType, TDataStrPtr, L"Directional") \ + HANDLE_COMPOSER_PROPERTY(scope, m_Scope, SObjectRefType, L"") \ + HANDLE_COMPOSER_PROPERTY(lightdiffuse, m_LightColor, SFloat4, SFloat4(1, 1, 1, 1)) \ + HANDLE_COMPOSER_PROPERTY(lightspecular, m_SpecularColor, SFloat4, SFloat4(1, 1, 1, 1)) \ + HANDLE_COMPOSER_PROPERTY(lightambient, m_AmbientColor, SFloat4, SFloat4(0, 0, 0, 1)) \ + HANDLE_COMPOSER_PROPERTY(brightness, m_Brightness, float, 100.0f) \ + HANDLE_COMPOSER_PROPERTY(linearfade, m_LinearFade, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(expfade, m_ExpFade, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(areawidth, m_AreaWidth, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(areaheight, m_AreaHeight, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(castshadow, m_CastShadow, bool, false) \ + HANDLE_COMPOSER_PROPERTY(shdwbias, m_ShadowBias, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(shdwfactor, m_ShadowFactor, float, 5.0f) \ + HANDLE_COMPOSER_PROPERTY(shdwmapres, m_ShadowMapRes, qt3ds::QT3DSI32, 9) \ + HANDLE_COMPOSER_PROPERTY(shdwmapfar, m_ShadowMapFar, float, 5000.0f) \ + HANDLE_COMPOSER_PROPERTY(shdwmapfov, m_ShadowMapFov, float, 90.0f) \ + HANDLE_COMPOSER_PROPERTY(shdwfilter, m_ShadowFilter, float, 35.0f) \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_CAMERA_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(orthographic, m_Orthographic, bool, false) \ + HANDLE_COMPOSER_PROPERTY(fov, m_Fov, float, 60.f) \ + HANDLE_COMPOSER_PROPERTY(fovhorizontal, m_FovHorizontal, bool, false) \ + HANDLE_COMPOSER_PROPERTY(clipnear, m_ClipNear, float, 10.f) \ + HANDLE_COMPOSER_PROPERTY(clipfar, m_ClipFar, float, 100000.f) \ + HANDLE_COMPOSER_PROPERTY(scalemode, m_ScaleMode, TDataStrPtr, L"Fit") \ + HANDLE_COMPOSER_PROPERTY(scaleanchor, m_ScaleAnchor, TDataStrPtr, L"Center") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_EDIT_CAMERA_PROPERTIES HANDLE_COMPOSER_PROPERTY(is3d, m_Is3d, bool, false) + +#define ITERATE_COMPOSER_TEXT_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(textstring, m_TextString, TDataStrPtr, L"Text") \ + HANDLE_COMPOSER_PROPERTY(textcolor, m_TextColor, SFloat4, SFloat4(1, 1, 1, 1)) \ + HANDLE_COMPOSER_PROPERTY(font, m_Font, TDataStrPtr, L"arial") \ + HANDLE_COMPOSER_PROPERTY(size, m_Size, float, 24.f) \ + HANDLE_COMPOSER_PROPERTY(horzalign, m_HorzAlign, TDataStrPtr, L"Center") \ + HANDLE_COMPOSER_PROPERTY(vertalign, m_VertAlign, TDataStrPtr, L"Middle") \ + HANDLE_COMPOSER_PROPERTY(leading, m_Leading, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(tracking, m_Tracking, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(dropshadow, m_DropShadow, bool, false) \ + HANDLE_COMPOSER_PROPERTY(dropshadowstrength, m_DropShadowStrength, float, 80.f) \ + HANDLE_COMPOSER_PROPERTY(dropshadowoffsetx, m_DropShadowOffsetX, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(dropshadowoffsety, m_DropShadowOffsetY, float, 0.f) \ + HANDLE_COMPOSER_PROPERTY(wordwrap, m_WordWrap, TDataStrPtr, L"WrapWord") \ + HANDLE_COMPOSER_PROPERTY(boundingbox, m_BoundingBox, SFloat2, SFloat2(0, 0)) \ + HANDLE_COMPOSER_PROPERTY(elide, m_Elide, TDataStrPtr, L"ElideNone") \ + HANDLE_COMPOSER_PROPERTY(enableacceleratedfont, m_EnableAcceleratedFont, bool, false) \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(variants, m_variants, TDataStrPtr, L"") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_SLIDE_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(componentid, m_ComponentId, SLong4, 0) \ + HANDLE_COMPOSER_PROPERTY(playmode, m_PlayMode, TDataStrPtr, L"Looping") \ + HANDLE_COMPOSER_PROPERTY(playthroughto, m_PlaythroughTo, SStringOrInt, L"Next") \ + HANDLE_COMPOSER_PROPERTY(initialplaystate, m_InitialPlayState, TDataStrPtr, L"Play") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_ACTION_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(actioneyeball, m_ActionEyeball, bool, true) + +#define ITERATE_COMPOSER_ALIAS_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(referencednode, m_ReferencedNode, SObjectRefType, L"") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_PATH_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(pathtype, m_PathType, TDataStrPtr, L"Geometry") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(width, m_Width, float, 5.0f) \ + HANDLE_COMPOSER_PROPERTY(linearerror, m_LinearError, float, 10) \ + HANDLE_COMPOSER_PROPERTY(edgetessamount, m_EdgeTessAmount, float, 8) \ + HANDLE_COMPOSER_PROPERTY(innertessamount, m_InnerTessAmount, float, 8) \ + HANDLE_COMPOSER_PROPERTY(begincap, m_BeginCap, TDataStrPtr, L"None") \ + HANDLE_COMPOSER_PROPERTY(begincapoffset, m_BeginCapOffset, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(begincapopacity, m_BeginCapOpacity, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(begincapwidth, m_BeginCapWidth, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(endcap, m_EndCap, TDataStrPtr, L"None") \ + HANDLE_COMPOSER_PROPERTY(endcapoffset, m_EndCapOffset, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(endcapopacity, m_EndCapOpacity, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(endcapwidth, m_EndCapWidth, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(paintstyle, m_PaintStyle, TDataStrPtr, L"Stroked") \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"") + +#define ITERATE_COMPOSER_PATH_ANCHOR_POINT_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY_DUPLICATE(position, m_Position, SFloat2, SFloat2(0.0f, 0.0f)) \ + HANDLE_COMPOSER_PROPERTY(incomingangle, m_IncomingAngle, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(incomingdistance, m_IncomingDistance, float, 0.0f) \ + HANDLE_COMPOSER_PROPERTY(outgoingdistance, m_OutgoingDistance, float, 0.0f) + +#define ITERATE_COMPOSER_PATH_SUBPATH_PROPERTIES \ + HANDLE_COMPOSER_PROPERTY(closed, m_Closed, bool, true) + +struct ComposerObjectTypes +{ + enum Enum { + Unknown = 0, +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) name, + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE + ControllableObject + }; + static const wchar_t *Convert(ComposerObjectTypes::Enum inType); + static ComposerObjectTypes::Enum Convert(const wchar_t *inType); + static ComposerObjectTypes::Enum Convert(const char8_t *inType); +}; + +struct ComposerPropertyNames +{ + enum Enum { + Unknown = 0, +#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) name, +#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, type, defaultValue) +#define HANDLE_COMPOSER_PROPERTY(name, memberName, type, defaultValue) name, +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) propmacro + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE +#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT +#undef HANDLE_COMPOSER_PROPERTY +#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE + }; + + static const wchar_t *Convert(ComposerPropertyNames::Enum inType); + static ComposerPropertyNames::Enum Convert(const wchar_t *inType); + static const char8_t *ConvertNarrow(ComposerPropertyNames::Enum inType); + static ComposerPropertyNames::Enum Convert(const char8_t *inType); +}; + +template <typename TDataType> +struct TypeToDataTypeMap +{ + bool force_compile_error; +}; +template <DataModelDataType::Value TEnum> +struct DataTypeToTypeMap +{ + bool force_compile_error; +}; + +#define QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(enumName, type) \ + template <> \ + struct TypeToDataTypeMap<type> \ + { \ + static DataModelDataType::Value GetDataType() { return enumName; } \ + }; \ + template <> \ + struct DataTypeToTypeMap<enumName> \ + { \ + typedef type TDataType; \ + }; + +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Float, float) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Float2, SFloat2) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Float3, SFloat3) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Float4, SFloat4) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Long, qt3ds::QT3DSI32) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::String, TDataStrPtr) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Bool, bool) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Long4, SLong4) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::StringRef, SStringRef) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::StringOrInt, SStringOrInt) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::ObjectRef, SObjectRefType) +QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::FloatList, TFloatList) + +#undef QT3DSDM_DEFINE_TYPE_TO_DATA_TYPE + +template <typename TDataType> +inline DataModelDataType::Value TypeToDataType() +{ + return TypeToDataTypeMap<TDataType>::GetDataType(); +} + +template <ComposerPropertyNames::Enum TPropName, typename TDataType> +struct SComposerPropertyDefinition +{ + qt3ds::foundation::Option<TDataType> m_DefaultValue; + Qt3DSDMPropertyHandle m_Property; + SComposerPropertyDefinition(IDataCore &inDataCore, Qt3DSDMInstanceHandle inInstance, + const TDataType &inDefault) + : m_DefaultValue(inDefault) + { + QT3DSDM_LOG_FUNCTION("SComposerPropertyDefinition-1"); + m_Property = inDataCore.AddProperty(inInstance, ComposerPropertyNames::Convert(TPropName), + TypeToDataType<TDataType>()); + if (m_DefaultValue.hasValue()) + inDataCore.SetInstancePropertyValue(inInstance, m_Property, m_DefaultValue.getValue()); + } + SComposerPropertyDefinition(IDataCore &inDataCore, Qt3DSDMInstanceHandle inInstance) + { + QT3DSDM_LOG_FUNCTION("SComposerPropertyDefinition-2"); + m_Property = inDataCore.AddProperty(inInstance, ComposerPropertyNames::Convert(TPropName), + TypeToDataType<TDataType>()); + } + operator Qt3DSDMPropertyHandle() const { return m_Property; } +}; + +// Define all the objects with their properties + +template <ComposerObjectTypes::Enum> +struct SComposerTypePropertyDefinition +{ + bool force_compile_error; +}; + +#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype) \ + SComposerPropertyDefinition<ComposerPropertyNames::name, dtype> memberName; + +#define HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue) \ + HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype) +#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, dtype, defaultValue) \ + HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue) + +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \ + template <> \ + struct SComposerTypePropertyDefinition<ComposerObjectTypes::name> \ + { \ + bool reserved; \ + propmacro SComposerTypePropertyDefinition(IDataCore &inCore, \ + Qt3DSDMInstanceHandle inInstance); \ + }; + +ITERATE_COMPOSER_OBJECT_TYPES + +#undef HANDLE_COMPOSER_OBJECT_TYPE +#undef HANDLE_COMPOSER_PROPERTY +#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT +#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE + +struct ComposerTypeDefinitionsHelper +{ + // Functions here so we don't have to include UICDMDataCore.h or UICDMMetaData.h + static void SetInstanceAsCanonical(IMetaData &inMetaData, Qt3DSDMInstanceHandle inInstance, + ComposerObjectTypes::Enum inObjectType); + static void SetInstancePropertyValue(IDataCore &inDataCore, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const wchar_t *inPropValue); + static void DeriveInstance(IDataCore &inDataCore, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent); +}; + +template <ComposerObjectTypes::Enum TEnumType> +struct SComposerBaseObjectDefinition : public SComposerTypePropertyDefinition<TEnumType> +{ + Qt3DSDMInstanceHandle m_Instance; + SComposerBaseObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance) + : SComposerTypePropertyDefinition<TEnumType>(inCore, inInstance) + , m_Instance(inInstance) + { + QT3DSDM_LOG_FUNCTION("SComposerBaseObjectDefinition"); + ComposerTypeDefinitionsHelper::SetInstanceAsCanonical(inMetaData, inInstance, TEnumType); + } + + template <ComposerObjectTypes::Enum TBaseType> + void Derive(IDataCore &inCore, const SComposerBaseObjectDefinition<TBaseType> &inParent) + { + QT3DSDM_LOG_FUNCTION("SComposerBaseObjectDefinition::Derive"); + ComposerTypeDefinitionsHelper::DeriveInstance(inCore, m_Instance, inParent.m_Instance); + } + void SetType(IDataCore &inCore, + const SComposerBaseObjectDefinition<ComposerObjectTypes::Typed> &inParent) + { + QT3DSDM_LOG_FUNCTION("SComposerBaseObjectDefinition::SetInstancePropertyValue"); + ComposerTypeDefinitionsHelper::SetInstancePropertyValue( + inCore, m_Instance, inParent.m_TypeProp, ComposerObjectTypes::Convert(TEnumType)); + } + void TypedDerive(IDataCore &inCore, + const SComposerBaseObjectDefinition<ComposerObjectTypes::Typed> &inParent) + { + QT3DSDM_LOG_FUNCTION("SComposerBaseObjectDefinition::TypedDerive"); + Derive(inCore, inParent); + SetType(inCore, inParent); + } +}; + +template <ComposerObjectTypes::Enum TEnumType> +struct SComposerObjectDefinition : public SComposerBaseObjectDefinition<TEnumType> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance) + : SComposerBaseObjectDefinition<TEnumType>(inCore, inMetaData, inInstance) + { + } +}; + +// Base class of slides +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Slide> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Slide> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Named> &inNamed) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Slide>(inCore, inMetaData, inInstance) + { + TypedDerive(inCore, inTyped); + Derive(inCore, inNamed); + } +}; + +// Base class of actions +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Action> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Action> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Action>(inCore, inMetaData, inInstance) + { + TypedDerive(inCore, inTyped); + } +}; + +// Base class of assets +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Asset> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Asset> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Guided> &inGuided, + SComposerObjectDefinition<ComposerObjectTypes::Named> &inNamed) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Asset>(inCore, inMetaData, inInstance) + { + TypedDerive(inCore, inTyped); + Derive(inCore, inGuided); + Derive(inCore, inNamed); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Scene> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Scene> +{ + SComposerObjectDefinition( + IDataCore &inCore, IMetaData &inMetaData, Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset, + SComposerObjectDefinition<ComposerObjectTypes::SlideOwner> &inSlideOwner) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Scene>(inCore, inMetaData, inInstance) + { + Derive(inCore, inAsset); + Derive(inCore, inSlideOwner); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Image> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Image> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Image>(inCore, inMetaData, inInstance) + { + Derive(inCore, inAsset); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::MaterialBase> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::MaterialBase> + +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset) + : SComposerBaseObjectDefinition<ComposerObjectTypes::MaterialBase>(inCore, inMetaData, + inInstance) + { + Derive(inCore, inAsset); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Lightmaps> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Lightmaps> + +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::MaterialBase> &inBase) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Lightmaps>(inCore, inMetaData, + inInstance) + { + Derive(inCore, inBase); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Material> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Material> + +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Lightmaps> &inBase) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Material>(inCore, inMetaData, + inInstance) + { + Derive(inCore, inBase); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::CustomMaterial> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::CustomMaterial> + +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Lightmaps> &inBase) + : SComposerBaseObjectDefinition<ComposerObjectTypes::CustomMaterial>(inCore, inMetaData, + inInstance) + { + Derive(inCore, inBase); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::ReferencedMaterial> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::ReferencedMaterial> + +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Lightmaps> &inBase) + : SComposerBaseObjectDefinition<ComposerObjectTypes::ReferencedMaterial>(inCore, inMetaData, + inInstance) + { + Derive(inCore, inBase); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Behavior> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Behavior> + +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Behavior>(inCore, inMetaData, + inInstance) + { + Derive(inCore, inAsset); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Effect> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Effect> + +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Effect>(inCore, inMetaData, inInstance) + { + Derive(inCore, inAsset); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Node> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Node> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Node>(inCore, inMetaData, inInstance) + { + Derive(inCore, inAsset); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Layer> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Layer> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Layer>(inCore, inMetaData, inInstance) + { + Derive(inCore, inNode); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Model> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Model> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Model>(inCore, inMetaData, inInstance) + { + Derive(inCore, inNode); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Group> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Group> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Group>(inCore, inMetaData, inInstance) + { + Derive(inCore, inNode); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Light> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Light> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Light>(inCore, inMetaData, inInstance) + { + Derive(inCore, inNode); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Camera> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Camera> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Camera>(inCore, inMetaData, inInstance) + { + Derive(inCore, inNode); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Text> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Text> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Text>(inCore, inMetaData, inInstance) + { + Derive(inCore, inNode); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Component> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Component> +{ + SComposerObjectDefinition( + IDataCore &inCore, IMetaData &inMetaData, Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode, + SComposerObjectDefinition<ComposerObjectTypes::SlideOwner> &inSlideOwner) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Component>(inCore, inMetaData, + inInstance) + { + Derive(inCore, inNode); + Derive(inCore, inSlideOwner); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::RenderPlugin> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::RenderPlugin> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset) + : SComposerBaseObjectDefinition<ComposerObjectTypes::RenderPlugin>(inCore, inMetaData, + inInstance) + { + Derive(inCore, inAsset); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Alias> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Alias> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Alias>(inCore, inMetaData, inInstance) + { + Derive(inCore, inNode); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::Path> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::Path> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode) + : SComposerBaseObjectDefinition<ComposerObjectTypes::Path>(inCore, inMetaData, inInstance) + { + Derive(inCore, inNode); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::PathAnchorPoint> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::PathAnchorPoint> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset) + : SComposerBaseObjectDefinition<ComposerObjectTypes::PathAnchorPoint>(inCore, inMetaData, + inInstance) + { + Derive(inCore, inAsset); + SetType(inCore, inTyped); + } +}; + +template <> +struct SComposerObjectDefinition<ComposerObjectTypes::SubPath> + : public SComposerBaseObjectDefinition<ComposerObjectTypes::SubPath> +{ + SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData, + Qt3DSDMInstanceHandle inInstance, + SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped, + SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset) + : SComposerBaseObjectDefinition<ComposerObjectTypes::SubPath>(inCore, inMetaData, + inInstance) + { + Derive(inCore, inAsset); + SetType(inCore, inTyped); + } +}; + +// Container object for all of the object definitions +class SComposerObjectDefinitions +{ +public: +#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \ + SComposerObjectDefinition<ComposerObjectTypes::name> m_##name; + ITERATE_COMPOSER_OBJECT_TYPES +#undef HANDLE_COMPOSER_OBJECT_TYPE + + SComposerObjectDefinitions(IDataCore &inDataCore, IMetaData &inMetaData); + SComposerObjectDefinitions() = default; + ~SComposerObjectDefinitions() = default; + + // RTTI API + bool IsA(Qt3DSDMInstanceHandle inInstance, ComposerObjectTypes::Enum inType); + // Could easily return None, meaning we can't identify the object type. + // Checks the type of the first derivation parent, so this won't ever return + // SlideOwner, for instance. + ComposerObjectTypes::Enum GetType(Qt3DSDMInstanceHandle inInstance); + + Qt3DSDMInstanceHandle GetInstanceForType(ComposerObjectTypes::Enum inType); +private: + IDataCore &m_DataCore; + SComposerObjectDefinitions(const SComposerObjectDefinitions&) = delete; + SComposerObjectDefinitions& operator=(const SComposerObjectDefinitions&) = delete; +}; +} diff --git a/src/dm/systems/Qt3DSDMDataCore.h b/src/dm/systems/Qt3DSDMDataCore.h new file mode 100644 index 0000000..793cddb --- /dev/null +++ b/src/dm/systems/Qt3DSDMDataCore.h @@ -0,0 +1,320 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_DATACORE_H +#define QT3DSDM_DATACORE_H +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMPropertyDefinition.h" +#include "HandleSystemBase.h" +#include "Qt3DSDMMetaData.h" +#include "Qt3DSDMValue.h" + +namespace qt3dsdm { + +typedef std::pair<Qt3DSDMPropertyHandle, SValue> TPropertyHandleValuePair; +typedef std::vector<TPropertyHandleValuePair> TPropertyHandleValuePairList; + +class IInstancePropertyCore +{ +public: + virtual ~IInstancePropertyCore() {} + + /** + * Find a given instance property by name. May return an invalid handle. + */ + virtual Qt3DSDMPropertyHandle + GetAggregateInstancePropertyByName(Qt3DSDMInstanceHandle inInstance, + const TCharStr &inStr) const = 0; + /** + * Get the entire list of instance properties; + */ + virtual void GetAggregateInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const = 0; + // Get the properties that are stored only on this instance, not on any parents. + virtual void GetSpecificInstancePropertyValues(Qt3DSDMInstanceHandle inHandle, + TPropertyHandleValuePairList &outValues) = 0; + /** + * Return true if this property is on this instance or one of its parents. + */ + virtual bool HasAggregateInstanceProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const = 0; + + /** + * Does this value match the approperty property type. + * error - PropertyNotFound + * error - ValueTypeError + */ + virtual void CheckValue(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) const = 0; + /** + * Get this property from this instance. This includes looking up the default value. If the + *instance doesn't have the property + * and it has no default the return value is false. + * error - InstanceNotFound + * error - PropertyNotFound if this property doesn't exist on this instance or doesn't exist. + */ + virtual bool GetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const = 0; + /** + * Set this property on this instance. + * error - InstanceNotFound + * error - PropertyNotFound if this property doesn't exist on this instance or doesn't exist. + * error - ValueTypeError if this value is of the wrong type + */ + virtual void SetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) = 0; +}; + +typedef std::shared_ptr<IInstancePropertyCore> TInstancePropertyCorePtr; + +class IStringTable; + +/** + * Primary interface to data model system. This allows you to define 'classes', which are + *really just + * collections of properties, and instances of those classes. A zero handle value is regarded + *as empty. + */ +class IDataCore : public IHandleBase, public IInstancePropertyCore +{ +public: + virtual ~IDataCore() {} + + // Bookkeeping + virtual IStringTable &GetStringTable() const = 0; + virtual std::shared_ptr<IStringTable> GetStringTablePtr() const = 0; + + //=============================================================== + // Instances + //=============================================================== + /** + * Create a new instance of a class. Instances can be named, in which case + * they are sometimes treated differently when serialized. If the name is null + * or has no length then it is ignored. If the name is non-null, then a check is + * run as named instances must have unique names. When a named instance is a parent + * of another instance, only its name is serialized out; not its handle thus you can safely + * use names as inter-application instance handles. + * May use a target id to specify what the ideal id is; id must not exist. + * - error DuplicateInstanceName + */ + virtual Qt3DSDMInstanceHandle + CreateInstance(Qt3DSDMInstanceHandle inTargetId = Qt3DSDMInstanceHandle()) = 0; + /** + * Delete an instance. + * error - InstanceNotFound + */ + virtual void DeleteInstance(Qt3DSDMInstanceHandle inHandle) = 0; + /** + * Return all the instances in the system. + */ + virtual void GetInstances(TInstanceHandleList &outInstances) const = 0; + /** + * Return all the instances in the system that is derived from parent. + */ + virtual void GetInstancesDerivedFrom(TInstanceHandleList &outInstances, + Qt3DSDMInstanceHandle inParentHandle) const = 0; + + //=============================================================== + // Instance Derivation + //=============================================================== + /** + * Derive an instance from another instance. This implies a rebuild of + * the aggregate properties of a given instance. + * error - InstanceNotFound if either instance or parent aren't found + */ + virtual void DeriveInstance(Qt3DSDMInstanceHandle inInstance, Qt3DSDMInstanceHandle inParent) = 0; + /** + * Return a count of the parent's of a given instance. + * error - InstanceNotFound + */ + virtual void GetInstanceParents(Qt3DSDMInstanceHandle inHandle, + TInstanceHandleList &outParents) const = 0; + + /** + * Returns true if the instance is derived from the parent somehow. + */ + virtual bool IsInstanceOrDerivedFrom(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) const = 0; + //=============================================================== + + //=============================================================== + // Class Properties + //=============================================================== + /** + * Add a new property to a given instances. You can use this to overshadow properties + * on base instances but you can't add two properties of the same name to a given + * instance. + * error - InstanceNotFound + * error - PropertyExists if the property already exists on this class + * error - ValueTypeError if the default value exists and is if a different type than + *inPropType + */ + virtual Qt3DSDMPropertyHandle AddProperty(Qt3DSDMInstanceHandle inInstance, TCharPtr inName, + DataModelDataType::Value inPropType) = 0; + /** + * Return the property definition that corresponds to a given property value. + */ + virtual const Qt3DSDMPropertyDefinition &GetProperty(Qt3DSDMPropertyHandle inProperty) const = 0; + /** + * Return the properties specific to this instance, not including properties + * gained by derivation + */ + virtual void GetInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const = 0; + /** + * Remove a property from an instance. Instances will no long have this property accessible + *nor will + * child instances. + */ + virtual void RemoveProperty(Qt3DSDMPropertyHandle inProperty) = 0; + /** + * Copy properties (definitions & values) specific to one instance, not including properties + * gained by derivation, to another instance. + */ + virtual void CopyInstanceProperties(Qt3DSDMInstanceHandle inSrcInstance, + Qt3DSDMInstanceHandle inDestInstance) = 0; + /** + * Removed cached intermediate values from the instance. DataModel pull properties from the + *inheritance hierarchy chain + * up to the current instance when someone requests a property in order to make the next + *request quicker. This breaks + * some forms of updating where a parent's default value gets changed and the instance won't + *reflect it (until you + * save/load the file). + */ + //=============================================================== + virtual void RemoveCachedValues(Qt3DSDMInstanceHandle inInstance) = 0; + + //=============================================================== + // Handle validation + //=============================================================== + /** + * Is valid and is instances + */ + virtual bool IsInstance(int inHandle) const = 0; + /** + * is valid and is property + */ + virtual bool IsProperty(int inHandle) const = 0; +}; + +typedef std::shared_ptr<IDataCore> TDataCorePtr; + +class IPropertySystem : public IHandleBase +{ +public: + virtual ~IPropertySystem() {} + + virtual Qt3DSDMInstanceHandle CreateInstance() = 0; + virtual void DeleteInstance(Qt3DSDMInstanceHandle inHandle) = 0; + virtual void DeriveInstance(Qt3DSDMInstanceHandle inInstance, Qt3DSDMInstanceHandle inParent) = 0; + + virtual void GetInstances(TInstanceHandleList &outInstances) const = 0; + + virtual Qt3DSDMPropertyHandle AddProperty(Qt3DSDMInstanceHandle inInstance, TCharPtr inName, + DataModelDataType::Value inPropType) = 0; + + virtual Qt3DSDMPropertyHandle + GetAggregateInstancePropertyByName(Qt3DSDMInstanceHandle inInstance, + const TCharStr &inStr) const = 0; + virtual void GetAggregateInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const = 0; + virtual bool HasAggregateInstanceProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const = 0; + + virtual bool GetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const = 0; + virtual void SetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) = 0; + + virtual bool IsInstanceOrDerivedFrom(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) const = 0; + + virtual DataModelDataType::Value GetDataType(Qt3DSDMPropertyHandle inProperty) const = 0; + virtual TCharStr GetName(Qt3DSDMPropertyHandle inProperty) const = 0; + virtual TCharStr GetFormalName(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const = 0; + virtual AdditionalMetaDataType::Value + GetAdditionalMetaDataType(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const = 0; + virtual TMetaDataData GetAdditionalMetaDataData(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const = 0; + virtual Qt3DSDMInstanceHandle GetPropertyOwner(Qt3DSDMPropertyHandle inProperty) const = 0; + + virtual QVector<Qt3DSDMPropertyHandle> GetControllableProperties( + Qt3DSDMInstanceHandle inInst) const = 0; + +}; +typedef std::shared_ptr<IPropertySystem> TPropertySystemPtr; + +template <typename TCoreType> +inline SValue GetInstancePropertyValue(TCoreType inCore, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) +{ + SValue retval; + if (!inCore->GetInstancePropertyValue(inInstance, inProperty, retval)) + throw PropertyNotFound(L""); + return retval; +} + +template <typename TDataType, typename TCoreType> +inline TDataType GetSpecificInstancePropertyValue(TCoreType inDataCore, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) +{ + return qt3dsdm::get<TDataType>(GetInstancePropertyValue(inDataCore, inInstance, inProperty)); +} + +template <typename TDataType, typename TCoreType> +inline TDataType GetNamedInstancePropertyValue(TCoreType inDataCore, + Qt3DSDMInstanceHandle inInstance, + const TCharStr &inName) +{ + Qt3DSDMPropertyHandle theProperty = + inDataCore->GetAggregateInstancePropertyByName(inInstance, inName); + return GetSpecificInstancePropertyValue<TDataType, TCoreType>(inDataCore, inInstance, + theProperty); +} + +inline Qt3DSDMPropertyHandle AddPropertyWithValue(IPropertySystem &inPropertySystem, + Qt3DSDMInstanceHandle inInstance, TCharPtr inName, + DataModelDataType::Value inDataType, + const SValue &inValue) +{ + Qt3DSDMPropertyHandle theProperty(inPropertySystem.AddProperty(inInstance, inName, inDataType)); + inPropertySystem.SetInstancePropertyValue(inInstance, theProperty, inValue); + return theProperty; +} +} + +#endif diff --git a/src/dm/systems/Qt3DSDMDataTypes.h b/src/dm/systems/Qt3DSDMDataTypes.h new file mode 100644 index 0000000..7a7157f --- /dev/null +++ b/src/dm/systems/Qt3DSDMDataTypes.h @@ -0,0 +1,891 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_DATA_H +#define QT3DSDM_DATA_H + +#include <memory> +#include <functional> + +#include "Qt3DSDMErrors.h" +#include "Qt3DSDMStringTable.h" +#include "Qt3DSDMWindowsCompatibility.h" +#include <stdexcept> +#include <vector> +#include <map> +#include <set> +#include <EABase/eabase.h> //char8_t, etc. +#include <EASTL/string.h> +#include <EASTL/vector.h> +#include "foundation/StrConvertUTF.h" +#include "foundation/Qt3DSDiscriminatedUnion.h" + +#include <QObject> + +namespace qt3dsdm { + +typedef const wchar_t *TCharPtr; +struct Qt3DSDMStr : public eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> +{ + typedef qt3ds::foundation::TWCharEASTLConverter::TCharType TCharType; + typedef eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> TStrType; + Qt3DSDMStr() {} + Qt3DSDMStr(const wchar_t *inStr) + : TStrType(qt3ds::NVUnionCast<const TCharType *>(inStr)) + { + } + Qt3DSDMStr(const TStrType &inOther) + : TStrType(inOther) + { + } + + const wchar_t *wide_str() const { return reinterpret_cast<const wchar_t *>(c_str()); } + bool operator==(const Qt3DSDMStr &inOther) const { return TStrType::compare(inOther) == 0; } + bool operator!=(const Qt3DSDMStr &inOther) const { return TStrType::compare(inOther) != 0; } + bool operator==(const wchar_t *inOther) const + { + return TStrType::compare(reinterpret_cast<const TCharType *>(inOther)) == 0; + } + bool operator!=(const wchar_t *inOther) const + { + return TStrType::compare(reinterpret_cast<const TCharType *>(inOther)) != 0; + } + + TStrType::size_type find_first_of(const wchar_t *p, size_type position = 0) const + { + return TStrType::find_first_of(reinterpret_cast<const TCharType *>(p), position); + } + TStrType::size_type find_first_not_of(const wchar_t *p, size_type position = 0) const + { + return TStrType::find_first_not_of(reinterpret_cast<const TCharType *>(p), position); + } + TStrType::size_type find_last_not_of(const wchar_t *p, + size_type position = TStrType::npos) const + { + return TStrType::find_last_not_of(reinterpret_cast<const TCharType *>(p), position); + } + TStrType::size_type find(const wchar_t *p, size_type position = 0) const + { + return TStrType::find(reinterpret_cast<const TCharType *>(p), position); + } + TStrType::size_type find(wchar_t p, size_type position = 0) const + { + return TStrType::find(static_cast<TCharType>(p), position); + } + TStrType::size_type rfind(const wchar_t *p, size_type position = TStrType::npos) const + { + return TStrType::rfind(reinterpret_cast<const TCharType *>(p), position); + } + TStrType::size_type rfind(wchar_t p, size_type position = TStrType::npos) const + { + return TStrType::rfind(p, position); + } + Qt3DSDMStr replace(size_type position, size_type length, const wchar_t *inNewStr) + { + return TStrType::replace(position, length, reinterpret_cast<const TCharType *>(inNewStr)); + } + + void append(const wchar_t *p) { TStrType::append(reinterpret_cast<const TCharType *>(p)); } + void append(const wchar_t *p, size_type position, size_type n) + { + TStrType::append(reinterpret_cast<const TCharType *>(p), position, n); + } + void append(const Qt3DSDMStr &p) { TStrType::append(p); } + void assign(const wchar_t *p) { TStrType::assign(reinterpret_cast<const TCharType *>(p)); } + void assign(const Qt3DSDMStr &p) { TStrType::assign(p); } +}; +typedef Qt3DSDMStr TCharStr; +typedef std::vector<wchar_t> TCharList; +typedef eastl::vector<TCharStr> TCharStrList; +typedef std::map<TCharStr, int> TCharStrIntMap; +typedef std::map<int, TCharStr> TIntTCharStrMap; +typedef std::vector<int> TIntList; +typedef std::set<int> TIntSet; +typedef eastl::vector<float> TFloatList; + +template <typename TDataType> +class CImmutableVector : private std::vector<TDataType> +{ +public: + typedef std::vector<TDataType> base; + + CImmutableVector(const std::vector<TDataType> &inSrc) + : base(inSrc) + { + } + CImmutableVector(const CImmutableVector &inSrc) + : base(inSrc) + { + } + + CImmutableVector &operator=(const CImmutableVector &inSrc) + { + base::operator=(inSrc); + return *this; + } + + typename std::vector<TDataType>::const_iterator begin() const { return base::begin(); } + typename std::vector<TDataType>::const_iterator end() const { return base::end(); } + + size_t size() const { return base::size(); } + + const TDataType &at(int inIndex) const { return base::at(inIndex); } + const TDataType &operator[](int inIndex) const { return base::at(inIndex); } +}; + +typedef CImmutableVector<TCharStr> TImmutableCharStrList; +typedef std::shared_ptr<TImmutableCharStrList> TImmutableCharStrListPtr; + +class CDataStr +{ + TCharList m_Data; + +public: + CDataStr() {} + CDataStr(TCharList &inData) { m_Data.swap(inData); } + CDataStr(const wchar_t *inData) + { + if (inData && *inData) + m_Data.insert(m_Data.begin(), inData, inData + wcslen(inData)); + m_Data.push_back(0); + } + CDataStr(const wchar_t *inData, size_t inLen) + { + if (inData && *inData) + m_Data.insert(m_Data.begin(), inData, inData + inLen); + if (m_Data.size() > 0 && m_Data.back() != 0) + m_Data.push_back(0); + } + CDataStr(const CDataStr &inOther) + : m_Data(inOther.m_Data) + { + } + virtual ~CDataStr() {} + + CDataStr &operator=(const CDataStr &inOther) + { + m_Data = inOther.m_Data; + return *this; + } + const wchar_t *GetData() const { return m_Data.size() <= 1 ? L"" : &(*m_Data.begin()); } + size_t GetLength() const { return m_Data.size() > 1 ? m_Data.size() - 1 : 0; } + bool operator==(const CDataStr &inOther) const { return m_Data == inOther.m_Data; } + QString toQString() const { return QString::fromWCharArray(GetData()); } +}; + +typedef std::shared_ptr<CDataStr> TDataStrPtr; + +struct SFloat2 +{ + float m_Floats[2]; + SFloat2(float f1 = 0, float f2 = 0) + { + m_Floats[0] = f1; + m_Floats[1] = f2; + } + SFloat2(const SFloat2 &inOther) { operator=(inOther); } + SFloat2 &operator=(const SFloat2 &inOther) + { + m_Floats[0] = inOther.m_Floats[0]; + m_Floats[1] = inOther.m_Floats[1]; + return *this; + } + bool operator==(const SFloat2 &other) const + { + return m_Floats[0] == other.m_Floats[0] && m_Floats[1] == other.m_Floats[1]; + } + float &operator[](size_t inIndex) + { + switch (inIndex) { + default: + throw std::out_of_range(""); + case 0: + case 1: + return m_Floats[inIndex]; + } + } + const float &operator[](size_t inIndex) const + { + switch (inIndex) { + default: + throw std::out_of_range(""); + case 0: + case 1: + return m_Floats[inIndex]; + } + } +}; + +struct SFloat3 +{ + float m_Floats[3]; + + SFloat3(float f1 = 0, float f2 = 0, float f3 = 0) + { + m_Floats[0] = f1; + m_Floats[1] = f2; + m_Floats[2] = f3; + } + SFloat3(const SFloat3 &inOther) { operator=(inOther); } + SFloat3 &operator=(const SFloat3 &inOther) + { + m_Floats[0] = inOther.m_Floats[0]; + m_Floats[1] = inOther.m_Floats[1]; + m_Floats[2] = inOther.m_Floats[2]; + return *this; + } + + bool operator==(const SFloat3 &other) const + { + return m_Floats[0] == other.m_Floats[0] && m_Floats[1] == other.m_Floats[1] + && m_Floats[2] == other.m_Floats[2]; + } + + float &operator[](size_t inIndex) + { + switch (inIndex) { + default: + throw std::out_of_range(""); + case 0: + case 1: + case 2: + return m_Floats[inIndex]; + } + } + const float &operator[](size_t inIndex) const + { + switch (inIndex) { + default: + throw std::out_of_range(""); + case 0: + case 1: + case 2: + return m_Floats[inIndex]; + } + } +}; + +struct SFloat4 +{ + float m_Floats[4]; + + SFloat4(float f1 = 0, float f2 = 0, float f3 = 0, float f4 = 1) + { + m_Floats[0] = f1; + m_Floats[1] = f2; + m_Floats[2] = f3; + m_Floats[3] = f4; + } + SFloat4(const SFloat4 &inOther) { operator=(inOther); } + SFloat4 &operator=(const SFloat4 &inOther) + { + m_Floats[0] = inOther.m_Floats[0]; + m_Floats[1] = inOther.m_Floats[1]; + m_Floats[2] = inOther.m_Floats[2]; + m_Floats[3] = inOther.m_Floats[3]; + return *this; + } + + bool operator==(const SFloat4 &other) const + { + return m_Floats[0] == other.m_Floats[0] && m_Floats[1] == other.m_Floats[1] + && m_Floats[2] == other.m_Floats[2] && m_Floats[3] == other.m_Floats[3]; + } + + float &operator[](size_t inIndex) + { + if (inIndex < 4) + return m_Floats[inIndex]; + + throw std::out_of_range(""); + } + const float &operator[](size_t inIndex) const + { + if (inIndex < 4) + return m_Floats[inIndex]; + + throw std::out_of_range(""); + } +}; + +struct SLong4 +{ + qt3ds::QT3DSU32 m_Longs[4]; + + SLong4(qt3ds::QT3DSU32 l1 = 0, + qt3ds::QT3DSU32 l2 = 0, + qt3ds::QT3DSU32 l3 = 0, + qt3ds::QT3DSU32 l4 = 0) + { + m_Longs[0] = l1; + m_Longs[1] = l2; + m_Longs[2] = l3; + m_Longs[3] = l4; + } + SLong4(const SLong4 &inOther) { operator=(inOther); } + SLong4 &operator=(const SLong4 &inOther) + { + m_Longs[0] = inOther.m_Longs[0]; + m_Longs[1] = inOther.m_Longs[1]; + m_Longs[2] = inOther.m_Longs[2]; + m_Longs[3] = inOther.m_Longs[3]; + return *this; + } + + bool operator==(const SLong4 &other) const + { + return m_Longs[0] == other.m_Longs[0] && m_Longs[1] == other.m_Longs[1] + && m_Longs[2] == other.m_Longs[2] && m_Longs[3] == other.m_Longs[3]; + } + + bool operator<(const SLong4 &other) const + { + if (m_Longs[0] < other.m_Longs[0]) + return true; + else if (m_Longs[0] == other.m_Longs[0]) { + if (m_Longs[1] < other.m_Longs[1]) + return true; + else if (m_Longs[1] == other.m_Longs[1]) { + if (m_Longs[2] < other.m_Longs[2]) + return true; + else if (m_Longs[3] < other.m_Longs[3]) + return true; + } + } + return false; + } + + bool Valid() const + { + bool retval = false; + for (int idx = 0; idx < 4; ++idx) + retval = retval || m_Longs[0] > 0; + return retval; + } +}; + +typedef std::vector<SLong4> TLong4Vec; + +struct SSizet4 +{ + size_t m_Longs[4]; + + SSizet4(size_t l1 = 0, size_t l2 = 0, size_t l3 = 0, size_t l4 = 0) + { + m_Longs[0] = l1; + m_Longs[1] = l2; + m_Longs[2] = l3; + m_Longs[3] = l4; + } + SSizet4(const SSizet4 &inOther) { operator=(inOther); } + SSizet4 &operator=(const SSizet4 &inOther) + { + m_Longs[0] = inOther.m_Longs[0]; + m_Longs[1] = inOther.m_Longs[1]; + m_Longs[2] = inOther.m_Longs[2]; + m_Longs[3] = inOther.m_Longs[3]; + return *this; + } + + bool operator==(const SSizet4 &other) const + { + return m_Longs[0] == other.m_Longs[0] && m_Longs[1] == other.m_Longs[1] + && m_Longs[2] == other.m_Longs[2] && m_Longs[3] == other.m_Longs[3]; + } + + bool operator<(const SSizet4 &other) const + { + if (m_Longs[0] < other.m_Longs[0]) + return true; + else if (m_Longs[0] == other.m_Longs[0]) { + if (m_Longs[1] < other.m_Longs[1]) + return true; + else if (m_Longs[1] == other.m_Longs[1]) { + if (m_Longs[2] < other.m_Longs[2]) + return true; + else if (m_Longs[3] < other.m_Longs[3]) + return true; + } + } + return false; + } + + bool Valid() const + { + bool retval = false; + for (int idx = 0; idx < 4; ++idx) + retval = retval || m_Longs[0] > 0; + return retval; + } +}; + +inline bool IsTrivial(const wchar_t *inStr) +{ + return inStr == NULL || *inStr == 0; +} +inline const wchar_t *NonNull(const wchar_t *inStr) +{ + return inStr ? inStr : L""; +} +inline bool AreEqual(const wchar_t *lhs, const wchar_t *rhs) +{ + return wcscmp(NonNull(lhs), NonNull(rhs)) == 0; +} + +inline bool IsTrivial(const char8_t *inStr) +{ + return inStr == NULL || *inStr == 0; +} +inline const char8_t *NonNull(const char8_t *inStr) +{ + return inStr ? inStr : ""; +} +inline bool AreEqual(const char8_t *lhs, const char8_t *rhs) +{ + return strcmp(NonNull(lhs), NonNull(rhs)) == 0; +} + +inline bool AreEqualCaseless(const char8_t *lhs, const char8_t *rhs) +{ + if (IsTrivial(lhs) && IsTrivial(rhs)) + return true; + if (IsTrivial(lhs) || IsTrivial(rhs)) + return false; + for (; *lhs && *rhs; ++lhs, ++rhs) + if (tolower(*lhs) != tolower(*rhs)) + return false; + if (*lhs || *rhs) + return false; + return true; +} + +struct SStringRef +{ + const wchar_t *m_Id; + + SStringRef(const wchar_t *id = L"") + : m_Id(NonNull(id)) + { + } + + operator const wchar_t *() const { return m_Id; } + bool operator==(const SStringRef &inOther) const { return AreEqual(m_Id, inOther.m_Id); } +}; +} + +// Traits specializations have to be in the same namespace as they were first declared. +namespace qt3ds { +namespace foundation { + + template <> + struct DestructTraits<qt3dsdm::SFloat2> + { + void destruct(qt3dsdm::SFloat2 &) {} + }; + template <> + struct DestructTraits<qt3dsdm::SFloat3> + { + void destruct(qt3dsdm::SFloat3 &) {} + }; + template <> + struct DestructTraits<qt3dsdm::SFloat4> + { + void destruct(qt3dsdm::SFloat4 &) {} + }; + template <> + struct DestructTraits<qt3dsdm::SLong4> + { + void destruct(qt3dsdm::SLong4 &) {} + }; + template <> + struct DestructTraits<qt3dsdm::SStringRef> + { + void destruct(qt3dsdm::SStringRef &) {} + }; + + template <> + struct EqualVisitorTraits<qt3dsdm::TDataStrPtr> + { + bool operator()(const qt3dsdm::TDataStrPtr &lhs, const qt3dsdm::TDataStrPtr &rhs) + { + if (lhs && rhs) + return *lhs == *rhs; + if (lhs || rhs) + return false; + return true; + } + }; +} +} + +namespace qt3dsdm { + +using qt3ds::NVUnionCast; + +struct ObjectReferenceType +{ + enum Enum { + Unknown = 0, + Absolute = 1, + Relative = 2, + }; +}; + +template <typename TDataType> +struct SObjectRefTypeTraits +{ +}; + +template <> +struct SObjectRefTypeTraits<SLong4> +{ + ObjectReferenceType::Enum getType() { return ObjectReferenceType::Absolute; } +}; +template <> +struct SObjectRefTypeTraits<TDataStrPtr> +{ + ObjectReferenceType::Enum getType() { return ObjectReferenceType::Relative; } +}; + +struct SObjectRefUnionTraits +{ + typedef ObjectReferenceType::Enum TIdType; + enum { + TBufferSize = sizeof(SSizet4), + }; + + static ObjectReferenceType::Enum getNoDataId() { return ObjectReferenceType::Unknown; } + + template <typename TDataType> + static TIdType getType() + { + return SObjectRefTypeTraits<TDataType>().getType(); + } + + template <typename TRetType, typename TVisitorType> + static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor) + { + switch (inType) { + case ObjectReferenceType::Absolute: + return inVisitor(*NVUnionCast<SLong4 *>(inData)); + case ObjectReferenceType::Relative: + return inVisitor(*NVUnionCast<TDataStrPtr *>(inData)); + default: + QT3DS_ASSERT(false); + case ObjectReferenceType::Unknown: + return inVisitor(); + } + } + + template <typename TRetType, typename TVisitorType> + static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor) + { + switch (inType) { + case ObjectReferenceType::Absolute: + return inVisitor(*NVUnionCast<const SLong4 *>(inData)); + case ObjectReferenceType::Relative: + return inVisitor(*NVUnionCast<const TDataStrPtr *>(inData)); + default: + QT3DS_ASSERT(false); + case ObjectReferenceType::Unknown: + return inVisitor(); + } + } +}; + +typedef qt3ds::foundation:: + DiscriminatedUnion<qt3ds::foundation:: + DiscriminatedUnionGenericBase<SObjectRefUnionTraits, + SObjectRefUnionTraits::TBufferSize>, + SObjectRefUnionTraits::TBufferSize> + TObjRefUnionType; + +template <typename TDataType> +struct Qt3DSDMGetter +{ +}; + +template <typename TRetType, typename TDataType> +TRetType get(const TDataType &inType) +{ + return Qt3DSDMGetter<TDataType>().template doGet<TRetType>(inType); +} + +template <> +struct Qt3DSDMGetter<TObjRefUnionType> +{ + template <typename TRetType> + TRetType doGet(const TObjRefUnionType &inValue) + { + return inValue.getData<TRetType>(); + } +}; + +// Either an absolute reference (SLong4) or a relative reference (string) +struct SObjectRefType +{ + TObjRefUnionType m_Value; + + SObjectRefType(const TDataStrPtr &inValue) + : m_Value(inValue) + { + } + SObjectRefType(const SLong4 &inValue) + : m_Value(inValue) + { + } + SObjectRefType(const SObjectRefType &inOther) + : m_Value(inOther.m_Value) + { + } + SObjectRefType() {} + SObjectRefType &operator=(const SObjectRefType &inOther) + { + m_Value = inOther.m_Value; + return *this; + } + ObjectReferenceType::Enum GetReferenceType() const { return m_Value.getType(); } + bool operator==(const SObjectRefType &inOther) const { return m_Value == inOther.m_Value; } +}; + +inline bool Equals(const SObjectRefType &lhs, const SObjectRefType &rhs) +{ + return lhs == rhs; +} + +struct SStringOrIntTypes +{ + enum Enum { + Unknown = 0, + Int, + String, + }; +}; + +template <typename TDataType> +struct SStringOrIntTypeTraits +{ +}; + +template <> +struct SStringOrIntTypeTraits<long> +{ + SStringOrIntTypes::Enum getType() { return SStringOrIntTypes::Int; } +}; +template <> +struct SStringOrIntTypeTraits<int> +{ + SStringOrIntTypes::Enum getType() { return SStringOrIntTypes::Int; } +}; +template <> +struct SStringOrIntTypeTraits<TDataStrPtr> +{ + SStringOrIntTypes::Enum getType() { return SStringOrIntTypes::String; } +}; + +struct SStringOrIntUnionTraits +{ + typedef SStringOrIntTypes::Enum TIdType; + enum { + TBufferSize = sizeof(TDataStrPtr), + }; + + static SStringOrIntTypes::Enum getNoDataId() { return SStringOrIntTypes::Unknown; } + + template <typename TDataType> + static TIdType getType() + { + return SStringOrIntTypeTraits<TDataType>().getType(); + } + + template <typename TRetType, typename TVisitorType> + static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor) + { + switch (inType) { + case SStringOrIntTypes::Int: + return inVisitor(*NVUnionCast<long *>(inData)); + case SStringOrIntTypes::String: + return inVisitor(*NVUnionCast<TDataStrPtr *>(inData)); + default: + QT3DS_ASSERT(false); + case SStringOrIntTypes::Unknown: + return inVisitor(); + } + } + + template <typename TRetType, typename TVisitorType> + static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor) + { + switch (inType) { + case SStringOrIntTypes::Int: + return inVisitor(*NVUnionCast<const qt3ds::QT3DSI32 *>(inData)); + case SStringOrIntTypes::String: + return inVisitor(*NVUnionCast<const TDataStrPtr *>(inData)); + default: + QT3DS_ASSERT(false); + case SStringOrIntTypes::Unknown: + return inVisitor(); + } + } +}; + +typedef qt3ds::foundation:: + DiscriminatedUnion<qt3ds::foundation:: + DiscriminatedUnionGenericBase<SStringOrIntUnionTraits, + SStringOrIntUnionTraits::TBufferSize>, + SStringOrIntUnionTraits::TBufferSize> + TStringOrIntUnionType; + +template <> +struct Qt3DSDMGetter<TStringOrIntUnionType> +{ + template <typename TRetType> + TRetType doGet(const TStringOrIntUnionType &inValue) + { + return inValue.getData<TRetType>(); + } +}; + +struct SStringOrInt +{ + TStringOrIntUnionType m_Value; + + SStringOrInt() {} + SStringOrInt(int inValue) + : m_Value(inValue) + { + } + SStringOrInt(TDataStrPtr inValue) + : m_Value(inValue) + { + } + SStringOrInt(const SStringOrInt &inOther) + : m_Value(inOther.m_Value) + { + } + + SStringOrInt &operator=(const SStringOrInt &inOther) + { + m_Value = inOther.m_Value; + return *this; + } + + SStringOrIntTypes::Enum GetType() const { return m_Value.getType(); } + + bool operator==(const SStringOrInt &inOther) const { return m_Value == inOther.m_Value; } +}; + +inline bool Equals(const SStringOrInt &lhs, const SStringOrInt &rhs) +{ + return lhs == rhs; +} + +//comes from broken X.h +#ifdef None +#undef None +#endif + +#ifdef Bool +#undef Bool +#endif + +struct DataModelDataType { + + enum Value { + None, + Float, + Float2, + Float3, + Float4, + Long, + String, + Bool, + Long4, + StringRef, + ObjectRef, + StringOrInt, + FloatList, + RangedNumber // datainput-specific type for editor only + }; + + + Q_ENUM(Value) + Q_GADGET +}; + + +class IStringTable; + +template <typename TDataType> +struct Qt3DSDMValueTyper +{ +}; + +template <typename TDataType> +inline DataModelDataType::Value GetValueType(const TDataType &inValue) +{ + return Qt3DSDMValueTyper<TDataType>().Get(inValue); +} + +template <typename TDataType> +struct SDefaulter +{ +}; + +template <typename TDataType> +inline bool SetDefault(DataModelDataType::Value inDataType, TDataType &outValue) +{ + return SDefaulter<TDataType>().SetDefault(inDataType, outValue); +} + +typedef void (*Qt3DSDMDebugLogFunction)(const char *message); +// UICDMSimpleDataCore.cpp +extern Qt3DSDMDebugLogFunction g_DataModelDebugLogger; + +#define QT3DSDM_DEBUG_LOG(msg) \ + { \ + if (g_DataModelDebugLogger) { \ + g_DataModelDebugLogger(msg); \ + } \ + } +struct Qt3DSDMLogScope +{ + const char *m_EndMessage; + Qt3DSDMLogScope(const char *inStartMessage, const char *inEndMessage) + : m_EndMessage(inEndMessage) + { + QT3DSDM_DEBUG_LOG(inStartMessage); + } + ~Qt3DSDMLogScope() { QT3DSDM_DEBUG_LOG(m_EndMessage); } +}; + +#define QT3DSDM_LOG_FUNCTION(fnname) Qt3DSDMLogScope __fn_scope(fnname " Enter", fnname " Leave"); +} + +#endif diff --git a/src/dm/systems/Qt3DSDMErrors.h b/src/dm/systems/Qt3DSDMErrors.h new file mode 100644 index 0000000..77ea7bf --- /dev/null +++ b/src/dm/systems/Qt3DSDMErrors.h @@ -0,0 +1,308 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_ERRORS_H +#define QT3DSDM_ERRORS_H +#include "Qt3DSDMWindowsCompatibility.h" + +namespace qt3dsdm { +class Qt3DSDMError : public std::exception +{ +public: + Qt3DSDMError(const wchar_t *inMessage) + : std::exception() + { + wcscpy_s(m_Message, inMessage); + } + wchar_t m_Message[1024]; +}; + +class HandleExists : public Qt3DSDMError +{ +public: + HandleExists(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class PropertyNotFound : public Qt3DSDMError +{ +public: + PropertyNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class PropertyExists : public Qt3DSDMError +{ +public: + PropertyExists(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class DuplicateInstanceName : public Qt3DSDMError +{ +public: + DuplicateInstanceName(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class InstanceNotFound : public Qt3DSDMError +{ +public: + InstanceNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class ValueTypeError : public Qt3DSDMError +{ +public: + ValueTypeError(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class SerializationError : public Qt3DSDMError +{ +public: + SerializationError(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class SlideNotFound : public Qt3DSDMError +{ +public: + SlideNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class SlideExists : public Qt3DSDMError +{ +public: + SlideExists(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class SlideDerivationError : public Qt3DSDMError +{ +public: + SlideDerivationError(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class SlideChildNotFoundError : public Qt3DSDMError +{ +public: + SlideChildNotFoundError(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class SlideGraphNotFound : public Qt3DSDMError +{ +public: + SlideGraphNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class SlideGraphExists : public Qt3DSDMError +{ +public: + SlideGraphExists(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class PropertyLinkError : public Qt3DSDMError +{ +public: + PropertyLinkError(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class RearrangeSlideArgumentsMustNotBeZero : public Qt3DSDMError +{ +public: + RearrangeSlideArgumentsMustNotBeZero(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class AnimationNotFound : public Qt3DSDMError +{ +public: + AnimationNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class AnimationExists : public Qt3DSDMError +{ +public: + AnimationExists(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class AnimationKeyframeTypeError : public Qt3DSDMError +{ +public: + AnimationKeyframeTypeError(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class AnimationKeyframeNotFound : public Qt3DSDMError +{ +public: + AnimationKeyframeNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class AnimationEvaluationError : public Qt3DSDMError +{ +public: + AnimationEvaluationError(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class ActionNotFound : public Qt3DSDMError +{ +public: + ActionNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class ActionExists : public Qt3DSDMError +{ +public: + ActionExists(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class HandlerArgumentNotFound : public Qt3DSDMError +{ +public: + HandlerArgumentNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class HandlerArgumentExists : public Qt3DSDMError +{ +public: + HandlerArgumentExists(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class CustomPropertyNotFound : public Qt3DSDMError +{ +public: + CustomPropertyNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class CustomEventNotFound : public Qt3DSDMError +{ +public: + CustomEventNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class CustomHandlerNotFound : public Qt3DSDMError +{ +public: + CustomHandlerNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class CustomHandlerParamNotFound : public Qt3DSDMError +{ +public: + CustomHandlerParamNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; + +class AttributeTypeNotFound : public Qt3DSDMError +{ +public: + AttributeTypeNotFound(const wchar_t *inMessage) + : Qt3DSDMError(inMessage) + { + } +}; +} + +#endif diff --git a/src/dm/systems/Qt3DSDMGuides.cpp b/src/dm/systems/Qt3DSDMGuides.cpp new file mode 100644 index 0000000..e8ea421 --- /dev/null +++ b/src/dm/systems/Qt3DSDMGuides.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "Qt3DSDMGuides.h" +#include <unordered_map> +#include "VectorTransactions.h" + +using namespace qt3dsdm; + +namespace { + +#define CONNECT(x) std::make_shared<qt3dsdm::QtSignalConnection>(QObject::connect(this, x, inCallback)) + +class SGuideSystem : public QObject, public IGuideSystem +{ + Q_OBJECT +public: + typedef std::unordered_map<long, SGuideInfo> TGuideMap; + typedef std::shared_ptr<IMergeableTransaction<SGuideInfo>> TMergeableTransaction; + typedef std::unordered_map<long, TMergeableTransaction> TGuideInfoMergeMap; + + long m_NextHandleValue; + TGuideMap m_Guides; + bool m_GuidesEditable; + + std::shared_ptr<ITransactionConsumer> m_CurrentTransaction; + TGuideInfoMergeMap m_GuideMergeMap; +Q_SIGNALS: + void guideCreated(Qt3DSDMGuideHandle, SGuideInfo); + void guideDestroyed(Qt3DSDMGuideHandle, SGuideInfo); + void guideModified(Qt3DSDMGuideHandle, SGuideInfo); + void guideModifiedImmediate(Qt3DSDMGuideHandle, SGuideInfo); +public: + SGuideSystem() + : m_NextHandleValue(0) + , m_GuidesEditable(true) + { + } + + void SignalGuideCreated(long hdl, const SGuideInfo &inInfo) { Q_EMIT guideCreated(hdl, inInfo); } + + void SignalGuideDestroyed(long hdl, const SGuideInfo &inInfo) { Q_EMIT guideDestroyed(hdl, inInfo); } + + void SignalGuideModified(long hdl, const SGuideInfo &inInfo) { Q_EMIT guideModified(hdl, inInfo); } + + Qt3DSDMGuideHandle CreateGuide() override + { + ++m_NextHandleValue; + std::pair<long, SGuideInfo> entry(std::make_pair(m_NextHandleValue, SGuideInfo())); + m_Guides.insert(entry); + if (m_CurrentTransaction) { + CreateHashMapInsertTransaction(__FILE__, __LINE__, m_CurrentTransaction, entry, + m_Guides); + m_CurrentTransaction->OnDoNotification(std::bind( + &SGuideSystem::SignalGuideCreated, this, m_NextHandleValue, SGuideInfo())); + m_CurrentTransaction->OnUndoNotification(std::bind( + &SGuideSystem::SignalGuideDestroyed, this, m_NextHandleValue, SGuideInfo())); + } + + return m_NextHandleValue; + } + + SGuideInfo *InternalGetGuideInfo(Qt3DSDMGuideHandle inGuideHandle) + { + TGuideMap::iterator theFind = m_Guides.find((long)inGuideHandle.GetHandleValue()); + if (theFind != m_Guides.end()) + return &theFind->second; + return NULL; + } + + const SGuideInfo *InternalGetGuideInfo(Qt3DSDMGuideHandle inGuideHandle) const + { + return const_cast<SGuideSystem &>(*this).InternalGetGuideInfo(inGuideHandle); + } + + void SetGuideInfo(Qt3DSDMGuideHandle inGuideHandle, const SGuideInfo &info) override + { + SGuideInfo *existing = InternalGetGuideInfo(inGuideHandle); + long theHdlValue = (long)inGuideHandle.GetHandleValue(); + TGuideInfoMergeMap::iterator iter = m_GuideMergeMap.find(theHdlValue); + if (iter != m_GuideMergeMap.end()) { + iter->second->Update(info); + *existing = info; + } else { + if (!existing) { + QT3DS_ASSERT(false); + return; + } + SGuideInfo oldValue(*existing); + *existing = info; + if (m_CurrentTransaction) { + TMergeableTransaction newTransaction = + CreateHashMapSwapTransaction(__FILE__, __LINE__, m_CurrentTransaction, + theHdlValue, oldValue, info, m_Guides); + m_GuideMergeMap.insert(std::make_pair(theHdlValue, newTransaction)); + m_CurrentTransaction->OnDoNotification( + std::bind(&SGuideSystem::SignalGuideModified, this, theHdlValue, info)); + m_CurrentTransaction->OnUndoNotification( + std::bind(&SGuideSystem::SignalGuideModified, this, theHdlValue, oldValue)); + } + } + if (AreDataModelSignalsEnabled()) + Q_EMIT guideModifiedImmediate(theHdlValue, info); + } + + SGuideInfo GetGuideInfo(Qt3DSDMGuideHandle inGuideHandle) const override + { + const SGuideInfo *existing = InternalGetGuideInfo(inGuideHandle); + if (existing) + return *existing; + QT3DS_ASSERT(false); + return SGuideInfo(); + } + + void DeleteGuide(Qt3DSDMGuideHandle inGuideHandle) override + { + + SGuideInfo *existing = InternalGetGuideInfo(inGuideHandle); + if (!existing) { + QT3DS_ASSERT(false); + return; + } + long theHdlValue = (long)inGuideHandle.GetHandleValue(); + SGuideInfo oldValue = *existing; + m_Guides.erase(theHdlValue); + + if (m_CurrentTransaction) { + std::pair<long, SGuideInfo> entry(std::make_pair(theHdlValue, oldValue)); + CreateHashMapEraseTransaction(__FILE__, __LINE__, m_CurrentTransaction, entry, + m_Guides); + m_CurrentTransaction->OnDoNotification( + std::bind(&SGuideSystem::SignalGuideDestroyed, this, theHdlValue, oldValue)); + m_CurrentTransaction->OnUndoNotification( + std::bind(&SGuideSystem::SignalGuideCreated, this, theHdlValue, oldValue)); + } + } + + TGuideHandleList GetAllGuides() const override + { + TGuideHandleList retval; + for (TGuideMap::const_iterator iter = m_Guides.begin(), end = m_Guides.end(); iter != end; + ++iter) + retval.push_back(iter->first); + return retval; + } + + bool IsGuideValid(Qt3DSDMGuideHandle inGuideHandle) const override + { + return InternalGetGuideInfo(inGuideHandle) != NULL; + } + bool AreGuidesEditable() const override { return m_GuidesEditable; } + void SetGuidesEditable(bool val) override { m_GuidesEditable = val; } + + // Undo/Redo + void SetConsumer(std::shared_ptr<ITransactionConsumer> inConsumer) override + { + m_CurrentTransaction = inConsumer; + m_GuideMergeMap.clear(); + } + + // These are events coming from undo/redo operations, not events coming directly from the + // modification of the guides + virtual TSignalConnectionPtr + ConnectGuideCreated(const std::function<void(Qt3DSDMGuideHandle, SGuideInfo)> &inCallback) override + { + return CONNECT(&SGuideSystem::guideCreated); + } + + virtual TSignalConnectionPtr + ConnectGuideDestroyed(const std::function<void(Qt3DSDMGuideHandle, SGuideInfo)> &inCallback) override + { + return CONNECT(&SGuideSystem::guideDestroyed); + } + + virtual TSignalConnectionPtr + ConnectGuideModified(const std::function<void(Qt3DSDMGuideHandle, SGuideInfo)> &inCallback) override + { + return CONNECT(&SGuideSystem::guideModified); + } + + // Signal happens immediately instead of on undo/redo, used for live-update of the inspector + // palette + TSignalConnectionPtr ConnectGuideModifiedImmediate( + const std::function<void(Qt3DSDMGuideHandle, SGuideInfo)> &inCallback) override + { + return CONNECT(&SGuideSystem::guideModifiedImmediate); + } +}; +} + +shared_ptr<IGuideSystem> IGuideSystem::CreateGuideSystem() +{ + return std::make_shared<SGuideSystem>(); +} + +#include "Qt3DSDMGuides.moc" diff --git a/src/dm/systems/Qt3DSDMGuides.h b/src/dm/systems/Qt3DSDMGuides.h new file mode 100644 index 0000000..0362abf --- /dev/null +++ b/src/dm/systems/Qt3DSDMGuides.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_GUIDES_H +#define QT3DSDM_GUIDES_H +#include "Qt3DSDMDataTypes.h" +#include "foundation/Qt3DSSimpleTypes.h" +#include "Qt3DSDMSignals.h" +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMTransactions.h" +#include <functional> + +namespace qt3dsdm { +struct GuideDirections +{ + enum Enum { + UnknownDirection = 0, + Vertical, + Horizontal, + }; +}; + +struct SGuideInfo +{ + qt3ds::QT3DSF32 m_Position; + GuideDirections::Enum m_Direction; + qt3ds::QT3DSI32 m_Width; + SGuideInfo(qt3ds::QT3DSF32 pos = 0.0f, GuideDirections::Enum dir = GuideDirections::UnknownDirection, + qt3ds::QT3DSI32 width = 1) + : m_Position(pos) + , m_Direction(dir) + , m_Width(width) + { + } +}; + +class IGuideSystem : public ITransactionProducer +{ +protected: + virtual ~IGuideSystem() {} +public: + friend class std::shared_ptr<IGuideSystem>; + + virtual Qt3DSDMGuideHandle CreateGuide() = 0; + virtual void SetGuideInfo(Qt3DSDMGuideHandle inGuideHandle, const SGuideInfo &info) = 0; + virtual SGuideInfo GetGuideInfo(Qt3DSDMGuideHandle inGuideHandle) const = 0; + virtual void DeleteGuide(Qt3DSDMGuideHandle inGuideHandle) = 0; + virtual TGuideHandleList GetAllGuides() const = 0; + virtual bool IsGuideValid(Qt3DSDMGuideHandle inGuideHandle) const = 0; + // No real effect on datamodel because you can still create guides when they are locked. + // Just used in the UI. + virtual bool AreGuidesEditable() const = 0; + virtual void SetGuidesEditable(bool val) = 0; + + // Undo/Redo + void SetConsumer(std::shared_ptr<ITransactionConsumer> inConsumer) override = 0; + + // These are events coming from undo/redo operations, not events coming directly from the + // modification of the guides + virtual TSignalConnectionPtr + ConnectGuideCreated(const std::function<void(Qt3DSDMGuideHandle, SGuideInfo)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectGuideDestroyed( + const std::function<void(Qt3DSDMGuideHandle, SGuideInfo)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectGuideModified( + const std::function<void(Qt3DSDMGuideHandle, SGuideInfo)> &inCallback) = 0; + + // Signal happens immediately instead of on undo/redo, used for live-update of the inspector + // palette + virtual TSignalConnectionPtr ConnectGuideModifiedImmediate( + const std::function<void(Qt3DSDMGuideHandle, SGuideInfo)> &inCallback) = 0; + + static std::shared_ptr<IGuideSystem> CreateGuideSystem(); +}; +} + +#endif diff --git a/src/dm/systems/Qt3DSDMHandles.h b/src/dm/systems/Qt3DSDMHandles.h new file mode 100644 index 0000000..05867a1 --- /dev/null +++ b/src/dm/systems/Qt3DSDMHandles.h @@ -0,0 +1,459 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_HANDLES_H +#define QT3DSDM_HANDLES_H + +#include <QMetaType> + +namespace qt3dsdm { + +class IDataCore; + +class CDataModelHandle +{ + int m_Handle; + +public: + inline CDataModelHandle(int inHandle = 0); + inline CDataModelHandle(const CDataModelHandle &other); + virtual ~CDataModelHandle(); + + // Operators + inline CDataModelHandle &operator=(const CDataModelHandle &other); + inline bool operator==(const CDataModelHandle &other) const; + inline bool operator<(const CDataModelHandle &other) const; + inline operator int() const { return GetHandleValue(); } + + // Use + inline bool Valid() const { return m_Handle != 0; } + int GetHandleValue() const { return m_Handle; } +}; + +inline CDataModelHandle::CDataModelHandle(int inHandle) + : m_Handle(inHandle) +{ +} +inline CDataModelHandle::CDataModelHandle(const CDataModelHandle &other) + : m_Handle(other.m_Handle) +{ +} +inline CDataModelHandle::~CDataModelHandle() +{ +} + +inline CDataModelHandle &CDataModelHandle::operator=(const CDataModelHandle &other) +{ + if (this != &other) { + m_Handle = other.m_Handle; + } + return *this; +} + +inline bool CDataModelHandle::operator==(const CDataModelHandle &other) const +{ + return m_Handle == other.m_Handle; +} + +inline bool CDataModelHandle::operator<(const CDataModelHandle &other) const +{ + return m_Handle < other.m_Handle; +} + +class Qt3DSDMInstanceHandle : public CDataModelHandle +{ +public: + Qt3DSDMInstanceHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMInstanceHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMInstanceHandle(const Qt3DSDMInstanceHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMInstanceHandle &operator=(const Qt3DSDMInstanceHandle &inOther) + { + return static_cast<Qt3DSDMInstanceHandle &>(CDataModelHandle::operator=(inOther)); + } + + inline bool operator==(const Qt3DSDMInstanceHandle &other) const + { + return CDataModelHandle::operator==(other); + } +}; + +typedef std::vector<Qt3DSDMInstanceHandle> TInstanceHandleList; + +class Qt3DSDMPropertyHandle : public CDataModelHandle +{ +public: + Qt3DSDMPropertyHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMPropertyHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMPropertyHandle(const Qt3DSDMInstanceHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMPropertyHandle &operator=(const Qt3DSDMPropertyHandle &inOther) + { + return static_cast<Qt3DSDMPropertyHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMPropertyHandle> TPropertyHandleList; + +class Qt3DSDMSlideHandle : public CDataModelHandle +{ +public: + Qt3DSDMSlideHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMSlideHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMSlideHandle(const Qt3DSDMSlideHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMSlideHandle &operator=(const Qt3DSDMSlideHandle &inOther) + { + return static_cast<Qt3DSDMSlideHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMSlideHandle> TSlideHandleList; + +class Qt3DSDMSlideGraphHandle : public CDataModelHandle +{ +public: + Qt3DSDMSlideGraphHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMSlideGraphHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMSlideGraphHandle(const Qt3DSDMSlideGraphHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMSlideGraphHandle &operator=(const Qt3DSDMSlideGraphHandle &inOther) + { + return static_cast<Qt3DSDMSlideGraphHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMSlideGraphHandle> TSlideGraphHandleList; + +class Qt3DSDMAnimationHandle : public CDataModelHandle +{ +public: + Qt3DSDMAnimationHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMAnimationHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMAnimationHandle(const Qt3DSDMAnimationHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMAnimationHandle &operator=(const Qt3DSDMAnimationHandle &inOther) + { + return static_cast<Qt3DSDMAnimationHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMAnimationHandle> TAnimationHandleList; + +class Qt3DSDMKeyframeHandle : public CDataModelHandle +{ +public: + Qt3DSDMKeyframeHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMKeyframeHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMKeyframeHandle(const Qt3DSDMKeyframeHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMKeyframeHandle &operator=(const Qt3DSDMKeyframeHandle &inOther) + { + return static_cast<Qt3DSDMKeyframeHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMKeyframeHandle> TKeyframeHandleList; + +class Qt3DSDMActionHandle : public CDataModelHandle +{ +public: + Qt3DSDMActionHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMActionHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMActionHandle(const Qt3DSDMActionHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMActionHandle &operator=(const Qt3DSDMActionHandle &inOther) + { + return static_cast<Qt3DSDMActionHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMActionHandle> TActionHandleList; + +class Qt3DSDMHandlerArgHandle : public CDataModelHandle +{ +public: + Qt3DSDMHandlerArgHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMHandlerArgHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMHandlerArgHandle(const Qt3DSDMHandlerArgHandle &inOther) + : CDataModelHandle(inOther) + { + } + Qt3DSDMHandlerArgHandle &operator=(const Qt3DSDMHandlerArgHandle &inOther) + { + return static_cast<Qt3DSDMHandlerArgHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMHandlerArgHandle> THandlerArgHandleList; + +class Qt3DSDMEventHandle : public CDataModelHandle +{ +public: + Qt3DSDMEventHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMEventHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMEventHandle(const Qt3DSDMEventHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMEventHandle &operator=(const Qt3DSDMEventHandle &inOther) + { + return static_cast<Qt3DSDMEventHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMEventHandle> TEventHandleList; + +class Qt3DSDMHandlerHandle : public CDataModelHandle +{ +public: + Qt3DSDMHandlerHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMHandlerHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMHandlerHandle(const Qt3DSDMHandlerHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMHandlerHandle &operator=(const Qt3DSDMHandlerHandle &inOther) + { + return static_cast<Qt3DSDMHandlerHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMHandlerHandle> THandlerHandleList; + +class Qt3DSDMHandlerParamHandle : public CDataModelHandle +{ +public: + Qt3DSDMHandlerParamHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMHandlerParamHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMHandlerParamHandle(const Qt3DSDMHandlerParamHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMHandlerParamHandle &operator=(const Qt3DSDMHandlerParamHandle &inOther) + { + return static_cast<Qt3DSDMHandlerParamHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMHandlerParamHandle> THandlerParamHandleList; + +class Qt3DSDMMetaDataPropertyHandle : public CDataModelHandle +{ +public: + Qt3DSDMMetaDataPropertyHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMMetaDataPropertyHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMMetaDataPropertyHandle(const Qt3DSDMMetaDataPropertyHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMMetaDataPropertyHandle &operator=(const Qt3DSDMMetaDataPropertyHandle &inOther) + { + return static_cast<Qt3DSDMMetaDataPropertyHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMMetaDataPropertyHandle> TMetaDataPropertyHandleList; + +class Qt3DSDMCategoryHandle : public CDataModelHandle +{ +public: + Qt3DSDMCategoryHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMCategoryHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMCategoryHandle(const Qt3DSDMCategoryHandle &inOther) + : CDataModelHandle(inOther) + { + } + Qt3DSDMCategoryHandle &operator=(const Qt3DSDMCategoryHandle &inOther) + { + return static_cast<Qt3DSDMCategoryHandle &>(CDataModelHandle::operator=(inOther)); + } +}; + +typedef std::vector<Qt3DSDMCategoryHandle> TCategoryHandleList; + +class Qt3DSDMGuideHandle : public CDataModelHandle +{ +public: + Qt3DSDMGuideHandle(int inHandle = 0) + : CDataModelHandle(inHandle) + { + } + + Qt3DSDMGuideHandle(const CDataModelHandle &inOther) + : CDataModelHandle(inOther) + { + } + + Qt3DSDMGuideHandle(const Qt3DSDMCategoryHandle &inOther) + : CDataModelHandle(inOther) + { + } + Qt3DSDMGuideHandle &operator=(const Qt3DSDMGuideHandle &inOther) + { + CDataModelHandle::operator=(inOther); + return *this; + } +}; + +typedef std::vector<Qt3DSDMGuideHandle> TGuideHandleList; +} + +Q_DECLARE_METATYPE(qt3dsdm::Qt3DSDMSlideHandle); + +#endif diff --git a/src/dm/systems/Qt3DSDMMetaData.cpp b/src/dm/systems/Qt3DSDMMetaData.cpp new file mode 100644 index 0000000..66f56ce --- /dev/null +++ b/src/dm/systems/Qt3DSDMMetaData.cpp @@ -0,0 +1,4170 @@ +/**************************************************************************** +** +** Copyright (C) 2008 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#ifdef _WIN32 +#pragma warning(disable : 4103) +#endif +#include "Qt3DSDMMetaData.h" +#include "Qt3DSDMXML.h" +#include "foundation/Qt3DSAssert.h" +#include "StandardExtensions.h" +#include <unordered_map> +#include <memory> +#include <unordered_set> +#include "Qt3DSDMTransactions.h" +#include "VectorTransactions.h" +#include "Qt3DSDMSignals.h" +// Pull in the fancy str-type implementations +#include "Qt3DSDMWStrOpsImpl.h" +#include "Qt3DSDMDataCore.h" +#include "DataCoreProducer.h" +#include "Qt3DSDMWindowsCompatibility.h" +#include "Qt3DSRenderEffectSystem.h" +#include "Qt3DSRenderDynamicObjectSystemCommands.h" +#include "foundation/StringConversionImpl.h" + +#include <QtCore/qdir.h> + +using namespace qt3dsdm; +using std::shared_ptr; +using std::make_shared; +using std::static_pointer_cast; +using std::unordered_map; +using std::unordered_set; +using std::function; +using std::bind; +using std::ref; +using std::get; +using qt3ds::foundation::Empty; + +typedef Qt3DSDMInstanceHandle TInstanceHandle; +typedef Qt3DSDMPropertyHandle TPropertyHandle; +typedef Qt3DSDMEventHandle TEventHandle; +typedef Qt3DSDMHandlerHandle THandlerHandle; +typedef Qt3DSDMHandlerArgHandle THandlerArgHandle; +typedef Qt3DSDMMetaDataPropertyHandle TMetaDataPropertyHandle; +typedef Qt3DSDMCategoryHandle TCategoryHandle; + +namespace qt3dsdm { +#define QT3DS_WCHAR_T_None L"None" +#define QT3DS_WCHAR_T_StringList L"StringList" +#define QT3DS_WCHAR_T_Range L"Range" +#define QT3DS_WCHAR_T_Image L"Image" +#define QT3DS_WCHAR_T_Color L"Color" +#define QT3DS_WCHAR_T_Rotation L"Rotation" +#define QT3DS_WCHAR_T_Font L"Font" +#define QT3DS_WCHAR_T_FontSize L"FontSize" +#define QT3DS_WCHAR_T_MultiLine L"MultiLine" +#define QT3DS_WCHAR_T_ObjectRef L"ObjectRef" +#define QT3DS_WCHAR_T_Mesh L"Mesh" +#define QT3DS_WCHAR_T_Import L"Import" +#define QT3DS_WCHAR_T_Texture L"Texture" +#define QT3DS_WCHAR_T_Image2D L"Image2D" +#define QT3DS_WCHAR_T_Buffer L"Buffer" +#define QT3DS_WCHAR_T_Property L"Property" +#define QT3DS_WCHAR_T_Dependent L"Dependent" +#define QT3DS_WCHAR_T_Slide L"Slide" +#define QT3DS_WCHAR_T_Event L"Event" +#define QT3DS_WCHAR_T_Object L"Object" +#define QT3DS_WCHAR_T_Signal L"Signal" +#define QT3DS_WCHAR_T_Renderable L"Renderable" +#define QT3DS_WCHAR_T_PathBuffer L"PathBuffer" +#define QT3DS_WCHAR_T_ShadowMapResolution L"ShadowMapResolution" +#define QT3DS_WCHAR_T_String L"String" + +#define ITERATE_ADDITIONAL_META_DATA_TYPES \ + HANDLE_ADDITIONAL_META_DATA_TYPE(None) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(StringList) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(Range) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(Image) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(Color) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(Rotation) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(Font) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(FontSize) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(MultiLine) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(ObjectRef) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(Mesh) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(Import) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(Texture) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(Renderable) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(PathBuffer) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(ShadowMapResolution) \ + HANDLE_ADDITIONAL_META_DATA_TYPE(String) +template <> +struct WStrOps<AdditionalMetaDataType::Value> +{ + QT3DSU32 ToStr(AdditionalMetaDataType::Value item, NVDataRef<wchar_t> buffer) + { + switch (item) { +#define HANDLE_ADDITIONAL_META_DATA_TYPE(name) \ + case AdditionalMetaDataType::name: \ + wcscpy_s(buffer.begin(), buffer.size(), QT3DS_WCHAR_T_##name); \ + return 1; + ITERATE_ADDITIONAL_META_DATA_TYPES + #undef HANDLE_ADDITIONAL_META_DATA_TYPE + } + return 0; + } + bool StrTo(const wchar_t *buffer, AdditionalMetaDataType::Value &item) + { +#define HANDLE_ADDITIONAL_META_DATA_TYPE(name) \ + if (AreEqual(buffer, QT3DS_WCHAR_T_##name)) { \ + item = AdditionalMetaDataType::name; \ + return true; \ + } + ITERATE_ADDITIONAL_META_DATA_TYPES + #undef HANDLE_ADDITIONAL_META_DATA_TYPE + return false; + } +}; + +#undef ITERATE_ADDITIONAL_META_DATA_TYPES + +#define ITERATE_HANDLER_ARG_TYPES \ + HANDLE_HANDLER_ARG_TYPE(None) \ + HANDLE_HANDLER_ARG_TYPE(Property) \ + HANDLE_HANDLER_ARG_TYPE(Dependent) \ + HANDLE_HANDLER_ARG_TYPE(Slide) \ + HANDLE_HANDLER_ARG_TYPE(Event) \ + HANDLE_HANDLER_ARG_TYPE(Object) \ + HANDLE_HANDLER_ARG_TYPE(Signal) + +QT3DSU32 WStrOps<HandlerArgumentType::Value>::ToStr(HandlerArgumentType::Value item, NVDataRef<wchar_t> buffer) +{ + switch (item) { +#define HANDLE_HANDLER_ARG_TYPE(name) \ + case HandlerArgumentType::name: \ + wcscpy_s(buffer.begin(), buffer.size(), QT3DS_WCHAR_T_##name); \ + return 1; + ITERATE_HANDLER_ARG_TYPES + #undef HANDLE_HANDLER_ARG_TYPE + } + return 0; +} + +bool WStrOps<HandlerArgumentType::Value>::StrTo(const wchar_t *buffer, HandlerArgumentType::Value &item) +{ +#define HANDLE_HANDLER_ARG_TYPE(name) \ + if (AreEqual(buffer, QT3DS_WCHAR_T_##name)) { \ + item = HandlerArgumentType::name; \ + return true; \ +} + ITERATE_HANDLER_ARG_TYPES + #undef HANDLE_HANDLER_ARG_TYPE + return false; +} + +#define QT3DS_WCHAR_T_FloatRange L"FloatRange" +#define QT3DS_WCHAR_T_LongRange L"LongRange" +#define QT3DS_WCHAR_T_Vector L"Vector" +#define QT3DS_WCHAR_T_MultiLineString L"MultiLineString" +#define QT3DS_WCHAR_T_Boolean L"Boolean" +#define QT3DS_WCHAR_T_Guid L"Guid" +#define QT3DS_WCHAR_T_StringListOrInt L"StringListOrInt" +#define QT3DS_WCHAR_T_Scale L"Scale" + +#define ITERATE_QT3DSDM_COMPLETE_TYPES \ + HANDLE_QT3DSDM_COMPLETE_NONE_TYPE \ + HANDLE_QT3DSDM_COMPLETE_TYPE(StringList, StringList, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(FloatRange, Range, DataModelDataType::Float) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(LongRange, Range, DataModelDataType::Long) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Float, None, DataModelDataType::Float) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Long, None, DataModelDataType::Long) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Float2, None, DataModelDataType::Float2) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Vector, None, DataModelDataType::Float3) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Scale, None, DataModelDataType::Float3) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Rotation, Rotation, DataModelDataType::Float3) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Color, Color, DataModelDataType::Float4) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Boolean, None, DataModelDataType::Bool) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Slide, None, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Font, Font, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(FontSize, FontSize, DataModelDataType::Float) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(String, String, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(MultiLineString, MultiLine, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(ObjectRef, ObjectRef, DataModelDataType::ObjectRef) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Image, Image, DataModelDataType::Long4) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Mesh, Mesh, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Import, Import, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Texture, Texture, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Image2D, Texture, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Buffer, Texture, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Guid, None, DataModelDataType::Long4) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(StringListOrInt, StringList, DataModelDataType::StringOrInt) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(Renderable, Renderable, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(PathBuffer, PathBuffer, DataModelDataType::String) \ + HANDLE_QT3DSDM_COMPLETE_TYPE(ShadowMapResolution, ShadowMapResolution, DataModelDataType::Long) + +DataModelDataType::Value CompleteMetaDataType::ToDataType(CompleteMetaDataType::Enum inCompleteType) +{ + switch (inCompleteType) { +#define HANDLE_QT3DSDM_COMPLETE_NONE_TYPE \ + case Unknown: \ + return DataModelDataType::None; +#define HANDLE_QT3DSDM_COMPLETE_TYPE(name, addtype, dtype) \ + case name: \ + return dtype; + ITERATE_QT3DSDM_COMPLETE_TYPES + #undef HANDLE_QT3DSDM_COMPLETE_NONE_TYPE + #undef HANDLE_QT3DSDM_COMPLETE_TYPE + } + QT3DS_ASSERT(false); + return DataModelDataType::None; +} + +AdditionalMetaDataType::Value +CompleteMetaDataType::ToAdditionalType(CompleteMetaDataType::Enum inCompleteType) +{ + switch (inCompleteType) { +#define HANDLE_QT3DSDM_COMPLETE_NONE_TYPE \ + case Unknown: \ + return AdditionalMetaDataType::None; +#define HANDLE_QT3DSDM_COMPLETE_TYPE(name, addtype, dtype) \ + case name: \ + return AdditionalMetaDataType::addtype; + ITERATE_QT3DSDM_COMPLETE_TYPES + #undef HANDLE_QT3DSDM_COMPLETE_NONE_TYPE + #undef HANDLE_QT3DSDM_COMPLETE_TYPE + } + QT3DS_ASSERT(false); + return AdditionalMetaDataType::None; +} + +CompleteMetaDataType::Enum +CompleteMetaDataType::ToCompleteType(DataModelDataType::Value inDataType, + AdditionalMetaDataType::Value inAdditionalType) +{ +#define HANDLE_QT3DSDM_COMPLETE_NONE_TYPE \ + if (inDataType == DataModelDataType::None) \ + return CompleteMetaDataType::Unknown; +#define HANDLE_QT3DSDM_COMPLETE_TYPE(name, addtype, dtype) \ + if (inDataType == dtype \ + && inAdditionalType == AdditionalMetaDataType::addtype) \ + return CompleteMetaDataType::name; + + ITERATE_QT3DSDM_COMPLETE_TYPES + #undef HANDLE_QT3DSDM_COMPLETE_NONE_TYPE + #undef HANDLE_QT3DSDM_COMPLETE_TYPE + QT3DS_ASSERT(false); + return CompleteMetaDataType::Unknown; +} + +QT3DSU32 WStrOps<CompleteMetaDataType::Enum>::ToStr(CompleteMetaDataType::Enum item, + NVDataRef<wchar_t> buffer) +{ + switch (item) { +#define HANDLE_QT3DSDM_COMPLETE_NONE_TYPE \ + case CompleteMetaDataType::Unknown: \ + wcscpy_s(buffer.begin(), buffer.size(), L"None"); \ + return 1; +#define HANDLE_QT3DSDM_COMPLETE_TYPE(name, addtype, dtype) \ + case CompleteMetaDataType::name: \ + wcscpy_s(buffer.begin(), buffer.size(), QT3DS_WCHAR_T_##name); \ + return 1; + + ITERATE_QT3DSDM_COMPLETE_TYPES + #undef HANDLE_QT3DSDM_COMPLETE_NONE_TYPE + #undef HANDLE_QT3DSDM_COMPLETE_TYPE + } + QT3DS_ASSERT(false); + return 0; +} +bool WStrOps<CompleteMetaDataType::Enum>::StrTo(const wchar_t *buffer, + CompleteMetaDataType::Enum &item) +{ + +#define HANDLE_QT3DSDM_COMPLETE_NONE_TYPE \ + if (AreEqual(buffer, L"None")) { \ + item = CompleteMetaDataType::Unknown; \ + return true; \ +} +#define HANDLE_QT3DSDM_COMPLETE_TYPE(name, addtype, dtype) \ + if (AreEqual(buffer, QT3DS_WCHAR_T_##name)) { \ + item = CompleteMetaDataType::name; \ + return true; \ +} + + ITERATE_QT3DSDM_COMPLETE_TYPES + #undef HANDLE_QT3DSDM_COMPLETE_NONE_TYPE + #undef HANDLE_QT3DSDM_COMPLETE_TYPE + return false; +} +} + +namespace { + +#ifndef QT3DSDM_META_DATA_NO_SIGNALS +#define CONNECT(x) std::make_shared<qt3dsdm::QtSignalConnection>(QObject::connect(this, x, inCallback)) +#else +#define CONNECT(x) std::shared_ptr<qt3dsdm::ISignalConnection>() + +struct SNullFunc +{ + template <typename TArgType> + void operator()(TArgType) + { + } + template <typename TA1, typename TA2> + void operator()(TA1, TA2) + { + } +}; + +#endif + +typedef TCharStr TStrType; +using std::hash; + +struct InstanceHandleVecHash +{ + size_t operator()(const vector<TInstanceHandle> &inInstances) const + { + size_t retval = 0; + for (size_t idx = 0, end = inInstances.size(); idx < end; ++idx) + retval = retval ^ hash<int>()(inInstances[idx]); + return retval; + } +}; + +struct SEventAndHandlerBase +{ + Qt3DSDMInstanceHandle m_Instance; + TStrType m_Name; + TStrType m_FormalName; + TStrType m_Category; + TStrType m_Description; + SEventAndHandlerBase() {} + SEventAndHandlerBase(Qt3DSDMInstanceHandle hdl) + : m_Instance(hdl) + { + } +}; + +struct SEvent : public SEventAndHandlerBase +{ + SEvent() {} + SEvent(Qt3DSDMInstanceHandle hdl) + : SEventAndHandlerBase(hdl) + { + } +}; + +struct SHandler : public SEventAndHandlerBase +{ + SHandler() {} + SHandler(Qt3DSDMInstanceHandle hdl) + : SEventAndHandlerBase(hdl) + { + } + vector<SMetaDataHandlerArgumentInfo> m_Arguments; +}; + +// Note that this hash item only works for strings that are in the string table. +// These have the property that pointer comparison also indicates string equality. +struct SInstanceStrHash +{ + size_t operator()(const pair<TInstanceHandle, TCharPtr> &inPair) const + { + return hash<int>()(inPair.first) ^ hash<const void *>()(inPair.second); + } +}; + +template <typename TDataType> +NVConstDataRef<TDataType> VecToCRef(const eastl::vector<TDataType> &inType) +{ + return NVConstDataRef<TDataType>(inType.data(), (QT3DSU32)inType.size()); +} + +struct SMetaDataDynamicObjectImpl +{ +private: + SMetaDataDynamicObjectImpl &operator=(const SMetaDataDynamicObjectImpl &inOther); + +public: + TCharStr m_Name; + TCharStr m_SourcePath; + eastl::vector<SMetaDataShader> m_Shaders; + eastl::vector<qt3ds::render::dynamic::SPropertyDefinition> m_Properties; + eastl::vector<eastl::vector<qt3ds::foundation::CRegisteredString> *> m_EnumValueNames; + ~SMetaDataDynamicObjectImpl() { ClearEnumValueNames(); } + + void ClearEnumValueNames() + { + for (QT3DSU32 idx = 0, end = m_EnumValueNames.size(); idx < end; ++idx) + delete (m_EnumValueNames[idx]); + m_EnumValueNames.clear(); + } +}; + +struct SMetaDataEffectImpl : public SMetaDataDynamicObjectImpl +{ +private: + SMetaDataEffectImpl &operator=(const SMetaDataEffectImpl &inOther); + +public: + eastl::vector<qt3ds::render::dynamic::SCommand *> m_EffectCommands; + + void ClearEffectCommands() + { + for (QT3DSU32 idx = 0, end = m_EnumValueNames.size(); idx < end; ++idx) + free(m_EffectCommands[idx]); + m_EffectCommands.clear(); + } + SMetaDataEffect ToEffect() const + { + return SMetaDataEffect(m_Name, VecToCRef(m_Shaders), VecToCRef(m_Properties), + VecToCRef(m_EffectCommands)); + } +}; + +struct SMetaDataCustomMaterialImpl : public SMetaDataDynamicObjectImpl +{ +private: + SMetaDataCustomMaterialImpl &operator=(const SMetaDataCustomMaterialImpl &); + +public: + eastl::vector<qt3ds::render::dynamic::SCommand *> + m_CustomerMaterialCommands; ///< our command stream used for rendering + bool m_HasTransparency; ///< this material is transparent + bool m_HasRefraction; ///< this material is refractive (e.g glass) + bool m_AlwaysDirty; + QT3DSU32 m_ShaderKey; ///< What does this shader contain ( e.g. specular, diffuse, ...) + QT3DSU32 m_LayerCount; ///< How much layers does this material have + + void ClearEffectCommands() + { + for (QT3DSU32 idx = 0, end = m_EnumValueNames.size(); idx < end; ++idx) { + free(m_CustomerMaterialCommands[idx]); + } + + m_CustomerMaterialCommands.clear(); + } + + SMetaDataCustomMaterial ToMaterial() const + { + return SMetaDataCustomMaterial(m_Name, VecToCRef(m_Shaders), VecToCRef(m_Properties), + VecToCRef(m_CustomerMaterialCommands), m_HasTransparency, + m_HasRefraction, m_AlwaysDirty, m_ShaderKey, m_LayerCount); + } +}; + +#ifndef QT3DSDM_META_DATA_NO_SIGNALS +class SNewMetaDataImpl : public QObject, public IMetaData +{ + Q_OBJECT +#else +class SNewMetaDataImpl : public IMetaData +{ +#endif +public: + typedef unordered_map<TCharPtr, TInstanceHandle> TStrInstanceMap; + typedef unordered_map<TInstanceHandle, TCharPtr, hash<int>> TInstanceStrMap; + // Caching the derivation chain lookup so we can quickly lookup the entire list of + // derived instances (and have it ordered, somewhat). + typedef unordered_map<vector<TInstanceHandle>, vector<TInstanceHandle>, InstanceHandleVecHash> + TDerivationMap; + + typedef unordered_map<TCategoryHandle, SCategoryInfo, hash<int>> TCategoryMap; + typedef unordered_map<TCharPtr, TCategoryHandle> TNameCategoryMap; + + typedef unordered_map<TMetaDataPropertyHandle, SMetaDataPropertyInfo, hash<int>> + TMetaDataPropertyMap; + typedef unordered_map<TInstanceHandle, vector<TMetaDataPropertyHandle>, hash<int>> + TInstancePropertyMap; + typedef unordered_map<pair<TInstanceHandle, TCharPtr>, TMetaDataPropertyHandle, + SInstanceStrHash> + TInstancePropertyNamePropertyMap; + typedef unordered_map<TMetaDataPropertyHandle, eastl::vector<SPropertyFilterInfo>, hash<int>> + TMetaDataPropertyFilterMap; + typedef unordered_map<TInstanceHandle, vector<TCharPtr>, hash<int>> TInstanceGroupMap; + + typedef unordered_map<TEventHandle, SEvent, hash<int>> TEventMap; + typedef unordered_map<TInstanceHandle, vector<TEventHandle>, hash<int>> TInstanceEventMap; + typedef unordered_map<pair<TInstanceHandle, TCharPtr>, TEventHandle, SInstanceStrHash> + TInstanceEventNameEventMap; + + typedef unordered_map<THandlerHandle, SHandler, hash<int>> THandlerMap; + typedef unordered_map<TInstanceHandle, vector<THandlerHandle>, hash<int>> TInstanceHandlerMap; + typedef unordered_map<pair<TInstanceHandle, TCharPtr>, THandlerHandle, SInstanceStrHash> + TInstanceHandlerNameHandlerMap; + + typedef unordered_map<TInstanceHandle, vector<TCharPtr>, hash<int>> TInstanceStringListMap; + typedef unordered_map<TCharPtr, SMetaDataEffectImpl> TEffectMap; + typedef unordered_map<TCharPtr, SMetaDataCustomMaterialImpl> TCustomMaterialMap; + + std::shared_ptr<IDataCore> m_DataCore; + IStringTable &m_StringTable; + TTransactionConsumerPtr m_Consumer; + + int m_NextId; + + // Helper objects to speed up queries + TStrInstanceMap m_CanonicalTypeToInstances; + TInstanceStrMap m_InstancesToCanonicalType; + TDerivationMap m_DerivationMap; + + TCategoryMap m_Categories; + TNameCategoryMap m_NameToCategories; + + TMetaDataPropertyMap m_Properties; + TInstancePropertyMap m_InstanceToProperties; + TInstancePropertyNamePropertyMap m_InstanceNameToProperties; + TMetaDataPropertyFilterMap m_PropertyFilters; + TInstanceGroupMap m_InstanceGroupMap; + + TEventMap m_Events; + TInstanceEventMap m_InstanceToEvents; + TInstanceEventNameEventMap m_InstanceNameToEvents; + + THandlerMap m_Handlers; + TInstanceHandlerMap m_InstanceToHandlers; + TInstanceHandlerNameHandlerMap m_InstanceNameToHandlers; + + TInstanceStringListMap m_InstanceToReferences; + + vector<TInstanceHandle> m_Parents; + vector<TInstanceHandle> m_NextParents; + vector<TInstanceHandle> m_DerivationChain; + unordered_set<int> m_UniqueSet; + unordered_set<size_t> m_SizeTSet; + + MemoryBuffer<RawAllocator> m_TempBuffer; + MemoryBuffer<RawAllocator> m_ReadBuffer; + + eastl::string m_ConvertStr; + + TCharStr m_ObjectName; + + TEffectMap m_EffectMap; + TCustomMaterialMap m_CustomMaterials; + +#ifndef QT3DSDM_META_DATA_NO_SIGNALS +Q_SIGNALS: + void internalCategoryDestroyed(Qt3DSDMCategoryHandle); + void internalMetaDataPropertyDestroyed(Qt3DSDMMetaDataPropertyHandle); + void internalEventDestroyed(Qt3DSDMEventHandle); + void internalHandlerDestroyed(Qt3DSDMHandlerHandle); + void internalHandlerArgDestroyed(Qt3DSDMHandlerHandle, QT3DSU32); +#else + SNullFunc internalCategoryDestroyed; + SNullFunc internalMetaDataPropertyDestroyed; + SNullFunc internalEventDestroyed; + SNullFunc internalHandlerDestroyed; + SNullFunc internalHandlerArgDestroyed; +#endif +public: + TSignalConnectionPtr m_PropertyDeletedConnection; + bool m_IgnorePropertyDeleted; + TSignalConnectionPtr m_InstanceDeletedConnection; + + SNewMetaDataImpl(std::shared_ptr<IDataCore> inDataCore) + : m_DataCore(inDataCore) + , m_StringTable(inDataCore->GetStringTable()) + , m_NextId(1) + , m_IgnorePropertyDeleted(false) + { +#ifndef QT3DSDM_META_DATA_NO_SIGNALS + CDataCoreProducer *producer = dynamic_cast<CDataCoreProducer *>(inDataCore.get()); + if (producer) { + m_PropertyDeletedConnection = producer->ConnectPropertyRemoved( + bind(&SNewMetaDataImpl::OnPropertyRemoved, this, + std::placeholders::_1, std::placeholders::_2)); + m_InstanceDeletedConnection = producer->ConnectBeforeInstanceDeleted( + bind(&SNewMetaDataImpl::OnInstanceRemoved, this, + std::placeholders::_1)); + } +#endif + } + + //////////////////////////////////////////////////////////////////////////// + // Helper Functions + + const wchar_t *Intern(TStrType inData) { return m_StringTable.RegisterStr(inData.wide_str()); } + const wchar_t *Intern(const char *inData) { return m_StringTable.GetWideStr(inData); } + + inline int GetNextId() + { + int retval = m_NextId; + ++m_NextId; + return retval; + } + + template <typename TMapType, typename THandleType> + static void AddItemToInstanceList(TInstanceHandle inInstance, THandleType inHandle, QT3DSU32 inIdx, + TMapType &ioMap) + { + pair<typename TMapType::iterator, bool> inserter = + ioMap.insert(make_pair(inInstance, vector<THandleType>())); + inserter.first->second.insert(inserter.first->second.begin() + inIdx, inHandle); + } + + template <typename TMapType, typename THandleType> + static QT3DSU32 AddItemToInstanceList(TInstanceHandle inInstance, THandleType inHandle, + TMapType &ioMap) + { + pair<typename TMapType::iterator, bool> inserter = + ioMap.insert(make_pair(inInstance, vector<THandleType>())); + QT3DSU32 offset = (QT3DSU32)inserter.first->second.size(); + inserter.first->second.push_back(inHandle); + return offset; + } + + template <typename TItemType> + struct VectorEqualPred + { + TItemType m_Item; + VectorEqualPred(const TItemType &inItem) + : m_Item(inItem) + { + } + + bool operator()(const TItemType &inOther) const { return m_Item == inOther; } + }; + + template <typename THandleType, typename TMapType> + static QT3DSU32 DoRemoveItemFromInstanceList(TInstanceHandle inInstance, THandleType inHandle, + TMapType &ioMap) + { + typename TMapType::iterator find = ioMap.find(inInstance); + if (find != ioMap.end()) { + typename vector<THandleType>::iterator theVecFind = + std::find(find->second.begin(), find->second.end(), inHandle); + if (theVecFind != find->second.end()) { + QT3DSU32 retval = (QT3DSU32)(theVecFind - find->second.begin()); + find->second.erase(theVecFind); + if (find->second.empty()) + ioMap.erase(find); + return retval; + } + } + QT3DS_ASSERT(false); + return QT3DS_MAX_U32; + } + + template <typename TMapType, typename THandleType> + struct InstanceListTransaction : ITransaction + { + TInstanceHandle m_Instance; + THandleType m_Handle; + TMapType &m_Map; + QT3DSU32 m_Idx; + bool m_InsertOnDo; + + InstanceListTransaction(const char *inFile, int inLine, TInstanceHandle inst, + THandleType handle, TMapType &map, QT3DSU32 inIdx, bool inInsertOnDo) + : ITransaction(inFile, inLine) + , m_Instance(inst) + , m_Handle(handle) + , m_Map(map) + , m_Idx(inIdx) + , m_InsertOnDo(inInsertOnDo) + { + } + + void insert() + { + SNewMetaDataImpl::AddItemToInstanceList(m_Instance, m_Handle, m_Idx, m_Map); + } + void remove() + { + SNewMetaDataImpl::DoRemoveItemFromInstanceList(m_Instance, m_Handle, m_Map); + } + + void Do() override + { + if (m_InsertOnDo) + insert(); + else + remove(); + } + void Undo() override + { + if (m_InsertOnDo) + remove(); + else + insert(); + } + }; + + template <typename THandleType, typename TMapType> + void RemoveItemFromInstanceList(const char *inFile, int inLine, TInstanceHandle inInstance, + THandleType inHandle, TMapType &ioMap) + { + typename TMapType::iterator find = ioMap.find(inInstance); + if (find != ioMap.end()) { + QT3DSU32 idx = DoRemoveItemFromInstanceList(inInstance, inHandle, ioMap); + if (m_Consumer != NULL) { + m_Consumer->OnTransaction( + std::make_shared<InstanceListTransaction<TMapType, THandleType>>( + inFile, inLine, inInstance, inHandle, std::ref(ioMap), idx, false)); + } + } + } + + template <typename THandleType, typename TValueType, typename TMapType, + typename TInstanceListMapType> + THandleType CreateItem(const char *inFile, int inLine, Qt3DSDMInstanceHandle inInstance, + TMapType &inMap, TInstanceListMapType &inInstanceListMap) + { + int retval = GetNextId(); + pair<THandleType, TValueType> thePair(make_pair(retval, TValueType(inInstance))); + inMap.insert(thePair); + QT3DSU32 idx = AddItemToInstanceList(inInstance, THandleType(retval), inInstanceListMap); + if (m_Consumer) { + CreateHashMapInsertTransaction(inFile, inLine, m_Consumer, thePair, inMap); + m_Consumer->OnTransaction( + std::make_shared<InstanceListTransaction<TInstanceListMapType, THandleType>>( + inFile, inLine, inInstance, retval, std::ref(inInstanceListMap), idx, true)); + } + return retval; + } + + template <typename TKeyType, typename TValueType, typename THashType> + TValueType *FindHashItem(TKeyType inHandle, + unordered_map<TKeyType, TValueType, THashType> &ioHash) + { + typename unordered_map<TKeyType, TValueType, THashType>::iterator find = + ioHash.find(inHandle); + if (find != ioHash.end()) + return &find->second; + return NULL; + } + + template <typename THandleType, typename TMapType> + static void DoReplaceNamedItem(TInstanceHandle inInst, TCharPtr inOldName, TCharPtr inNewName, + THandleType inNewHandle, TMapType &ioMap) + { + ioMap.erase(make_pair(inInst, inOldName)); + bool success = ioMap.insert(make_pair(make_pair(inInst, inNewName), inNewHandle)).second; + (void)success; + QT3DS_ASSERT(success); + } + + template <typename TMapType, typename THandleType> + struct ReplaceNamedItemTransaction : ITransaction + { + TInstanceHandle m_Instance; + TCharPtr m_OldName; + TCharPtr m_NewName; + THandleType m_OldHandle; + THandleType m_NewHandle; + TMapType &m_Map; + ReplaceNamedItemTransaction(const char *inFile, int inLine, TInstanceHandle inst, + TCharPtr oldNm, TCharPtr newNm, THandleType oldHdl, + THandleType newHdl, TMapType &map) + : ITransaction(inFile, inLine) + , m_Instance(inst) + , m_OldName(oldNm) + , m_NewName(newNm) + , m_OldHandle(oldHdl) + , m_NewHandle(newHdl) + , m_Map(map) + { + } + void Do() override + { + SNewMetaDataImpl::DoReplaceNamedItem(m_Instance, m_OldName, m_NewName, m_NewHandle, + m_Map); + } + void Undo() override + { + SNewMetaDataImpl::DoReplaceNamedItem(m_Instance, m_NewName, m_OldName, m_OldHandle, + m_Map); + } + }; + + template <typename THandleType, typename TMapType> + void ReplaceNamedItem(const char *inFile, int inLine, TInstanceHandle inInst, + TCharPtr inOldName, TCharPtr inNewName, THandleType inNewHandle, + TMapType &ioMap) + { + typename TMapType::iterator find = ioMap.find(std::make_pair(inInst, inOldName)); + THandleType oldHandle; + if (find != ioMap.end()) + oldHandle = find->second; + DoReplaceNamedItem(inInst, inOldName, inNewName, inNewHandle, ioMap); + if (m_Consumer) { + if (oldHandle.Valid()) { + m_Consumer->OnTransaction( + std::make_shared<ReplaceNamedItemTransaction<TMapType, THandleType>>( + inFile, inLine, inInst, inOldName, inNewName, oldHandle, inNewHandle, + std::ref(ioMap))); + } else + CreateHashMapInsertTransaction(__FILE__, __LINE__, m_Consumer, + make_pair(make_pair(inInst, inNewName), inNewHandle), + ioMap); + } + } + + template <typename THandleType, typename TMapType> + void DestroyNamedItem(const char *inFile, int inLine, TInstanceHandle inInst, TCharPtr inName, + TMapType &ioMap) + { + typename TMapType::iterator iter = ioMap.find(make_pair(inInst, inName)); + if (iter != ioMap.end()) { + pair<pair<TInstanceHandle, TCharPtr>, THandleType> existing(*iter); + ioMap.erase(iter); + CreateHashMapEraseTransaction(inFile, inLine, m_Consumer, existing, ioMap); + } + } + + template <typename THandleType, typename TInfoType, typename TMapType, typename TNamedMapType> + void SetItemInfo(const char *inFile, int inLine, THandleType inItem, const TInfoType &oldInfo, + const TInfoType &newInfo, TMapType &inMap, TNamedMapType &inNamedMap) + { + TCharPtr newName = Intern(newInfo.m_Name.wide_str()); + TCharPtr oldName = Intern(oldInfo.m_Name.wide_str()); + ReplaceNamedItem(inFile, inLine, newInfo.m_Instance, oldName, newName, inItem, inNamedMap); + CreateHashMapSwapTransaction(inFile, inLine, m_Consumer, inItem, oldInfo, newInfo, inMap); + } + + bool AddDerivationChainItem(TInstanceHandle inInst) + { + if (m_UniqueSet.find(inInst) == m_UniqueSet.end()) { + m_DerivationChain.push_back(inInst); + m_UniqueSet.insert(inInst); + return true; + } + return false; + } + + void GetDerivationChain(TInstanceHandle inInst) + { + m_Parents.clear(); + m_DerivationChain.clear(); + m_UniqueSet.clear(); + m_NextParents.clear(); + m_DataCore->GetInstanceParents(inInst, m_Parents); + + TDerivationMap::iterator mapIter = m_DerivationMap.find(m_Parents); + if (mapIter != m_DerivationMap.end()) + m_DerivationChain = mapIter->second; + else { + while (m_Parents.empty() == false) { + for (size_t idx = 0, end = m_Parents.size(); idx < end; ++idx) { + if (AddDerivationChainItem(m_Parents[idx])) + m_DataCore->GetInstanceParents(m_Parents[idx], m_NextParents); + } + m_Parents = m_NextParents; + m_NextParents.clear(); + } + m_NextParents.clear(); + + m_DataCore->GetInstanceParents(inInst, m_NextParents); + m_DerivationMap.insert(make_pair(m_NextParents, m_DerivationChain)); + } + } + + template <typename THandleType, typename TMapType> + THandleType FindItemByName(TInstanceHandle inInst, TCharPtr inName, TMapType &ioMap) + { + typename TMapType::iterator find(ioMap.find(make_pair(inInst, inName))); + if (find != ioMap.end()) + return find->second; + + GetDerivationChain(inInst); + for (size_t idx = 0, end = m_DerivationChain.size(); idx < end; ++idx) { + find = ioMap.find(make_pair(m_DerivationChain[idx], inName)); + if (find != ioMap.end()) + return find->second; + } + return 0; + } + + template <typename TItemType, typename TVectorType> + void AddListMapItems(const std::vector<TItemType> &inMapEntry, TVectorType &outVector) + { + typedef typename std::vector<TItemType>::const_iterator TIterType; + for (TIterType theIter = inMapEntry.begin(), theEnd = inMapEntry.end(); theIter != theEnd; + ++theIter) + outVector.push_back(*theIter); + } + + template <typename TListMapType, typename TSizeTOpType, typename TVectorType> + void DoGetHandleList(Qt3DSDMInstanceHandle inInstance, TListMapType &inMap, + TVectorType &outHandles, TSizeTOpType inOperator) + { + typename TListMapType::iterator find; + GetDerivationChain(inInstance); + for (size_t idx = 0, end = m_DerivationChain.size(); idx < end; ++idx) { + // Add base classes to the list first + find = inMap.find(m_DerivationChain[end - idx - 1]); + if (find != inMap.end()) + AddListMapItems(find->second, outHandles); + } + find = inMap.find(inInstance); + if (find != inMap.end()) + AddListMapItems(find->second, outHandles); + m_SizeTSet.clear(); + for (size_t ridx = 0; ridx < outHandles.size(); ++ridx) { + size_t idx = outHandles.size() - ridx - 1; + // Run through the list backwards, making sure that items further in the list + // completely overshadow items earlier in the list. + + // Create unique key from the item that we can check against + size_t item = inOperator(outHandles[idx]); + if (m_SizeTSet.insert(item).second == false) { + outHandles.erase(outHandles.begin() + idx); + --ridx; + } + } + } + + template <typename THandleType, typename TMapType> + struct NameSizeTOpType + { + SNewMetaDataImpl &m_Impl; + TMapType &m_Map; + NameSizeTOpType(SNewMetaDataImpl &inImpl, TMapType &inMap) + : m_Impl(inImpl) + , m_Map(inMap) + { + } + + size_t operator()(THandleType inHandle) + { + return reinterpret_cast<size_t>(m_Impl.Intern(m_Map[inHandle].m_Name)); + } + }; + + // Ensure we don't return two items of the same name. + template <typename THandleType, typename TListMapType, typename TMapType> + void GetHandleList(Qt3DSDMInstanceHandle inInstance, TListMapType &inMap, TMapType &inTypeName, + vector<THandleType> &outHandles) + { + DoGetHandleList(inInstance, inMap, outHandles, + NameSizeTOpType<THandleType, TMapType>(*this, inTypeName)); + } + + template <typename THandleType, typename TMapType, typename TNameMapType, + typename TListMapType> + bool DestroyItem(const char *inFile, int inLine, THandleType inItem, + TMapType &inMap, TNameMapType &inNameMap, TListMapType &inListMap) + { + typename TMapType::iterator find(inMap.find(inItem)); + if (find == inMap.end()) + return false; + DestroyNamedItem<THandleType>(inFile, inLine, find->second.m_Instance, + Intern(find->second.m_Name.wide_str()), inNameMap); + RemoveItemFromInstanceList(inFile, inLine, find->second.m_Instance, inItem, inListMap); + CreateHashMapEraseTransaction(inFile, inLine, m_Consumer, + make_pair(find->first, find->second), inMap); + inMap.erase(find); + return true; + } + + template <typename THandleType, typename TListMapType> + void ForEachItem(Qt3DSDMInstanceHandle inInstance, TListMapType &ioMap, + function<void(THandleType)> inOperation) + { + typename TListMapType::iterator find = ioMap.find(inInstance); + if (find != ioMap.end()) { + vector<THandleType> itemData(find->second); + for (size_t idx = 0, end = itemData.size(); idx < end; ++idx) + inOperation(itemData[idx]); + } + } + + SCategoryInfo *FindCategory(Qt3DSDMCategoryHandle inCategory) + { + return FindHashItem(inCategory, m_Categories); + } + + SMetaDataPropertyInfo *FindProperty(Qt3DSDMMetaDataPropertyHandle inPropertyHandle) + { + return FindHashItem(inPropertyHandle, m_Properties); + } + + SEvent *FindEvent(Qt3DSDMEventHandle inEventHandle) + { + return FindHashItem(inEventHandle, m_Events); + } + + SHandler *FindHandler(Qt3DSDMHandlerHandle inHandle) + { + return FindHashItem(inHandle, m_Handlers); + } + + SMetaDataHandlerArgumentInfo *FindHandlerArg(Qt3DSDMHandlerHandle inHandler, QT3DSU32 inIdx) + { + SHandler *theHandler(FindHandler(inHandler)); + if (theHandler && theHandler->m_Arguments.size() > inIdx) + return &theHandler->m_Arguments[inIdx]; + return NULL; + } + + void OnPropertyRemoved(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) + { + if (m_IgnorePropertyDeleted) + return; + + vector<Qt3DSDMMetaDataPropertyHandle> propertiesToDestroy; + for (TMetaDataPropertyMap::iterator iter = m_Properties.begin(), end = m_Properties.end(); + iter != end; ++iter) { + if (iter->second.m_Property == inProperty) + propertiesToDestroy.push_back(iter->first); + } + + for (size_t idx = 0, end = propertiesToDestroy.size(); idx < end; ++idx) + DestroyMetaDataProperty(propertiesToDestroy[idx]); + } + + void OnInstanceRemoved(Qt3DSDMInstanceHandle inInstance) { DestroyMetaData(inInstance); } + template <typename TEntryType, typename TMapType> + void InsertWithTransaction(const char *inFile, int inLine, const TEntryType &inEntry, + TMapType &inMap) + { + inMap.insert(inEntry); + CreateHashMapInsertTransaction(inFile, inLine, m_Consumer, inEntry, inMap); + } + + template <typename TKeyType, typename TMapType> + void EraseWithTransaction(const char *inFile, int inLine, TKeyType inKey, TMapType &inMap) + { + typename TMapType::iterator find(inMap.find(inKey)); + if (find != inMap.end()) { + CreateHashMapEraseTransaction(inFile, inLine, m_Consumer, + std::make_pair(find->first, find->second), inMap); + inMap.erase(find); + } + } + + template <typename TEntryType, typename TMapType> + void InsertOrUpdateWithTransaction(const TEntryType &inEntry, TMapType &inMap) + { + pair<typename TMapType::iterator, bool> inserter = inMap.insert(inEntry); + if (inserter.second) + CreateHashMapInsertTransaction(__FILE__, __LINE__, m_Consumer, inEntry, inMap); + else { + typename TMapType::iterator theIter(inserter.first); + CreateHashMapSwapTransaction(__FILE__, __LINE__, m_Consumer, theIter->first, + theIter->second, inEntry.second, inMap); + theIter->second = inEntry.second; + } + } + + //////////////////////////////////////////////////////////////////////////////////// + // API Implementation + + //////////////////////////////////////////////////////////////////////////////////// + // Sharing some utility objects + IStringTable &GetStringTable() override { return m_DataCore->GetStringTable(); } + TStringTablePtr GetStringTablePtr() override { return m_DataCore->GetStringTablePtr(); } + TDataCorePtr GetDataCore() override { return m_DataCore; } + + //////////////////////////////////////////////////////////////////////////////////// + // Canonical Instances + void SetInstanceAsCanonical(Qt3DSDMInstanceHandle inInstance, TStrType inTypename) override + { + const wchar_t *theTypename(Intern(inTypename)); + if (g_DataModelDebugLogger) + g_DataModelDebugLogger("IMetaData::SetInstanceAsCanonical Enter"); + if (g_DataModelDebugLogger) + g_DataModelDebugLogger(GetStringTable().GetNarrowStr(inTypename.wide_str())); + m_CanonicalTypeToInstances.insert(make_pair(theTypename, inInstance)); + m_InstancesToCanonicalType.insert(make_pair(inInstance, theTypename)); + CreateHashMapInsertTransaction(__FILE__, __LINE__, m_Consumer, + make_pair(theTypename, inInstance), + m_CanonicalTypeToInstances); + CreateHashMapInsertTransaction(__FILE__, __LINE__, m_Consumer, + make_pair(inInstance, theTypename), + m_InstancesToCanonicalType); + if (g_DataModelDebugLogger) + g_DataModelDebugLogger("IMetaData::SetInstanceAsCanonical Leave"); + } + + Qt3DSDMInstanceHandle GetCanonicalInstanceForType(TStrType inTypename) override + { + TStrInstanceMap::iterator find = m_CanonicalTypeToInstances.find(Intern(inTypename)); + if (find != m_CanonicalTypeToInstances.end()) + return find->second; + return 0; + } + + Option<TCharStr> GetTypeForCanonicalInstance(Qt3DSDMInstanceHandle inInstance) override + { + TInstanceStrMap::iterator find = m_InstancesToCanonicalType.find(inInstance); + if (find != m_InstancesToCanonicalType.end()) + return TCharStr(find->second); + return Empty(); + } + + Option<TCharStr> GetTypeForInstance(Qt3DSDMInstanceHandle inInstance) override + { + Option<TCharStr> theType = GetTypeForCanonicalInstance(inInstance); + if (theType.hasValue()) + return theType; + GetDerivationChain(inInstance); + for (size_t idx = 0, end = m_DerivationChain.size(); idx < end; ++idx) { + theType = GetTypeForCanonicalInstance(m_DerivationChain[idx]); + if (theType.hasValue()) + return theType; + } + return Empty(); + } + + QT3DSU32 GetGroupCountForInstance(Qt3DSDMInstanceHandle inInstance) override + { + std::vector<TCharStr> outNames; + QT3DSU32 count = GetGroupNamesForInstance(inInstance, outNames); + return (count == 0) ? 1 : count; + } + + QT3DSU32 GetGroupNamesForInstance(Qt3DSDMInstanceHandle inInstance, + std::vector<TCharStr> &outNames) override + { + TInstanceStrMap::iterator canonicalFind = m_InstancesToCanonicalType.find(inInstance); + if (canonicalFind != m_InstancesToCanonicalType.end()) { + TInstanceGroupMap::iterator find = m_InstanceGroupMap.find(inInstance); + if (find != m_InstanceGroupMap.end()) { + pair<typename TInstanceGroupMap::iterator, bool> inserter = + m_InstanceGroupMap.insert(make_pair(inInstance, vector<TCharPtr>())); + vector<TCharPtr> &itemList = inserter.first->second; + for (size_t i = 0, j = itemList.size(); i < j; ++i) { + bool alreadyInList = false; + // discard duplicates + for (size_t k = 0, l = outNames.size(); k < l; ++k) { + TCharStr curListName = itemList[i]; + if (curListName == outNames[k].wide_str()) { + alreadyInList = true; + break; + } + } + if (!alreadyInList) + outNames.push_back(itemList[i]); + } + } + return (QT3DSU32)outNames.size(); + } + + GetDerivationChain(inInstance); + + for (int idx = (int)m_DerivationChain.size() - 1, end = 0; idx >= end; --idx) { + TInstanceGroupMap::iterator find = m_InstanceGroupMap.find(m_DerivationChain[idx]); + if (find != m_InstanceGroupMap.end()) { + pair<typename TInstanceGroupMap::iterator, bool> inserter = + m_InstanceGroupMap.insert( + make_pair(m_DerivationChain[idx], vector<TCharPtr>())); + vector<TCharPtr> &itemList = inserter.first->second; + for (size_t i = 0, j = itemList.size(); i < j; ++i) { + bool alreadyInList = false; + // discard duplicates + for (size_t k = 0, l = outNames.size(); k < l; ++k) { + TCharStr curListName = itemList[i]; + if (curListName == outNames[k].wide_str()) { + alreadyInList = true; + break; + } + } + if (!alreadyInList) + outNames.push_back(itemList[i]); + } + } + } + + return (QT3DSU32)outNames.size(); + } + + Option<TCharStr> GetGroupFilterNameForInstance(Qt3DSDMInstanceHandle inInstance, + long inIndex) override + { + std::vector<TCharStr> outNames; + QT3DSU32 count = GetGroupNamesForInstance(inInstance, outNames); + if (count > (QT3DSU32)inIndex) + return outNames[inIndex]; + + return Empty(); + } + + //////////////////////////////////////////////////////////////////////////////////// + // Categories + + std::pair<Qt3DSDMCategoryHandle, bool> GetOrCreateCategory(TStrType inName) override + { + TCharPtr theName(Intern(inName)); + TNameCategoryMap::iterator find = m_NameToCategories.find(theName); + if (find != m_NameToCategories.end()) + return make_pair(find->second, false); + + TCategoryHandle retval(GetNextId()); + InsertWithTransaction(__FILE__, __LINE__, make_pair(retval, SCategoryInfo(inName)), + m_Categories); + InsertWithTransaction(__FILE__, __LINE__, make_pair(theName, retval), m_NameToCategories); + return make_pair(retval, true); + } + + void SetCategoryInfo(Qt3DSDMCategoryHandle inCategory, TStrType inIcon, + TStrType inHighlight, TStrType inDescription) override + { + SCategoryInfo *infoPtr(FindCategory(inCategory)); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + SCategoryInfo &newInfo(*infoPtr); + SCategoryInfo oldInfo(newInfo); + + newInfo.m_Icon = inIcon; + newInfo.m_HighlightIcon = inHighlight; + newInfo.m_Description = inDescription; + CreateHashMapSwapTransaction(__FILE__, __LINE__, m_Consumer, inCategory, oldInfo, newInfo, + m_Categories); + } + + void DestroyCategory(Qt3DSDMCategoryHandle inCategory) override + { + SCategoryInfo *infoPtr(FindCategory(inCategory)); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + EraseWithTransaction(__FILE__, __LINE__, Intern(infoPtr->m_Name), m_NameToCategories); + EraseWithTransaction(__FILE__, __LINE__, inCategory, m_Categories); + } + Option<SCategoryInfo> GetCategoryInfo(Qt3DSDMCategoryHandle inCategory) override + { + SCategoryInfo *infoPtr(FindCategory(inCategory)); + if (infoPtr) + return *infoPtr; + return Empty(); + } + Qt3DSDMCategoryHandle FindCategoryByName(TStrType inName) override + { + TCharPtr theName(Intern(inName)); + TNameCategoryMap::iterator find = m_NameToCategories.find(theName); + if (find != m_NameToCategories.end()) + return find->second; + return 0; + } + + void GetCategories(vector<Qt3DSDMCategoryHandle> &outCategories) override + { + for (TCategoryMap::iterator iter = m_Categories.begin(), end = m_Categories.end(); + iter != end; ++iter) + outCategories.push_back(iter->first); + } + + Option<SCategoryInfo> GetEventCategory(TStrType inName) override + { + return GetCategoryInfo(FindCategoryByName(inName)); + } + + Option<SCategoryInfo> GetHandlerCategory(TStrType inName) override + { + return GetCategoryInfo(FindCategoryByName(inName)); + } + + //////////////////////////////////////////////////////////////////////////////////// + // Properties + + Qt3DSDMMetaDataPropertyHandle CreateMetaDataProperty(Qt3DSDMInstanceHandle inInstance) override + { + return CreateItem<Qt3DSDMMetaDataPropertyHandle, SMetaDataPropertyInfo>( + __FILE__, __LINE__, inInstance, m_Properties, m_InstanceToProperties); + } + + void EnsureDataCoreProperty(SMetaDataPropertyInfo &newInfo) + { + m_IgnorePropertyDeleted = true; + // If the existing property under the new name doesn't match + // the new info, then we also have to delete the property + Qt3DSDMPropertyHandle theExistingProperty = + m_DataCore->GetAggregateInstancePropertyByName(newInfo.m_Instance, newInfo.m_Name); + // Ensure the types match. + if (theExistingProperty.Valid()) { + Qt3DSDMPropertyDefinition theDefinition(m_DataCore->GetProperty(theExistingProperty)); + if (theDefinition.m_Name != newInfo.m_Name + || theDefinition.m_Type != newInfo.GetDataType()) { + m_DataCore->RemoveProperty(theExistingProperty); + theExistingProperty = 0; + } + } + + // Finally, if we don't have a property at this point, create a new property + if (theExistingProperty.Valid() == false) + theExistingProperty = m_DataCore->AddProperty( + newInfo.m_Instance, newInfo.m_Name.wide_str(), newInfo.GetDataType()); + newInfo.m_Property = theExistingProperty; + m_IgnorePropertyDeleted = false; + } + + // If the type doesn't match the default, then it has no default. + SValue VerifyDefaultPropertyType(DataModelDataType::Value inDataType, const SValue &inValue) + { + if (inValue.empty() == false) { + DataModelDataType::Value theType = GetValueType(inValue); + if (theType != inDataType) { + return SValue(0.0f); + } + } + return inValue; + } + // If the datatype doesn't match the value, force the value to match the type. + // some types *have* to have values. + TMetaDataData VerifyMetaDataDataType(AdditionalMetaDataType::Value inDataType, + const TMetaDataData &inValue) + { + if (inDataType == AdditionalMetaDataType::StringList + || inDataType == AdditionalMetaDataType::Range) { + if (inValue.empty() == true || inDataType != GetMetaDataValueType(inValue)) { + QT3DS_ASSERT(false); + if (inDataType == AdditionalMetaDataType::StringList) + return TMetaDataStringList(); + if (inDataType == AdditionalMetaDataType::Range) + return SMetaDataRange(0, 1); + } + } + return inValue; + } + + void SetPropertyBaseInfo(SMetaPropertyBase &newInfo, TStrType inName, TStrType inFormalName, + TStrType inDescription, TStrType inUsage, + CompleteMetaDataType::Enum inDataType, const SValue &inDefaultValue, + const TMetaDataData &inMetaData) + { + newInfo.m_Name = inName; + newInfo.m_FormalName = inFormalName; + newInfo.m_Description = inDescription; + newInfo.m_Usage = inUsage; + newInfo.m_CompleteType = inDataType; + newInfo.m_DefaultValue = + VerifyDefaultPropertyType(CompleteMetaDataType::ToDataType(inDataType), + inDefaultValue); + newInfo.m_MetaDataData = + VerifyMetaDataDataType(CompleteMetaDataType::ToAdditionalType(inDataType), + inMetaData); + } + + // For properties, you set the default values separately + // This may delete the underlying data model property rebuild it. + void SetMetaDataPropertyInfo(Qt3DSDMMetaDataPropertyHandle inPropertyHandle, + TStrType inName, TStrType inFormalName, + TStrType inDescription, TStrType inUsage, + CompleteMetaDataType::Enum inDataType, + const SValue &inDefaultValue, + const TMetaDataData &inMetaData, TStrType inGroupName, + bool inIsHidden, bool inIsAnimatable, + bool inIsControllable) override + { + SMetaDataPropertyInfo *infoPtr = FindProperty(inPropertyHandle); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + SMetaDataPropertyInfo &newInfo(*infoPtr); + SMetaDataPropertyInfo oldInfo(newInfo); + + SetPropertyBaseInfo(newInfo, inName, inFormalName, inDescription, inUsage, inDataType, + inDefaultValue, inMetaData); + newInfo.m_IsHidden = inIsHidden; + newInfo.m_Animatable = inIsAnimatable; + newInfo.m_Controllable = inIsControllable; + newInfo.m_GroupName = inGroupName; + EnsureDataCoreProperty(newInfo); + + SetItemInfo(__FILE__, __LINE__, inPropertyHandle, oldInfo, newInfo, m_Properties, + m_InstanceNameToProperties); + + SetPropertyDefault(newInfo, CompleteMetaDataType::ToDataType(inDataType)); + } + + void SetPropertyDefault(SMetaDataPropertyInfo &newInfo, DataModelDataType::Value inDataType) + { + if (newInfo.m_DefaultValue.empty() == false + && GetValueType(newInfo.m_DefaultValue) == inDataType) { + m_DataCore->SetInstancePropertyValue(newInfo.m_Instance, newInfo.m_Property, + newInfo.m_DefaultValue); + } + } + + // Destroy just this meta data property + void DestroyMetaDataProperty(Qt3DSDMMetaDataPropertyHandle inProperty) override + { + SMetaDataPropertyInfo *infoPtr = FindProperty(inProperty); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + if (DestroyItem(__FILE__, __LINE__, inProperty, + m_Properties, m_InstanceNameToProperties, m_InstanceToProperties)) { + Q_EMIT internalMetaDataPropertyDestroyed(inProperty); + } + + RemoveMetaDataPropertyFilters(inProperty); + } + + Qt3DSDMMetaDataPropertyHandle GetMetaDataProperty(Qt3DSDMInstanceHandle inInstance, + TStrType inPropertyName) override + { + return FindItemByName<Qt3DSDMMetaDataPropertyHandle>(inInstance, Intern(inPropertyName), + m_InstanceNameToProperties); + } + Qt3DSDMMetaDataPropertyHandle GetMetaDataProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + Qt3DSDMPropertyDefinition propDef(m_DataCore->GetProperty(inProperty)); + return GetMetaDataProperty(inInstance, propDef.m_Name); + } + // Sets the value in the data core + virtual Option<SMetaDataPropertyInfo> + GetMetaDataPropertyInfo(Qt3DSDMMetaDataPropertyHandle inProperty) override + { + SMetaDataPropertyInfo *infoPtr = FindProperty(inProperty); + if (infoPtr == NULL) { + return Empty(); + } + return *infoPtr; + } + + void GetMetaDataProperties(Qt3DSDMInstanceHandle inInstance, + vector<Qt3DSDMMetaDataPropertyHandle> &outProperties) override + { + return GetHandleList<Qt3DSDMMetaDataPropertyHandle>(inInstance, m_InstanceToProperties, + m_Properties, outProperties); + } + virtual Qt3DSDMMetaDataPropertyHandle + GetSpecificMetaDataProperty(Qt3DSDMInstanceHandle inInstance, TStrType inPropertyName) + { + TInstancePropertyNamePropertyMap::iterator theFind = m_InstanceNameToProperties.find( + make_pair(inInstance, m_StringTable.RegisterStr(inPropertyName.wide_str()))); + if (theFind != m_InstanceNameToProperties.end()) + return theFind->second; + return 0; + } + virtual Qt3DSDMMetaDataPropertyHandle + GetOrCreateSpecificMetaDataProperty(Qt3DSDMInstanceHandle inInstance, + TStrType inPropertyName) override + { + Qt3DSDMMetaDataPropertyHandle theProp( + GetSpecificMetaDataProperty(inInstance, inPropertyName)); + if (theProp.Valid()) + return theProp; + return CreateMetaDataProperty(inInstance); + } + + void GetSpecificMetaDataProperties(Qt3DSDMInstanceHandle inInstance, + vector<Qt3DSDMMetaDataPropertyHandle> &outProperties) override + { + TInstancePropertyMap::iterator find = m_InstanceToProperties.find(inInstance); + if (find != m_InstanceToProperties.end()) + outProperties.insert(outProperties.end(), find->second.begin(), find->second.end()); + } + + TCharStr GetFormalName(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + Qt3DSDMMetaDataPropertyHandle propHandle(GetMetaDataProperty(inInstance, inProperty)); + SMetaDataPropertyInfo *infoPtr = FindProperty(propHandle); + if (infoPtr) + return infoPtr->m_FormalName; + return TCharStr(); + } + AdditionalMetaDataType::Value GetAdditionalMetaDataType( + Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) override + { + Qt3DSDMMetaDataPropertyHandle propHandle(GetMetaDataProperty(inInstance, inProperty)); + SMetaDataPropertyInfo *infoPtr = FindProperty(propHandle); + if (infoPtr) + return infoPtr->GetAdditionalType(); + return AdditionalMetaDataType::None; + } + TMetaDataData GetAdditionalMetaDataData(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + Qt3DSDMMetaDataPropertyHandle propHandle(GetMetaDataProperty(inInstance, inProperty)); + SMetaDataPropertyInfo *infoPtr = FindProperty(propHandle); + if (propHandle.Valid()) + return infoPtr->m_MetaDataData; + return TMetaDataData(); + } + + bool IsCustomInstance(Qt3DSDMInstanceHandle inInstance) + { + return m_InstancesToCanonicalType.find(inInstance) == m_InstancesToCanonicalType.end(); + } + + SValue GetDefaultValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + Qt3DSDMMetaDataPropertyHandle theProperty(GetMetaDataProperty(inInstance, inProperty)); + if (theProperty.Valid() == false) { + QT3DS_ASSERT(false); + return SValue(); + } + return FindProperty(theProperty)->m_DefaultValue; + } + + bool IsCustomProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + Qt3DSDMMetaDataPropertyHandle propHandle(GetMetaDataProperty(inInstance, inProperty)); + SMetaDataPropertyInfo *infoPtr = FindProperty(propHandle); + if (infoPtr) + return IsCustomInstance(infoPtr->m_Instance); + + return false; + } + + bool IsFilterValid(Qt3DSDMMetaDataPropertyHandle inProperty, + const SPropertyFilterInfo &inFilter) + { + SMetaDataPropertyInfo *infoPtr = FindProperty(inProperty); + if (m_DataCore->IsProperty(inFilter.m_FilterProperty) == false) { + QT3DS_ASSERT(false); + return false; + } + + Qt3DSDMPropertyDefinition theProp(m_DataCore->GetProperty(inFilter.m_FilterProperty)); + Qt3DSDMPropertyHandle propCheck = + m_DataCore->GetAggregateInstancePropertyByName(infoPtr->m_Instance, theProp.m_Name); + if (propCheck != inFilter.m_FilterProperty) { + QT3DS_ASSERT(false); + return false; + } + + DataModelDataType::Value theType = GetValueType(inFilter.m_Value); + if (theType != theProp.m_Type) { + QT3DS_ASSERT(false); + return false; + } + + return true; + } + + void SetMetaDataPropertyFilters(Qt3DSDMMetaDataPropertyHandle inProperty, + NVConstDataRef<SPropertyFilterInfo> inFilters) override + { + SMetaDataPropertyInfo *infoPtr = FindProperty(inProperty); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + + eastl::vector<SPropertyFilterInfo> newFilters; + for (QT3DSU32 idx = 0, end = inFilters.size(); idx < end; ++idx) { + const SPropertyFilterInfo &theFilter(inFilters[idx]); + if (IsFilterValid(inProperty, theFilter)) + newFilters.push_back(theFilter); + } + + InsertOrUpdateWithTransaction(std::make_pair(inProperty, newFilters), m_PropertyFilters); + } + + virtual NVConstDataRef<SPropertyFilterInfo> + GetMetaDataPropertyFilters(Qt3DSDMMetaDataPropertyHandle inProperty) override + { + TMetaDataPropertyFilterMap::iterator theIter(m_PropertyFilters.find(inProperty)); + if (theIter != m_PropertyFilters.end()) + return qt3ds::foundation::toDataRef(theIter->second.data(), theIter->second.size()); + return NVConstDataRef<SPropertyFilterInfo>(); + } + + void RemoveMetaDataPropertyFilters(Qt3DSDMMetaDataPropertyHandle inProperty) override + { + TMetaDataPropertyFilterMap::iterator theIter(m_PropertyFilters.find(inProperty)); + if (theIter != m_PropertyFilters.end()) + EraseWithTransaction(__FILE__, __LINE__, inProperty, m_PropertyFilters); + } + + //////////////////////////////////////////////////////////////////////////////////// + // Properties + Qt3DSDMEventHandle CreateMetaDataEvent(TInstanceHandle inInstance) override + { + return CreateItem<Qt3DSDMEventHandle, SEvent>(__FILE__, __LINE__, inInstance, m_Events, + m_InstanceToEvents); + } + + void SetEventInfo(Qt3DSDMEventHandle inEventHandle, TStrType inName, + TStrType inFormalName, TStrType inCategory, TStrType inDescription) override + { + SEvent *infoPtr = FindEvent(inEventHandle); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + SEvent &newInfo(*infoPtr); + SEvent oldInfo(newInfo); + newInfo.m_Name = inName; + newInfo.m_FormalName = inFormalName; + newInfo.m_Category = inCategory; + newInfo.m_Description = inDescription; + SetItemInfo(__FILE__, __LINE__, inEventHandle, oldInfo, newInfo, m_Events, + m_InstanceNameToEvents); + } + + void DestroyEvent(Qt3DSDMEventHandle inEventHandle) override + { + if (DestroyItem(__FILE__, __LINE__, inEventHandle, m_Events, + m_InstanceNameToEvents, m_InstanceToEvents)) { + Q_EMIT internalEventDestroyed(inEventHandle); + } + } + + void GetEvents(Qt3DSDMInstanceHandle inInstance, TEventHandleList &outEvents) override + { + return GetHandleList<Qt3DSDMEventHandle>(inInstance, m_InstanceToEvents, m_Events, + outEvents); + } + + Qt3DSDMEventHandle FindEvent(Qt3DSDMInstanceHandle inInstance, TStrType inName) override + { + return FindItemByName<Qt3DSDMEventHandle>(inInstance, Intern(inName), + m_InstanceNameToEvents); + } + + Option<SEventInfo> GetEventInfo(Qt3DSDMEventHandle inEventHandle) override + { + SEvent *infoPtr = FindEvent(inEventHandle); + if (infoPtr == NULL) { + return Empty(); + } + SEventInfo retval; + retval.m_Name = infoPtr->m_Name; + retval.m_FormalName = infoPtr->m_FormalName; + retval.m_Description = infoPtr->m_Description; + retval.m_Category = infoPtr->m_Category; + return retval; + } + + bool IsCustomEvent(Qt3DSDMEventHandle inEventHandle) override + { + SEvent *infoPtr = FindEvent(inEventHandle); + if (infoPtr != NULL) + return IsCustomInstance(infoPtr->m_Instance); + return false; + } + + void GetSpecificEvents(Qt3DSDMInstanceHandle inInstance, TEventHandleList &outEvents) override + { + TInstanceEventMap::iterator theFind(m_InstanceToEvents.find(inInstance)); + if (theFind != m_InstanceToEvents.end()) + outEvents.insert(outEvents.end(), theFind->second.begin(), theFind->second.end()); + } + + Qt3DSDMEventHandle GetOrCreateSpecificEvent(Qt3DSDMInstanceHandle inInstance, + TStrType inName) override + { + TInstanceEventNameEventMap::iterator theFind( + m_InstanceNameToEvents.find(make_pair(inInstance, Intern(inName)))); + if (theFind != m_InstanceNameToEvents.end()) + return theFind->second; + return CreateMetaDataEvent(inInstance); + } + + //////////////////////////////////////////////////////////////////////////////////// + // Handlers + + Qt3DSDMHandlerHandle CreateHandler(Qt3DSDMInstanceHandle inInstance) override + { + return CreateItem<Qt3DSDMHandlerHandle, SHandler>(__FILE__, __LINE__, inInstance, + m_Handlers, m_InstanceToHandlers); + } + + void SetHandlerInfo(Qt3DSDMHandlerHandle inHandle, TStrType inName, + TStrType inFormalName, TStrType inCategoryName, + TStrType inDescription) override + { + SHandler *infoPtr = FindHandler(inHandle); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + SHandler &newInfo(*infoPtr); + SHandler oldInfo(newInfo); + newInfo.m_Name = inName; + newInfo.m_FormalName = inFormalName; + newInfo.m_Description = inDescription; + newInfo.m_Category = inCategoryName; + SetItemInfo(__FILE__, __LINE__, inHandle, oldInfo, newInfo, m_Handlers, + m_InstanceNameToHandlers); + } + + void DestroyHandler(Qt3DSDMHandlerHandle inHandlerHandle) override + { + SHandler *infoPtr(FindHandler(inHandlerHandle)); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + while (infoPtr->m_Arguments.empty() == false) + DestroyHandlerArgument(inHandlerHandle, (QT3DSU32)infoPtr->m_Arguments.size() - 1); + if (DestroyItem(__FILE__, __LINE__, inHandlerHandle, m_Handlers, + m_InstanceNameToHandlers, m_InstanceToHandlers)) { + Q_EMIT internalHandlerDestroyed(inHandlerHandle); + } + } + + Qt3DSDMHandlerHandle FindHandlerByName(Qt3DSDMInstanceHandle inInstance, + TStrType inName) override + { + return FindItemByName<Qt3DSDMHandlerHandle>(inInstance, Intern(inName), + m_InstanceNameToHandlers); + } + + Option<SHandlerInfo> GetHandlerInfo(Qt3DSDMHandlerHandle inHandlerHandle) override + { + SHandler *infoPtr = FindHandler(inHandlerHandle); + if (infoPtr == NULL) + return Empty(); + + SHandlerInfo retval; + retval.m_Name = infoPtr->m_Name; + retval.m_FormalName = infoPtr->m_FormalName; + retval.m_Category = infoPtr->m_Category; + retval.m_Description = infoPtr->m_Description; + + return retval; + } + + void GetHandlers(Qt3DSDMInstanceHandle inInstance, THandlerHandleList &outHandlers) override + { + return GetHandleList<Qt3DSDMHandlerHandle>(inInstance, m_InstanceToHandlers, m_Handlers, + outHandlers); + } + + bool IsCustomHandler(Qt3DSDMHandlerHandle inHandle) override + { + SHandler *infoPtr = FindHandler(inHandle); + if (infoPtr != NULL) + return IsCustomInstance(infoPtr->m_Instance); + return false; + } + + void GetSpecificHandlers(Qt3DSDMInstanceHandle inInstance, + THandlerHandleList &outHandlers) override + { + TInstanceHandlerMap::iterator theFind = m_InstanceToHandlers.find(inInstance); + if (theFind != m_InstanceToHandlers.end()) + outHandlers.insert(outHandlers.end(), theFind->second.begin(), theFind->second.end()); + } + + Qt3DSDMHandlerHandle GetOrCreateSpecificHandler(Qt3DSDMInstanceHandle inInstance, + TStrType inName) override + { + TInstanceHandlerNameHandlerMap::iterator theFind = + m_InstanceNameToHandlers.find(make_pair(inInstance, Intern(inName))); + if (theFind != m_InstanceNameToHandlers.end()) + return theFind->second; + return CreateHandler(inInstance); + } + + //////////////////////////////////////////////////////////////////////////////////// + // Handler Arguments + + void DoAddHandlerArgument(Qt3DSDMHandlerHandle inHandler, + const SMetaDataHandlerArgumentInfo &inArgHandle, QT3DSU32 inIdx) + { + SHandler *infoPtr = FindHandler(inHandler); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + infoPtr->m_Arguments.insert(infoPtr->m_Arguments.begin() + inIdx, inArgHandle); + } + + struct ArgNameEqual + { + const TCharStr &m_Name; + ArgNameEqual(const TCharStr &nm) + : m_Name(nm) + { + } + bool operator()(const SMetaDataHandlerArgumentInfo &info) const + { + return m_Name == info.m_Name; + } + }; + + void DoRemoveHandlerArgument(Qt3DSDMHandlerHandle inHandler, + const SMetaDataHandlerArgumentInfo &inArgHandle) + { + SHandler *infoPtr = FindHandler(inHandler); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + erase_if(infoPtr->m_Arguments, ArgNameEqual(inArgHandle.m_Name)); + } + + struct HandlerArgumentAddRemoveTransaction : public ITransaction + { + SNewMetaDataImpl &m_Impl; + Qt3DSDMHandlerHandle m_Handler; + SMetaDataHandlerArgumentInfo m_Arg; + QT3DSU32 m_Idx; + bool m_AddOnDo; + + HandlerArgumentAddRemoveTransaction(const char *inFile, int inLine, SNewMetaDataImpl &impl, + Qt3DSDMHandlerHandle hdl, + const SMetaDataHandlerArgumentInfo &arg, QT3DSU32 inIdx, + bool inAddOnDo) + : ITransaction(inFile, inLine) + , m_Impl(impl) + , m_Handler(hdl) + , m_Arg(arg) + , m_Idx(inIdx) + , m_AddOnDo(inAddOnDo) + { + } + void insert() { m_Impl.DoAddHandlerArgument(m_Handler, m_Arg, m_Idx); } + void remove() { m_Impl.DoRemoveHandlerArgument(m_Handler, m_Arg); } + void Do() override + { + if (m_AddOnDo) + insert(); + else + remove(); + } + void Undo() override + { + if (m_AddOnDo) + remove(); + else + insert(); + } + }; + + QT3DSU32 AddHandlerArgument(Qt3DSDMHandlerHandle inHandler) override + { + SHandler *infoPtr = FindHandler(inHandler); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return 0; + } + + SMetaDataHandlerArgumentInfo theInfo(inHandler); + QT3DSU32 idx = (QT3DSU32)infoPtr->m_Arguments.size(); + DoAddHandlerArgument(inHandler, theInfo, idx); + if (m_Consumer) + m_Consumer->OnTransaction(make_shared<HandlerArgumentAddRemoveTransaction>( + __FILE__, __LINE__, ref(*this), inHandler, theInfo, + idx, true)); + + return idx; + } + + void DoSetHandlerArgument(THandlerHandle inHandler, QT3DSU32 inIdx, + const SMetaDataHandlerArgumentInfo &inInfo) + { + SMetaDataHandlerArgumentInfo *infoPtr(FindHandlerArg(inHandler, inIdx)); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + *infoPtr = inInfo; + } + + struct SetHandlerArgumentInfoTrans : public ITransaction + { + SNewMetaDataImpl &m_Impl; + THandlerHandle m_Handler; + QT3DSU32 m_Idx; + SMetaDataHandlerArgumentInfo m_NewValue; + SMetaDataHandlerArgumentInfo m_OldValue; + SetHandlerArgumentInfoTrans(const char *inFile, int inLine, SNewMetaDataImpl &impl, + THandlerHandle handler, QT3DSU32 inIdx, + const SMetaDataHandlerArgumentInfo &inNewVal, + const SMetaDataHandlerArgumentInfo &inOldVal) + : ITransaction(inFile, inLine) + , m_Impl(impl) + , m_Handler(handler) + , m_Idx(inIdx) + , m_NewValue(inNewVal) + , m_OldValue(inOldVal) + { + } + void Do() override { m_Impl.DoSetHandlerArgument(m_Handler, m_Idx, m_NewValue); } + void Undo() override { m_Impl.DoSetHandlerArgument(m_Handler, m_Idx, m_OldValue); } + }; + + void SetHandlerArgumentInfo(THandlerHandle inHandler, QT3DSU32 inIdx, TStrType inName, + TStrType inFormalName, TStrType inDescription, + CompleteMetaDataType::Enum inDataType, + const SValue &inDefaultValue, + const TMetaDataData &inMetaData, + HandlerArgumentType::Value inArgType) override + { + SMetaDataHandlerArgumentInfo *infoPtr(FindHandlerArg(inHandler, inIdx)); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + SMetaDataHandlerArgumentInfo &newInfo(*infoPtr); + SMetaDataHandlerArgumentInfo oldInfo(newInfo); + SetPropertyBaseInfo(newInfo, inName, inFormalName, inDescription, L"", inDataType, + inDefaultValue, inMetaData); + newInfo.m_ArgType = inArgType; + if (m_Consumer != NULL) + m_Consumer->OnTransaction(make_shared<SetHandlerArgumentInfoTrans>( + __FILE__, __LINE__, ref(*this), inHandler, inIdx, + newInfo, oldInfo)); + } + + void DestroyHandlerArgument(THandlerHandle inHandler, QT3DSU32 inIdx) override + { + SHandler *ownerPtr = FindHandler(inHandler); + SMetaDataHandlerArgumentInfo *infoPtr(FindHandlerArg(inHandler, inIdx)); + if (infoPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + if (ownerPtr == NULL) { + QT3DS_ASSERT(false); + return; + } + + Q_EMIT internalHandlerArgDestroyed(inHandler, inIdx); + + if (m_Consumer) + m_Consumer->OnTransaction(make_shared<HandlerArgumentAddRemoveTransaction>( + __FILE__, __LINE__, ref(*this), infoPtr->m_Handler, + *infoPtr, inIdx, false)); + + DoRemoveHandlerArgument(infoPtr->m_Handler, *infoPtr); + } + + Option<SMetaDataHandlerArgumentInfo> FindHandlerArgumentByName(THandlerHandle inHandler, + TStrType inName) override + { + SHandler *ownerPtr = FindHandler(inHandler); + if (ownerPtr == NULL) { + return Empty(); + } + for (size_t idx = 0, end = ownerPtr->m_Arguments.size(); idx < end; ++idx) { + if (ownerPtr->m_Arguments[idx].m_Name == inName) + return ownerPtr->m_Arguments[idx]; + } + return Empty(); + } + + void GetHandlerArguments(THandlerHandle inHandler, + vector<SMetaDataHandlerArgumentInfo> &outArguments) override + { + SHandler *ownerPtr = FindHandler(inHandler); + if (ownerPtr == NULL) { + return; + } + outArguments.insert(outArguments.end(), ownerPtr->m_Arguments.begin(), + ownerPtr->m_Arguments.end()); + } + + virtual Option<SMetaDataHandlerArgumentInfo> + GetHandlerArgumentInfo(Qt3DSDMHandlerHandle inHandle, QT3DSU32 inIdx) override + { + SMetaDataHandlerArgumentInfo *infoPtr(FindHandlerArg(inHandle, inIdx)); + if (infoPtr == NULL) { + return Empty(); + } + return *infoPtr; + } + + QT3DSU32 GetNumHandlerArguments(Qt3DSDMHandlerHandle inHandler) override + { + SHandler *ownerPtr = FindHandler(inHandler); + if (ownerPtr == NULL) { + return 0; + } + return (QT3DSU32)ownerPtr->m_Arguments.size(); + } + + //////////////////////////////////////////////////////////////////////////////////// + // References + void AddReference(Qt3DSDMInstanceHandle inInstance, TStrType inRefString) override + { + // trim whitespace from the beginning and the end of the string + TCharStr::size_type startPos = inRefString.find_first_not_of(L"\n\r\t "); + TCharStr::size_type endPos = inRefString.find_last_not_of(L"\n\r\t "); + const wchar_t *theStr = NULL; + if (startPos != TCharStr::npos) { + TStrType temp = inRefString.substr(startPos, endPos - startPos + 1); + theStr = Intern(temp); + } else + theStr = Intern(inRefString); + + QT3DSU32 idx = AddItemToInstanceList(inInstance, theStr, m_InstanceToReferences); + if (m_Consumer) { + m_Consumer->OnTransaction( + std::make_shared<InstanceListTransaction<TInstanceStringListMap, + const wchar_t *>>( + __FILE__, __LINE__, inInstance, theStr, + std::ref(m_InstanceToReferences), idx, + true)); + } + } + + void DestroyReferences(Qt3DSDMInstanceHandle inInstance) override + { + TInstanceStringListMap::iterator find = m_InstanceToReferences.find(inInstance); + + if (find == m_InstanceToReferences.end()) + return; + + CreateHashMapEraseTransaction(__FILE__, __LINE__, m_Consumer, + make_pair(find->first, find->second), m_InstanceToReferences); + m_InstanceToReferences.erase(find); + } + + struct InternSizeTOpType + { + SNewMetaDataImpl &m_Impl; + InternSizeTOpType(SNewMetaDataImpl &inImpl) + : m_Impl(inImpl) + { + } + + size_t operator()(const TCharStr &inHandle) + { + return reinterpret_cast<size_t>(m_Impl.Intern(inHandle)); + } + }; + + void GetReferences(Qt3DSDMInstanceHandle inInstance, vector<TCharStr> &outReferences) override + { + DoGetHandleList(inInstance, m_InstanceToReferences, outReferences, + InternSizeTOpType(*this)); + } + + //////////////////////////////////////////////////////////////////////////////////// + // Instance-global functions + // Destroy all meta data that relates to this instance. + // Calling this on a derived instance does nothing, this only works if this specific + // instance was mapped to a type. + // This function must be completely undoable. + void DestroyMetaData(Qt3DSDMInstanceHandle inInstance) override + { + ForEachItem<TMetaDataPropertyHandle>( + inInstance, m_InstanceToProperties, + bind(&SNewMetaDataImpl::DestroyMetaDataProperty, this, + std::placeholders::_1)); + ForEachItem<TEventHandle>(inInstance, m_InstanceToEvents, + bind(&SNewMetaDataImpl::DestroyEvent, this, + std::placeholders::_1)); + ForEachItem<THandlerHandle>(inInstance, m_InstanceToHandlers, + bind(&SNewMetaDataImpl::DestroyHandler, this, + std::placeholders::_1)); + DestroyReferences(inInstance); + + TInstanceStrMap::iterator find = m_InstancesToCanonicalType.find(inInstance); + if (find != m_InstancesToCanonicalType.end()) { + TCharPtr theName(find->second); + m_CanonicalTypeToInstances.erase(theName); + m_InstancesToCanonicalType.erase(inInstance); + CreateHashMapEraseTransaction(__FILE__, __LINE__, m_Consumer, + make_pair(theName, inInstance), + m_CanonicalTypeToInstances); + CreateHashMapEraseTransaction(__FILE__, __LINE__, m_Consumer, + make_pair(inInstance, theName), + m_InstancesToCanonicalType); + } + } + + //////////////////////////////////////////////////////////////////////////////////// + // Serialization + // You can either save out in canonical format (and it will only save canonical-instance-related + // information *or* you can save out in normal format where we link directly to instance handle + // instead of to typename + template <typename THashType> + void AddInstancesFromHash(THashType &inHash, + unordered_set<TInstanceHandle, hash<int>> &outInstances) + { + for (typename THashType::const_iterator iter = inHash.begin(), end = inHash.end(); + iter != end; ++iter) + outInstances.insert(iter->first); + } + + void SerializeMetaDataData(IDOMWriter &inWriter, TMetaDataData &inItem, + AdditionalMetaDataType::Value inType) + { + if (!inItem.empty()) { + if (inType == AdditionalMetaDataType::Range) { + SMetaDataRange theRange(get<SMetaDataRange>(inItem)); + inWriter.Att(L"min", theRange.m_min); + inWriter.Att(L"max", theRange.m_max); + inWriter.Att(L"decimals", theRange.m_decimals); + } else if (inType == AdditionalMetaDataType::StringList) { + const TMetaDataStringList &theList(get<TMetaDataStringList>(inItem)); + TCharStr theBuffer; + for (uint32_t idx = 0, end = theList.size(); idx < end; ++idx) { + if (idx) + theBuffer.append(L":"); + theBuffer.append(theList[idx]); + } + inWriter.Att(L"list", theBuffer.wide_str()); + } + } + } + + void SerializeDataModelValue(IDOMWriter &inWriter, const SValue &inValue, + DataModelDataType::Value /*inType*/, + const wchar_t *inName = L"default") + { + if (inValue.empty()) + return; + + m_TempBuffer.clear(); + WCharTWriter writer(m_TempBuffer); + WStrOps<SValue>().ToBuf(inValue, writer); + + if (m_TempBuffer.size()) { + m_TempBuffer.write((QT3DSU16)0); + inWriter.Att(inName, (const wchar_t *)m_TempBuffer.begin()); + } + } + + void SerializeDataModelValue(IDOMReader &inReader, SValue &outValue, + DataModelDataType::Value inType, + const wchar_t *inName = L"default") + { + const char8_t *theDefaultValue; + qt3ds::foundation::ConvertUTF( + reinterpret_cast<const qt3ds::foundation::TWCharEASTLConverter::TCharType *>( + inName), 0, + m_ConvertStr); + if (inReader.UnregisteredAtt(m_ConvertStr.c_str(), theDefaultValue)) { + m_TempBuffer.clear(); + // We have to write a temporary value because the parsing of floats, + // in order to be efficient, is destructive. + if (theDefaultValue && *theDefaultValue) + m_TempBuffer.write(theDefaultValue, (QT3DSU32)strlen(theDefaultValue) + 1); + + if (m_TempBuffer.size() == 0) { + SetDefault(inType, outValue); + return; + } + m_ReadBuffer.clear(); + + char8_t *trashPtr = (char8_t *)m_TempBuffer.begin(); + WCharTReader theReader(trashPtr, m_ReadBuffer, m_StringTable); + outValue = WStrOps<SValue>().BufTo(inType, theReader); + } else + SetDefault(inType, outValue); + } + + void SerializeMetaDataData(IDOMReader &inReader, TMetaDataData &ioItem, + CompleteMetaDataType::Enum &ioType) + { + // Use the meta data extra information to force the type + // to something that works correctly. + SMetaDataRange theRange; + if (inReader.Att("min", theRange.m_min) && inReader.Att("max", theRange.m_max)) { + inReader.Att("decimals", theRange.m_decimals); + ioItem = theRange; + if (ioType == CompleteMetaDataType::Long) + ioType = CompleteMetaDataType::LongRange; + else + ioType = CompleteMetaDataType::FloatRange; + } else { + TMetaDataStringList theList; + TCharStr theItems; + if (inReader.Att(L"list", theItems)) { + for (TCharStr::size_type theIter = theItems.find_first_of(L":,"); + theIter != theItems.npos; theIter = theItems.find_first_of(L":,")) { + theList.push_back(theItems.substr(0, theIter)); + theItems = theItems.substr(theIter + 1); + } + theList.push_back(theItems); + ioItem = theList; + if (ioType != CompleteMetaDataType::StringListOrInt) + ioType = CompleteMetaDataType::StringList; + } + } + } + void EnsureCategory(IDOMWriter &, const TCharStr &, const TCharStr &) {} + void EnsureCategory(IDOMReader &, TCharStr &inCategory, const TCharStr &inObjectName) + { + Qt3DSDMCategoryHandle theCategory = FindCategoryByName(inCategory); + if (theCategory.Valid() == false) { + if (inObjectName.empty()) { + QT3DS_ASSERT(false); + } else { + if (inCategory.empty()) + inCategory = inObjectName; + + pair<Qt3DSDMCategoryHandle, bool> theGetOrCreateResult( + GetOrCreateCategory(inCategory)); + + if (theGetOrCreateResult.second == true) { + SetCategoryInfo(theGetOrCreateResult.first, L"Objects-Behavior-Normal.png", + L"Objects-Behavior-Normal.png", inCategory); + } + } + } + } + + void SerializePropertyBase(IDOMWriter &inArchive, SMetaPropertyBase &inItem) + { + inArchive.Att(L"name", inItem.m_Name); + if (inItem.m_FormalName != inItem.m_Name) + inArchive.Att(L"formalName", inItem.m_FormalName); + if (inItem.m_Description != inItem.m_Name) + inArchive.Att(L"description", inItem.m_Description); + if (inItem.m_CompleteType != CompleteMetaDataType::Float + && inItem.m_CompleteType != CompleteMetaDataType::FloatRange + && inItem.m_CompleteType != CompleteMetaDataType::LongRange + && inItem.m_CompleteType != CompleteMetaDataType::StringList) { + inArchive.Att(L"type", inItem.m_CompleteType); + } + + // Ensure that all types work + if (inItem.GetAdditionalType() != AdditionalMetaDataType::None) + SerializeMetaDataData(inArchive, inItem.m_MetaDataData, inItem.GetAdditionalType()); + + if (inItem.GetDataType() != DataModelDataType::None) { + SValue theGlobalDefault; + SetDefault(inItem.GetDataType(), theGlobalDefault); + if (!Equals(theGlobalDefault.toOldSkool(), inItem.m_DefaultValue.toOldSkool())) + SerializeDataModelValue(inArchive, inItem.m_DefaultValue, inItem.GetDataType()); + } + } + + void SerializePropertyBase(IDOMReader &inArchive, SMetaPropertyBase &inItem) + { + inArchive.Att(L"name", inItem.m_Name); + inArchive.Att(L"formalName", inItem.m_FormalName); + inArchive.Att(L"usage", inItem.m_Usage); + inArchive.Att(L"description", inItem.m_Description); + inArchive.Att(L"type", inItem.m_CompleteType); + // Setup reasonable defaults in the case where the users are specifying little information + // in the file format + if (inItem.m_FormalName.empty()) + inItem.m_FormalName = inItem.m_Name; + if (inItem.m_Description.empty()) + inItem.m_Description = inItem.m_FormalName; + + // Ensure that users can use a float type and make minimal decisions + SerializeMetaDataData(inArchive, inItem.m_MetaDataData, inItem.m_CompleteType); + + if (inItem.GetDataType() != DataModelDataType::None) + SerializeDataModelValue(inArchive, inItem.m_DefaultValue, inItem.GetDataType()); + } + + void FinalizeCategory(IDOMWriter &, SCategoryInfo &) {} + + void FinalizeCategory(IDOMReader &, SCategoryInfo &inCategory) + { + if (inCategory.m_Description.empty()) + inCategory.m_Description = inCategory.m_Name; + } + + template <typename TArchiveType> + void SerializeItem(TArchiveType &inArchive, SCategoryInfo &inItem) + { + inArchive.Att(L"name", inItem.m_Name); + inArchive.Att(L"description", inItem.m_Description); + inArchive.Att(L"icon", inItem.m_Icon); + inArchive.Att(L"highlightIcon", inItem.m_HighlightIcon); + + FinalizeCategory(inArchive, inItem); + } + + void SerializeItem(IDOMWriter &inArchive, SMetaDataPropertyInfo &inItem, + Qt3DSDMMetaDataPropertyHandle inHandle) + { + SerializePropertyBase(inArchive, inItem); + if (inItem.m_IsHidden == true) + inArchive.Att("hidden", inItem.m_IsHidden); + if (inItem.m_Animatable == false) + inArchive.Att("animatable", inItem.m_Animatable); + if (inItem.m_Controllable == true) + inArchive.Att("controllable", inItem.m_Controllable); + NVConstDataRef<SPropertyFilterInfo> theInfos = GetMetaDataPropertyFilters(inHandle); + for (QT3DSU32 idx = 0, end = theInfos.size(); idx < end; ++idx) { + const SPropertyFilterInfo &theInfo(theInfos[idx]); + Qt3DSDMPropertyDefinition thePropertyInfo( + m_DataCore->GetProperty(theInfo.m_FilterProperty)); + + const wchar_t *theFilterName; + if (theInfo.m_FilterType == PropertyFilterTypes::HideIfEqual) + theFilterName = L"HideIfEqual"; + else + theFilterName = L"ShowIfEqual"; + + IDOMWriter::Scope filterScope(inArchive, theFilterName); + inArchive.Att(L"property", thePropertyInfo.m_Name); + SerializeDataModelValue(inArchive, theInfo.m_Value, thePropertyInfo.m_Type, L"value"); + } + } + + void SerializeItem(IDOMReader &inArchive, SMetaDataPropertyInfo &inItem, + Qt3DSDMMetaDataPropertyHandle inHandle) + { + QT3DS_ASSERT(inHandle.Valid()); + + SerializePropertyBase(inArchive, inItem); + inArchive.Att("hidden", inItem.m_IsHidden); + inArchive.Att("animatable", inItem.m_Animatable); + inArchive.Att("controllable", inItem.m_Controllable); + inArchive.Att(L"category", inItem.m_GroupName); + } + + void ReadChildren(IDOMReader &inArchive, SMetaDataPropertyInfo &inItem, + Qt3DSDMMetaDataPropertyHandle inHandle) + { + IDOMReader::Scope __readerScope(inArchive); + eastl::vector<SPropertyFilterInfo> theFilters; + for (bool success = inArchive.MoveToFirstChild(); success; + success = inArchive.MoveToNextSibling()) { + + if (AreEqual(inArchive.GetElementName(), L"ShowIfEqual")) { + TCharStr theName; + inArchive.Att(L"property", theName); + Qt3DSDMPropertyHandle theProperty = + m_DataCore->GetAggregateInstancePropertyByName(inItem.m_Instance, theName); + if (theProperty.Valid() == false) { + QT3DS_ASSERT(false); + return; + } + Qt3DSDMPropertyDefinition thePropDef(m_DataCore->GetProperty(theProperty)); + + SPropertyFilterInfo theInfo; + theInfo.m_FilterType = PropertyFilterTypes::ShowIfEqual; + theInfo.m_FilterProperty = theProperty; + SerializeDataModelValue(inArchive, theInfo.m_Value, thePropDef.m_Type, L"value"); + theFilters.push_back(theInfo); + } else if (AreEqual(inArchive.GetElementName(), L"HideIfEqual")) { + TCharStr theName; + inArchive.Att(L"property", theName); + Qt3DSDMPropertyHandle theProperty = + m_DataCore->GetAggregateInstancePropertyByName(inItem.m_Instance, theName); + if (theProperty.Valid() == false) { + QT3DS_ASSERT(false); + return; + } + Qt3DSDMPropertyDefinition thePropDef(m_DataCore->GetProperty(theProperty)); + + SPropertyFilterInfo theInfo; + theInfo.m_FilterType = PropertyFilterTypes::HideIfEqual; + theInfo.m_FilterProperty = theProperty; + SerializeDataModelValue(inArchive, theInfo.m_Value, thePropDef.m_Type, L"value"); + theFilters.push_back(theInfo); + } else { + QT3DS_ASSERT(false); + } + } + if (theFilters.size()) + SetMetaDataPropertyFilters( + inHandle, qt3ds::foundation::toDataRef(theFilters.data(), + theFilters.size())); + } + + void EnsureEventHandlerBase(IDOMWriter &, SEventAndHandlerBase &) {} + + void EnsureEventHandlerBase(IDOMReader &, SEventAndHandlerBase &inItem) + { + if (inItem.m_FormalName.empty()) + inItem.m_FormalName = inItem.m_Name; + if (inItem.m_Description.empty()) + inItem.m_Description = inItem.m_Name; + } + + void SerializeItem(IDOMWriter &inArchive, SEvent &inItem, Qt3DSDMEventHandle &) + { + inArchive.Att(L"name", inItem.m_Name); + if (inItem.m_Name != inItem.m_FormalName) + inArchive.Att(L"formalName", inItem.m_FormalName); + if (inItem.m_Category != L"Default") + inArchive.Att(L"category", inItem.m_Category); + if (inItem.m_Description != inItem.m_Name) + inArchive.Att(L"description", inItem.m_Description); + + EnsureCategory(inArchive, inItem.m_Category, m_ObjectName); + EnsureEventHandlerBase(inArchive, inItem); + } + + void SerializeItem(IDOMReader &inArchive, SEvent &inItem, Qt3DSDMEventHandle &) + { + inArchive.Att(L"name", inItem.m_Name); + inArchive.Att(L"formalName", inItem.m_FormalName); + inArchive.Att(L"category", inItem.m_Category); + EnsureCategory(inArchive, inItem.m_Category, m_ObjectName); + inArchive.Att(L"description", inItem.m_Description); + EnsureEventHandlerBase(inArchive, inItem); + } + + void SerializeHandlerArgument(IDOMWriter &inArchive, SMetaDataHandlerArgumentInfo &inArgument) + { + SerializePropertyBase(inArchive, inArgument); + if (inArgument.m_ArgType != HandlerArgumentType::None) + inArchive.Att(L"argumentType", inArgument.m_ArgType); + } + + void SerializeHandlerArgument(IDOMReader &inArchive, SMetaDataHandlerArgumentInfo &inArgument) + { + SerializePropertyBase(inArchive, inArgument); + inArchive.Att(L"argumentType", inArgument.m_ArgType); + } + + void SerializeHandlerArguments(IDOMWriter &inWriter, SHandler &inItem, Qt3DSDMHandlerHandle &) + { + for (size_t idx = 0, end = inItem.m_Arguments.size(); idx < end; ++idx) { + SMetaDataHandlerArgumentInfo &theArg(inItem.m_Arguments[idx]); + IDOMWriter::Scope __argScope(inWriter, L"Argument"); + SerializeHandlerArgument(inWriter, theArg); + } + } + + void SerializeHandlerArguments(IDOMReader &inReader, SHandler &inItem, THandlerHandle &inHandle) + { + if (inHandle.GetHandleValue() == 0) + inHandle = THandlerHandle(GetNextId()); + + IDOMReader::Scope __handlerScope(inReader); + for (bool success = inReader.MoveToFirstChild(); success; + success = inReader.MoveToNextSibling()) { + SMetaDataHandlerArgumentInfo theArg(inHandle); + SerializeHandlerArgument(inReader, theArg); + inItem.m_Arguments.push_back(theArg); + } + } + + void SerializeHandlerItem(IDOMWriter &inArchive, SHandler &inItem) + { + inArchive.Att(L"name", inItem.m_Name); + if (inItem.m_FormalName != inItem.m_Name) + inArchive.Att(L"formalName", inItem.m_FormalName); + if (inItem.m_Category != L"Default") + inArchive.Att(L"category", inItem.m_Category); + if (inItem.m_Description != inItem.m_Name) + inArchive.Att(L"description", inItem.m_Description); + EnsureEventHandlerBase(inArchive, inItem); + } + + void SerializeHandlerItem(IDOMReader &inArchive, SHandler &inItem) + { + inArchive.Att(L"name", inItem.m_Name); + inArchive.Att(L"formalName", inItem.m_FormalName); + inArchive.Att(L"category", inItem.m_Category); + EnsureCategory(inArchive, inItem.m_Category, m_ObjectName); + inArchive.Att(L"description", inItem.m_Description); + EnsureEventHandlerBase(inArchive, inItem); + } + + template <typename TArchiveType> + void SerializeItem(TArchiveType &inArchive, SHandler &inItem, Qt3DSDMHandlerHandle &inHandle) + { + SerializeHandlerItem(inArchive, inItem); + SerializeHandlerArguments(inArchive, inItem, inHandle); + } + + template <typename TInfoType, typename THandleType, typename TListMapType, typename THashType, + typename TNameMapType> + void SerializeInstanceData(IDOMWriter &inArchive, TInstanceHandle inInstanceHandle, + TCharPtr inElementName, + unordered_map<THandleType, TInfoType, THashType> &inMap, + TListMapType &inListMap, TNameMapType & /*inNameMap*/) + { + typedef unordered_map<THandleType, TInfoType, THashType> TMapType; + typename TListMapType::iterator find = inListMap.find(inInstanceHandle); + if (find == inListMap.end()) + return; + + vector<THandleType> &itemList = find->second; + for (size_t idx = 0, end = itemList.size(); idx < end; ++idx) { + typename TMapType::iterator iter = inMap.find(itemList[idx]); + if (iter == inMap.end()) { + QT3DS_ASSERT(false); + continue; + } + TInfoType &theType = iter->second; + IDOMWriter::Scope __elemScope(inArchive, inElementName); + SerializeItem(inArchive, theType, itemList[idx]); + } + } + + void CreateInstanceGroupInfo(SMetaDataPropertyInfo &inProperty) + { + if (!inProperty.m_GroupName.empty()) { + const wchar_t *theGroupName = Intern(inProperty.m_GroupName); + bool found = false; + pair<typename TInstanceGroupMap::iterator, bool> inserter = + m_InstanceGroupMap.insert(make_pair(inProperty.m_Instance, vector<TCharPtr>())); + vector<TCharPtr> &itemList = inserter.first->second; + for (size_t idx = 0, end = itemList.size(); idx < end; ++idx) { + TCharStr curListName = itemList[idx]; + if (curListName == theGroupName) { + found = true; + break; + } + } + if (!found && !inProperty.m_IsHidden) + inserter.first->second.push_back(theGroupName); + } + } + void CreateInstanceGroupInfo(SEvent &) {} + void CreateInstanceGroupInfo(SHandler &) {} + + // Make sure the data core + void PostLoad(SMetaDataPropertyInfo &inProperty) + { + EnsureDataCoreProperty(inProperty); + SetPropertyDefault(inProperty, inProperty.GetDataType()); + } + + void ReadChildren(IDOMReader &, SEvent &, Qt3DSDMEventHandle) {} + void ReadChildren(IDOMReader &, SHandler &, Qt3DSDMHandlerHandle) {} + + void PostLoad(SEvent &) {} + void PostLoad(SHandler &) {} + template <typename TInfoType, typename THandleType, typename TListMapType, typename THashType, + typename TNameMapType> + void SerializeInstanceData(IDOMReader &inArchive, TInstanceHandle inInstanceHandle, + TCharPtr inElementName, + unordered_map<THandleType, TInfoType, THashType> &inMap, + TListMapType &inListMap, TNameMapType &inNameMap) + { + // Ensure we pop out to where we were. + IDOMReader::Scope __readerScope(inArchive); + for (bool success = inArchive.MoveToFirstChild(inElementName); success; + success = inArchive.MoveToNextSibling(inElementName)) { + TInfoType theInfo(inInstanceHandle); + THandleType theHandle(GetNextId()); + SerializeItem(inArchive, theInfo, theHandle); + PostLoad(theInfo); + CreateInstanceGroupInfo(theInfo); + inMap.insert(make_pair(theHandle, theInfo)); + this->AddItemToInstanceList(inInstanceHandle, theHandle, inListMap); + inNameMap.insert( + make_pair(make_pair(inInstanceHandle, Intern(theInfo.m_Name)), theHandle)); + ReadChildren(inArchive, theInfo, theHandle); + } + } + + void SerializeInstanceData(IDOMWriter &inArchive, TInstanceHandle inInstance, + TCharPtr inElementName, TInstanceStringListMap &inMap) + { + TInstanceStringListMap::iterator iter = inMap.find(inInstance); + if (iter == inMap.end()) + return; + const vector<TCharPtr> &theValueList(iter->second); + for (size_t idx = 0, end = theValueList.size(); idx < end; ++idx) { + IDOMWriter::Scope __elemScope(inArchive, inElementName); + inArchive.Value(theValueList[idx]); + } + } + + void SerializeInstanceData(IDOMReader &inArchive, TInstanceHandle inInstance, + TCharPtr inElementName, TInstanceStringListMap &inMap) + { + IDOMReader::Scope __readerScope(inArchive); + for (bool success = inArchive.MoveToFirstChild(inElementName); success; + success = inArchive.MoveToNextSibling(inElementName)) { + const wchar_t *theValue; + if (inArchive.RegisteredValue(theValue)) + AddItemToInstanceList(inInstance, theValue, inMap); + } + } + + template <typename TArchiveType> + void SerializeInstance(TArchiveType &inArchive, TInstanceHandle inInstance) + { + SerializeInstanceData(inArchive, inInstance, L"Property", m_Properties, + m_InstanceToProperties, m_InstanceNameToProperties); + SerializeInstanceData(inArchive, inInstance, L"Event", m_Events, m_InstanceToEvents, + m_InstanceNameToEvents); + SerializeInstanceData(inArchive, inInstance, L"Handler", m_Handlers, m_InstanceToHandlers, + m_InstanceNameToHandlers); + SerializeInstanceData(inArchive, inInstance, L"Reference", m_InstanceToReferences); + } + void SerializeCategories(IDOMWriter &inWriter) + { + for (TCategoryMap::iterator iter = m_Categories.begin(), end = m_Categories.end(); + iter != end; ++iter) { + IDOMWriter::Scope __writerScope(inWriter, L"Category"); + SerializeItem(inWriter, iter->second); + } + } + void SerializeCategories(IDOMReader &inReader) + { + IDOMReader::Scope __readerScope(inReader); + for (bool success = inReader.MoveToFirstChild(L"Category"); success; + success = inReader.MoveToNextSibling(L"Category")) { + SCategoryInfo theInfo; + SerializeItem(inReader, theInfo); + TCategoryHandle newHandle(GetNextId()); + theInfo.m_Canonical = true; + m_Categories.insert(make_pair(newHandle, theInfo)); + m_NameToCategories.insert(make_pair(Intern(theInfo.m_Name), newHandle)); + } + } + + struct SInstanceSorter + { + const TInstanceStrMap &m_Map; + SInstanceSorter(const TInstanceStrMap &inMap) + : m_Map(inMap) + { + } + bool operator()(TInstanceHandle lhs, TInstanceHandle rhs) + { + TInstanceStrMap::const_iterator lhsIter(m_Map.find(lhs)); + TInstanceStrMap::const_iterator rhsIter(m_Map.find(rhs)); + if (lhsIter == rhsIter) + return false; + if (lhsIter == m_Map.end()) + return false; + if (rhsIter == m_Map.end()) + return true; + return wcscmp(lhsIter->second, rhsIter->second) < 0; + } + }; + + void Save(IDOMWriter &inWriter) override + { + SerializeCategories(inWriter); + typedef unordered_set<TInstanceHandle, hash<int>> TInstanceListType; + TInstanceListType theInstanceList; + // Get the list of instances to serialize. + + AddInstancesFromHash(m_InstanceToProperties, theInstanceList); + AddInstancesFromHash(m_InstanceToEvents, theInstanceList); + AddInstancesFromHash(m_InstanceToHandlers, theInstanceList); + AddInstancesFromHash(m_InstanceToReferences, theInstanceList); + + vector<TInstanceHandle> theInstances; + theInstances.reserve(theInstanceList.size()); + theInstances.insert(theInstances.begin(), theInstanceList.begin(), theInstanceList.end()); + sort(theInstances.begin(), theInstances.end(), SInstanceSorter(m_InstancesToCanonicalType)); + + for (vector<TInstanceHandle>::iterator iter = theInstances.begin(), + end = theInstances.end(); + iter != end; ++iter) { + TInstanceHandle instHandle = *iter; + Option<TCharStr> theType(GetTypeForCanonicalInstance(*iter)); + if (theType.hasValue()) { + IDOMWriter::Scope __instanceElem(inWriter, theType->wide_str()); + SerializeInstance(inWriter, *iter); + } + } + } + + // Loading expects the canonical instances to be setup already which means that + // it will perform lookups based on + void Load(IDOMReader &inReader) override + { + if (!inReader.Att("NextId", m_NextId)) + m_NextId = 1; + m_ObjectName = L""; + SerializeCategories(inReader); + IDOMReader::Scope __instanceGatherScope(inReader); + for (bool success = inReader.MoveToFirstChild(); success; + success = inReader.MoveToNextSibling()) { + const wchar_t *elemName = inReader.GetElementName(); + TStrInstanceMap::iterator find = m_CanonicalTypeToInstances.find(elemName); + if (find == m_CanonicalTypeToInstances.end()) { + continue; + } + + SerializeInstance(inReader, find->second); + } + } + + template <typename THandleType, typename TMapType> + void RemoveOldItemsAndSetOrder( + Qt3DSDMInstanceHandle inInstance, vector<THandleType> &inNewHandles, + void (SNewMetaDataImpl::*inGetSpecificFun)(Qt3DSDMInstanceHandle, vector<THandleType> &), + void (SNewMetaDataImpl::*inDestroyFun)(THandleType), TMapType &inListMap) + { + vector<THandleType> theHandles; + (this->*inGetSpecificFun)(inInstance, theHandles); + for (size_t idx = 0, end = theHandles.size(); idx < end; ++idx) + if (find(inNewHandles.begin(), inNewHandles.end(), theHandles[idx]) + == inNewHandles.end()) + (this->*inDestroyFun)(theHandles[idx]); + + InsertOrUpdateWithTransaction(make_pair(inInstance, inNewHandles), inListMap); + } + + // Load meta data and apply it to just this instance + // This needs to be undoable so we have to do this through a slightly different + // system than we did before. + void LoadInstance(IDOMReader &inReader, Qt3DSDMInstanceHandle inInstance, + const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings) override + { + const wchar_t *theAtt; + vector<Qt3DSDMMetaDataPropertyHandle> theProperties; + vector<Qt3DSDMEventHandle> theEvents; + vector<Qt3DSDMHandlerHandle> theHandlers; + DestroyReferences(inInstance); + m_ObjectName = inObjectName; + for (bool success = inReader.MoveToFirstChild(); success; + success = inReader.MoveToNextSibling()) { + if (AreEqual(inReader.GetElementName(), L"Category")) { + SCategoryInfo theInfo; + SerializeItem(inReader, theInfo); + Qt3DSDMCategoryHandle theCategoryInfo(GetOrCreateCategory(theInfo.m_Name).first); + SetCategoryInfo(theCategoryInfo, theInfo.m_Icon, theInfo.m_HighlightIcon, + theInfo.m_Description); + } else if (AreEqual(inReader.GetElementName(), L"Property")) { + SMetaDataPropertyInfo theInfo(inInstance); + if (inReader.Att(L"name", theAtt)) { + Qt3DSDMMetaDataPropertyHandle theProperty( + GetOrCreateSpecificMetaDataProperty(inInstance, theAtt)); + SerializeItem(inReader, theInfo, theProperty); + SetMetaDataPropertyInfo(theProperty, theInfo.m_Name, theInfo.m_FormalName, + theInfo.m_Description, theInfo.m_Usage, + theInfo.m_CompleteType, theInfo.m_DefaultValue, + theInfo.m_MetaDataData, theInfo.m_GroupName, + theInfo.m_IsHidden, theInfo.m_Animatable, + theInfo.m_Controllable); + CreateInstanceGroupInfo(theInfo); + theProperties.push_back(theProperty); + ReadChildren(inReader, theInfo, theProperty); + } else + outWarnings.push_back( + SMetaDataLoadWarning(MetaDataLoadWarningType::InvalidProperty, + MetaDataLoadWarningMessage::MissingName)); + } else if (AreEqual(inReader.GetElementName(), L"Event")) { + SEvent theInfo(inInstance); + if (inReader.Att(L"name", theAtt)) { + Qt3DSDMEventHandle theEvent(GetOrCreateSpecificEvent(inInstance, theAtt)); + SerializeItem(inReader, theInfo, theEvent); + SetEventInfo(theEvent, theInfo.m_Name, theInfo.m_FormalName, theInfo.m_Category, + theInfo.m_Description); + theEvents.push_back(theEvent); + } else + outWarnings.push_back( + SMetaDataLoadWarning(MetaDataLoadWarningType::InvalidEvent, + MetaDataLoadWarningMessage::MissingName)); + } else if (AreEqual(inReader.GetElementName(), L"Handler")) { + if (inReader.Att(L"name", theAtt)) { + Qt3DSDMHandlerHandle theHandler(GetOrCreateSpecificHandler(inInstance, theAtt)); + SHandler theInfo(inInstance); + SerializeHandlerItem(inReader, theInfo); + SetHandlerInfo(theHandler, theInfo.m_Name, theInfo.m_FormalName, + theInfo.m_Category, theInfo.m_Description); + IDOMReader::Scope __argScope(inReader); + QT3DSU32 argIdx = 0; + for (bool argSuccess = inReader.MoveToFirstChild(); argSuccess; + argSuccess = inReader.MoveToNextSibling(), ++argIdx) { + SMetaDataHandlerArgumentInfo theArg(theHandler); + SerializeHandlerArgument(inReader, theArg); + while (argIdx >= GetNumHandlerArguments(theHandler)) + AddHandlerArgument(theHandler); + + if (argIdx < GetNumHandlerArguments(theHandler)) { + SetHandlerArgumentInfo(theHandler, argIdx, theArg.m_Name, + theArg.m_FormalName, theArg.m_Description, + theArg.m_CompleteType, theArg.m_DefaultValue, + theArg.m_MetaDataData, theArg.m_ArgType); + } + } + while (GetNumHandlerArguments(theHandler) > argIdx) + DestroyHandlerArgument(theHandler, GetNumHandlerArguments(theHandler) - 1); + theHandlers.push_back(theHandler); + } else + outWarnings.push_back( + SMetaDataLoadWarning(MetaDataLoadWarningType::InvalidHandler, + MetaDataLoadWarningMessage::MissingName)); + } else if (AreEqual(inReader.GetElementName(), L"Reference")) { + const wchar_t *theValue; + if (inReader.Value(theValue)) + AddReference(inInstance, theValue); + } else { + QT3DS_ASSERT(false); + } + } + RemoveOldItemsAndSetOrder( + inInstance, theProperties, &SNewMetaDataImpl::GetSpecificMetaDataProperties, + &SNewMetaDataImpl::DestroyMetaDataProperty, m_InstanceToProperties); + RemoveOldItemsAndSetOrder(inInstance, theEvents, &SNewMetaDataImpl::GetSpecificEvents, + &SNewMetaDataImpl::DestroyEvent, m_InstanceToEvents); + RemoveOldItemsAndSetOrder(inInstance, theHandlers, &SNewMetaDataImpl::GetSpecificHandlers, + &SNewMetaDataImpl::DestroyHandler, m_InstanceToHandlers); + } + + // Save just this instances meta data out to the writer + void SaveInstance(IDOMWriter &inWriter, Qt3DSDMInstanceHandle inInstance) override + { + SerializeInstance(inWriter, inInstance); + } + + // Helper to convert char to wchar_t + eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> m_Buf; + const wchar_t *ConvertChar(const char *inName) + { + if (inName && *inName) { + qt3ds::foundation::ConvertUTF(inName, 0, m_Buf); + return reinterpret_cast<const wchar_t *>(m_Buf.c_str()); + } + return NULL; + } + + void LoadEffectInstance(const char *inShaderFile, Qt3DSDMInstanceHandle inInstance, + const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings, + qt3ds::foundation::IInStream &inStream) override + { + QString shaderFile(inShaderFile); + if (shaderFile.endsWith(".effect")) { + LoadEffectXMLFromSourcePath(inShaderFile, inInstance, inObjectName, outWarnings, + inStream); + } else { + QT3DS_ASSERT(false); + } + } + + bool IsEffectInstanceRegistered(const char *inName) override + { + return m_EffectMap.find(Intern(inName)) != m_EffectMap.end(); + } + + inline qt3ds::render::NVRenderTextureFormats::Enum + ConvertTypeAndFormatToTextureFormat(const char8_t *inType, const char8_t *inFormat) + { + qt3ds::render::NVRenderTextureFormats::Enum retval + = qt3ds::render::NVRenderTextureFormats::RGBA8; + if (AreEqual(inFormat, "source")) + retval = qt3ds::render::NVRenderTextureFormats::Unknown; + else if (AreEqual(inFormat, "depth24stencil8")) + retval = qt3ds::render::NVRenderTextureFormats::Depth24Stencil8; + else { + if (AreEqual(inType, "ubyte")) { + if (AreEqual(inFormat, "rgb")) + retval = qt3ds::render::NVRenderTextureFormats::RGB8; + else if (AreEqual(inFormat, "rgba")) + retval = qt3ds::render::NVRenderTextureFormats::RGBA8; + else if (AreEqual(inFormat, "alpha")) + retval = qt3ds::render::NVRenderTextureFormats::Alpha8; + else if (AreEqual(inFormat, "lum")) + retval = qt3ds::render::NVRenderTextureFormats::Luminance8; + else if (AreEqual(inFormat, "lum_alpha")) + retval = qt3ds::render::NVRenderTextureFormats::LuminanceAlpha8; + else if (AreEqual(inFormat, "rg")) + retval = qt3ds::render::NVRenderTextureFormats::RG8; + } else if (AreEqual(inType, "ushort")) { + if (AreEqual(inFormat, "rgb")) + retval = qt3ds::render::NVRenderTextureFormats::RGB565; + else if (AreEqual(inFormat, "rgba")) + retval = qt3ds::render::NVRenderTextureFormats::RGBA5551; + } else if (AreEqual(inType, "fp16")) { + if (AreEqual(inFormat, "rgba")) + retval = qt3ds::render::NVRenderTextureFormats::RGBA16F; + else if (AreEqual(inFormat, "rg")) + retval = qt3ds::render::NVRenderTextureFormats::RG16F; + } else if (AreEqual(inType, "fp32")) { + if (AreEqual(inFormat, "rgba")) + retval = qt3ds::render::NVRenderTextureFormats::RGBA32F; + else if (AreEqual(inFormat, "rg")) + retval = qt3ds::render::NVRenderTextureFormats::RG32F; + } else { + QT3DS_ASSERT(false); + // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported texture type %s, + // defaulting to RGBA8", inType ); + } + } + return retval; + } + + static inline qt3ds::render::NVRenderTextureMagnifyingOp::Enum + ConvertFilterToMagOp(const char8_t *inFilter) + { + if (AreEqual(inFilter, "linear")) + return qt3ds::render::NVRenderTextureMagnifyingOp::Linear; + if (IsTrivial(inFilter) || AreEqual(inFilter, "nearest")) + return qt3ds::render::NVRenderTextureMagnifyingOp::Nearest; + else { + QT3DS_ASSERT(false); + // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting to + // linear", inFilter ); + return qt3ds::render::NVRenderTextureMagnifyingOp::Linear; + } + } + + static inline qt3ds::render::NVRenderTextureMinifyingOp::Enum + ConvertFilterToMinOp(const char8_t *inFilter) + { + // we make the decision based on the texture usage + if (AreEqual(inFilter, "linear")) + return qt3ds::render::NVRenderTextureMinifyingOp::Linear; + if (AreEqual(inFilter, "nearest")) + return qt3ds::render::NVRenderTextureMinifyingOp::Nearest; + if (AreEqual(inFilter, "linearMipmapLinear")) + return qt3ds::render::NVRenderTextureMinifyingOp::LinearMipmapLinear; + if (AreEqual(inFilter, "nearestMipmapNearest")) + return qt3ds::render::NVRenderTextureMinifyingOp::NearestMipmapNearest; + if (AreEqual(inFilter, "nearestMipmapLinear")) + return qt3ds::render::NVRenderTextureMinifyingOp::NearestMipmapLinear; + if (AreEqual(inFilter, "linearMipmapNearest")) + return qt3ds::render::NVRenderTextureMinifyingOp::LinearMipmapNearest; + else { + QT3DS_ASSERT(false); + // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting + // to linear", inFilter ); + return qt3ds::render::NVRenderTextureMinifyingOp::Linear; + } + } + + static inline qt3ds::render::NVRenderTextureCoordOp::Enum + ConvertTextureCoordOp(const char8_t *inWrap) + { + if (IsTrivial(inWrap) || AreEqual(inWrap, "clamp")) + return qt3ds::render::NVRenderTextureCoordOp::ClampToEdge; + if (AreEqual(inWrap, "repeat")) + return qt3ds::render::NVRenderTextureCoordOp::Repeat; + else { + QT3DS_ASSERT(false); + // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported wrap type %s, defaulting to + // clamp", inWrap ); + return qt3ds::render::NVRenderTextureCoordOp::ClampToEdge; + } + } + + static inline qt3ds::render::NVRenderTextureTypeValue::Enum + ConvertTextureType(const char8_t *inTexType) + { + // this usually comes from a MDL description file + if (IsTrivial(inTexType)) + return qt3ds::render::NVRenderTextureTypeValue::Unknown; + if (AreEqual(inTexType, "environment")) + return qt3ds::render::NVRenderTextureTypeValue::Environment; + if (AreEqual(inTexType, "diffuse")) + return qt3ds::render::NVRenderTextureTypeValue::Diffuse; + if (AreEqual(inTexType, "specular")) + return qt3ds::render::NVRenderTextureTypeValue::Specular; + if (AreEqual(inTexType, "bump")) + return qt3ds::render::NVRenderTextureTypeValue::Bump; + if (AreEqual(inTexType, "displacement")) + return qt3ds::render::NVRenderTextureTypeValue::Displace; + if (AreEqual(inTexType, "shadow")) + return qt3ds::render::NVRenderTextureTypeValue::LightmapShadow; + if (AreEqual(inTexType, "emissive")) + return qt3ds::render::NVRenderTextureTypeValue::Emissive; + if (AreEqual(inTexType, "emissive_mask")) + return qt3ds::render::NVRenderTextureTypeValue::Emissive2; + else { + return qt3ds::render::NVRenderTextureTypeValue::Unknown; + } + } + + static inline qt3ds::render::NVRenderSrcBlendFunc::Enum + ConvertToSrcBlendFunc(const char8_t *inFilter) + { + if (AreEqual(inFilter, "SrcAlpha")) + return qt3ds::render::NVRenderSrcBlendFunc::SrcAlpha; + if (AreEqual(inFilter, "OneMinusSrcAlpha")) + return qt3ds::render::NVRenderSrcBlendFunc::OneMinusSrcAlpha; + if (AreEqual(inFilter, "One")) + return qt3ds::render::NVRenderSrcBlendFunc::One; + else { + QT3DS_ASSERT(false); + // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting + // to linear", inFilter ); + return qt3ds::render::NVRenderSrcBlendFunc::One; + } + } + + static inline qt3ds::render::NVRenderDstBlendFunc::Enum + ConvertToDstBlendFunc(const char8_t *inFilter) + { + if (AreEqual(inFilter, "SrcAlpha")) + return qt3ds::render::NVRenderDstBlendFunc::SrcAlpha; + if (AreEqual(inFilter, "OneMinusSrcAlpha")) + return qt3ds::render::NVRenderDstBlendFunc::OneMinusSrcAlpha; + if (AreEqual(inFilter, "One")) + return qt3ds::render::NVRenderDstBlendFunc::One; + else { + QT3DS_ASSERT(false); + // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting + // to linear", inFilter ); + return qt3ds::render::NVRenderDstBlendFunc::One; + } + } + + static inline qt3ds::render::NVRenderState::Enum ConvertRenderState(const char8_t *inState) + { + if (AreEqual(inState, "Stencil")) + return qt3ds::render::NVRenderState::StencilTest; + else { + QT3DS_ASSERT(false); + // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting + // to linear", inFilter ); + return qt3ds::render::NVRenderState::StencilTest; + } + } + + static inline qt3ds::render::NVRenderImageAccessType::Enum + ConvertToImageAccessType(const char8_t *inAccess) + { + if (AreEqual(inAccess, "read")) + return qt3ds::render::NVRenderImageAccessType::Read; + if (AreEqual(inAccess, "write")) + return qt3ds::render::NVRenderImageAccessType::Write; + if (AreEqual(inAccess, "readwrite")) + return qt3ds::render::NVRenderImageAccessType::ReadWrite; + else + QT3DS_ASSERT(false); + + return qt3ds::render::NVRenderImageAccessType::ReadWrite; + } + + static inline size_t GetTypeSize(const char8_t *inType) + { + if (AreEqual(inType, "uint")) + return sizeof(QT3DSU32); + else if (AreEqual(inType, "int")) + return sizeof(QT3DSI32); + else if (AreEqual(inType, "uvec4")) + return sizeof(QT3DSU32) * 4; + else + QT3DS_ASSERT(false); + + return 1; + } + + inline qt3ds::render::NVRenderBufferBindValues::Enum + ConvertFormatToBufferBindFlags(const char8_t *inFormat) + { + if (AreEqual(inFormat, "storage")) + return qt3ds::render::NVRenderBufferBindValues::Storage; + else if (AreEqual(inFormat, "indirect")) + return qt3ds::render::NVRenderBufferBindValues::Draw_Indirect; + else + QT3DS_ASSERT(false); + + return qt3ds::render::NVRenderBufferBindValues::Unknown; + } + + static inline void AppendShaderUniform(const char8_t *type, const char8_t *name, + eastl::string &shaderPrefix) + { + shaderPrefix.append("uniform "); + shaderPrefix.append(type); + shaderPrefix.append(" "); + shaderPrefix.append(name); + shaderPrefix.append(";\n"); + } + static inline void AppendShaderCode( + const char8_t *inCode, Qt3DSDMStr &ioStr, + eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> + &inConvertBuffer) + { + qt3ds::foundation::ConvertUTF(inCode, 0, inConvertBuffer); + ioStr.append(inConvertBuffer); + } + void HideEffectProperty(Qt3DSDMInstanceHandle inInstance, const char8_t *inParamName) + { + Qt3DSDMMetaDataPropertyHandle theProp = + GetSpecificMetaDataProperty(inInstance, Intern(inParamName)); + if (theProp.Valid()) { + SMetaDataPropertyInfo theInfo = GetMetaDataPropertyInfo(theProp); + SetMetaDataPropertyInfo(theProp, theInfo.m_Name, theInfo.m_FormalName, + theInfo.m_Description, theInfo.m_Usage, theInfo.m_CompleteType, + theInfo.m_DefaultValue, theInfo.m_MetaDataData, + theInfo.m_GroupName, true, theInfo.m_Animatable, + theInfo.m_Controllable); + } + } + + static inline void GetShaderName(const TCharStr &inObjectName, + const char8_t *inShaderSpecificName, + eastl::string &outShaderName) + { + outShaderName.clear(); + qt3ds::foundation::ConvertUTF(inObjectName.c_str(), 0, outShaderName); + outShaderName.append(" - "); + outShaderName.append(inShaderSpecificName); + } + + void LoadDynamicObjectProperties(IDOMReader &inStream, SMetaDataDynamicObjectImpl &ioObject, + Qt3DSDMInstanceHandle inInstance, const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings, + eastl::string &shaderPrefix) + { + eastl::string vertexUniforms; + eastl::string fragmentUniforms; + vertexUniforms += "#ifdef VERTEX_SHADER\n"; + fragmentUniforms += "#ifdef FRAGMENT_SHADER\n"; + using namespace qt3ds::render::dynamic; + ioObject.m_Properties.clear(); + ioObject.ClearEnumValueNames(); + IDOMReader::Scope __readerScope(inStream); + if (inStream.MoveToFirstChild("MetaData")) { + { + IDOMReader::Scope __readerScope(inStream); + LoadInstance(inStream, inInstance, inObjectName, outWarnings); + } + + vector<Qt3DSDMMetaDataPropertyHandle> theProperties; + GetSpecificMetaDataProperties(inInstance, theProperties); + size_t propIdx = 0, propEnd = theProperties.size(); + for (bool success = inStream.MoveToFirstChild("Property"); success && propIdx < propEnd; + success = inStream.MoveToNextSibling("Property"), ++propIdx) { + ioObject.m_Properties.push_back(); + SPropertyDefinition &theNewDefinition = ioObject.m_Properties.back(); + SMetaDataPropertyInfo theInfo(GetMetaDataPropertyInfo(theProperties[propIdx])); + theNewDefinition.m_Name = + m_StringTable.GetRenderStringTable().RegisterStr(theInfo.m_Name.c_str()); + const char8_t *xmlName; + inStream.Att("name", xmlName); + const char8_t *stage; + inStream.Att("stage", stage); + eastl::string uniforms; + if (AreEqual(xmlName, theNewDefinition.m_Name.c_str())) { + switch (theInfo.GetDataType()) { + case DataModelDataType::Bool: + theNewDefinition.m_DataType = + qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool; + AppendShaderUniform("bool", theNewDefinition.m_Name.c_str(), uniforms); + break; + case DataModelDataType::Long: + theNewDefinition.m_DataType + = qt3ds::render::NVRenderShaderDataTypes::QT3DSI32; + AppendShaderUniform("int", theNewDefinition.m_Name.c_str(), uniforms); + break; + case DataModelDataType::Float2: + theNewDefinition.m_DataType + = qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2; + AppendShaderUniform("vec2", theNewDefinition.m_Name.c_str(), uniforms); + break; + case DataModelDataType::Float3: + theNewDefinition.m_DataType + = qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3; + AppendShaderUniform("vec3", theNewDefinition.m_Name.c_str(), uniforms); + break; + case DataModelDataType::Float4: + theNewDefinition.m_DataType + = qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4; + AppendShaderUniform("vec4", theNewDefinition.m_Name.c_str(), uniforms); + break; + case DataModelDataType::String: + if (theInfo.m_CompleteType == CompleteMetaDataType::Texture) { + theNewDefinition.m_DataType = + qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr; + const char8_t *filter = "linear", *minFilter = "linear", + *clamp = "clamp", *usage = "", *path = ""; + if (inStream.Att("filter", filter)) + theNewDefinition.m_MagFilterOp = ConvertFilterToMagOp(filter); + if (inStream.Att("minfilter", minFilter)) + theNewDefinition.m_MinFilterOp = ConvertFilterToMinOp(minFilter); + if (inStream.Att("clamp", clamp)) + theNewDefinition.m_CoordOp = ConvertTextureCoordOp(clamp); + if (inStream.Att("usage", usage)) + theNewDefinition.m_TexUsageType = ConvertTextureType(usage); + if (inStream.Att("default", path)) { + TDataStrPtr theDataStr( + theInfo.m_DefaultValue.getData<TDataStrPtr>()); + theNewDefinition.m_ImagePath = + m_StringTable.GetRenderStringTable().RegisterStr( + theDataStr->GetData()); + } + + // Output macro so we can change the set of variables used for this + // independent of the + // meta data system. + uniforms.append("SNAPPER_SAMPLER2D("); + uniforms.append(theNewDefinition.m_Name.c_str()); + uniforms.append(", "); + uniforms.append(theNewDefinition.m_Name.c_str()); + uniforms.append(", "); + uniforms.append(filter); + uniforms.append(", "); + uniforms.append(clamp); + uniforms.append(", "); + uniforms.append("false )\n"); + } else if (theInfo.m_CompleteType == CompleteMetaDataType::StringList) { + theNewDefinition.m_DataType = + qt3ds::render::NVRenderShaderDataTypes::QT3DSI32; + const TMetaDataStringList &theList = + qt3dsdm::get<TMetaDataStringList>(theInfo.m_MetaDataData); + ioObject.m_EnumValueNames.push_back( + new eastl::vector<qt3ds::foundation::CRegisteredString>()); + eastl::vector<qt3ds::foundation::CRegisteredString> &theBack = + *ioObject.m_EnumValueNames.back(); + for (QT3DSU32 idx = 0, end = (QT3DSU32)theList.size(); idx < end; ++idx) + theBack.push_back(m_StringTable.GetRenderStringTable().RegisterStr( + theList[idx].c_str())); + theNewDefinition.m_EnumValueNames = VecToCRef(theBack); + theNewDefinition.m_IsEnumProperty = true; + AppendShaderUniform("int", theNewDefinition.m_Name.c_str(), + uniforms); + } else if (theInfo.m_CompleteType == CompleteMetaDataType::Image2D) { + theNewDefinition.m_DataType = + qt3ds::render::NVRenderShaderDataTypes::NVRenderImage2DPtr; + const char8_t *format = "", *binding = "", *access = "readonly"; + uniforms.append("layout("); + inStream.Att("format", format); + uniforms.append(format); + if (inStream.Att("binding", binding)) { + uniforms.append(", binding = "); + uniforms.append(binding); + } + uniforms.append(") "); + + // if we have format layout we cannot set an additional access qualifier + if (inStream.Att("access", access) && !AreEqual(format, "")) + uniforms.append(access); + + uniforms.append(" uniform image2D "); + uniforms.append(theNewDefinition.m_Name.c_str()); + uniforms.append(";\n"); + } else if (theInfo.m_CompleteType == CompleteMetaDataType::Buffer) { + theNewDefinition.m_DataType = + qt3ds::render::NVRenderShaderDataTypes::NVRenderDataBufferPtr; + const char8_t *align = "std140", *usage = "storage", *binding = "", + *format = "float"; + uniforms.append("layout("); + + inStream.Att("format", format); + inStream.Att("usage", usage); + if (AreEqual(usage, "storage")) { + inStream.Att("align", align); + uniforms.append(align); + + if (inStream.Att("binding", binding)) { + uniforms.append(", binding = "); + uniforms.append(binding); + } + + uniforms.append(") "); + + uniforms.append("buffer "); + uniforms.append(theNewDefinition.m_Name.c_str()); + uniforms.append("\n{ \n"); + uniforms.append(format); + uniforms.append(" "); + uniforms.append(theNewDefinition.m_Name.c_str()); + uniforms.append("_data[]; \n};\n"); + } else { + // currently we only handle storage counters + QT3DS_ASSERT(false); + } + } + break; + default: + QT3DS_ASSERT(false); + // Fallthrough intentional + case DataModelDataType::Float: + theNewDefinition.m_DataType = qt3ds::render::NVRenderShaderDataTypes::QT3DSF32; + AppendShaderUniform("float", theNewDefinition.m_Name.c_str(), uniforms); + break; + } + } else { + // It is conceivable that we not every property tag gets parsed into a property. + QT3DS_ASSERT(false); + // So we will bump to the next item and try again. + --propIdx; + } + + if (AreEqual(stage, "vertex")) { + vertexUniforms += uniforms; + } else if (AreEqual(stage, "fragment")) { + fragmentUniforms += uniforms; + } else { + vertexUniforms += uniforms; + fragmentUniforms += uniforms; + } + } + } + vertexUniforms += "#endif\n"; + fragmentUniforms += "#endif\n"; + shaderPrefix.append(vertexUniforms); + shaderPrefix.append(fragmentUniforms); + } + + void LoadDynamicObjectShaders(IDOMReader &inStream, SMetaDataDynamicObjectImpl &ioObject, + eastl::string &shaderPrefix, const TCharStr &inObjectName) + { + eastl::string theShaderNameStr; + eastl::string theShaderTypeStr; + eastl::string theShaderVersionStr; + { + IDOMReader::Scope __readerScope(inStream); + eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> theConvertBuffer; + if (inStream.MoveToFirstChild("Shaders")) { + const char8_t *globalShared = ""; + const char8_t *globalVertexShared = ""; + const char8_t *globalFragmentShared = ""; + inStream.ChildValue("Shared", globalShared); + inStream.ChildValue("VertexShaderShared", globalVertexShared); + inStream.ChildValue("FragmentShaderShared", globalFragmentShared); + + inStream.Att("type", theShaderTypeStr); // can be empty + inStream.Att("version", theShaderVersionStr); // can be empty + + for (bool success = inStream.MoveToFirstChild(); success; + success = inStream.MoveToNextSibling()) { + IDOMReader::Scope __shaderScope(inStream); + const char8_t *elemName = inStream.GetNarrowElementName(); + // If this is neither a compute shader nor a normal shader, go on and ignore + // element. + if (!(AreEqual(elemName, "Shader") || AreEqual(elemName, "ComputeShader"))) + continue; + + ioObject.m_Shaders.push_back(); + SMetaDataShader &theShader = ioObject.m_Shaders.back(); + + qt3ds::foundation::ConvertUTF(theShaderTypeStr.c_str(), theShaderTypeStr.size(), + theShader.m_Type); + qt3ds::foundation::ConvertUTF(theShaderVersionStr.c_str(), + theShaderVersionStr.size(), theShader.m_Version); + const char8_t *theName = ""; + char8_t theITOABuffer[64] = { 0 }; + if (!inStream.Att("name", theName)) { + sprintf(theITOABuffer, "%d", (int)ioObject.m_Shaders.size() - 1); + theName = theITOABuffer; + } + GetShaderName(inObjectName, theName, theShaderNameStr); + qt3ds::foundation::ConvertUTF(theShaderNameStr.c_str(), theShaderNameStr.size(), + theShader.m_Name); + + if (AreEqual(elemName, "Shader")) { + const char8_t *shaderShared = ""; + inStream.ChildValue("Shared", shaderShared); + const char8_t *vertexCode = ""; + inStream.ChildValue("VertexShader", vertexCode); + if (IsTrivial(vertexCode)) + vertexCode = "void vert(){}"; + const char8_t *fragmentCode = "void frag(){}"; + inStream.ChildValue("FragmentShader", fragmentCode); + if (IsTrivial(fragmentCode)) + fragmentCode = "void frag(){}"; + const char8_t *geomCode = ""; + inStream.ChildValue("GeometryShader", geomCode); + + AppendShaderCode(shaderPrefix.c_str(), theShader.m_Code, theConvertBuffer); + AppendShaderCode(globalShared, theShader.m_Code, theConvertBuffer); + AppendShaderCode(shaderShared, theShader.m_Code, theConvertBuffer); + AppendShaderCode("\n#ifdef VERTEX_SHADER\n", theShader.m_Code, + theConvertBuffer); + AppendShaderCode(globalVertexShared, theShader.m_Code, theConvertBuffer); + AppendShaderCode(vertexCode, theShader.m_Code, theConvertBuffer); + AppendShaderCode("\n#endif\n", theShader.m_Code, theConvertBuffer); + if (!IsTrivial(geomCode)) { + AppendShaderCode("\n#ifdef USER_GEOMETRY_SHADER\n", theShader.m_Code, + theConvertBuffer); + AppendShaderCode(geomCode, theShader.m_Code, theConvertBuffer); + AppendShaderCode("\n#endif\n", theShader.m_Code, theConvertBuffer); + theShader.m_HasGeomShader = true; + } + AppendShaderCode("\n#ifdef FRAGMENT_SHADER\n", theShader.m_Code, + theConvertBuffer); + AppendShaderCode(globalFragmentShared, theShader.m_Code, theConvertBuffer); + AppendShaderCode(fragmentCode, theShader.m_Code, theConvertBuffer); + AppendShaderCode("\n#endif\n", theShader.m_Code, theConvertBuffer); + } else if (AreEqual(elemName, "ComputeShader")) { + const char8_t *shaderCode = ""; + inStream.Value(shaderCode); + theShader.m_IsComputeShader = true; + AppendShaderCode(shaderCode, theShader.m_Code, theConvertBuffer); + } + } + } + } + } + + static size_t Align(size_t inValue) + { + if (inValue % 4) + return inValue + (4 - (inValue % 4)); + return inValue; + } + + static qt3ds::render::dynamic::SDepthStencilFlags ParseDepthStencilFlags(const char8_t *inFlags) + { + eastl::string parseStr(inFlags); + eastl::string tokenStr; + qt3ds::render::dynamic::SDepthStencilFlags retval; + for (uint32_t pos = parseStr.find('|'); parseStr.empty() == false; + pos = parseStr.find('|')) { + if (pos != eastl::string::npos) { + tokenStr = parseStr.substr(pos); + parseStr.erase(parseStr.begin(), parseStr.begin() + pos + 1); + } else { + tokenStr = parseStr; + parseStr.clear(); + } + if (AreEqual(tokenStr.c_str(), "clear-stencil")) + retval |= qt3ds::render::dynamic::DepthStencilFlagValues::ClearStencil; + if (AreEqual(tokenStr.c_str(), "clear-depth")) + retval |= qt3ds::render::dynamic::DepthStencilFlagValues::ClearDepth; + } + return retval; + } + + static qt3ds::render::NVRenderBoolOp::Enum ParseBoolOp(const char8_t *inOp) + { + if (AreEqual(inOp, "never")) + return qt3ds::render::NVRenderBoolOp::Never; + if (AreEqual(inOp, "less")) + return qt3ds::render::NVRenderBoolOp::Less; + if (AreEqual(inOp, "less-than-or-equal")) + return qt3ds::render::NVRenderBoolOp::LessThanOrEqual; + if (AreEqual(inOp, "equal")) + return qt3ds::render::NVRenderBoolOp::Equal; + if (AreEqual(inOp, "not-equal")) + return qt3ds::render::NVRenderBoolOp::NotEqual; + if (AreEqual(inOp, "greater")) + return qt3ds::render::NVRenderBoolOp::Greater; + if (AreEqual(inOp, "greater-than-or-equal")) + return qt3ds::render::NVRenderBoolOp::GreaterThanOrEqual; + if (AreEqual(inOp, "always")) + return qt3ds::render::NVRenderBoolOp::AlwaysTrue; + + QT3DS_ASSERT(false); + return qt3ds::render::NVRenderBoolOp::Unknown; + } + + static qt3ds::render::NVRenderStencilOp::Enum ParseStencilOp(const char8_t *inOp) + { + + if (AreEqual(inOp, "keep")) + return qt3ds::render::NVRenderStencilOp::Keep; + if (AreEqual(inOp, "zero")) + return qt3ds::render::NVRenderStencilOp::Zero; + if (AreEqual(inOp, "replace")) + return qt3ds::render::NVRenderStencilOp::Replace; + if (AreEqual(inOp, "increment")) + return qt3ds::render::NVRenderStencilOp::Increment; + if (AreEqual(inOp, "increment-wrap")) + return qt3ds::render::NVRenderStencilOp::IncrementWrap; + if (AreEqual(inOp, "decrement")) + return qt3ds::render::NVRenderStencilOp::Decrement; + if (AreEqual(inOp, "decrement-wrap")) + return qt3ds::render::NVRenderStencilOp::DecrementWrap; + if (AreEqual(inOp, "invert")) + return qt3ds::render::NVRenderStencilOp::Invert; + + QT3DS_ASSERT(false); + return qt3ds::render::NVRenderStencilOp::Unknown; + } + + // Reloads an effect if one is already loaded so we can replace the existing effect definition + void LoadEffectXML(IDOMReader &inStream, Qt3DSDMInstanceHandle inInstance, + const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings, + const TCharStr &inSourcePath) override + { + using namespace qt3ds::render::dynamic; + std::pair<TEffectMap::iterator, bool> theInserter = + m_EffectMap.insert(std::make_pair(Intern(inObjectName), SMetaDataEffectImpl())); + /*if ( inStream.MoveToFirstChild( "Effect" ) == false ) + { + outWarnings.push_back( SMetaDataLoadWarning( MetaDataLoadWarningType::Unknown, + MetaDataLoadWarningMessage::GeneralError, L"File doesn't appear to be an effect xml file, + missing top level Effect tag" ) ); + return; + }*/ + eastl::string shaderPrefix = "#include \"effect.glsllib\"\n"; + + SMetaDataEffectImpl &theEffect = theInserter.first->second; + m_ObjectName = inObjectName; + theEffect.m_Name = inObjectName; + theEffect.m_SourcePath = inSourcePath; + theEffect.ClearEffectCommands(); + LoadDynamicObjectProperties(inStream, theEffect, inInstance, inObjectName, outWarnings, + shaderPrefix); + theEffect.m_Shaders.clear(); + LoadDynamicObjectShaders(inStream, theEffect, shaderPrefix, inObjectName); + eastl::string theShaderNameStr; + { + IDOMReader::Scope __readerScope(inStream); + if (inStream.MoveToFirstChild("Passes")) { + for (bool success = inStream.MoveToFirstChild(); success; + success = inStream.MoveToNextSibling()) { + IDOMReader::Scope __passScope(inStream); + if (AreEqual("Pass", inStream.GetNarrowElementName())) { + bool drawIndirect = false; + const char8_t *shader = "", *input = "[source]", *output = "[dest]", + *outputFormat = "rgba"; + inStream.Att("shader", shader); + inStream.Att("input", input); + inStream.Att("output", output); + // this is only for the final output of the effect + inStream.Att("format", outputFormat); + qt3ds::render::NVRenderTextureFormats::Enum theOutputFormat = + ConvertTypeAndFormatToTextureFormat("ubyte", outputFormat); + if (AreEqual(output, "[dest]") || IsTrivial(output)) + theEffect.m_EffectCommands.push_back(new SBindTarget(theOutputFormat)); + else + theEffect.m_EffectCommands.push_back( + new SBindBuffer( + m_StringTable.GetRenderStringTable().RegisterStr(output), + false)); + GetShaderName(inObjectName, shader, theShaderNameStr); + theEffect.m_EffectCommands.push_back( + new SBindShader(m_StringTable.GetRenderStringTable().RegisterStr( + theShaderNameStr.c_str()))); + theEffect.m_EffectCommands.push_back(new SApplyInstanceValue()); + if (AreEqual(input, "[source]") || IsTrivial(input)) + theEffect.m_EffectCommands.push_back( + new SApplyBufferValue( + m_StringTable.GetRenderStringTable().RegisterStr(""), + m_StringTable.GetRenderStringTable().RegisterStr(""))); + else + theEffect.m_EffectCommands.push_back( + new SApplyBufferValue( + m_StringTable.GetRenderStringTable().RegisterStr(input), + m_StringTable.GetRenderStringTable().RegisterStr(""))); + for (bool bufParam = inStream.MoveToFirstChild(); bufParam; + bufParam = inStream.MoveToNextSibling()) { + if (AreEqual("BufferInput", inStream.GetNarrowElementName())) { + const char8_t *param = ""; + const char8_t *value = ""; + inStream.Att("param", param); + inStream.Att("value", value); + if (AreEqual("[source]", value)) + value = ""; + theEffect.m_EffectCommands.push_back( + new SApplyBufferValue( + m_StringTable.GetRenderStringTable().RegisterStr( + value), + m_StringTable.GetRenderStringTable().RegisterStr( + param))); + HideEffectProperty(inInstance, param); + } else if (AreEqual("DepthInput", inStream.GetNarrowElementName())) { + const char8_t *param = ""; + inStream.Att("param", param); + theEffect.m_EffectCommands.push_back( + new SApplyDepthValue( + m_StringTable.GetRenderStringTable().RegisterStr( + param))); + HideEffectProperty(inInstance, param); + } else if (AreEqual("ImageInput", inStream.GetNarrowElementName())) { + bool useAsTexture = false; + bool needSync = false; + const char8_t *param = ""; + const char8_t *value = ""; + const char8_t *usage = ""; + const char8_t *sync = ""; + inStream.Att("param", param); + inStream.Att("value", value); + if (AreEqual("[source]", value)) + value = ""; + inStream.Att("usage", usage); + if (AreEqual("texture", usage)) + useAsTexture = true; + inStream.Att("sync", sync); + if (AreEqual("true", sync)) + needSync = true; + + theEffect.m_EffectCommands.push_back( + new SApplyImageValue( + m_StringTable.GetRenderStringTable().RegisterStr( + value), + m_StringTable.GetRenderStringTable().RegisterStr( + param), useAsTexture, needSync)); + HideEffectProperty(inInstance, param); + } else if (AreEqual("DataBufferInput", + inStream.GetNarrowElementName())) { + const char8_t *param = ""; + const char8_t *usage = ""; + inStream.Att("param", param); + inStream.Att("usage", usage); + qt3ds::render::NVRenderBufferBindValues::Enum bufType = + ConvertFormatToBufferBindFlags(usage); + + // check if we using an indirect buffer for drawing + if (bufType == qt3ds::render::NVRenderBufferBindValues::Draw_Indirect) + drawIndirect = true; + + theEffect.m_EffectCommands.push_back( + new SApplyDataBufferValue( + m_StringTable.GetRenderStringTable().RegisterStr( + param), bufType)); + HideEffectProperty(inInstance, param); + } else if (AreEqual("SetParam", inStream.GetNarrowElementName())) { + const char8_t *name = ""; + inStream.Att("name", name); + const char8_t *value = ""; + inStream.Att("value", value); + // find the param and the type. + qt3ds::foundation::CRegisteredString propName = + m_StringTable.GetRenderStringTable().RegisterStr(name); + qt3ds::render::dynamic::SPropertyDefinition *theDefinition = NULL; + for (uint32_t propIdx = 0, propEnd = theEffect.m_Properties.size(); + propIdx < propEnd && theDefinition == NULL; ++propIdx) { + if (theEffect.m_Properties[propIdx].m_Name == propName) + theDefinition = &theEffect.m_Properties[propIdx]; + } + if (theDefinition != NULL) { + // Hack it for now because the shader datatypes don't have a + // built in sizeof operator. + QT3DSU32 valueSize = 4; + qt3ds::render::NVRenderShaderDataTypes::Enum theDataType = + theDefinition->m_DataType; + size_t allocSize = sizeof(SApplyValue) + valueSize; + QT3DSU8 *theCommandData = (QT3DSU8 *)malloc(allocSize); + QT3DSU8 *theValueData = theCommandData + sizeof(SApplyValue); + new (theCommandData) SApplyValue(propName, theDataType); + SApplyValue *theCommand = + reinterpret_cast<SApplyValue *>(theCommandData); + switch (theDataType) { + case qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool: { + bool &target = *reinterpret_cast<bool *>(theValueData); + qt3ds::foundation::StringConversion<bool>().StrTo(value, + target); + } break; + case qt3ds::render::NVRenderShaderDataTypes::QT3DSI32: { + QT3DSI32 &target = *reinterpret_cast<QT3DSI32 *>( + theValueData); + qt3ds::foundation::StringConversion<QT3DSI32>().StrTo( + value, target); + } break; + default: + QT3DS_ASSERT(false); + // Fallthrough intentional + case qt3ds::render::NVRenderShaderDataTypes::QT3DSF32: { + QT3DSF32 &target = *reinterpret_cast<QT3DSF32 *>( + theValueData); + qt3ds::foundation::StringConversion<QT3DSF32>().StrTo( + value, target); + } break; + } + theCommand->m_Value = NVDataRef<QT3DSU8>(theValueData, + valueSize); + theEffect.m_EffectCommands.push_back(theCommand); + } + } else if (AreEqual("Blending", inStream.GetNarrowElementName())) { + const char8_t *theSrcBlendFuncStr = "", *theDestBlendFuncStr = ""; + inStream.Att("source", theSrcBlendFuncStr); + inStream.Att("dest", theDestBlendFuncStr); + + qt3ds::render::NVRenderSrcBlendFunc::Enum theSrcBlendFunc = + ConvertToSrcBlendFunc(theSrcBlendFuncStr); + qt3ds::render::NVRenderDstBlendFunc::Enum theDstBlendFuc = + ConvertToDstBlendFunc(theDestBlendFuncStr); + + // this will setup blending + theEffect.m_EffectCommands.push_back( + new SApplyBlending(theSrcBlendFunc, theDstBlendFuc)); + } else if (AreEqual("RenderState", inStream.GetNarrowElementName())) { + const char8_t *name = ""; + inStream.Att("name", name); + const char8_t *value = ""; + inStream.Att("value", value); + // find the param and the type. + bool theStateEnable = false; + qt3ds::render::NVRenderState::Enum theState + = ConvertRenderState(name); + if (AreEqual("true", value)) + theStateEnable = true; + + // this will setup blending + theEffect.m_EffectCommands.push_back( + new SApplyRenderState(theState, theStateEnable)); + } else if (AreEqual("DepthStencil", inStream.GetNarrowElementName())) { + const char8_t *bufferName = ""; + inStream.Att("buffer", bufferName); + QT3DSU32 stencilvalue = 0; + inStream.Att("reference", stencilvalue); + const char8_t *flags = ""; + inStream.Att("flags", flags); + QT3DSU32 mask = QT3DS_MAX_U32; + inStream.Att("mask", mask); + qt3ds::render::NVRenderBoolOp::Enum stencilFunction = + qt3ds::render::NVRenderBoolOp::Equal; + qt3ds::render::NVRenderStencilOp::Enum stencilFailOperation = + qt3ds::render::NVRenderStencilOp::Keep; + qt3ds::render::NVRenderStencilOp::Enum depthPass = + qt3ds::render::NVRenderStencilOp::Keep; + qt3ds::render::NVRenderStencilOp::Enum depthFail = + qt3ds::render::NVRenderStencilOp::Keep; + const char8_t *temp; + if (inStream.Att("stencil-fail", temp)) + stencilFailOperation = ParseStencilOp(temp); + if (inStream.Att("depth-pass", temp)) + depthPass = ParseStencilOp(temp); + if (inStream.Att("depth-fail", temp)) + depthFail = ParseStencilOp(temp); + if (inStream.Att("stencil-function", temp)) + stencilFunction = ParseBoolOp(temp); + + qt3ds::render::dynamic::SDepthStencilFlags flagValues = + ParseDepthStencilFlags(flags); + theEffect.m_EffectCommands.push_back( + new SDepthStencil( + m_StringTable.GetRenderStringTable().RegisterStr( + bufferName), flagValues, stencilFailOperation, + depthPass, depthFail, stencilFunction, stencilvalue, + mask)); + } else { + QT3DS_ASSERT(false); + } + } + theEffect.m_EffectCommands.push_back(new SRender(drawIndirect)); + } else if (AreEqual("Buffer", inStream.GetNarrowElementName()) + || AreEqual("Image", inStream.GetNarrowElementName())) { + SAllocateBufferFlags theFlags; + const char8_t *theLifetimeStr = "", *theType = "", *theFormat = "", + *theFilter = "", *theWrap = "", *theName = ""; + QT3DSF32 theSize = 1.0f; + bool isImage = AreEqual("Image", inStream.GetNarrowElementName()); + inStream.Att("name", theName); + inStream.Att("lifetime", theLifetimeStr); + inStream.Att("type", theType); + inStream.Att("format", theFormat); + inStream.Att("filter", theFilter); + inStream.Att("wrap", theWrap); + inStream.Att("size", theSize); + // Clamp the size to valid amounts + if (theSize <= 0) + theSize = 1.0f; + if (theSize > 1.0f) + theSize = 1.0f; + if (AreEqual(theLifetimeStr, "scene")) + theFlags.SetSceneLifetime(true); + qt3ds::render::NVRenderTextureFormats::Enum theTexFormat = + ConvertTypeAndFormatToTextureFormat(theType, theFormat); + qt3ds::render::NVRenderTextureMagnifyingOp::Enum theMagOp = + ConvertFilterToMagOp(theFilter); + qt3ds::render::NVRenderTextureCoordOp::Enum theCoordOp = + ConvertTextureCoordOp(theWrap); + if (*theName == 0) { + QT3DS_ASSERT(false); + // inFoundation.error( QT3DS_INVALID_PARAMETER, "Buffer is missing its + // name" ); + } else if (isImage) { + const char8_t *temp; + qt3ds::render::NVRenderImageAccessType::Enum theAccess = + qt3ds::render::NVRenderImageAccessType::ReadWrite; + if (inStream.Att("access", temp)) + theAccess = ConvertToImageAccessType(temp); + + theEffect.m_EffectCommands.push_back( + new SAllocateImage( + m_StringTable.GetRenderStringTable().RegisterStr( + theName), theTexFormat, theMagOp, theCoordOp, + theSize, theFlags, theAccess)); + } else { + theEffect.m_EffectCommands.push_back( + new SAllocateBuffer( + m_StringTable.GetRenderStringTable().RegisterStr( + theName), theTexFormat, theMagOp, theCoordOp, + theSize, theFlags)); + } + } else if (AreEqual("DataBuffer", inStream.GetNarrowElementName())) { + SAllocateBufferFlags theFlags; + const char8_t *theLifetimeStr = "", *theType = "", *theWrapName = "", + *theWrapType = "", *theFormat = "", *theName = ""; + QT3DSF32 theSize = 1.0f; + qt3ds::render::NVRenderBufferBindValues::Enum bufType, + wrapBufType = qt3ds::render::NVRenderBufferBindValues::Unknown; + + inStream.Att("name", theName); + inStream.Att("lifetime", theLifetimeStr); + inStream.Att("type", theType); + inStream.Att("format", theFormat); + inStream.Att("size", theSize); + if (AreEqual(theLifetimeStr, "scene")) + theFlags.SetSceneLifetime(true); + bufType = ConvertFormatToBufferBindFlags(theType); + + if (inStream.Att("wrapType", theWrapType)) { + wrapBufType = ConvertFormatToBufferBindFlags(theWrapType); + inStream.Att("wrapName", theWrapName); + if (*theWrapName == 0) + QT3DS_ASSERT(false); + } + + theSize *= GetTypeSize(theFormat); + + if (theSize <= 0) + theSize = 1.0f; + + if (*theName == 0) { + QT3DS_ASSERT(false); + } else { + theEffect.m_EffectCommands.push_back( + new SAllocateDataBuffer( + m_StringTable.GetRenderStringTable().RegisterStr( + theName), bufType, + m_StringTable.GetRenderStringTable().RegisterStr( + theWrapName), wrapBufType, theSize, theFlags)); + } + } else { + QT3DS_ASSERT(false); // Unrecognized effect passes member. + } + } + + } else { + if (theEffect.m_Shaders.size()) { + // Create the minimal set of commands that we could run the first shader with. + theEffect.m_EffectCommands.push_back(new SBindTarget()); + theEffect.m_EffectCommands.push_back( + new SBindShader(m_StringTable.GetRenderStringTable().RegisterStr( + theEffect.m_Shaders[0].m_Name.c_str()))); + theEffect.m_EffectCommands.push_back(new SApplyInstanceValue()); + theEffect.m_EffectCommands.push_back(new SRender(false)); + } + } + } + } + + bool LoadEffectXMLFromSourcePath(const char *inSourcePath, + Qt3DSDMInstanceHandle inInstance, + const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings, + qt3ds::foundation::IInStream &inStream) override + { + std::shared_ptr<IDOMFactory> theFactory( + IDOMFactory::CreateDOMFactory(m_DataCore->GetStringTablePtr())); + qt3dsdm::SDOMElement *theElem = CDOMSerializer::Read(*theFactory, inStream, NULL); + if (theElem != NULL) { + std::shared_ptr<IDOMReader> theReader( + IDOMReader::CreateDOMReader(*theElem, m_DataCore->GetStringTablePtr(), + theFactory)); + LoadEffectXML(*theReader, inInstance, inObjectName, outWarnings, + TCharStr(Intern(inSourcePath))); + return true; + } + return false; + } + + Option<SMetaDataEffect> GetEffectBySourcePath(const char *inSourcePath) override + { + QDir sourcePath = QDir::cleanPath(QString(inSourcePath)); + for (TEffectMap::iterator iter = m_EffectMap.begin(), end = m_EffectMap.end(); iter != end; + ++iter) { + QDir effectPath = QDir::cleanPath(QString::fromWCharArray( + iter->second.m_SourcePath.wide_str())); + if (effectPath == sourcePath) + return iter->second.ToEffect(); + } + return Empty(); + } + + void LoadMaterialInstance(const char *inShaderFile, Qt3DSDMInstanceHandle inInstance, + const TCharStr &inName, + std::vector<SMetaDataLoadWarning> &outWarnings, + qt3ds::foundation::IInStream &inStream) override + { + QString shaderFile(inShaderFile); + if (shaderFile.endsWith(".material") || shaderFile.endsWith(".shader")) { + LoadMaterialClassFromSourcePath(inShaderFile, inInstance, inName, outWarnings, + inStream); + } else { + QT3DS_ASSERT(false); + } + } + + bool IsMaterialClassRegistered(const char *inName) override + { + return m_CustomMaterials.find(Intern(inName)) != m_CustomMaterials.end(); + } + + void LoadMaterialClassXML(IDOMReader &inStream, Qt3DSDMInstanceHandle inInstance, + const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings, + const TCharStr &inSourcePath) override + { + using namespace qt3ds::render::dynamic; + + std::pair<TCustomMaterialMap::iterator, bool> theInserter = m_CustomMaterials.insert( + std::make_pair(Intern(inObjectName), SMetaDataCustomMaterialImpl())); + /*if ( inStream.MoveToFirstChild( "Effect" ) == false ) + { + outWarnings.push_back( SMetaDataLoadWarning( MetaDataLoadWarningType::Unknown, + MetaDataLoadWarningMessage::GeneralError, L"File doesn't appear to be an effect xml file, + missing top level Effect tag" ) ); + return; + }*/ + eastl::string shaderPrefix = "#include \"customMaterial.glsllib\"\n"; + + SMetaDataCustomMaterialImpl &theMaterial = theInserter.first->second; + m_ObjectName = inObjectName; + theMaterial.m_Name = inObjectName; + theMaterial.m_SourcePath = inSourcePath; + theMaterial.m_HasTransparency = false; + theMaterial.m_HasRefraction = false; + theMaterial.m_AlwaysDirty = false; + theMaterial.m_ShaderKey = 0; + theMaterial.m_LayerCount = 0; + inStream.Att("always-dirty", theMaterial.m_AlwaysDirty); + LoadDynamicObjectProperties(inStream, theMaterial, inInstance, inObjectName, outWarnings, + shaderPrefix); + LoadDynamicObjectShaders(inStream, theMaterial, shaderPrefix, inObjectName); + + // currently single pass shader only + if (theMaterial.m_Shaders.size()) { + eastl::string theShaderNameStr; + + // in Passes we store additional render commands + IDOMReader::Scope __readerScope(inStream); + if (inStream.MoveToFirstChild("Passes")) { + for (bool success = inStream.MoveToFirstChild(); success; + success = inStream.MoveToNextSibling()) { + IDOMReader::Scope __passScope(inStream); + if (AreEqual("Pass", inStream.GetNarrowElementName())) { + const char8_t *typeStr; + if (!inStream.UnregisteredAtt("type", typeStr)) + typeStr = "render"; + if (AreEqual(typeStr, "render")) { + const char8_t *shader = "", *input = "[source]", *output = "[dest]", + *outputFormat = "rgba", *clear = ""; + bool needsClear = false; + inStream.Att("shader", shader); + inStream.Att("input", input); + inStream.Att("output", output); + // for multi pass materials + inStream.Att("clear", clear); + if (AreEqual("true", clear)) + needsClear = true; + + GetShaderName(inObjectName, shader, theShaderNameStr); + // this is only for the final output of the effect + inStream.Att("format", outputFormat); + qt3ds::render::NVRenderTextureFormats::Enum theOutputFormat = + ConvertTypeAndFormatToTextureFormat("ubyte", outputFormat); + + if (AreEqual(output, "[dest]") || IsTrivial(output)) { + theMaterial.m_CustomerMaterialCommands.push_back( + new SBindTarget(theOutputFormat)); + } else { + theMaterial.m_CustomerMaterialCommands.push_back( + new SBindBuffer( + m_StringTable.GetRenderStringTable().RegisterStr( + output), needsClear)); + } + + // add shader to command stream + qt3ds::render::CRegisteredString theShaderName; + if (!IsTrivial(shader)) { + for (QT3DSU32 idx = 0, end = theMaterial.m_Shaders.size(); + idx < end && theShaderName.IsValid() == false; ++idx) { + qt3ds::render::CRegisteredString thePossibleNameStr = + m_StringTable.GetRenderStringTable().RegisterStr( + theMaterial.m_Shaders[idx].m_Name.c_str()); + if (AreEqual(thePossibleNameStr.c_str(), + theShaderNameStr.c_str())) + theShaderName = thePossibleNameStr; + } + } + if (theShaderName.IsValid() == false + && theMaterial.m_Shaders.empty() == false) + theShaderName = m_StringTable.GetRenderStringTable().RegisterStr( + theMaterial.m_Shaders[0].m_Name.c_str()); + if (theShaderName.IsValid()) { + theMaterial.m_CustomerMaterialCommands.push_back( + new SBindShader(theShaderName)); + // this is a place holder for our input values to the shader + theMaterial.m_CustomerMaterialCommands.push_back( + new SApplyInstanceValue()); + + for (bool bufParam = inStream.MoveToFirstChild(); bufParam; + bufParam = inStream.MoveToNextSibling()) { + if (AreEqual("BufferBlit", inStream.GetNarrowElementName())) { + const char8_t *value = ""; + const char8_t *dest = ""; + const char8_t *source = ""; + inStream.Att("dest", dest); + if (AreEqual("[dest]", dest)) + value = ""; + inStream.Att("source", source); + if (AreEqual("[source]", source)) + value = ""; + + theMaterial.m_CustomerMaterialCommands.push_back( + new SApplyBlitFramebuffer( + m_StringTable.GetRenderStringTable().RegisterStr( + source), + m_StringTable.GetRenderStringTable().RegisterStr( + dest))); + + // note need a better way to pass information from MDL to + // our input + // We use buffer blits to simulate glass refraction + theMaterial.m_HasRefraction = true; + } else if (AreEqual("BufferInput", + inStream.GetNarrowElementName())) { + const char8_t *param = ""; + const char8_t *value = ""; + inStream.Att("param", param); + inStream.Att("value", value); + if (AreEqual("[source]", value)) + value = ""; + theMaterial.m_CustomerMaterialCommands.push_back( + new SApplyBufferValue( + m_StringTable.GetRenderStringTable().RegisterStr( + value), + m_StringTable.GetRenderStringTable().RegisterStr( + param))); + HideEffectProperty(inInstance, param); + } else if (AreEqual("Blending", + inStream.GetNarrowElementName())) { + const char8_t *theSrcBlendFuncStr = "", + *theDestBlendFuncStr = ""; + inStream.Att("source", theSrcBlendFuncStr); + inStream.Att("dest", theDestBlendFuncStr); + + qt3ds::render::NVRenderSrcBlendFunc::Enum theSrcBlendFunc = + ConvertToSrcBlendFunc(theSrcBlendFuncStr); + qt3ds::render::NVRenderDstBlendFunc::Enum theDstBlendFuc = + ConvertToDstBlendFunc(theDestBlendFuncStr); + + // this will setup blending + theMaterial.m_CustomerMaterialCommands.push_back( + new SApplyBlending(theSrcBlendFunc, + theDstBlendFuc)); + // if we have blending we have transparency + theMaterial.m_HasTransparency = true; + } else if (AreEqual("RenderState", + inStream.GetNarrowElementName())) { + // UdoL Todo: add this one + } + } + } + // add the render command as last thing in the pass, it is a render + // pass. + theMaterial.m_CustomerMaterialCommands.push_back(new SRender(false)); + } + } else if (AreEqual("ShaderKey", inStream.GetNarrowElementName())) { + QT3DSU32 theValue = 0; + inStream.Att("value", theValue); + theMaterial.m_ShaderKey = theValue; + } else if (AreEqual("LayerKey", inStream.GetNarrowElementName())) { + QT3DSU32 theValue = 0; + inStream.Att("count", theValue); + theMaterial.m_LayerCount = theValue; + } else if (AreEqual("Buffer", inStream.GetNarrowElementName())) { + SAllocateBufferFlags theFlags; + const char8_t *theLifetimeStr = "", *theType = "", *theFormat = "", + *theFilter = "", *theWrap = "", *theName = ""; + QT3DSF32 theSize = 1.0f; + inStream.Att("name", theName); + inStream.Att("lifetime", theLifetimeStr); + inStream.Att("type", theType); + inStream.Att("format", theFormat); + inStream.Att("filter", theFilter); + inStream.Att("wrap", theWrap); + inStream.Att("size", theSize); + // Clamp the size to valid amounts + if (theSize <= 0) + theSize = 1.0f; + if (theSize > 1.0f) + theSize = 1.0f; + if (AreEqual(theLifetimeStr, "scene")) + theFlags.SetSceneLifetime(true); + qt3ds::render::NVRenderTextureFormats::Enum theTexFormat = + ConvertTypeAndFormatToTextureFormat(theType, theFormat); + qt3ds::render::NVRenderTextureMagnifyingOp::Enum theMagOp = + ConvertFilterToMagOp(theFilter); + qt3ds::render::NVRenderTextureCoordOp::Enum theCoordOp = + ConvertTextureCoordOp(theWrap); + if (*theName == 0) { + QT3DS_ASSERT(false); + // inFoundation.error( QT3DS_INVALID_PARAMETER, "Buffer is missing its + // name" ); + } else { + theMaterial.m_CustomerMaterialCommands.push_back( + new SAllocateBuffer( + m_StringTable.GetRenderStringTable().RegisterStr( + theName), theTexFormat, theMagOp, theCoordOp, + theSize, theFlags)); + } + } + } + } + + if (theMaterial.m_CustomerMaterialCommands.size() == 0) { + // add minimal set + // add shader to command stream + theMaterial.m_CustomerMaterialCommands.push_back( + new SBindShader(m_StringTable.GetRenderStringTable().RegisterStr( + theMaterial.m_Shaders[0].m_Name.c_str()))); + // this is a place holder for our input values to the shader + theMaterial.m_CustomerMaterialCommands.push_back(new SApplyInstanceValue()); + // add the render command as last thing + theMaterial.m_CustomerMaterialCommands.push_back(new SRender(false)); + } + } + } + + bool LoadMaterialClassFromSourcePath(const char *inSourcePath, + Qt3DSDMInstanceHandle inInstance, + const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings, + qt3ds::foundation::IInStream &inStream) override + { + std::shared_ptr<IDOMFactory> theFactory( + IDOMFactory::CreateDOMFactory(m_DataCore->GetStringTablePtr())); + qt3dsdm::SDOMElement *theElem = CDOMSerializer::Read(*theFactory, inStream, NULL); + if (theElem != NULL) { + std::shared_ptr<IDOMReader> theReader( + IDOMReader::CreateDOMReader(*theElem, m_DataCore->GetStringTablePtr(), + theFactory)); + LoadMaterialClassXML(*theReader, inInstance, inObjectName, outWarnings, + TCharStr(Intern(inSourcePath))); + return true; + } + return false; + } + + Option<SMetaDataCustomMaterial> GetMaterialBySourcePath(const char *inSourcePath) override + { + TCharStr theSourcePath(Intern(inSourcePath)); + for (TCustomMaterialMap::iterator iter = m_CustomMaterials.begin(), + end = m_CustomMaterials.end(); + iter != end; ++iter) { + if (iter->second.m_SourcePath == theSourcePath) + return iter->second.ToMaterial(); + } + return Empty(); + } + + //////////////////////////////////////////////////////////////////////////////////// + // Undo/Redo + void SetConsumer(TTransactionConsumerPtr inConsumer) override { m_Consumer = inConsumer; } + + //////////////////////////////////////////////////////////////////////////////////// + // Signals + virtual TSignalConnectionPtr + ConnectInternalCategoryDestroyed(function<void(Qt3DSDMCategoryHandle)> inCallback) + { + return CONNECT(&SNewMetaDataImpl::internalCategoryDestroyed); + } + virtual TSignalConnectionPtr + ConnectInternalPropertyDestroyed(function<void(Qt3DSDMMetaDataPropertyHandle)> inCallback) + { + return CONNECT(&SNewMetaDataImpl::internalMetaDataPropertyDestroyed); + } + virtual TSignalConnectionPtr + ConnectInternalEventDestroyed(function<void(Qt3DSDMEventHandle)> inCallback) + { + return CONNECT(&SNewMetaDataImpl::internalEventDestroyed); + } + virtual TSignalConnectionPtr + ConnectInternalHandlerDestroyed(function<void(Qt3DSDMHandlerHandle)> inCallback) + { + return CONNECT(&SNewMetaDataImpl::internalHandlerDestroyed); + } + virtual TSignalConnectionPtr + ConnectInternalHandlerArgDestroyed(function<void(Qt3DSDMHandlerHandle, QT3DSU32)> inCallback) + { + return CONNECT(&SNewMetaDataImpl::internalHandlerArgDestroyed); + } +}; +} + +std::shared_ptr<IMetaData> IMetaData::CreateNewMetaData(std::shared_ptr<IDataCore> inDataCore) +{ + return std::make_shared<SNewMetaDataImpl>(inDataCore); +} +#ifndef QT3DSDM_META_DATA_NO_SIGNALS +#include "Qt3DSDMMetaData.moc" +#endif diff --git a/src/dm/systems/Qt3DSDMMetaData.h b/src/dm/systems/Qt3DSDMMetaData.h new file mode 100644 index 0000000..67a7fb1 --- /dev/null +++ b/src/dm/systems/Qt3DSDMMetaData.h @@ -0,0 +1,400 @@ +/**************************************************************************** +** +** Copyright (C) 2008 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once + +#include "Qt3DSDMMetaDataTypes.h" +#include "foundation/Qt3DSOption.h" +#include <functional> +#include <memory> +#include "Qt3DSDMActionInfo.h" +#include "Qt3DSDMStringTable.h" +#include "Qt3DSDMValue.h" + +struct SShaderParameters; +namespace qt3ds { +namespace foundation { + class IInStream; +} +} + +namespace qt3dsdm { + +using qt3ds::foundation::Option; +using qt3ds::QT3DSU32; +using std::pair; +using std::vector; + +class ISignalConnection; +class ITransactionConsumer; +class IDOMWriter; +class IDOMReader; +class IDataCore; +class CDataCoreProducer; + +struct MetaDataLoadWarningType +{ + enum Enum { + Unknown = 0, + InvalidProperty, + InvalidEvent, + InvalidHandler, + }; +}; + +struct MetaDataLoadWarningMessage +{ + enum Enum { + Unknown = 0, + GeneralError, + MissingName, + InvalidDefault, + }; +}; + +struct SMetaDataLoadWarning +{ + MetaDataLoadWarningType::Enum m_Type; + MetaDataLoadWarningMessage::Enum m_Message; + TCharStr m_ExtraInfo; + + SMetaDataLoadWarning(MetaDataLoadWarningType::Enum inType, + MetaDataLoadWarningMessage::Enum inMessage, TCharStr inInfo = TCharStr()) + : m_Type(inType) + , m_Message(inMessage) + , m_ExtraInfo(inInfo) + { + } + SMetaDataLoadWarning() + : m_Type(MetaDataLoadWarningType::Unknown) + , m_Message(MetaDataLoadWarningMessage::Unknown) + { + } +}; + +/** + * Meta data class to hold meta data descriptions of the objects used in DataModel. + * A user-visible type in DataModel (things in the timeline) has a specific set of metadata, + * the type can have properties, events, handlers, and references. + * + * Properties are exactly what they sound like. Events are messages the object can send, + * and handlers are functions that are exported from the object. + * + * Events are hooked up to handlers using an ActionCore which takes tuples + * of instance, event, handler and slide and maintains a specific instance of an action. + * + * References allow us to track which properties are being accessed. Properties are stripped + * from the engine portion of the runtime (although they still appear in the scenegraph) + * if they aren't animated nor set in a given slide. + */ +class IMetaData +{ +protected: + virtual ~IMetaData() {} +public: + typedef const TCharStr &TStrType; + + //////////////////////////////////////////////////////////////////////////////////// + // Sharing some utility objects + virtual IStringTable &GetStringTable() = 0; + virtual TStringTablePtr GetStringTablePtr() = 0; + virtual std::shared_ptr<IDataCore> GetDataCore() = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // Canonical Instances + // Map an instance to a given type name. The type name is stored, along with the instance + // handle in the file if this object is *not* canonical. + // If this object is canonical, then we expect this mapping setup before loading the + // canonical data, and we will use a type lookup instead of a direct handle lookup + // when loading canonical information. + virtual void SetInstanceAsCanonical(Qt3DSDMInstanceHandle inInstance, TStrType inTypename) = 0; + + virtual Qt3DSDMInstanceHandle GetCanonicalInstanceForType(TStrType inTypename) = 0; + // If this instance wasn't registered as canonical, then we return empty. + virtual Option<TCharStr> GetTypeForCanonicalInstance(Qt3DSDMInstanceHandle inInstance) = 0; + // Gets the type for this instance via derivation + virtual Option<TCharStr> GetTypeForInstance(Qt3DSDMInstanceHandle inInstance) = 0; + // Get group count for instance + virtual QT3DSU32 GetGroupCountForInstance(Qt3DSDMInstanceHandle inInstance) = 0; + // Get all group names + virtual QT3DSU32 GetGroupNamesForInstance(Qt3DSDMInstanceHandle inInstance, + std::vector<TCharStr> &outNames) = 0; + // Get group count for instance + virtual Option<TCharStr> GetGroupFilterNameForInstance(Qt3DSDMInstanceHandle inInstance, + long inIndex) = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // Categories + // Categories appear in the UI to divide up large lists of events, actions, and properties. + // Returns <handle,true> if a category was created + // else returns <handle,false> + virtual pair<Qt3DSDMCategoryHandle, bool> GetOrCreateCategory(TStrType inName) = 0; + + virtual void SetCategoryInfo(Qt3DSDMCategoryHandle inCategory, TStrType inIcon, + TStrType inHighlight, TStrType inDescription) = 0; + virtual void DestroyCategory(Qt3DSDMCategoryHandle inCategory) = 0; + + virtual Option<SCategoryInfo> GetCategoryInfo(Qt3DSDMCategoryHandle inCategory) = 0; + virtual Qt3DSDMCategoryHandle FindCategoryByName(TStrType inName) = 0; + virtual void GetCategories(vector<Qt3DSDMCategoryHandle> &outCategories) = 0; + virtual Option<SCategoryInfo> GetEventCategory(TStrType inName) = 0; + virtual Option<SCategoryInfo> GetHandlerCategory(TStrType inName) = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // Properties + // Will create the property on the instance associated with this type name if it doesn't exist. + // Metadata properties can be redifined for child instances and this re-definition will override + // the parent definition. We currently use this to give different formal names and description + // to the sourcepath property (for models it is mesh, for materials it is image). + virtual Qt3DSDMMetaDataPropertyHandle + CreateMetaDataProperty(Qt3DSDMInstanceHandle inInstance) = 0; + + // For properties, you set the default values separately + // This may delete the underlying data model property rebuild it. + virtual void SetMetaDataPropertyInfo(Qt3DSDMMetaDataPropertyHandle inPropertyHandle, + TStrType inName, TStrType inFormalName, + TStrType inDescription, TStrType inUsage, + CompleteMetaDataType::Enum inDataType, + const SValue &inDefaultValue, + const TMetaDataData &inMetaData, TStrType inGroupName, + bool inIsHidden = false, bool inIsAnimatable = false, + bool inIsControllable = false) = 0; + + // Destroy just this meta data property + // Does not destroy the underlying data core property, so this function isn't a perfect + // reverse of the above system. This *just* destroyed the meta data pointed to by + // this property. + virtual void DestroyMetaDataProperty(Qt3DSDMMetaDataPropertyHandle inProperty) = 0; + + virtual Qt3DSDMMetaDataPropertyHandle GetMetaDataProperty(Qt3DSDMInstanceHandle inInstance, + TStrType inPropertyName) = 0; + virtual Qt3DSDMMetaDataPropertyHandle GetMetaDataProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual Option<SMetaDataPropertyInfo> + GetMetaDataPropertyInfo(Qt3DSDMMetaDataPropertyHandle inProperty) = 0; + // Get all of the meta data properties defined on this object or its derivation parents + virtual void GetMetaDataProperties(Qt3DSDMInstanceHandle inInstance, + vector<Qt3DSDMMetaDataPropertyHandle> &outProperties) = 0; + + // Get the meta data properties defined on *only* this object, don't search parents + virtual Qt3DSDMMetaDataPropertyHandle + GetOrCreateSpecificMetaDataProperty(Qt3DSDMInstanceHandle inInstance, + TStrType inPropertyName) = 0; + virtual void + GetSpecificMetaDataProperties(Qt3DSDMInstanceHandle inInstance, + vector<Qt3DSDMMetaDataPropertyHandle> &outProperties) = 0; + + virtual TCharStr GetFormalName(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual AdditionalMetaDataType::Value GetAdditionalMetaDataType(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual TMetaDataData GetAdditionalMetaDataData(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual bool IsCustomProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual SValue GetDefaultValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + + virtual void + SetMetaDataPropertyFilters(Qt3DSDMMetaDataPropertyHandle inProperty, + qt3ds::foundation::NVConstDataRef<SPropertyFilterInfo> inFilters) = 0; + virtual qt3ds::foundation::NVConstDataRef<SPropertyFilterInfo> + GetMetaDataPropertyFilters(Qt3DSDMMetaDataPropertyHandle inProperty) = 0; + virtual void RemoveMetaDataPropertyFilters(Qt3DSDMMetaDataPropertyHandle inProperty) = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // Events + // CreateMetaDataEvent was original named CreateEvent but this collides with + // the microsoft macro CreateEvent which expands to CreateEventA or CreateEventW + virtual Qt3DSDMEventHandle CreateMetaDataEvent(Qt3DSDMInstanceHandle inInstance) = 0; + virtual void SetEventInfo(Qt3DSDMEventHandle inEventHandle, TStrType inName, + TStrType inFormalName, TStrType inCategory, + TStrType inDescription) = 0; + + virtual void DestroyEvent(Qt3DSDMEventHandle inEventHandle) = 0; + + virtual void GetEvents(Qt3DSDMInstanceHandle inInstance, TEventHandleList &outEvents) = 0; + virtual Qt3DSDMEventHandle FindEvent(Qt3DSDMInstanceHandle inInstance, TStrType inName) = 0; + virtual Option<SEventInfo> GetEventInfo(Qt3DSDMEventHandle inEventHandle) = 0; + virtual bool IsCustomEvent(Qt3DSDMEventHandle inEventHandle) = 0; + + // Get/Find an event that occurs on just this instance, don't search parent instances + virtual void GetSpecificEvents(Qt3DSDMInstanceHandle inInstance, + TEventHandleList &outEvents) = 0; + virtual Qt3DSDMEventHandle GetOrCreateSpecificEvent(Qt3DSDMInstanceHandle inInstance, + TStrType inName) = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // Handlers + virtual Qt3DSDMHandlerHandle CreateHandler(Qt3DSDMInstanceHandle inInstance) = 0; + virtual void SetHandlerInfo(Qt3DSDMHandlerHandle inHandle, TStrType inName, + TStrType inFormalName, TStrType inCategory, + TStrType inDescription) = 0; + virtual void DestroyHandler(Qt3DSDMHandlerHandle inHandlerHandle) = 0; + + virtual Qt3DSDMHandlerHandle FindHandlerByName(Qt3DSDMInstanceHandle inInstance, + TStrType inName) = 0; + virtual Option<SHandlerInfo> GetHandlerInfo(Qt3DSDMHandlerHandle inHandlerHandle) = 0; + virtual void GetHandlers(Qt3DSDMInstanceHandle inInstance, THandlerHandleList &outHandlers) = 0; + virtual bool IsCustomHandler(Qt3DSDMHandlerHandle inEventHandle) = 0; + + virtual void GetSpecificHandlers(Qt3DSDMInstanceHandle inInstance, + THandlerHandleList &outHandlers) = 0; + virtual Qt3DSDMHandlerHandle GetOrCreateSpecificHandler(Qt3DSDMInstanceHandle inInstance, + TStrType inName) = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // Handler Arguments + virtual QT3DSU32 AddHandlerArgument(Qt3DSDMHandlerHandle inHandler) = 0; + virtual void + SetHandlerArgumentInfo(Qt3DSDMHandlerHandle inHandler, QT3DSU32 inArgIndex, TStrType inName, + TStrType inFormalName, TStrType inDescription, + CompleteMetaDataType::Enum inDataType, const SValue &inDefaultValue, + const TMetaDataData &inMetaData, HandlerArgumentType::Value inArgType) = 0; + + virtual void DestroyHandlerArgument(Qt3DSDMHandlerHandle inHandler, QT3DSU32 inArgIndex) = 0; + + virtual Option<SMetaDataHandlerArgumentInfo> + FindHandlerArgumentByName(Qt3DSDMHandlerHandle inHandler, TStrType inName) = 0; + virtual void GetHandlerArguments(Qt3DSDMHandlerHandle inHandler, + vector<SMetaDataHandlerArgumentInfo> &outArguments) = 0; + virtual Option<SMetaDataHandlerArgumentInfo> + GetHandlerArgumentInfo(Qt3DSDMHandlerHandle inHandle, QT3DSU32 inIndex) = 0; + virtual QT3DSU32 GetNumHandlerArguments(Qt3DSDMHandlerHandle inHandler) = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // References + // Duplicate references are removed from this instance + virtual void AddReference(Qt3DSDMInstanceHandle inInstance, TStrType inRefString) = 0; + virtual void DestroyReferences(Qt3DSDMInstanceHandle inInstance) = 0; + + // Does the recursive gather from all the parents. Duplicate references are removed from the + // final list. + virtual void GetReferences(Qt3DSDMInstanceHandle inInstance, + std::vector<TCharStr> &outReferences) = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // Instance-global functions + // Destroy all meta data that relates to this instance. + // Calling this on a derived instance does nothing, this only works if this specific + // instance was mapped directly to meta data. + virtual void DestroyMetaData(Qt3DSDMInstanceHandle inInstance) = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // Serialization + // You can either save out in canonical format (and it will only save canonical-instance-related + // information *or* you can save out in normal format where we link directly to instance handle + // instead of to typename + virtual void Save(IDOMWriter &inWriter) = 0; + // Loading expects the canonical instances to be setup already which means that + // it will perform lookups based on + // One huge assumption is that the reader is using the same string table + // that this object was built with + // InIsCanonical tells us whether to mark loaded categories as canonical + // or not. + virtual void Load(IDOMReader &ioStream) = 0; + + // Load meta data and apply it to just this instance + virtual void LoadInstance(IDOMReader &inReader, Qt3DSDMInstanceHandle inInstance, + const TCharStr &inName, + std::vector<SMetaDataLoadWarning> &outWarnings) = 0; + + // Save just this instances meta data out to the writer + virtual void SaveInstance(IDOMWriter &inWriter, Qt3DSDMInstanceHandle inInstance) = 0; + + // Load effect meta data from file and apply it to just this instance + virtual void LoadEffectInstance(const char *inShaderFile, Qt3DSDMInstanceHandle inInstance, + const TCharStr &inName, + std::vector<SMetaDataLoadWarning> &outWarnings, + qt3ds::foundation::IInStream &inStream) = 0; + + virtual bool IsEffectInstanceRegistered(const char *inName) = 0; + virtual void LoadEffectXML(IDOMReader &inStream, Qt3DSDMInstanceHandle inInstance, + const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings, + const TCharStr &inSourcePath) = 0; + virtual bool LoadEffectXMLFromSourcePath(const char *inSourcePath, + Qt3DSDMInstanceHandle inInstance, + const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings, + qt3ds::foundation::IInStream &inStream) = 0; + virtual Option<SMetaDataEffect> GetEffectBySourcePath(const char *inName) = 0; + + virtual void LoadMaterialInstance(const char *inShaderFile, + Qt3DSDMInstanceHandle inInstance, + const TCharStr &inName, + std::vector<SMetaDataLoadWarning> &outWarnings, + qt3ds::foundation::IInStream &inStream) = 0; + virtual bool IsMaterialClassRegistered(const char *inName) = 0; + virtual void LoadMaterialClassXML(IDOMReader &inStream, Qt3DSDMInstanceHandle inInstance, + const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings, + const TCharStr &inSourcePath) = 0; + virtual bool LoadMaterialClassFromSourcePath(const char *inSourcePath, + Qt3DSDMInstanceHandle inInstance, + const TCharStr &inObjectName, + std::vector<SMetaDataLoadWarning> &outWarnings, + qt3ds::foundation::IInStream &inStream) = 0; + virtual Option<SMetaDataCustomMaterial> GetMaterialBySourcePath(const char *inSourcePath) = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // Undo/Redo + virtual void SetConsumer(std::shared_ptr<ITransactionConsumer> inConsumer) = 0; + +#ifndef QT3DSDM_META_DATA_NO_SIGNALS + //////////////////////////////////////////////////////////////////////////////////// + // Signals + // These events are sent out only once, they aren't set into the transaction consumer + // to be sent out upon undo and redo. These events are meant for chaining together side effects + // so other systems don't have references to invalid handler arguments and handles. + // Also, the objects in these messages are still valid so you can query information about them + // at this time. They will be destroyed subsequent to the event. + virtual std::shared_ptr<ISignalConnection> + ConnectInternalCategoryDestroyed(std::function<void(Qt3DSDMCategoryHandle)> inCallback) = 0; + virtual std::shared_ptr<ISignalConnection> ConnectInternalPropertyDestroyed( + std::function<void(Qt3DSDMMetaDataPropertyHandle)> inCallback) = 0; + virtual std::shared_ptr<ISignalConnection> + ConnectInternalEventDestroyed(std::function<void(Qt3DSDMEventHandle)> inCallback) = 0; + virtual std::shared_ptr<ISignalConnection> + ConnectInternalHandlerDestroyed(std::function<void(Qt3DSDMHandlerHandle)> inCallback) = 0; + virtual std::shared_ptr<ISignalConnection> ConnectInternalHandlerArgDestroyed( + std::function<void(Qt3DSDMHandlerHandle, QT3DSU32)> inCallback) = 0; +#endif + + //////////////////////////////////////////////////////////////////////////////////// + // Creation/Lifetime Management + friend class std::shared_ptr<IMetaData>; + // The data core is used to create the properties if they don't exist or + // query their underlying type if they do exist. We also subscribe to + // the datacore's beforeInstanceDelete function in order to ensure + // that we delete our existing meta data for instances that are being deleted. + static std::shared_ptr<IMetaData> CreateNewMetaData(std::shared_ptr<IDataCore> inDataCore); +}; + +typedef std::shared_ptr<IMetaData> TNewMetaDataPtr; +} diff --git a/src/dm/systems/Qt3DSDMMetaDataTypes.h b/src/dm/systems/Qt3DSDMMetaDataTypes.h new file mode 100644 index 0000000..5532e0a --- /dev/null +++ b/src/dm/systems/Qt3DSDMMetaDataTypes.h @@ -0,0 +1,350 @@ +/**************************************************************************** +** +** Copyright (C) 2008 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#include "Qt3DSDMMetaDataValue.h" + +namespace qt3ds { +namespace render { + namespace dynamic { + struct SCommand; + struct SPropertyDeclaration; + struct SPropertyDefinition; + } +} +} + +namespace qt3dsdm { + +struct HandlerArgumentType { + + enum Value { + None, + Property, // Property reference. Load the Properties of the Target Object. + Dependent, // Property type depends on another property. + Slide, // Slide reference. Load the list of slides of the Target Object if + // applicable. + Event, // Event reference. Load the applicable Events of the Target Object. + Object, // Object reference. Used for dynamic actions with object referenced + // property. + Signal, // Signal reference. Used for emiting signals fired from the trigger + // object. + }; + + Q_ENUM(Value) + Q_GADGET +}; + +struct CompleteMetaDataType +{ + enum Enum { + Unknown = 0, + StringList, + FloatRange, + LongRange, + Float, + Long, + Float2, + Vector, + Scale, + Rotation, + Color, + Boolean, + Slide, + Font, + FontSize, + String, + MultiLineString, + ObjectRef, + Image, + Mesh, + Import, + Texture, + Guid, + StringListOrInt, + Renderable, + Image2D, + Buffer, + PathBuffer, + ShadowMapResolution, + }; + + // Functions defined in UICDMMetaData.cpp + static DataModelDataType::Value ToDataType(Enum inCompleteType); + static AdditionalMetaDataType::Value ToAdditionalType(Enum inCompleteType); + static CompleteMetaDataType::Enum ToCompleteType(DataModelDataType::Value inDataType, + AdditionalMetaDataType::Value inAdditionalType); + Q_ENUM(Enum) + Q_GADGET +}; + +typedef std::pair<DataModelDataType::Value, AdditionalMetaDataType::Value> TDataTypePair; + +inline bool Equals(const TMetaDataData &lhs, const TMetaDataData &rhs) +{ + return rhs == lhs; +} + +inline AdditionalMetaDataType::Value GetMetaDataValueType(const TMetaDataData &inValue) +{ + return inValue.getType(); +} + +// Base class shared between property info +// and handler arguments. +struct SMetaPropertyBase +{ + TCharStr m_Name; + TCharStr m_FormalName; + TCharStr m_Usage; + TCharStr m_Description; + CompleteMetaDataType::Enum m_CompleteType; + TMetaDataData m_MetaDataData; + SValue m_DefaultValue; + + SMetaPropertyBase() + : m_CompleteType(CompleteMetaDataType::Float) + { + } + bool operator==(const SMetaPropertyBase &inOther) const + { + return m_Name == inOther.m_Name && m_FormalName == inOther.m_FormalName + && m_Usage == inOther.m_Usage && m_Description == inOther.m_Description + && m_CompleteType == inOther.m_CompleteType + && Equals(m_DefaultValue.toOldSkool(), inOther.m_DefaultValue.toOldSkool()) + && Equals(m_MetaDataData, inOther.m_MetaDataData); + } + DataModelDataType::Value GetDataType() const + { + return CompleteMetaDataType::ToDataType(m_CompleteType); + } + AdditionalMetaDataType::Value GetAdditionalType() const + { + return CompleteMetaDataType::ToAdditionalType(m_CompleteType); + } +}; + +struct SMetaDataPropertyInfo : SMetaPropertyBase +{ + Qt3DSDMInstanceHandle m_Instance; + Qt3DSDMPropertyHandle m_Property; + bool m_Controllable = false; // Can this property be controlled via data input (default no) + bool m_IsHidden = false; // Is this property hidden in the inspector (default no) + bool m_Animatable = true; // Is this property animatable (default yes) + // Note: all animatables are controllable + + TCharStr m_GroupName; // Name of the group this property belongs to or "default" + + SMetaDataPropertyInfo(Qt3DSDMInstanceHandle inInstance) + : m_Instance(inInstance) + { + } + SMetaDataPropertyInfo() {} + + bool operator==(const SMetaDataPropertyInfo &inOther) const + { + return m_Instance == inOther.m_Instance && m_Property == inOther.m_Property + && m_IsHidden == inOther.m_IsHidden && m_Animatable == inOther.m_Animatable + && m_GroupName == inOther.m_GroupName + && m_Controllable == inOther.m_Controllable + && SMetaPropertyBase::operator==(inOther); + } + + bool operator!=(const SMetaDataPropertyInfo &inOther) const { return !(*this == inOther); } +}; + +struct SMetaDataHandlerArgumentInfo : SMetaPropertyBase +{ + Qt3DSDMHandlerHandle m_Handler; + HandlerArgumentType::Value m_ArgType; + SMetaDataHandlerArgumentInfo(Qt3DSDMHandlerHandle inHandler = Qt3DSDMHandlerHandle()) + : m_Handler(inHandler) + , m_ArgType(HandlerArgumentType::None) + { + } +}; + +struct SCategoryInfo +{ + TCharStr m_Name; + TCharStr m_Description; + TCharStr m_Icon; + TCharStr m_HighlightIcon; + bool m_Canonical; + + SCategoryInfo() + : m_Canonical(false) + { + } + SCategoryInfo(TCharStr inName) + : m_Name(inName) + , m_Canonical(false) + { + } +}; + +struct SEventInfo +{ + bool operator!=(const SEventInfo &inEvent) const + { + return (m_Name != inEvent.m_Name || m_FormalName != inEvent.m_FormalName + || m_Category != inEvent.m_Category || m_Description != inEvent.m_Description); + } + + TCharStr m_Name; + TCharStr m_FormalName; + TCharStr m_Category; + TCharStr m_Description; +}; + +struct SHandlerInfo +{ + TCharStr m_Name; + TCharStr m_FormalName; + TCharStr m_Category; + TCharStr m_Description; + + bool operator!=(const SHandlerInfo &inHandler) const + { + return (m_Name != inHandler.m_Name || m_FormalName != inHandler.m_FormalName + || m_Category != inHandler.m_Category || m_Description != inHandler.m_Description); + } +}; + +struct PropertyFilterTypes +{ + enum Enum { + Unknown, + ShowIfEqual, + HideIfEqual, + }; +}; + +struct SPropertyFilterInfo +{ + PropertyFilterTypes::Enum m_FilterType; + Qt3DSDMPropertyHandle m_FilterProperty; + SValue m_Value; + SPropertyFilterInfo() + : m_FilterType(PropertyFilterTypes::Unknown) + { + } + SPropertyFilterInfo(PropertyFilterTypes::Enum inFilterType, Qt3DSDMPropertyHandle inProp, + const SValue &inValue) + : m_FilterType(inFilterType) + , m_FilterProperty(inProp) + , m_Value(inValue) + { + } +}; +struct SMetaDataShader +{ + TCharStr m_Name; + TCharStr m_Type; ///< shader type (GLSL or HLSL) + TCharStr m_Version; ///< shader version (e.g. 330 vor GLSL) + // Code contains both the vertex and fragment portions separated by #define's. + //#define VERTEX_SHADER, #define FRAGMENT_SHADER + TCharStr m_Code; + bool m_HasGeomShader; + bool m_IsComputeShader; + SMetaDataShader() + : m_HasGeomShader(false) + , m_IsComputeShader(false) + { + } + SMetaDataShader(const TCharStr &inName, const TCharStr &inType, const TCharStr &inVersion, + const TCharStr &inCode, bool hasGeom, bool isCompute) + : m_Name(inName) + , m_Type(inType) + , m_Version(inVersion) + , m_Code(inCode) + , m_HasGeomShader(hasGeom) + , m_IsComputeShader(isCompute) + { + } +}; + +struct SMetaDataDynamicObject +{ + TCharStr m_Name; + qt3ds::foundation::NVConstDataRef<SMetaDataShader> m_Shaders; + qt3ds::foundation::NVConstDataRef<qt3ds::render::dynamic::SPropertyDefinition> m_Properties; + SMetaDataDynamicObject() {} + SMetaDataDynamicObject( + const TCharStr &inName, qt3ds::foundation::NVConstDataRef<SMetaDataShader> inShaders, + qt3ds::foundation::NVConstDataRef<qt3ds::render::dynamic::SPropertyDefinition> inProperties) + : m_Name(inName) + , m_Shaders(inShaders) + , m_Properties(inProperties) + { + } +}; + +struct SMetaDataEffect : public SMetaDataDynamicObject +{ + qt3ds::foundation::NVConstDataRef<qt3ds::render::dynamic::SCommand *> m_EffectCommands; + SMetaDataEffect() {} + SMetaDataEffect( + const TCharStr &inName, qt3ds::foundation::NVConstDataRef<SMetaDataShader> inShaders, + qt3ds::foundation::NVConstDataRef<qt3ds::render::dynamic::SPropertyDefinition> inProperties, + qt3ds::foundation::NVConstDataRef<qt3ds::render::dynamic::SCommand *> inEffectCommands) + : SMetaDataDynamicObject(inName, inShaders, inProperties) + , m_EffectCommands(inEffectCommands) + { + } +}; + +struct SMetaDataCustomMaterial : public SMetaDataDynamicObject +{ + qt3ds::foundation::NVConstDataRef<qt3ds::render::dynamic::SCommand *> m_CustomMaterialCommands; + bool m_HasTransparency; + bool m_HasRefraction; + bool m_AlwaysDirty; + unsigned int m_ShaderKey; + unsigned int m_LayerCount; + SMetaDataCustomMaterial() {} + SMetaDataCustomMaterial( + const TCharStr &inName, qt3ds::foundation::NVConstDataRef<SMetaDataShader> inShaders, + qt3ds::foundation::NVConstDataRef<qt3ds::render::dynamic::SPropertyDefinition> inProperties, + qt3ds::foundation::NVConstDataRef<qt3ds::render::dynamic::SCommand *> inCustomMaterialCommands, + bool inHasTransparency, bool inHasRefraction, bool inIsAlwaysDirty, + unsigned int inShaderKey, unsigned int inLayerCount) + : SMetaDataDynamicObject(inName, inShaders, inProperties) + , m_CustomMaterialCommands(inCustomMaterialCommands) + , m_HasTransparency(inHasTransparency) + , m_HasRefraction(inHasRefraction) + , m_AlwaysDirty(inIsAlwaysDirty) + , m_ShaderKey(inShaderKey) + , m_LayerCount(inLayerCount) + { + } +}; +} + +Q_DECLARE_METATYPE(qt3dsdm::HandlerArgumentType::Value) + diff --git a/src/dm/systems/Qt3DSDMMetaDataValue.h b/src/dm/systems/Qt3DSDMMetaDataValue.h new file mode 100644 index 0000000..b981b95 --- /dev/null +++ b/src/dm/systems/Qt3DSDMMetaDataValue.h @@ -0,0 +1,251 @@ +/**************************************************************************** +** +** Copyright (C) 2008 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#include <EASTL/string.h> +#include <EASTL/vector.h> +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMDataTypes.h" +#include "foundation/Qt3DSDataRef.h" +#include "Qt3DSDMValue.h" + +#include <QStringList> + +namespace qt3dsdm { + +struct AdditionalMetaDataType { + + enum Value { + None, + StringList, + Range, + Image, + Color, + Rotation, + Font, + FontSize, + MultiLine, + ObjectRef, + Mesh, + Import, + Texture, + Renderable, + PathBuffer, + ShadowMapResolution, + String, + }; + + + Q_ENUM(Value) + Q_GADGET +}; + +// List type metadata +typedef eastl::vector<TCharStr> TMetaDataStringList; + +// Float type metadata +struct SMetaDataRange +{ + SMetaDataRange() {} + + SMetaDataRange(float min, float max, int decimals = -1) + : m_min(min) + , m_max(max) + , m_decimals(decimals) + { + } + + bool operator==(const SMetaDataRange &other) const + { + // no need to check m_decimals for quality as it is not significant to the range value + return m_min == other.m_min && m_max == other.m_max; + } + + float m_min = 0.0f; + float m_max = 0.0f; + int m_decimals = -1; // num decimals to show, -1: dynamically calculated +}; +} + +namespace qt3ds { +namespace foundation { + + template <> + struct DestructTraits<qt3dsdm::SMetaDataRange> + { + void destruct(qt3dsdm::SMetaDataRange &) {} + }; +} +} + +namespace qt3dsdm { + +template <typename TDataType> +struct SMetaDataTypeToEnumMap +{ +}; +template <> +struct SMetaDataTypeToEnumMap<eastl::vector<TCharStr>> +{ + static AdditionalMetaDataType::Value getType() { return AdditionalMetaDataType::StringList; } +}; +template <> +struct SMetaDataTypeToEnumMap<SMetaDataRange> +{ + static AdditionalMetaDataType::Value getType() { return AdditionalMetaDataType::Range; } +}; + +struct SMetaDataValueTraits +{ + typedef AdditionalMetaDataType::Value TIdType; + + enum { + TBufferSize = sizeof(TMetaDataStringList), + }; + + static TIdType getNoDataId() { return AdditionalMetaDataType::None; } + + template <typename TDataType> + static TIdType getType() + { + return SMetaDataTypeToEnumMap<TDataType>::getType(); + } + + template <typename TRetType, typename TVisitorType> + static TRetType visit(char *inData, AdditionalMetaDataType::Value inType, TVisitorType inVisitor) + { + switch (inType) { + case AdditionalMetaDataType::StringList: + return inVisitor(*reinterpret_cast<TMetaDataStringList *>(inData)); + case AdditionalMetaDataType::Range: + return inVisitor(*reinterpret_cast<SMetaDataRange *>(inData)); + default: + QT3DS_ASSERT(false); + case AdditionalMetaDataType::None: + return inVisitor(); + } + } + + template <typename TRetType, typename TVisitorType> + static TRetType visit(const char *inData, AdditionalMetaDataType::Value inType, + TVisitorType inVisitor) + { + switch (inType) { + case AdditionalMetaDataType::StringList: + return inVisitor(*reinterpret_cast<const TMetaDataStringList *>(inData)); + case AdditionalMetaDataType::Range: + return inVisitor(*reinterpret_cast<const SMetaDataRange *>(inData)); + default: + QT3DS_ASSERT(false); + case AdditionalMetaDataType::None: + return inVisitor(); + } + } +}; + +struct SMetaDataData + : public qt3ds::foundation:: + DiscriminatedUnion<qt3ds::foundation:: + DiscriminatedUnionGenericBase<SMetaDataValueTraits, + Qt3DSDMDataTypeUnionTraits:: + TBufferSize>, + SMetaDataValueTraits::TBufferSize> +{ + typedef qt3ds::foundation:: + DiscriminatedUnion<qt3ds::foundation::DiscriminatedUnionGenericBase<SMetaDataValueTraits, + Qt3DSDMDataTypeUnionTraits:: + TBufferSize>, + SMetaDataValueTraits::TBufferSize> + TBase; + SMetaDataData() {} + SMetaDataData(const SMetaDataData &inOther) + : TBase(static_cast<const TBase &>(inOther)) + { + } + SMetaDataData &operator=(const SMetaDataData &inOther) + { + TBase::operator=(static_cast<const TBase &>(inOther)); + return *this; + } + SMetaDataData(const TMetaDataStringList &inData) + : TBase(inData) + { + } + SMetaDataData(const SMetaDataRange &inData) + : TBase(inData) + { + } + SMetaDataData &operator=(const TMetaDataStringList &inData) + { + TBase::operator=(inData); + return *this; + } + SMetaDataData &operator=(const SMetaDataRange &inData) + { + TBase::operator=(inData); + return *this; + } + bool empty() const { return getType() == AdditionalMetaDataType::None; } +}; + +template <> +struct Qt3DSDMGetter<SMetaDataData> +{ + template <typename TRetType> + TRetType doGet(const SMetaDataData &inValue) + { + return inValue.getData<TRetType>(); + } +}; + +template <> +struct Qt3DSDMValueTyper<SMetaDataData> +{ + AdditionalMetaDataType::Value Get(const SMetaDataData &inValue) { return inValue.getType(); } +}; + +typedef SMetaDataData TMetaDataData; + + +template <> +inline QStringList get<QStringList>(const qt3dsdm::SMetaDataData &inType) +{ + QStringList result; + if (inType.getType() == qt3dsdm::AdditionalMetaDataType::None) + return result; + + auto list = qt3dsdm::get<qt3dsdm::TMetaDataStringList>(inType); + std::transform(list.begin(), list.end(), std::back_inserter(result), [](const Qt3DSDMStr &s) { + return QString::fromWCharArray(s.wide_str()); + }); + return result; +} +} + +Q_DECLARE_METATYPE(qt3dsdm::AdditionalMetaDataType) + diff --git a/src/dm/systems/Qt3DSDMPropertyDefinition.h b/src/dm/systems/Qt3DSDMPropertyDefinition.h new file mode 100644 index 0000000..d324b53 --- /dev/null +++ b/src/dm/systems/Qt3DSDMPropertyDefinition.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_PROPERTY_DEFINITION_H +#define QT3DSDM_PROPERTY_DEFINITION_H + +#include "Qt3DSDMDataTypes.h" + +namespace qt3dsdm { + +struct Qt3DSDMPropertyDefinition +{ + TCharStr m_Name; + Qt3DSDMInstanceHandle m_Instance; + DataModelDataType::Value m_Type; + + Qt3DSDMPropertyDefinition() + : m_Type(DataModelDataType::None) + { + } + Qt3DSDMPropertyDefinition(Qt3DSDMInstanceHandle inInstanceHandle, TCharPtr inName, + DataModelDataType::Value inType) + : m_Name(inName) + , m_Instance(inInstanceHandle) + , m_Type(inType) + { + } + Qt3DSDMPropertyDefinition(const Qt3DSDMPropertyDefinition &inOther) + : m_Name(inOther.m_Name) + , m_Instance(inOther.m_Instance) + , m_Type(inOther.m_Type) + { + } + + Qt3DSDMPropertyDefinition &operator=(const Qt3DSDMPropertyDefinition &inOther) + { + if (this != &inOther) { + m_Name = inOther.m_Name; + m_Instance = inOther.m_Instance; + m_Type = inOther.m_Type; + } + return *this; + } +}; + +typedef std::vector<Qt3DSDMPropertyDefinition> TPropertyDefinitionList; +} + +#endif diff --git a/src/dm/systems/Qt3DSDMSignalStructImpl.h b/src/dm/systems/Qt3DSDMSignalStructImpl.h new file mode 100644 index 0000000..9664566 --- /dev/null +++ b/src/dm/systems/Qt3DSDMSignalStructImpl.h @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_SIGNAL_STRUCT_IMPL_H +#define QT3DSDM_SIGNAL_STRUCT_IMPL_H +#include "Qt3DSDMSignalStructs.h" + +namespace qt3dsdm { + +struct SSignalDataStruct0 +{ + typedef SSignalDataStruct0 TThisType; + typedef std::function<void()> TFunType; + static void Send(ISignalSystem &system, void *sender, const char *sigName) + { + system.Signal(sender, sigName, NULL, 0); + } + + static void Unpack(void *inSender, const char *inName, const char *inData, size_t inDataSize, + TFunType inHandler) + { + if (inDataSize == 0) + inHandler(); + else { + QT3DS_ASSERT(false); + } + } + + static TGenericSignalHandlerFunc CreateHandler(std::function<void()> inHandler) + { + return std::bind(&TThisType::Unpack, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4, inHandler); + } + + static std::shared_ptr<ISignalConnection> AddListener(ISignalSystem &inSystem, void *inSender, + const char *inName, TFunType inHandler) + { + return inSystem.AddListener(inSender, inName, CreateHandler(inHandler)); + } +}; + +#define QT3DSDM_SIGNALS_DEFINE_SPECIFIC_SIGNAL_STRUCT0(name) \ + std::shared_ptr<ISignalConnection> Sig##name::AddListener( \ + ISignalSystem &inSystem, void *inSender, std::function<void()> inHandler) \ + { \ + typedef SSignalDataStruct0 TBase; \ + return TBase::AddListener(inSystem, inSender, #name, inHandler); \ + } \ + void Sig##name::Send(ISignalSystem &system, void *sender) \ + { \ + typedef SSignalDataStruct0 TBase; \ + TBase::Send(system, sender, #name); \ + } + +template <typename TData1> +struct SSignalDataStruct1 +{ + typedef SSignalDataStruct1<TData1> TThisType; + TData1 m_Data1; + typedef std::function<void(TData1)> TFunType; + SSignalDataStruct1(TData1 d1) + : m_Data1(d1) + { + } + static void Send(ISignalSystem &system, void *sender, const char *sigName, const TData1 &d1) + { + TThisType theData(d1); + system.Signal(sender, sigName, reinterpret_cast<const char *>(&theData), sizeof(TThisType)); + } + + static void Unpack(void *inSender, const char *inName, const char *inData, size_t inDataSize, + TFunType inHandler) + { + if (inDataSize == sizeof(TThisType)) { + const TThisType *theData = reinterpret_cast<const TThisType *>(inData); + inHandler(theData->m_Data1); + } else { + QT3DS_ASSERT(false); + } + } + + static TGenericSignalHandlerFunc CreateHandler(TFunType inHandler) + { + return std::bind(&TThisType::Unpack, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4, inHandler); + } + + static std::shared_ptr<ISignalConnection> AddListener(ISignalSystem &inSystem, void *inSender, + const char *inName, TFunType inHandler) + { + return inSystem.AddListener(inSender, inName, CreateHandler(inHandler)); + } +}; + +#define QT3DSDM_SIGNALS_DEFINE_SPECIFIC_SIGNAL_STRUCT1(name, d1) \ + std::shared_ptr<ISignalConnection> Sig##name::AddListener( \ + ISignalSystem &inSystem, void *inSender, std::function<void(d1)> inHandler) \ + { \ + typedef SSignalDataStruct1<d1> TBase; \ + return TBase::AddListener(inSystem, inSender, #name, inHandler); \ + } \ + void Sig##name::Send(ISignalSystem &system, void *sender, const d1 &arg) \ + { \ + typedef SSignalDataStruct1<d1> TBase; \ + TBase::Send(system, sender, #name, arg); \ + } + +template <typename TData1, typename TData2> +struct SSignalDataStruct2 +{ + typedef SSignalDataStruct2<TData1, TData2> TThisType; + typedef std::function<void(TData1, TData2)> TFunType; + TData1 m_Data1; + TData2 m_Data2; + SSignalDataStruct2(TData1 d1, TData2 d2) + : m_Data1(d1) + , m_Data2(d2) + { + } + static void Send(ISignalSystem &system, void *sender, const char *sigName, const TData1 &d1, + const TData2 &d2) + { + TThisType theData(d1, d2); + system.Signal(sender, sigName, reinterpret_cast<const char *>(&theData), sizeof(TThisType)); + } + + static void Unpack(void *inSender, const char *inName, const char *inData, size_t inDataSize, + TFunType inHandler) + { + if (inDataSize == sizeof(TThisType)) { + const TThisType *theData = reinterpret_cast<const TThisType *>(inData); + inHandler(theData->m_Data1, theData->m_Data2); + } else { + QT3DS_ASSERT(false); + } + } + + static TGenericSignalHandlerFunc CreateHandler(TFunType inHandler) + { + return std::bind(&TThisType::Unpack, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4, inHandler); + } + + static std::shared_ptr<ISignalConnection> AddListener(ISignalSystem &inSystem, void *inSender, + const char *inName, TFunType inHandler) + { + return inSystem.AddListener(inSender, inName, CreateHandler(inHandler)); + } +}; + +#define QT3DSDM_SIGNALS_DEFINE_SPECIFIC_SIGNAL_STRUCT2(name, d1, d2) \ + std::shared_ptr<ISignalConnection> Sig##name::AddListener( \ + ISignalSystem &inSystem, void *inSender, std::function<void(d1, d2)> inHandler) \ + { \ + return SSignalDataStruct2<d1, d2>::AddListener(inSystem, inSender, #name, inHandler); \ + } \ + void Sig##name::Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2) \ + { \ + SSignalDataStruct2<d1, d2>::Send(system, sender, #name, arg1, arg2); \ + } + +template <typename TData1, typename TData2, typename TData3> +struct SSignalDataStruct3 +{ + typedef SSignalDataStruct3<TData1, TData2, TData3> TThisType; + typedef std::function<void(TData1, TData2, TData3)> TFunType; + TData1 m_Data1; + TData2 m_Data2; + TData3 m_Data3; + SSignalDataStruct3(const TData1 &d1, const TData2 &d2, const TData3 &d3) + : m_Data1(d1) + , m_Data2(d2) + , m_Data3(d3) + { + } + static void Send(ISignalSystem &system, void *sender, const char *sigName, const TData1 &d1, + const TData2 &d2, const TData3 &d3) + { + TThisType theData(d1, d2, d3); + system.Signal(sender, sigName, reinterpret_cast<const char *>(&theData), sizeof(TThisType)); + } + + static void Unpack(void *inSender, const char *inName, const char *inData, size_t inDataSize, + TFunType inHandler) + { + if (inDataSize == sizeof(TThisType)) { + const TThisType *theData = reinterpret_cast<const TThisType *>(inData); + inHandler(theData->m_Data1, theData->m_Data2, theData->m_Data2); + } else { + QT3DS_ASSERT(false); + } + } + + static TGenericSignalHandlerFunc CreateHandler(TFunType inHandler) + { + return std::bind(&TThisType::Unpack, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4, inHandler); + } + + static std::shared_ptr<ISignalConnection> AddListener(ISignalSystem &inSystem, void *inSender, + const char *inName, TFunType inHandler) + { + return inSystem.AddListener(inSender, inName, CreateHandler(inHandler)); + } +}; + +#define QT3DSDM_SIGNALS_DEFINE_SPECIFIC_SIGNAL_STRUCT3(name, d1, d2, d3) \ + std::shared_ptr<ISignalConnection> Sig##name::AddListener( \ + ISignalSystem &inSystem, void *inSender, std::function<void(d1, d2, d3)> inHandler) \ + { \ + return SSignalDataStruct3<d1, d2, d3>::AddListener(inSystem, inSender, #name, inHandler); \ + } \ + void Sig##name::Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2, \ + const d3 &arg3) \ + { \ + SSignalDataStruct3<d1, d2, d3>::Send(system, sender, #name, arg1, arg2, arg3); \ + } + +template <typename TData1, typename TData2, typename TData3, typename TData4> +struct SSignalDataStruct4 +{ + typedef SSignalDataStruct4<TData1, TData2, TData3, TData4> TThisType; + typedef std::function<void(TData1, TData2, TData3, TData4)> TFunType; + TData1 m_Data1; + TData2 m_Data2; + TData3 m_Data3; + TData4 m_Data4; + SSignalDataStruct4(const TData1 &d1, const TData2 &d2, const TData3 &d3, const TData4 &d4) + : m_Data1(d1) + , m_Data2(d2) + , m_Data3(d3) + , m_Data4(d4) + { + } + static void Send(ISignalSystem &system, void *sender, const char *sigName, const TData1 &d1, + const TData2 &d2, const TData3 &d3, const TData4 &d4) + { + TThisType theData(d1, d2, d3, d4); + system.Signal(sender, sigName, reinterpret_cast<const char *>(&theData), sizeof(TThisType)); + } + + static void Unpack(void *inSender, const char *inName, const char *inData, size_t inDataSize, + TFunType inHandler) + { + if (inDataSize == sizeof(TThisType)) { + const TThisType *theData = reinterpret_cast<const TThisType *>(inData); + inHandler(theData->m_Data1, theData->m_Data2, theData->m_Data2, theData->m_Data4); + } else { + QT3DS_ASSERT(false); + } + } + + static TGenericSignalHandlerFunc CreateHandler(TFunType inHandler) + { + return std::bind(&TThisType::Unpack, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4, inHandler); + } + + static std::shared_ptr<ISignalConnection> AddListener(ISignalSystem &inSystem, void *inSender, + const char *inName, TFunType inHandler) + { + return inSystem.AddListener(inSender, inName, CreateHandler(inHandler)); + } +}; + +#define QT3DSDM_SIGNALS_DEFINE_SPECIFIC_SIGNAL_STRUCT4(name, d1, d2, d3, d4) \ + std::shared_ptr<ISignalConnection> Sig##name::AddListener( \ + ISignalSystem &inSystem, void *inSender, std::function<void(d1, d2, d3, d4)> inHandler) \ + { \ + return SSignalDataStruct4<d1, d2, d3, d4>::AddListener(inSystem, inSender, #name, \ + inHandler); \ + } \ + void Sig##name::Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2, \ + const d3 &arg3, const d4 &arg4) \ + { \ + SSignalDataStruct4<d1, d2, d3, d4>::Send(system, sender, #name, arg1, arg2, arg3, arg4); \ + } +} +#endif diff --git a/src/dm/systems/Qt3DSDMSignalStructs.h b/src/dm/systems/Qt3DSDMSignalStructs.h new file mode 100644 index 0000000..86c09fd --- /dev/null +++ b/src/dm/systems/Qt3DSDMSignalStructs.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_SIGNAL_STRUCTS_H +#define QT3DSDM_SIGNAL_STRUCTS_H +#include "Qt3DSDMSignalSystem.h" +// Helper structs for signals of different arity. +namespace qt3dsdm { +// Helper defines to create static tables of signals +// Macros with the same number of args but with 'declare' replaced by 'define +// are available in UICDMSignalStructImpl.h. You will need to place these somewhere but +// they rely on std::bind so I don't place them here. +#define QT3DSDM_SIGNALS_DECLARE_SPECIFIC_SIGNAL_STRUCT0(name) \ + struct Sig##name \ + { \ + static std::shared_ptr<ISignalConnection> \ + AddListener(ISignalSystem &inSystem, void *inSender, std::function<void()> inHandler); \ + static void Send(ISignalSystem &system, void *sender); \ + }; + +// Helper defines to create static tables of signals +#define QT3DSDM_SIGNALS_DECLARE_SPECIFIC_SIGNAL_STRUCT1(name, d1) \ + struct Sig##name \ + { \ + static std::shared_ptr<ISignalConnection> \ + AddListener(ISignalSystem &inSystem, void *inSender, std::function<void(d1)> inHandler); \ + static void Send(ISignalSystem &system, void *sender, const d1 &arg); \ + }; + +// Helper defines to create static tables of signals +#define QT3DSDM_SIGNALS_DECLARE_SPECIFIC_SIGNAL_STRUCT2(name, d1, d2) \ + struct Sig##name \ + { \ + static std::shared_ptr<ISignalConnection> \ + AddListener(ISignalSystem &inSystem, void *inSender, \ + std::function<void(d1, d2)> inHandler); \ + static void Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2); \ + }; + +// Helper defines to create static tables of signals +#define QT3DSDM_SIGNALS_DECLARE_SPECIFIC_SIGNAL_STRUCT3(name, d1, d2, d3) \ + struct Sig##name \ + { \ + static std::shared_ptr<ISignalConnection> \ + AddListener(ISignalSystem &inSystem, void *inSender, \ + std::function<void(d1, d2, d3)> inHandler); \ + static void Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2, \ + const d3 &arg3); \ + }; + +// Helper defines to create static tables of signals +#define QT3DSDM_SIGNALS_DECLARE_SPECIFIC_SIGNAL_STRUCT4(name, d1, d2, d3, d4) \ + struct Sig##name \ + { \ + static std::shared_ptr<ISignalConnection> \ + AddListener(ISignalSystem &inSystem, void *inSender, \ + std::function<void(d1, d2, d3, d4)> inHandler); \ + static void Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2, \ + const d3 &arg3, const d4 &arg4); \ + }; +} + +#endif diff --git a/src/dm/systems/Qt3DSDMSignalSystem.cpp b/src/dm/systems/Qt3DSDMSignalSystem.cpp new file mode 100644 index 0000000..37d0200 --- /dev/null +++ b/src/dm/systems/Qt3DSDMSignalSystem.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "Qt3DSDMSignalSystem.h" +#include "EASTL/hash_map.h" + +using namespace qt3dsdm; + +namespace { + +struct SSignalListener; +class ISignalSystemImpl +{ +public: + virtual ~ISignalSystemImpl() {} + virtual void RemoveListener(SSignalListener &inListener) = 0; +}; + +struct SSignalSystemKey +{ + void *m_Sender; + const char *m_SignalName; + SSignalSystemKey(void *inSender, const char *inSigName, IStringTable &inStrTable) + : m_Sender(inSender) + , m_SignalName(inStrTable.GetNarrowStr(inSigName)) + { + } + SSignalSystemKey(const SSignalSystemKey &inOther) + : m_Sender(inOther.m_Sender) + , m_SignalName(inOther.m_SignalName) + { + } + + SSignalSystemKey &operator=(const SSignalSystemKey &inOther) + { + if (this != &inOther) { + m_Sender = inOther.m_Sender; + m_SignalName = inOther.m_SignalName; + } + return *this; + } + + bool operator==(const SSignalSystemKey &inOther) const + { + return m_Sender == inOther.m_Sender && m_SignalName == inOther.m_SignalName; + } +}; + +struct SSignalListener : ISignalConnection +{ + shared_ptr<ISignalSystemImpl> m_SignalSystem; + TGenericSignalHandlerFunc m_Handler; + SSignalSystemKey m_Key; + SSignalListener(shared_ptr<ISignalSystemImpl> inSystem, TGenericSignalHandlerFunc inHandler, + SSignalSystemKey inKey) + : m_SignalSystem(inSystem) + , m_Handler(inHandler) + , m_Key(inKey) + { + } + ~SSignalListener() { m_SignalSystem->RemoveListener(*this); } + void Signal(void *inSender, const char *inName, const char *inData, size_t inDataSize) + { + m_Handler(inSender, inName, inData, inDataSize); + } +}; + +typedef eastl::vector<SSignalListener *> TSignalListenerPtrList; +} + +namespace eastl { +template <> +struct hash<SSignalSystemKey> +{ + size_t operator()(const SSignalSystemKey &inKey) const + { + return hash<void *>()(inKey.m_Sender) ^ hash<const char *>()(inKey.m_SignalName); + } +}; +} + +namespace { +typedef eastl::hash_map<SSignalSystemKey, TSignalListenerPtrList> TSignalHandlerMap; + +struct SSignalSystemImpl : public ISignalSystemImpl +{ + TSignalHandlerMap m_SignalHandlers; + shared_ptr<IStringTable> m_StringTable; + SSignalSystemImpl(shared_ptr<IStringTable> inStrTable) + : m_StringTable(inStrTable) + { + } + + TSignalListenerPtrList *FindListenerList(const SSignalSystemKey &inKey) + { + TSignalHandlerMap::iterator theIter = m_SignalHandlers.find(inKey); + if (theIter != m_SignalHandlers.end()) + return &theIter->second; + return NULL; + } + + void Signal(void *inSender, const char *inName, const char *inData, size_t inDataSize) + { + TSignalListenerPtrList *theSignals = + FindListenerList(SSignalSystemKey(inSender, inName, *m_StringTable)); + if (theSignals) { + for (eastl_size_t idx = 0, end = theSignals->size(); idx < end; ++idx) { + (*theSignals)[idx]->Signal(inSender, inName, inData, inDataSize); + } + } + } + + void RemoveListener(SSignalListener &inListener) override + { + TSignalListenerPtrList *theSignals = FindListenerList(inListener.m_Key); + if (theSignals) { + // If we could allow unordered access then this could potentially be a lot faster. + TSignalListenerPtrList::iterator theFind = + eastl::find(theSignals->begin(), theSignals->end(), &inListener); + if (theFind != theSignals->end()) + theSignals->erase(theFind); + } + } +}; + +struct SSignalSystem : public ISignalSystem +{ + shared_ptr<SSignalSystemImpl> m_System; + SSignalSystem(shared_ptr<IStringTable> inStrTable) + { + m_System = std::make_shared<SSignalSystemImpl>(inStrTable); + } + + shared_ptr<ISignalConnection> AddListener(void *inSender, const char *inName, + TGenericSignalHandlerFunc inFunc) override + { + SSignalSystemKey theKey(inSender, inName, *m_System->m_StringTable); + TSignalHandlerMap::iterator theIter = + m_System->m_SignalHandlers.insert(eastl::make_pair(theKey, TSignalListenerPtrList())) + .first; + TSignalListenerPtrList &theList(theIter->second); + shared_ptr<SSignalListener> theSender = + std::make_shared<SSignalListener>(m_System, inFunc, theKey); + theList.push_back(theSender.get()); + return theSender; + } + + void Signal(void *inSender, const char *inName, const char *inData, size_t inDataSize) override + { + m_System->Signal(inSender, inName, inData, inDataSize); + } +}; +} + +shared_ptr<ISignalSystem> ISignalSystem::CreateSignalSystem(shared_ptr<IStringTable> inStrTable) +{ + return std::make_shared<SSignalSystem>(inStrTable); +} diff --git a/src/dm/systems/Qt3DSDMSignalSystem.h b/src/dm/systems/Qt3DSDMSignalSystem.h new file mode 100644 index 0000000..cd80010 --- /dev/null +++ b/src/dm/systems/Qt3DSDMSignalSystem.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_SIGNAL_SYSTEM_H +#define QT3DSDM_SIGNAL_SYSTEM_H +#include <functional> +#include "Qt3DSDMSignals.h" + +namespace qt3dsdm { +typedef std::function<void(void *, const char *, const char *, size_t)> TGenericSignalHandlerFunc; + +class ISignalSystem +{ +protected: + virtual ~ISignalSystem() {} +public: + virtual shared_ptr<ISignalConnection> AddListener(void *inSender, const char *inName, + TGenericSignalHandlerFunc inFunc) = 0; + virtual void Signal(void *inSender, const char *inName, const char *inData, + size_t inDataSize) = 0; + + static shared_ptr<ISignalSystem> CreateSignalSystem(shared_ptr<IStringTable> inStrTable); +}; +} + +#endif diff --git a/src/dm/systems/Qt3DSDMSignals.h b/src/dm/systems/Qt3DSDMSignals.h new file mode 100644 index 0000000..57b9659 --- /dev/null +++ b/src/dm/systems/Qt3DSDMSignals.h @@ -0,0 +1,611 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_SIGNALS_H +#define QT3DSDM_SIGNALS_H +#include "Qt3DSDMDataTypes.h" +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMAnimation.h" +#include "Qt3DSDMActionInfo.h" +#include "Qt3DSDMValue.h" +#include <functional> +#include <string> + +namespace qt3dsdm { + +class ISignalConnection +{ +public: + virtual ~ISignalConnection() {} +}; + +class ISignalItem +{ +public: + virtual ~ISignalItem() {} +}; + +typedef std::shared_ptr<ISignalItem> TSignalItemPtr; + +typedef std::shared_ptr<ISignalConnection> TSignalConnectionPtr; + +class QtSignalConnection : public ISignalConnection +{ + Q_DISABLE_COPY(QtSignalConnection) +private: + QMetaObject::Connection m_connection; +public: + QtSignalConnection(const QMetaObject::Connection &inConnection) + : m_connection(inConnection) + { + } + ~QtSignalConnection() override + { + QObject::disconnect(m_connection); + } +}; + + +class IInstancePropertyCoreSignalProvider : public ISignalItem +{ +public: + virtual TSignalConnectionPtr ConnectInstancePropertyValue( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, const SValue &)> + &inCallback) = 0; +}; + +class IInstancePropertyCoreSignalSender : public ISignalItem +{ +public: + virtual void SignalInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) = 0; +}; + +class IDataCoreSignalProvider : public ISignalItem +{ +public: + virtual TSignalConnectionPtr + ConnectInstanceCreated(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectBeforeInstanceDeleted(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectInstanceDeleted(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectInstanceDerived( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectInstanceParentRemoved( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectPropertyAdded(const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + TCharPtr, DataModelDataType::Value)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectPropertyRemoved( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, TCharPtr, + DataModelDataType::Value)> &inCallback) = 0; +}; + +class IDataCoreSignalSender : public ISignalItem +{ +public: + virtual void SignalInstanceCreated(Qt3DSDMInstanceHandle inInstance) = 0; + virtual void SignalBeforeInstanceDeleted(Qt3DSDMInstanceHandle inInstance) = 0; + virtual void SignalInstanceDeleted(Qt3DSDMInstanceHandle inInstance) = 0; + virtual void SignalInstanceDerived(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) = 0; + virtual void SignalInstanceParentRemoved(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) = 0; + virtual void SignalPropertyAdded(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, TCharPtr inName, + DataModelDataType::Value inDataType) = 0; + virtual void SignalPropertyRemoved(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, TCharPtr inName, + DataModelDataType::Value inDataType) = 0; +}; + +class ISlideCoreSignalProvider : public ISignalItem +{ +public: + virtual TSignalConnectionPtr + ConnectSlideCreated(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectBeforeSlideDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectSlideDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectSlideDerived( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMSlideHandle, int)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectInstancePropertyValueSet( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectInstancePropertyValueRemoved( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectSlideTimeChanged(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) = 0; +}; + +class ISlideCoreSignalSender : public ISignalItem +{ +public: + virtual void SendSlideCreated(Qt3DSDMSlideHandle inSlide) = 0; + virtual void SendBeforeSlideDeleted(Qt3DSDMSlideHandle inSlide) = 0; + virtual void SendSlideDeleted(Qt3DSDMSlideHandle inSlide) = 0; + virtual void SendSlideDerived(Qt3DSDMSlideHandle inSlide, Qt3DSDMSlideHandle inParent, + int inIndex) = 0; + virtual void SendPropertyValueSet(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inParent, const SValue &inValue) = 0; + // This gives clients a chance to override a property value the first time it is set on a slide + virtual void SendPropertyValueRemoved(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inParent, const SValue &inValue) = 0; + virtual void SendSlideTimeChanged(Qt3DSDMSlideHandle inSlide) = 0; +}; + +class ISlideGraphCoreSignalProvider : public ISignalItem +{ +public: + virtual TSignalConnectionPtr ConnectGraphCreated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectGraphDeleted( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectInstanceAssociated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) = 0; + virtual TSignalConnectionPtr ConnectInstanceDissociated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) = 0; + virtual TSignalConnectionPtr ConnectGraphActiveSlide( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) = 0; +}; + +class ISlideGraphCoreSignalSender : public ISignalItem +{ +public: + virtual void SendGraphCreated(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide) = 0; + virtual void SendGraphDeleted(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide) = 0; + virtual void SendInstanceAssociated(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) = 0; + virtual void SendInstanceDissociated(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) = 0; + virtual void SendGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph, + Qt3DSDMSlideHandle inSlide) = 0; +}; + +class IAnimationCoreSignalProvider : public ISignalItem +{ +public: + virtual TSignalConnectionPtr ConnectAnimationCreated( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectBeforeAnimationDeleted( + const std::function<void(Qt3DSDMAnimationHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectAnimationDeleted( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectKeyframeInserted( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle, const TKeyframe &)> + &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectBeforeKeyframeErased(const std::function<void(Qt3DSDMKeyframeHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectKeyframeErased( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle, const TKeyframe &)> + &inCallback) = 0; + virtual TSignalConnectionPtr ConnectBeforeAllKeyframesErased( + const std::function<void(Qt3DSDMAnimationHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectKeyframeUpdated( + const std::function<void(Qt3DSDMKeyframeHandle, const TKeyframe &)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectFirstKeyframeDynamicSet( + const std::function<void(Qt3DSDMAnimationHandle, bool)> &inCallback) = 0; +}; + +class IAnimationCoreSignalSender : public ISignalItem +{ +public: + virtual void SendAnimationCreated(Qt3DSDMAnimationHandle inAnimation, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType) = 0; + virtual void SendBeforeAnimationDeleted(Qt3DSDMAnimationHandle inAnimation) = 0; + virtual void SendAnimationDeleted(Qt3DSDMAnimationHandle inAnimation, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType) = 0; + virtual void SendKeyframeInserted(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData) = 0; + virtual void SendBeforeKeyframeErased(Qt3DSDMKeyframeHandle inAnimation) = 0; + virtual void SendKeyframeErased(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData) = 0; + virtual void SendBeforeAllKeyframesErased(Qt3DSDMAnimationHandle inAnimation) = 0; + virtual void SendKeyframeUpdated(Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData) = 0; + virtual void SendFirstKeyframeDynamicSet(Qt3DSDMAnimationHandle inAnimation, + bool inKeyframeDynamic) = 0; +}; + +class IActionCoreSignalProvider : public ISignalItem +{ +public: + virtual TSignalConnectionPtr ConnectTriggerObjectSet( + const std::function<void(Qt3DSDMActionHandle, SObjectRefType &)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectTargetObjectSet( + const std::function<void(Qt3DSDMActionHandle, SObjectRefType &)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectEventSet( + const std::function<void(Qt3DSDMActionHandle, const wstring &)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectHandlerSet( + const std::function<void(Qt3DSDMActionHandle, const wstring &)> &inCallback) = 0; + + virtual TSignalConnectionPtr ConnectHandlerArgumentAdded( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectHandlerArgumentRemoved( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectHandlerArgumentValueSet( + const std::function<void(Qt3DSDMHandlerArgHandle, const SValue &)> &inCallback) = 0; +}; + +class IActionCoreSignalSender : public ISignalItem +{ +public: + virtual void SendTriggerObjectSet(Qt3DSDMActionHandle inAction, + SObjectRefType &inTriggerObject) = 0; + virtual void SendTargetObjectSet(Qt3DSDMActionHandle inAction, + SObjectRefType &inTargetObject) = 0; + virtual void SendEventSet(Qt3DSDMActionHandle inAction, const wstring &inEventHandle) = 0; + virtual void SendHandlerSet(Qt3DSDMActionHandle inAction, const wstring &inActionName) = 0; + + virtual void SendHandlerArgumentAdded(Qt3DSDMActionHandle inAction, + Qt3DSDMHandlerArgHandle inHandlerArgument, + const TCharStr &inName, HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) = 0; + virtual void SendHandlerArgumentRemoved(Qt3DSDMActionHandle inAction, + Qt3DSDMHandlerArgHandle inHandlerArgument, + const TCharStr &inName, HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) = 0; + virtual void SendHandlerArgumentValueSet(Qt3DSDMHandlerArgHandle inHandlerArgument, + const SValue &inValue) = 0; +}; + +class IActionSystemSignalProvider : public ISignalItem +{ +public: + virtual TSignalConnectionPtr ConnectActionCreated( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) = 0; + virtual TSignalConnectionPtr ConnectActionDeleted( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) = 0; +}; + +class IActionSystemSignalSender : public ISignalItem +{ +public: + virtual void SendActionCreated(Qt3DSDMActionHandle inAction, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendActionDeleted(Qt3DSDMActionHandle inAction, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) = 0; +}; + +class ICustomPropCoreSignalProvider : public ISignalItem +{ +public: + virtual TSignalConnectionPtr ConnectCustomPropertyCreated( + const std::function<void(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomPropertyDeleted( + const std::function<void(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomPropertyModified( + const std::function<void(Qt3DSDMPropertyHandle)> &inCallback) = 0; + + virtual TSignalConnectionPtr ConnectCustomEventCreated( + const std::function<void(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomEventDeleted( + const std::function<void(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectCustomEventModified(const std::function<void(Qt3DSDMEventHandle)> &inCallback) = 0; + + virtual TSignalConnectionPtr ConnectCustomHandlerCreated( + const std::function<void(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomHandlerDeleted( + const std::function<void(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectCustomHandlerModified(const std::function<void(Qt3DSDMHandlerHandle)> &inCallback) = 0; + + virtual TSignalConnectionPtr ConnectCustomHandlerParamCreated( + const std::function<void(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomHandlerParamDeleted( + const std::function<void(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomHandlerParamModified( + const std::function<void(Qt3DSDMHandlerParamHandle)> &inCallback) = 0; + + virtual TSignalConnectionPtr ConnectCustomReferencesModified( + const std::function<void(Qt3DSDMInstanceHandle, const TCharStr &)> &inCallback) = 0; +}; + +class ICustomPropCoreSignalSender : public ISignalItem +{ +public: + virtual void SendCustomPropertyCreated(Qt3DSDMPropertyHandle inProp, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomPropertyDeleted(Qt3DSDMPropertyHandle inProp, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomPropertyModified(Qt3DSDMPropertyHandle inProp) = 0; + + virtual void SendCustomEventCreated(Qt3DSDMEventHandle inEvent, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomEventDeleted(Qt3DSDMEventHandle inEvent, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomEventModified(Qt3DSDMEventHandle inEvent) = 0; + + virtual void SendCustomHandlerCreated(Qt3DSDMHandlerHandle inHandler, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomHandlerDeleted(Qt3DSDMHandlerHandle inHandler, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomHandlerModified(Qt3DSDMHandlerHandle inHandler) = 0; + + virtual void SendCustomHandlerParamCreated(Qt3DSDMHandlerParamHandle inParameter, + Qt3DSDMHandlerHandle inHandler) = 0; + virtual void SendCustomHandlerParamDeleted(Qt3DSDMHandlerParamHandle inParameter, + Qt3DSDMHandlerHandle inHandler) = 0; + virtual void SendCustomHandlerParamModified(Qt3DSDMHandlerParamHandle inParameter) = 0; + + virtual void SendCustomReferencesModified(Qt3DSDMInstanceHandle inOwner, + const TCharStr &inString) = 0; +}; + +class ISlideSystemSignalProvider : public ISignalItem +{ +public: + virtual TSignalConnectionPtr + ConnectMasterCreated(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectMasterDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectSlideCreated( + const std::function<void(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectSlideDeleted( + const std::function<void(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectSlideRearranged( + const std::function<void(Qt3DSDMSlideHandle, int, int)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectInstanceAssociated( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectInstanceDissociated( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectPropertyLinked( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> + &inCallback) = 0; + virtual TSignalConnectionPtr ConnectPropertyUnlinked( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> + &inCallback) = 0; + virtual TSignalConnectionPtr ConnectActiveSlide( + const std::function<void(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle, Qt3DSDMSlideHandle)> + &inCallback) = 0; +}; + +class ISlideSystemSignalSender : public ISignalItem +{ +public: + virtual void SendMasterCreated(Qt3DSDMSlideHandle inMaster) = 0; + virtual void SendMasterDeleted(Qt3DSDMSlideHandle inMaster) = 0; + virtual void SendSlideCreated(Qt3DSDMSlideHandle inMaster, int inIndex, + Qt3DSDMSlideHandle inSlide) = 0; + virtual void SendSlideDeleted(Qt3DSDMSlideHandle inMaster, int inIndex, + Qt3DSDMSlideHandle inSlide) = 0; + virtual void SendSlideRearranged(Qt3DSDMSlideHandle inMaster, int inOldIndex, + int inNewIndex) = 0; + virtual void SendInstanceAssociated(Qt3DSDMSlideHandle inMaster, + Qt3DSDMInstanceHandle inInstance) = 0; + virtual void SendInstanceDissociated(Qt3DSDMSlideHandle inMaster, + Qt3DSDMInstanceHandle inInstance) = 0; + virtual void SendPropertyLinked(Qt3DSDMSlideHandle inMaster, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual void SendPropertyUnlinked(Qt3DSDMSlideHandle inMaster, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual void SendActiveSlide(Qt3DSDMSlideHandle inMaster, int inIndex, + Qt3DSDMSlideHandle inOldSlide, Qt3DSDMSlideHandle inNewSlide) = 0; +}; + +class IStudioFullSystemSignalProvider : public ISignalItem +{ +public: + virtual TSignalConnectionPtr + ConnectSlideCreated(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectSlideDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectSlideRearranged( + const std::function<void(Qt3DSDMSlideHandle, int, int)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectBeginComponentSeconds(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectComponentSeconds(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectPropertyLinked( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> + &inCallback) = 0; + virtual TSignalConnectionPtr ConnectPropertyUnlinked( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> + &inCallback) = 0; + virtual TSignalConnectionPtr ConnectActiveSlide( + const std::function<void(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle)> &inCallback) = 0; + + virtual TSignalConnectionPtr + ConnectInstanceCreated(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectInstanceDeleted(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) = 0; + + virtual TSignalConnectionPtr + ConnectAnimationCreated(const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectAnimationDeleted(const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectKeyframeInserted( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectKeyframeErased( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectKeyframeUpdated(const std::function<void(Qt3DSDMKeyframeHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectFirstKeyframeDynamicSet( + const std::function<void(Qt3DSDMAnimationHandle, bool)> &inCallback) = 0; + + virtual TSignalConnectionPtr ConnectInstancePropertyValue( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> &inCallback) = 0; + + virtual TSignalConnectionPtr ConnectActionCreated( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) = 0; + virtual TSignalConnectionPtr ConnectActionDeleted( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectTriggerObjectSet(const std::function<void(Qt3DSDMActionHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectTargetObjectSet(const std::function<void(Qt3DSDMActionHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectEventSet(const std::function<void(Qt3DSDMActionHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectHandlerSet(const std::function<void(Qt3DSDMActionHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectHandlerArgumentValueSet( + const std::function<void(Qt3DSDMHandlerArgHandle)> &inCallback) = 0; + + virtual TSignalConnectionPtr ConnectCustomPropertyCreated( + const std::function<void(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomPropertyDeleted( + const std::function<void(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomPropertyModified( + const std::function<void(Qt3DSDMPropertyHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomEventCreated( + const std::function<void(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomEventDeleted( + const std::function<void(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectCustomEventModified(const std::function<void(Qt3DSDMEventHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomHandlerCreated( + const std::function<void(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomHandlerDeleted( + const std::function<void(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr + ConnectCustomHandlerModified(const std::function<void(Qt3DSDMHandlerHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomHandlerParamCreated( + const std::function<void(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomHandlerParamDeleted( + const std::function<void(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomHandlerParamModified( + const std::function<void(Qt3DSDMHandlerParamHandle)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectCustomReferencesModified( + const std::function<void(Qt3DSDMInstanceHandle, const TCharStr &)> &inCallback) = 0; + virtual TSignalConnectionPtr ConnectControlledToggled( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> &inCallback) = 0; +}; + +class IStudioFullSystemSignalSender : public ISignalItem +{ +public: + virtual void SendSlideCreated(Qt3DSDMSlideHandle inSlide) = 0; + virtual void SendSlideDeleted(Qt3DSDMSlideHandle inSlide) = 0; + virtual void SendSlideRearranged(Qt3DSDMSlideHandle inMaster, int inOldIndex, + int inNewIndex) = 0; + virtual void SendComponentSeconds(Qt3DSDMSlideHandle inMaster) = 0; + virtual void SendBeginComponentSeconds(Qt3DSDMSlideHandle inMaster) = 0; + virtual void SendPropertyLinked(Qt3DSDMSlideHandle inMaster, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual void SendPropertyUnlinked(Qt3DSDMSlideHandle inMaster, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual void SendActiveSlide(Qt3DSDMSlideHandle inMaster, int inIndex, + Qt3DSDMSlideHandle inSlide) = 0; + + virtual void SendInstanceCreated(Qt3DSDMInstanceHandle inInstance) = 0; + virtual void SendInstanceDeleted(Qt3DSDMInstanceHandle inInstance) = 0; + + virtual void SendAnimationCreated(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual void SendAnimationDeleted(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual void SendKeyframeInserted(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMKeyframeHandle inKeyframe) = 0; + virtual void SendKeyframeErased(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMKeyframeHandle inKeyframe) = 0; + virtual void SendKeyframeUpdated(Qt3DSDMKeyframeHandle inKeyframe) = 0; + virtual void SendConnectFirstKeyframeDynamicSet(Qt3DSDMAnimationHandle inAnimation, + bool inDynamic) = 0; + + virtual void SendInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + + virtual void SendActionCreated(Qt3DSDMActionHandle inAction, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendActionDeleted(Qt3DSDMActionHandle inAction, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendTriggerObjectSet(Qt3DSDMActionHandle inAction) = 0; + virtual void SendTargetObjectSet(Qt3DSDMActionHandle inAction) = 0; + virtual void SendEventSet(Qt3DSDMActionHandle inAction) = 0; + virtual void SendHandlerSet(Qt3DSDMActionHandle inAction) = 0; + virtual void SendHandlerArgumentValueSet(Qt3DSDMHandlerArgHandle inHandlerArgument) = 0; + + virtual void SendCustomPropertyCreated(Qt3DSDMPropertyHandle inProp, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomPropertyDeleted(Qt3DSDMPropertyHandle inProp, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomPropertyModified(Qt3DSDMPropertyHandle inProp) = 0; + virtual void SendCustomEventCreated(Qt3DSDMEventHandle inEvent, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomEventDeleted(Qt3DSDMEventHandle inEvent, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomEventModified(Qt3DSDMEventHandle inEvent) = 0; + virtual void SendCustomHandlerCreated(Qt3DSDMHandlerHandle inHandler, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomHandlerDeleted(Qt3DSDMHandlerHandle inHandler, + Qt3DSDMInstanceHandle inOwner) = 0; + virtual void SendCustomHandlerModified(Qt3DSDMHandlerHandle inHandler) = 0; + virtual void SendCustomHandlerParamCreated(Qt3DSDMHandlerParamHandle inParameter, + Qt3DSDMHandlerHandle inHandler) = 0; + virtual void SendCustomHandlerParamDeleted(Qt3DSDMHandlerParamHandle inParameter, + Qt3DSDMHandlerHandle inHandler) = 0; + virtual void SendCustomHandlerParamModified(Qt3DSDMHandlerParamHandle inParameter) = 0; + virtual void SendCustomReferencesModified(Qt3DSDMInstanceHandle inOwner, + const TCharStr &inString) = 0; + virtual void SendControlledToggled(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; +}; + +// Use this if you want to register for only a specific instance or specific property +template <typename TTransaction> +inline void MaybackCallbackInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + Qt3DSDMInstanceHandle inDesiredInstance, + Qt3DSDMPropertyHandle inDesiredProperty, + TTransaction inCallback) +{ + if ((!inDesiredInstance.Valid() || (inDesiredInstance == inInstance)) + && (!inDesiredProperty.Valid() || (inDesiredProperty == inProperty))) + inCallback(inInstance, inProperty); +} + +void SetDataModelSignalsEnabled(bool inEnabled); +// Defaults to true +bool AreDataModelSignalsEnabled(); +} + +#endif diff --git a/src/dm/systems/Qt3DSDMSlideCore.h b/src/dm/systems/Qt3DSDMSlideCore.h new file mode 100644 index 0000000..8216b01 --- /dev/null +++ b/src/dm/systems/Qt3DSDMSlideCore.h @@ -0,0 +1,239 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_SLIDE_CORE_H +#define QT3DSDM_SLIDE_CORE_H +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMDataTypes.h" +#include "HandleSystemBase.h" +#include "Qt3DSDMStringTable.h" +#include "Qt3DSDMDataCore.h" + +namespace qt3dsdm { +typedef std::pair<Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle> TInstancePropertyPair; +typedef std::vector<TInstancePropertyPair> TInstancePropertyPairList; + +// instance,property,value +typedef std::tuple<Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, SValue> TSlideEntry; +typedef std::vector<TSlideEntry> TSlideEntryList; + +class ISlideCore : public IHandleBase +{ +public: + virtual ~ISlideCore() {} + virtual TStringTablePtr GetStringTablePtr() const = 0; + virtual IStringTable &GetStringTable() const = 0; + //=============================================================== + // Slide lifetime management + //=============================================================== + /** + * Create a new slide. Slides must have an instance allocated for them. + */ + virtual Qt3DSDMSlideHandle CreateSlide(Qt3DSDMInstanceHandle inInstance) = 0; + /** + * Return the instance that was allocated for this slide. + */ + virtual Qt3DSDMInstanceHandle GetSlideInstance(Qt3DSDMSlideHandle inSlide) const = 0; + /** + * Reverse lookup into the slide system so you can match slides to instances. + */ + virtual Qt3DSDMSlideHandle GetSlideByInstance(Qt3DSDMInstanceHandle inSlide) const = 0; + /** + * Delete a given slide. This recursively deletes all children. All associated instances + * are returned in the outInstances list so the caller can further delete them. + * The deleted object is removed from the parent's list of children. Child objects are + * also deleted. + */ + virtual void DeleteSlide(Qt3DSDMSlideHandle inSlide, TInstanceHandleList &outInstances) = 0; + /** + * Return all of the slides in the core. + */ + virtual void GetSlides(TSlideHandleList &outSlides) const = 0; + + virtual float GetSlideTime(Qt3DSDMSlideHandle inSlide) const = 0; + + virtual void SetSlideTime(Qt3DSDMSlideHandle inSlide, float inNewTime) = 0; + + //=============================================================== + // Slide derivation + //=============================================================== + /** + * Derive a slide from another slide. This simply provides an alternate path for property + *lookup + * if it isn't found on this slide. OK for parent to be an invalid handle. It is also fine + * for the slide to have a valid parent; all involved parties are notified and updated. + */ + virtual void DeriveSlide(Qt3DSDMSlideHandle inSlide, Qt3DSDMSlideHandle inParent, + int inIndex = -1) = 0; + /** + * Return the parent slide for this slide. Invalid handle if no parent. + */ + virtual Qt3DSDMSlideHandle GetParentSlide(Qt3DSDMSlideHandle inSlide) const = 0; + /** + * Return a list of derived slides for this slide. + */ + virtual void GetChildSlides(Qt3DSDMSlideHandle inSlide, TSlideHandleList &outChildren) const = 0; + + /** + * Return the index of this child. Exception if child isn't found + */ + virtual int GetChildIndex(Qt3DSDMSlideHandle inParent, Qt3DSDMSlideHandle inChild) const = 0; + //=============================================================== + + //=============================================================== + // Instance Property Access + //=============================================================== + /** + * Get this property from this instance in this slide. Includes lookup into any parent slides. + */ + virtual bool GetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const = 0; + + /** + * Set this property. If this slide doesn't already contain an entry + *(PushPropertyValueToChildren) + * then this will attempt to set it on the parent slide. If it does not have a parent slide or + *if + * it already has a property entry then it sets the value locally. + */ + virtual void SetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) = 0; + + /** + * Set this property on this slide; do not try to set on parent slide under any circumstances. + *Always adds entry to this slide. + */ + virtual void ForceSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) = 0; + + /** + * Set a property value on an instance on all slides. + */ + virtual void forceSetInstancePropertyValueOnAllSlides(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) = 0; + + /** + * Return the value for this property if it exists on this slide. + */ + virtual bool GetSpecificInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const = 0; + + /** + * Return all of the properties for this instance stored on this slide. + */ + virtual void GetSpecificInstancePropertyValues(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + TPropertyHandleValuePairList &outValues) = 0; + + /** + * Get all of the property entries for the slide. + */ + virtual void GetSlidePropertyEntries(Qt3DSDMSlideHandle inSlide, + TSlideEntryList &outEntries) const = 0; + + /** + * Set this property value on all my child slides. + */ + virtual void PushPropertyValueToChildren(Qt3DSDMSlideHandle inParent, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) = 0; + + /** + * If any property entries in slide1 intersect (have matching instance and property handles) + *with slide 2, + * add said property entry from slide1 to outEntries; + */ + virtual void GetIntersectingProperties(Qt3DSDMSlideHandle inSlide1, Qt3DSDMSlideHandle inSlide2, + TSlideEntryList &outEntries) const = 0; + + /** + * Take the intersection of the properties of slide1 and slide2 and push values from slide1 to + *destination. + * Used for new slide operations. + */ + virtual void PushIntersectingProperties(Qt3DSDMSlideHandle inSlide1, Qt3DSDMSlideHandle inSlide2, + Qt3DSDMSlideHandle inDestination) = 0; + + /** + * Ensure the children of this parent item do not contain entries for a given property. + */ + virtual void ClearChildrenPropertyValues(Qt3DSDMSlideHandle inParent, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) = 0; + + /** + * Delete all property entries related to this instance. + */ + virtual void DeleteAllInstanceEntries(Qt3DSDMInstanceHandle inHandle) = 0; + + /** + * Delete all of the property entries related to this property + */ + virtual void DeleteAllPropertyEntries(Qt3DSDMPropertyHandle inHandle) = 0; + + /** + * Delete all property entries that have an instance in the instances list *and* + * a property in the properties list. + */ + virtual void DeleteAllInstancePropertyEntries(const TInstanceHandleList &inInstances, + const TPropertyHandleList &inProperties) = 0; + + /** + * Does this slide contain this property? + */ + virtual bool ContainsProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) const = 0; + + /** + * Copy the properties from the source slide and source instance to the destination slide and + *destination + * instance. + */ + virtual void CopyProperties(Qt3DSDMSlideHandle inSourceSlide, + Qt3DSDMInstanceHandle inSourceInstance, + Qt3DSDMSlideHandle inDestSlide, + Qt3DSDMInstanceHandle inDestInstance) = 0; + + virtual bool IsSlide(Qt3DSDMSlideHandle inSlide) const = 0; +}; + +typedef std::shared_ptr<ISlideCore> TSlideCorePtr; +} + +#endif diff --git a/src/dm/systems/Qt3DSDMSlideGraphCore.h b/src/dm/systems/Qt3DSDMSlideGraphCore.h new file mode 100644 index 0000000..34c04e1 --- /dev/null +++ b/src/dm/systems/Qt3DSDMSlideGraphCore.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_SLIDE_GRAPH_CORE_H +#define QT3DSDM_SLIDE_GRAPH_CORE_H + +#include "Qt3DSDMHandles.h" +#include "HandleSystemBase.h" + +namespace qt3dsdm { + +typedef std::pair<Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle> TSlideInstancePair; +typedef std::vector<TSlideInstancePair> TSlideInstancePairList; +typedef std::pair<Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle> TGraphSlidePair; + +/** + * Binding instances to slide graphs. + */ +class ISlideGraphCore : public IHandleBase +{ +public: + virtual ~ISlideGraphCore() {} + + /** + * A slide graph is used to associate a set of instances to a set of slides. + * This allows rapid lookup of properties, as an implementation of these. + * There are a few assumptions here. First is that a given slide can be a member + * of one and only one graph (i.e. it does not derive from another slide outside of the graph). + * Second is that an instance is a member of one and only one graph. + */ + virtual Qt3DSDMSlideGraphHandle CreateSlideGraph(Qt3DSDMSlideHandle inRoot) = 0; + virtual Qt3DSDMSlideHandle GetGraphRoot(Qt3DSDMSlideGraphHandle inGraph) const = 0; + virtual Qt3DSDMSlideGraphHandle GetSlideGraph(Qt3DSDMSlideHandle inSlide) const = 0; + virtual void GetSlideGraphs(TSlideGraphHandleList &outGraphs) const = 0; + virtual void DeleteSlideGraph(Qt3DSDMSlideGraphHandle inHandle) = 0; + + /** + * Associate a given instance handle with a given graph. This will ensure that property + *lookups + * will travel through this graph before they hit the main data core. Instances may be + *associated + * with a sub-slide of a given graph, not just the root. An instance associated with the root + *is + * implicitly associated with any root-derived slides. + */ + virtual void AssociateInstance(Qt3DSDMSlideGraphHandle inSlideGraph, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) = 0; + virtual void GetAssociatedInstances(Qt3DSDMSlideGraphHandle inSlideGraph, + TSlideInstancePairList &outAssociations) const = 0; + virtual TGraphSlidePair GetAssociatedGraph(Qt3DSDMInstanceHandle inInstance) const = 0; + virtual void DissociateInstance(Qt3DSDMInstanceHandle inInstance) = 0; + + /** + * All graphs always have an active slide. This is assumed to be the root right off the bat. + */ + virtual void SetGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide) = 0; + virtual Qt3DSDMSlideHandle GetGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph) const = 0; +}; + +typedef std::shared_ptr<ISlideGraphCore> TSlideGraphCorePtr; +} + +#endif
\ No newline at end of file diff --git a/src/dm/systems/Qt3DSDMSlides.h b/src/dm/systems/Qt3DSDMSlides.h new file mode 100644 index 0000000..aa7c27c --- /dev/null +++ b/src/dm/systems/Qt3DSDMSlides.h @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_SLIDES_H +#define QT3DSDM_SLIDES_H +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMSlideCore.h" + +namespace qt3dsdm { +/** + * Some properties point to instances which act like extended properties. + * An example of this would be the images on materials. If a material has an + * image in one of its slots, that image should be duplicated upon property unlink + * and deleted upon property link. It (and its animations) should be duplicated upon + * create slide and deleted upon slide destruction such that the concept that the image + * is really a property on the material stays sound. + */ +class IPropertyInstanceInfo +{ +public: + virtual ~IPropertyInstanceInfo() {} + + /** + * Return the instance that relates to this property + */ + virtual Qt3DSDMInstanceHandle GetInstanceForProperty(const SValue &inValue) = 0; + + /** + * Duplicate this instance and whichever properties and animations you desire, + * returning a new data model value that will be set on the newly created property. + * Don't forget to associate the instance with a the dest slide. I doubt things + * will work correctly if you do not. + */ + virtual SValue CreateInstanceForProperty(Qt3DSDMSlideHandle inSourceSlide, + Qt3DSDMSlideHandle inDestSlide, + Qt3DSDMInstanceHandle inInstance) = 0; +}; + +typedef std::shared_ptr<IPropertyInstanceInfo> TPropertyInstanceInfoPtr; + +struct SInstanceSlideInformation +{ + // The slide associated with the instance + Qt3DSDMSlideHandle m_AssociatedSlide; + // The master slide of the component. + Qt3DSDMSlideHandle m_MasterSlide; + // The active slide of the component. + Qt3DSDMSlideHandle m_ActiveSlide; + // The current milliseconds of the active slide on the component. + long m_ComponentMilliseconds; + + SInstanceSlideInformation() + : m_ComponentMilliseconds(0) + { + } + SInstanceSlideInformation(Qt3DSDMSlideHandle inAssoc, Qt3DSDMSlideHandle inMaster, + Qt3DSDMSlideHandle inActive, long inMilliseconds) + : m_AssociatedSlide(inAssoc) + , m_MasterSlide(inMaster) + , m_ActiveSlide(inActive) + , m_ComponentMilliseconds(inMilliseconds) + { + } +}; + +class ISlideSystem +{ +public: + virtual ~ISlideSystem() {} + virtual Qt3DSDMSlideHandle CreateMasterSlide() = 0; + virtual Qt3DSDMSlideHandle CreateSlide(Qt3DSDMSlideHandle inMaster, int inIndex = -1) = 0; + // Duplicate this slide and put it into the master's child lists at index. + virtual Qt3DSDMSlideHandle DuplicateSlide(Qt3DSDMSlideHandle inSourceSlide, int inDestIndex) = 0; + virtual Qt3DSDMSlideHandle GetMasterSlide(Qt3DSDMSlideHandle inSlide) const = 0; + virtual bool IsMasterSlide(Qt3DSDMSlideHandle inSlide) const = 0; + virtual Qt3DSDMSlideHandle GetMasterSlideByComponentGuid(SLong4 inGuid) const = 0; + // Indexes are 1 based. Index 0 refers to the master slide; you can't delete this. + virtual void DeleteSlideByIndex(Qt3DSDMSlideHandle inMaster, size_t inIndex) = 0; + virtual void GetSlideReferencedInstances(Qt3DSDMSlideHandle inMaster, size_t inIndex, + TInstanceHandleList &outReferencedInstances) = 0; + virtual Qt3DSDMSlideHandle GetSlideByIndex(Qt3DSDMSlideHandle inMaster, size_t inIndex) const = 0; + virtual void SetActiveSlide(Qt3DSDMSlideHandle inMaster, size_t inIndex) = 0; + virtual void RearrangeSlide(Qt3DSDMSlideHandle inMaster, size_t inOldIndex, + size_t inNewIndex) = 0; + /** + * Set the current component time. This object will figure out the component from the slide. + */ + virtual void SetComponentSeconds(Qt3DSDMSlideHandle inSlide, float inSeconds) = 0; + /** + * Return the current time of the component + */ + virtual float GetComponentSeconds(Qt3DSDMSlideHandle inSlide) const = 0; + virtual long GetComponentSecondsLong(Qt3DSDMSlideHandle inSlide) const = 0; + virtual long GetComponentSecondsLong(Qt3DSDMInstanceHandle inInstance) const = 0; + + // The fastest way possible, get all of the slide information for this instance. + virtual SInstanceSlideInformation + GetInstanceSlideInformation(Qt3DSDMInstanceHandle inInstance) const = 0; + /** + * Slide count includes the master slide; + */ + virtual size_t GetSlideCount(Qt3DSDMSlideHandle inMaster) const = 0; + /** + * Use the instance for storing information such as name, or the GUID of the object + * this slide links to. + */ + virtual Qt3DSDMInstanceHandle GetSlideInstance(Qt3DSDMSlideHandle inSlide) const = 0; + /** + * Reverse lookup into the slide system so you can match slides to instances. + */ + virtual Qt3DSDMSlideHandle GetSlideByInstance(Qt3DSDMInstanceHandle inInstance) const = 0; + /** + * Slide may be either a master slide + */ + virtual void AssociateInstanceWithSlide(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) = 0; + virtual Qt3DSDMSlideHandle GetAssociatedSlide(Qt3DSDMInstanceHandle inInstance) const = 0; + virtual void GetAssociatedInstances( + Qt3DSDMSlideHandle inMaster, + std::vector<std::pair<Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle>> &outAssociations) const = 0; + virtual void GetAssociatedInstances(Qt3DSDMSlideHandle inSlide, + TInstanceHandleList &outAssociations) const = 0; + virtual void LinkProperty(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) = 0; + virtual void UnlinkProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) = 0; + virtual bool IsPropertyLinked(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const = 0; + virtual bool CanPropertyBeLinked(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const = 0; + virtual void GetUnionOfProperties(Qt3DSDMSlideHandle inSlide1, Qt3DSDMSlideHandle inSlide, + TInstancePropertyPairList &outProperties) const = 0; + + virtual bool GetSlidePropertyValue(size_t inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) = 0; + + virtual void SetActiveSlide(Qt3DSDMSlideHandle inSlide) = 0; + virtual Qt3DSDMSlideHandle GetAssociatedSlide(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const = 0; + + virtual bool SlideValid(Qt3DSDMSlideHandle inSlide) const = 0; + virtual int GetSlideIndex(Qt3DSDMSlideHandle inSlide) const = 0; + virtual int GetActiveSlideIndex(Qt3DSDMSlideHandle inMaster) const = 0; + virtual Qt3DSDMSlideHandle GetActiveSlide(Qt3DSDMSlideHandle inMaster) const = 0; + virtual Qt3DSDMInstanceHandle GetSlideSelectedInstance(Qt3DSDMSlideHandle inSlide) const = 0; + virtual void SetSlideSelectedInstance(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) = 0; + + virtual Qt3DSDMSlideHandle GetApplicableSlide(Qt3DSDMInstanceHandle inHandle) = 0; + virtual Qt3DSDMSlideHandle GetApplicableSlide(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) = 0; + + virtual bool GetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const = 0; + virtual bool GetCanonicalInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const = 0; + virtual void ForceSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) = 0; + + /** + * Let this object know that this property will sometimes reference another property + * and give an outside entity the chance to create new objects and properties when + * the property is unlinked and linked. + */ + virtual void RegisterPropertyInstance(Qt3DSDMPropertyHandle inPropertyHandle, + TPropertyInstanceInfoPtr inPropertyInfo) = 0; +}; + +typedef std::shared_ptr<ISlideSystem> TSlideSystemPtr; +} + +#endif diff --git a/src/dm/systems/Qt3DSDMStringTable.cpp b/src/dm/systems/Qt3DSDMStringTable.cpp new file mode 100644 index 0000000..58db71c --- /dev/null +++ b/src/dm/systems/Qt3DSDMStringTable.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "Qt3DSDMStringTable.h" +#include "foundation/StringTable.h" +#include "foundation/TrackingAllocator.h" + +using namespace qt3dsdm; +using namespace eastl; +using namespace qt3ds; + +namespace { + +struct StringTableImpl : public IStringTable +{ + qt3ds::foundation::MallocAllocator m_MallocAllocator; + qt3ds::foundation::IStringTable &m_StringTable; + StringTableImpl() + : m_StringTable(qt3ds::foundation::IStringTable::CreateStringTable(m_MallocAllocator)) + { + m_StringTable.addRef(); + } + StringTableImpl(qt3ds::foundation::IStringTable &inStrTable) + : m_StringTable(inStrTable) + { + m_StringTable.addRef(); + } + + virtual ~StringTableImpl() { m_StringTable.release(); } + const wchar_t *RegisterStr(const wchar_t *inStr) override + { + return m_StringTable.GetWideStr(inStr); + } + const char8_t *RegisterStr(const char8_t *inStr) override + { + return m_StringTable.GetNarrowStr(inStr); + } + // Get the utf-8 or utf-(sizeof wchar_t) converted strings + const wchar_t *GetWideStr(const char8_t *inStr) override + { + return m_StringTable.GetWideStr(inStr); + } + const char8_t *GetNarrowStr(const wchar_t *inStr) override + { + return m_StringTable.GetNarrowStr(inStr); + } + qt3ds::foundation::IStringTable &GetRenderStringTable() override { return m_StringTable; } +}; +} + +TStringTablePtr IStringTable::CreateStringTable() +{ + return std::make_shared<StringTableImpl>(); +} + +TStringTablePtr IStringTable::CreateStringTable(qt3ds::foundation::IStringTable &inStrTable) +{ + return std::make_shared<StringTableImpl>(std::ref(inStrTable)); +} diff --git a/src/dm/systems/Qt3DSDMStringTable.h b/src/dm/systems/Qt3DSDMStringTable.h new file mode 100644 index 0000000..7f1e945 --- /dev/null +++ b/src/dm/systems/Qt3DSDMStringTable.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_IMPORT_STRINGTABLE_H +#define QT3DS_IMPORT_STRINGTABLE_H + +#include <string> +#include <EABase/eabase.h> +#include "foundation/Qt3DSPreprocessor.h" + +namespace qt3ds { +namespace foundation { + class IStringTable; +} +} + +namespace qt3dsdm { + +class QT3DS_AUTOTEST_EXPORT IStringTable +{ +public: + virtual ~IStringTable() {} + + virtual const wchar_t *RegisterStr(const wchar_t *inStr) = 0; + virtual const char8_t *RegisterStr(const char8_t *inStr) = 0; + // Get the utf-8 or utf-(sizeof wchar_t) converted strings + virtual const wchar_t *GetWideStr(const char8_t *inStr) = 0; + virtual const char8_t *GetNarrowStr(const wchar_t *inStr) = 0; + + const wchar_t *GetWideStr(const wchar_t *inStr) { return RegisterStr(inStr); } + const char8_t *GetNarrowStr(const char8_t *inStr) { return RegisterStr(inStr); } + + const wchar_t *RegisterStr(const std::wstring &inStr) { return RegisterStr(inStr.c_str()); } + const char8_t *RegisterStr(const std::string &inStr) { return RegisterStr(inStr.c_str()); } + + virtual qt3ds::foundation::IStringTable &GetRenderStringTable() = 0; + + static std::shared_ptr<IStringTable> CreateStringTable(); + static std::shared_ptr<IStringTable> + CreateStringTable(qt3ds::foundation::IStringTable &inStrTable); +}; +typedef std::shared_ptr<IStringTable> TStringTablePtr; +}; + +#endif diff --git a/src/dm/systems/Qt3DSDMTestOps.h b/src/dm/systems/Qt3DSDMTestOps.h new file mode 100644 index 0000000..ac43eaf --- /dev/null +++ b/src/dm/systems/Qt3DSDMTestOps.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_OPS_H +#define QT3DSDM_OPS_H + +namespace qt3dsdm { +inline const TCharStr &GetPropertyName(const IDataCore &inModel, Qt3DSDMPropertyHandle inProperty) +{ + return inModel.GetProperty(inProperty).m_Name; +} + +inline bool PropertyNameMatches(const IDataCore &inModel, const TCharStr &inName, + Qt3DSDMPropertyHandle inProperty) +{ + return inName == GetPropertyName(inModel, inProperty); +} + +inline const Qt3DSDMPropertyHandle +GetPropertyByName(const IDataCore &inModel, Qt3DSDMInstanceHandle inInstance, const TCharStr &inName) +{ + using namespace std; + TPropertyHandleList properties; + inModel.GetAggregateInstanceProperties(inInstance, properties); + TPropertyHandleList::iterator theProp = + std::find_if(properties.begin(), properties.end(), + std::bind(PropertyNameMatches, std::ref(inModel), inName, + std::placeholders::_1)); + if (theProp != properties.end()) + return *theProp; + return 0; +} +} + +#endif diff --git a/src/dm/systems/Qt3DSDMTransactions.h b/src/dm/systems/Qt3DSDMTransactions.h new file mode 100644 index 0000000..f6ed3da --- /dev/null +++ b/src/dm/systems/Qt3DSDMTransactions.h @@ -0,0 +1,244 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_TRANSACTIONS_H +#define QT3DSDM_TRANSACTIONS_H +#include "Qt3DSDMDataTypes.h" +#include "StandardExtensions.h" +#include <functional> + +namespace qt3dsdm { + +/** + * Transaction is some small entity that changes data. A transaction consumer is expected to + *execute + * a list of these either forward on a "redo" command or backwards on an "undo" command. + * + * Transactions merely change data. There are two other lists on consumers for "do" + *notifications + * and "undo" notifications. These lists control the events sent out to the UI about what + *actually + * changed in the model. Note that undo/do notifications may be more clever than simple + *send-signal + * commands in that they may check if an object is alive or not before sending a notification + *and may + * decline to send a notification if the target object is not currently alive. + * + * Currently the undo/redo system first executes all of the transactions and then sends the + *appropriate + * notifications. This means that when the UI receives any notification, the model is in its + *most-updated + * state. + */ +class ITransaction +{ +public: + const char *m_File; + int m_Line; + + ITransaction(const char *inFile, int inLine) + : m_File(inFile) + , m_Line(inLine) + { + } + virtual ~ITransaction() {} + virtual void Do() = 0; + virtual void Undo() = 0; +}; + +/** + * Merging allows us to efficient handle situations where the users are continuously + * modifying an object (or set of objects). These are referred to as live-update + * scenarios. Dragging an object in the 3d view or dragging keyframes in the timeline + * would be an example of live-update scenarios. + */ +template <typename TValueType> +class IMergeableTransaction +{ +public: + virtual ~IMergeableTransaction() {} + // Called when a new value has arrived and we would rather update + // an existing representation rather than create a new one. + virtual void Update(const TValueType &inValue) = 0; +}; + +/** + * A consumer is an object that records the transaction. This interface keeps the + * base producer objects from binding to how the transaction or the notifications + * are stored. + */ +class ITransactionConsumer +{ +public: + virtual ~ITransactionConsumer() {} + virtual void OnTransaction(std::shared_ptr<ITransaction> inTransaction) = 0; + // Notifications to be sent for undo/redo These are used to + // notify clients that something is different. + virtual void OnDoNotification(std::function<void()> inNotification) = 0; + virtual void OnUndoNotification(std::function<void()> inNotification) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Implementation of helper objects and functions. +/////////////////////////////////////////////////////////////////////////////// + +typedef std::vector<std::function<void()>> TVoidFunctionList; + +typedef std::shared_ptr<ITransactionConsumer> TTransactionConsumerPtr; + +class ITransactionProducer +{ +public: + virtual ~ITransactionProducer() {} + virtual void SetConsumer(TTransactionConsumerPtr inConsumer) = 0; +}; + +template <typename TDoTransaction, typename TUndoTransaction> +class CGenericTransaction : public ITransaction +{ + Q_DISABLE_COPY(CGenericTransaction) + + TUndoTransaction m_UndoTransaction; + TDoTransaction m_DoTransaction; + +public: + CGenericTransaction(const char *inFile, int inLine, TDoTransaction inDo, + TUndoTransaction inUndo) + : ITransaction(inFile, inLine) + , m_UndoTransaction(inUndo) + , m_DoTransaction(inDo) + { + } + void Do() override { m_DoTransaction(); } + void Undo() override { m_UndoTransaction(); } +}; + +template <typename TDoTransaction, typename TUndoTransaction> +ITransaction *DoCreateGenericTransaction(const char *inFile, int inLine, TDoTransaction inDo, + TUndoTransaction inUndo) +{ + return static_cast<ITransaction *>( + new CGenericTransaction<TDoTransaction, TUndoTransaction>(inFile, inLine, inDo, inUndo)); +} + +#define CREATE_GENERIC_TRANSACTION(inDo, inUndo) \ + DoCreateGenericTransaction(__FILE__, __LINE__, inDo, inUndo) + +typedef std::shared_ptr<ITransaction> TTransactionPtr; +typedef std::vector<TTransactionPtr> TTransactionPtrList; + +struct CTransactionConsumer : public ITransactionConsumer +{ + TTransactionPtrList m_TransactionList; + TVoidFunctionList m_DoNotifications; + TVoidFunctionList m_UndoNotifications; + void OnTransaction(TTransactionPtr inTransaction) override + { + m_TransactionList.push_back(inTransaction); + } + void OnDoNotification(std::function<void()> inNotification) override + { + m_DoNotifications.push_back(inNotification); + } + void OnUndoNotification(std::function<void()> inNotification) override + { + m_UndoNotifications.push_back(inNotification); + } + + // Merge with another CTransactionConsumer + virtual void Merge(const ITransactionConsumer *inConsumer) + { + const CTransactionConsumer *theConsumer = + static_cast<const CTransactionConsumer *>(inConsumer); + m_TransactionList.insert(m_TransactionList.begin(), theConsumer->m_TransactionList.begin(), + theConsumer->m_TransactionList.end()); + } + void Reset() + { + m_TransactionList.clear(); + m_DoNotifications.clear(); + m_UndoNotifications.clear(); + } +}; + +template <typename TTransactionType> +inline void RunWithConsumer(TTransactionConsumerPtr inConsumer, TTransactionType inTransaction) +{ + if (inConsumer) + inTransaction(inConsumer); +} + +template <typename TDoTransaction, typename TUndoTransaction> +inline void CreateGenericTransactionWithConsumer(const char *inFile, int inLine, + TTransactionConsumerPtr inConsumer, + TDoTransaction inDoTransaction, + TUndoTransaction inUndoTransaction) +{ + if (inConsumer) + inConsumer->OnTransaction(TTransactionPtr( + DoCreateGenericTransaction(inFile, inLine, inDoTransaction, inUndoTransaction))); +} + +template <typename TItemType> +inline void DoSetConsumer(TTransactionConsumerPtr inConsumer, + std::shared_ptr<TItemType> inTypePtr) +{ + ITransactionProducer *theProducer = dynamic_cast<ITransactionProducer *>(inTypePtr.get()); + if (theProducer) + theProducer->SetConsumer(inConsumer); +} + +template <typename TContainer> +inline void Undo(TContainer &inTransactions) +{ + std::for_each(inTransactions.rbegin(), inTransactions.rend(), std::bind(&ITransaction::Undo, + std::placeholders::_1)); +} + +template <typename TContainer> +inline void Redo(TContainer &inTransactions) +{ + do_all(inTransactions, std::bind(&ITransaction::Do, std::placeholders::_1)); +} + +template <typename TItemType> +void Notify(std::vector<TItemType> &inNotifications) +{ + do_all(inNotifications, std::bind(&TItemType::operator(), std::placeholders::_1)); +} + +template <typename TItemType> +void NotifyReverse(std::vector<TItemType> &inNotifications) +{ + std::for_each(inNotifications.rbegin(), inNotifications.rend(), + std::bind(&TItemType::operator(), std::placeholders::_1)); +} +} + +#endif diff --git a/src/dm/systems/Qt3DSDMValue.cpp b/src/dm/systems/Qt3DSDMValue.cpp new file mode 100644 index 0000000..94c5a59 --- /dev/null +++ b/src/dm/systems/Qt3DSDMValue.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "Qt3DSDMValue.h" + +#include <QColor> +#include <QDebug> +#include <QVariant> + +using namespace qt3dsdm; + +SValue::SValue(const QVariant &inData) +{ + switch (inData.type()) { + case QVariant::Bool: + { + *this = inData.toBool(); + break; + } + case QVariant::Color: + { + const QColor c = inData.value<QColor>(); + *this = qt3dsdm::SFloat4(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + break; + } + case QVariant::String: + { + const QString q = inData.toString(); + const int count = q.size() + 1; +#ifdef __INTEGRITY + wchar_t* tempBuf = reinterpret_cast<wchar_t*>(malloc(count * sizeof(wchar_t))); +#else + wchar_t* tempBuf = reinterpret_cast<wchar_t*>(alloca(count * sizeof(wchar_t))); +#endif + tempBuf[count - 1] = 0; + q.toWCharArray(tempBuf); + *this = std::make_shared<qt3dsdm::CDataStr>(tempBuf); +#ifdef __INTEGRITY + free(tempBuf); +#endif + break; + } + case QVariant::Int: { + *this = inData.toInt(); + break; + } + case QVariant::Double: { + *this = inData.toFloat(); + break; + } + + case QVariant::Vector2D: { + const auto v = inData.value<QVector2D>(); + *this = qt3dsdm::SFloat2(v.x(), v.y()); + break; + } + + case QVariant::Vector3D: { + const auto v = inData.value<QVector3D>(); + *this = qt3dsdm::SFloat3(v.x(), v.y(), v.z()); + break; + } + + default: + qDebug() << "Add a handler for QVariant::type" << inData.type(); + throw std::runtime_error("Cannot transform this QVariant into SValue"); + } +} + +QVariant SValue::toQVariant() const +{ + switch (getType()) { + case DataModelDataType::String: + case DataModelDataType::StringRef: + { + return get<QString>(*this); + } + case DataModelDataType::Float: { + return get<float>(*this); + } + case DataModelDataType::Float2: { + return QVariant::fromValue(get<QVector2D>(*this)); + } + case DataModelDataType::Float3: { + return QVariant::fromValue(get<QVector3D>(*this)); + } + case DataModelDataType::Float4: { + return QVariant::fromValue(get<QVector<float> >(*this)); + } + case DataModelDataType::Long: { + return QVariant::fromValue(get<qt3ds::QT3DSI32>(*this)); + } + case DataModelDataType::Bool: { + return get<bool>(*this); + } + case DataModelDataType::FloatList: { + //KDAB_TODO + qDebug() << "Add a handler for type DataModelDataType::FloatList"; + return {}; + } + case DataModelDataType::Long4: { + return QVariant::fromValue(get<QVector<qt3ds::QT3DSU32> >(*this)); + } + case DataModelDataType::ObjectRef: { + const SObjectRefType &theRef(get<SObjectRefType>(*this)); + switch (theRef.GetReferenceType()) { + case ObjectReferenceType::Absolute: + return SValue(get<SLong4>(theRef.m_Value)).toQVariant(); + break; + case ObjectReferenceType::Relative: + return SValue(get<TDataStrPtr>(theRef.m_Value)).toQVariant(); + break; + case ObjectReferenceType::Unknown: + return QVariant::fromValue(QVector<qt3ds::QT3DSU32>()); + break; + } + } + case DataModelDataType::StringOrInt: { + const SStringOrInt &theData(get<SStringOrInt>(*this)); + if (theData.GetType() == SStringOrIntTypes::Int) { + return QVariant::fromValue(get<qt3ds::QT3DSI32>(theData.m_Value)); + } else if (theData.GetType() == SStringOrIntTypes::String) { + auto wideStr = get<TDataStrPtr>(theData.m_Value)->GetData(); + return QString::fromWCharArray(wideStr); + } else { + return {}; + } + + } + case DataModelDataType::None: + return {}; + default: + break; + } + return {}; +} + +SInternValue::SInternValue(const SValue &inValue, IStringTable &inStringTable) +{ + if (GetValueType(inValue) == DataModelDataType::StringRef) { + const SStringRef ¤t = get<SStringRef>(inValue); + SStringRef newId = inStringTable.RegisterStr(current.m_Id); + m_Value = SValue(newId); + } else { + m_Value = inValue; + } +} + +SInternValue::SInternValue(const SInternValue &inOther) + : m_Value(inOther.m_Value) +{ +} diff --git a/src/dm/systems/Qt3DSDMValue.h b/src/dm/systems/Qt3DSDMValue.h new file mode 100644 index 0000000..9e00632 --- /dev/null +++ b/src/dm/systems/Qt3DSDMValue.h @@ -0,0 +1,341 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_VALUE_H +#define QT3DSDM_VALUE_H +#include "Qt3DSDMDataTypes.h" + +#include <QColor> +#include <QMetaType> +#include <QVariant> +#include <QVector> +#include <QVector2D> +#include <QVector3D> + +namespace qt3dsdm { + +template <typename TDataType> +struct SDataTypeToEnumMap +{ +}; + +template <DataModelDataType::Value TEnumVal> +struct SEnumToDataTypeMap +{ +}; + +#define DEFINE_QT3DSDM_DATA_TYPE_MAP(dtype, enumName) \ + template <> \ + struct SDataTypeToEnumMap<dtype> \ + { \ + static DataModelDataType::Value getType() { return enumName; } \ + }; \ + template <> \ + struct SEnumToDataTypeMap<enumName> \ + { \ + typedef dtype TDataType; \ + }; + +#define ITERATE_QT3DSDM_DATA_TYPES \ + HANDLE_QT3DSDM_DATA_TYPE(float, DataModelDataType::Float); \ + HANDLE_QT3DSDM_DATA_TYPE(SFloat2, DataModelDataType::Float2); \ + HANDLE_QT3DSDM_DATA_TYPE(SFloat3, DataModelDataType::Float3); \ + HANDLE_QT3DSDM_DATA_TYPE(SFloat4, DataModelDataType::Float4); \ + HANDLE_QT3DSDM_DATA_TYPE(qt3ds::QT3DSI32, DataModelDataType::Long); \ + HANDLE_QT3DSDM_DATA_TYPE(TDataStrPtr, DataModelDataType::String); \ + HANDLE_QT3DSDM_DATA_TYPE(bool, DataModelDataType::Bool); \ + HANDLE_QT3DSDM_DATA_TYPE(SLong4, DataModelDataType::Long4); \ + HANDLE_QT3DSDM_DATA_TYPE(SStringRef, DataModelDataType::StringRef); \ + HANDLE_QT3DSDM_DATA_TYPE(SObjectRefType, DataModelDataType::ObjectRef); \ + HANDLE_QT3DSDM_DATA_TYPE(SStringOrInt, DataModelDataType::StringOrInt); \ + HANDLE_QT3DSDM_DATA_TYPE(TFloatList, DataModelDataType::FloatList); + +#define HANDLE_QT3DSDM_DATA_TYPE(a, b) DEFINE_QT3DSDM_DATA_TYPE_MAP(a, b) +ITERATE_QT3DSDM_DATA_TYPES +#undef HANDLE_QT3DSDM_DATA_TYPE + +struct Qt3DSDMDataTypeUnionTraits +{ + typedef DataModelDataType::Value TIdType; + + enum { + TBufferSize = sizeof(SObjectRefType), + }; + + static TIdType getNoDataId() { return DataModelDataType::None; } + + template <typename TDataType> + static TIdType getType() + { + return SDataTypeToEnumMap<TDataType>::getType(); + } + + template <typename TRetType, typename TVisitorType> + static TRetType visit(char *inData, DataModelDataType::Value inType, TVisitorType inVisitor) + { + switch (inType) { +#define HANDLE_QT3DSDM_DATA_TYPE(dtype, enumType) \ + case enumType: \ + return inVisitor(*NVUnionCast<dtype *>(inData)); + ITERATE_QT3DSDM_DATA_TYPES +#undef HANDLE_QT3DSDM_DATA_TYPE + + default: + QT3DS_ASSERT(false); + case DataModelDataType::None: + return inVisitor(); + } + } + + template <typename TRetType, typename TVisitorType> + static TRetType visit(const char *inData, DataModelDataType::Value inType, TVisitorType inVisitor) + { + switch (inType) { +#define HANDLE_QT3DSDM_DATA_TYPE(dtype, enumType) \ + case enumType: \ + return inVisitor(*NVUnionCast<const dtype *>(inData)); + ITERATE_QT3DSDM_DATA_TYPES +#undef HANDLE_QT3DSDM_DATA_TYPE + + default: + QT3DS_ASSERT(false); + case DataModelDataType::None: + return inVisitor(); + } + } +}; + +typedef qt3ds::foundation:: + DiscriminatedUnion<qt3ds::foundation:: + DiscriminatedUnionGenericBase<Qt3DSDMDataTypeUnionTraits, + Qt3DSDMDataTypeUnionTraits::TBufferSize>, + Qt3DSDMDataTypeUnionTraits::TBufferSize> + TValue; + +struct SValue : public TValue +{ + SValue() {} + SValue(const SValue &inOther) + : TValue(static_cast<const TValue &>(inOther)) + { + } + SValue(const QVariant &inData); + + template <typename TDataType> + SValue(const TDataType &inData) + : TValue(inData) + { + } + SValue &operator=(const SValue &inOther) + { + TValue::operator=(inOther); + return *this; + } + bool operator==(const SValue &inOther) const { return TValue::operator==(inOther); } + bool operator!=(const SValue &inOther) const { return TValue::operator!=(inOther); } + bool empty() const { return getType() == DataModelDataType::None; } + + // Conversion from this data type into a data model value + const SValue &toOldSkool() const { return *this; } + + QVariant toQVariant() const; +}; + +typedef std::shared_ptr<SValue> SValuePtr; + +template <> +struct Qt3DSDMGetter<SValue> +{ + template <typename TRetType> + TRetType doGet(const SValue &inValue) + { + return inValue.getData<TRetType>(); + } +}; + +template <> +struct Qt3DSDMValueTyper<SValue> +{ + DataModelDataType::Value Get(const SValue &inValue) { return inValue.getType(); } +}; + +inline bool CheckValueType(DataModelDataType::Value inType, const SValue &inValue) +{ + bool retval = inType == inValue.getType(); + if (!retval) + throw ValueTypeError(L""); + return retval; +} + +inline bool Equals(const SValue &lhs, const SValue &rhs) +{ + return lhs == rhs; +} + +class SInternValue +{ + SValue m_Value; + +public: + SInternValue(const SValue &inValue, IStringTable &inTable); + SInternValue() {} + SInternValue(const SInternValue &inOther); + SInternValue &operator=(const SInternValue &inOther) + { + m_Value = inOther.m_Value; + return *this; + } + + static SInternValue ISwearThisHasAlreadyBeenInternalized(const SValue &inValue) + { + SInternValue retval; + retval.m_Value = inValue; + return retval; + } + + const SValue &GetValue() const { return m_Value; } + operator const SValue &() const { return m_Value; } +}; + +template <> +struct SDefaulter<SValue> +{ + inline bool SetDefault(DataModelDataType::Value inDataType, SValue &outValue) + { + switch (inDataType) { + case DataModelDataType::Float: + outValue = SValue(0.f); + break; + case DataModelDataType::Float2: + outValue = SValue(SFloat2()); + break; + case DataModelDataType::Float3: + outValue = SValue(SFloat3()); + break; + case DataModelDataType::Float4: + outValue = SValue(SFloat4()); + break; + case DataModelDataType::Long: + outValue = SValue(0); + break; + case DataModelDataType::String: + outValue = SValue(TDataStrPtr(new CDataStr(L""))); + break; + case DataModelDataType::Bool: + outValue = SValue(false); + break; + case DataModelDataType::Long4: + outValue = SValue(SLong4()); + break; + case DataModelDataType::StringRef: + outValue = SValue(SStringRef()); + break; + case DataModelDataType::ObjectRef: + outValue = SValue(SObjectRefType()); + break; + case DataModelDataType::FloatList: + outValue = SValue(TFloatList()); + break; + case DataModelDataType::StringOrInt: + default: + outValue = SValue(SStringOrInt()); + return false; + } + return true; + } +}; + +inline SObjectRefType ConvertToObjectRef(const SValue &inValue) +{ + using namespace std; + switch (GetValueType(inValue)) { + case DataModelDataType::StringRef: + return SObjectRefType(make_shared<CDataStr>(get<SStringRef>(inValue).m_Id)); + case DataModelDataType::String: + return SObjectRefType(get<TDataStrPtr>(inValue)); + case DataModelDataType::Long4: + return SObjectRefType(get<SLong4>(inValue)); + case DataModelDataType::ObjectRef: + return get<SObjectRefType>(inValue); + default: + break; + } + return SObjectRefType(); +} + + +template <> +inline QColor get<QColor>(const SValue &inType) +{ + auto f = get<qt3dsdm::SFloat4>(inType); + qreal r = qBound<qreal>(0.0, f.m_Floats[0], 1.0); + qreal g = qBound<qreal>(0.0, f.m_Floats[1], 1.0); + qreal b = qBound<qreal>(0.0, f.m_Floats[2], 1.0); + qreal a = qBound<qreal>(0.0, f.m_Floats[3], 1.0); + return QColor::fromRgbF(r, g, b, a); +} + +template <> +inline QString get<QString>(const qt3dsdm::SValue &inType) +{ + return QString::fromWCharArray(qt3dsdm::get<qt3dsdm::TDataStrPtr>(inType)->GetData()); +} + +template <> +inline QVector2D get<QVector2D>(const qt3dsdm::SValue &inType) +{ + auto f = get<qt3dsdm::SFloat2>(inType); + return QVector2D(f.m_Floats[0], f.m_Floats[1]); +} + +template <> +inline QVector3D get<QVector3D>(const qt3dsdm::SValue &inType) +{ + auto f = get<qt3dsdm::SFloat3>(inType); + return QVector3D(f.m_Floats[0], f.m_Floats[1], f.m_Floats[2]); +} + +template <> +inline QVector<float> get<QVector<float> >(const qt3dsdm::SValue &inType) +{ + auto f = get<qt3dsdm::SFloat4>(inType); + return {f.m_Floats[0], f.m_Floats[1], f.m_Floats[2], f.m_Floats[3]}; +} + +// KDAB_TODO Shortcut to not define our own 4 member long structure +template <> +inline QVector<qt3ds::QT3DSU32> get<QVector<qt3ds::QT3DSU32> >(const qt3dsdm::SValue &inType) +{ + auto f = get<qt3dsdm::SLong4>(inType); + return {f.m_Longs[0], f.m_Longs[1], f.m_Longs[2], f.m_Longs[3]}; +} + +} +Q_DECLARE_METATYPE(qt3dsdm::DataModelDataType) +#endif diff --git a/src/dm/systems/Qt3DSDMWStrOps.h b/src/dm/systems/Qt3DSDMWStrOps.h new file mode 100644 index 0000000..b1e1fb0 --- /dev/null +++ b/src/dm/systems/Qt3DSDMWStrOps.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_WSTR_OPS_H +#define QT3DSDM_WSTR_OPS_H +namespace qt3dsdm { +// Template base class so that we can convert items to and from wide string +template <typename TDataType> +struct WStrOps +{ + bool force_compile_error; +}; +} +#endif
\ No newline at end of file diff --git a/src/dm/systems/Qt3DSDMWStrOpsImpl.h b/src/dm/systems/Qt3DSDMWStrOpsImpl.h new file mode 100644 index 0000000..d65ac13 --- /dev/null +++ b/src/dm/systems/Qt3DSDMWStrOpsImpl.h @@ -0,0 +1,761 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_IMPORT_WSTR_OPS_IMPL_H +#define QT3DS_IMPORT_WSTR_OPS_IMPL_H +#include "Qt3DSDMDataTypes.h" +#include "Qt3DSDMWStrOps.h" +#include "foundation/Qt3DSMemoryBuffer.h" +#include "foundation/Qt3DSMemoryBuffer.h" +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMAnimation.h" +#include "Qt3DSDMMetaDataTypes.h" +#include "Qt3DSDMXML.h" +#include "EABase/eabase.h" +#include "Qt3DSDMStringTable.h" + +namespace qt3dsdm { +using qt3ds::QT3DSI8; +using qt3ds::QT3DSU8; +using qt3ds::QT3DSI16; +using qt3ds::QT3DSU16; +using qt3ds::QT3DSU32; +using qt3ds::QT3DSI32; +using qt3ds::QT3DSU64; +using qt3ds::QT3DSI64; +using qt3ds::QT3DSF32; +using qt3ds::QT3DSF64; +template <> +struct WStrOps<bool> +{ + QT3DSU32 ToStr(bool item, NVDataRef<wchar_t> buffer) + { + return static_cast<QT3DSU32>( + swprintf(buffer.begin(), buffer.size(), L"%s", item ? L"True" : L"False")); + } + bool StrTo(const wchar_t *buffer, bool &item) + { + if (AreEqual(buffer, L"True")) + item = true; + else + item = false; + return true; + } + QT3DSU32 ToStr(bool item, NVDataRef<char8_t> buffer) + { + return static_cast<QT3DSU32>( + _snprintf(buffer.begin(), buffer.size(), "%s", item ? "True" : "False")); + } + bool StrTo(const char8_t *buffer, bool &item) + { + if (AreEqualCaseless(buffer, "True")) + item = true; + else + item = false; + return true; + } +}; +template <> +struct WStrOps<QT3DSU8> +{ + QT3DSU32 ToStr(QT3DSU8 item, NVDataRef<wchar_t> buffer) + { + return static_cast<QT3DSU32>( + swprintf(buffer.begin(), buffer.size(), L"%hu", static_cast<QT3DSU16>(item))); + } + bool StrTo(const char8_t *buffer, QT3DSU8 &item) + { + item = static_cast<QT3DSU8>(strtoul(buffer, NULL, 10)); + return true; + } +}; +template <> +struct WStrOps<QT3DSI8> +{ + QT3DSU32 ToStr(QT3DSI8 item, NVDataRef<wchar_t> buffer) + { + return static_cast<QT3DSU32>( + swprintf(buffer.begin(), buffer.size(), L"%hd", static_cast<QT3DSI16>(item))); + } + bool StrTo(const char8_t *buffer, QT3DSI8 &item) + { + item = static_cast<QT3DSI8>(strtol(buffer, NULL, 10)); + return true; + } +}; +template <> +struct WStrOps<QT3DSU16> +{ + QT3DSU32 ToStr(QT3DSU16 item, NVDataRef<wchar_t> buffer) + { + return static_cast<QT3DSU32>(swprintf(buffer.begin(), buffer.size(), L"%hu", item)); + } + bool StrTo(const char8_t *buffer, QT3DSU16 &item) + { + item = static_cast<QT3DSU16>(strtoul(buffer, NULL, 10)); + return true; + } +}; +template <> +struct WStrOps<QT3DSI16> +{ + QT3DSU32 ToStr(QT3DSI16 item, NVDataRef<wchar_t> buffer) + { + return static_cast<QT3DSU32>(swprintf(buffer.begin(), buffer.size(), L"%hd", item)); + } + QT3DSU32 ToStr(QT3DSI16 item, NVDataRef<char8_t> buffer) + { + return static_cast<QT3DSU32>(sprintf(buffer.begin(), "%hd", item)); + } + bool StrTo(const char8_t *buffer, QT3DSI16 &item) + { + item = static_cast<QT3DSI16>(strtol(buffer, NULL, 10)); + return true; + } +}; + +template <> +struct WStrOps<QT3DSU32> +{ + QT3DSU32 ToStr(QT3DSU32 item, NVDataRef<wchar_t> buffer) + { + return static_cast<QT3DSU32>(swprintf(buffer.begin(), buffer.size(), L"%lu", item)); + } + QT3DSU32 ToStr(QT3DSU32 item, NVDataRef<char8_t> buffer) + { + // hope the buffer is big enough... + return static_cast<QT3DSU32>(sprintf(buffer.begin(), "%u", item)); + } + bool StrTo(const char8_t *buffer, QT3DSU32 &item) + { + item = strtoul(buffer, NULL, 10); + return true; + } +}; + +template <> +struct WStrOps<QT3DSI32> +{ + QT3DSU32 ToStr(QT3DSI32 item, NVDataRef<wchar_t> buffer) + { + return static_cast<QT3DSU32>(swprintf(buffer.begin(), buffer.size(), L"%ld", item)); + } + bool StrTo(const char8_t *buffer, QT3DSI32 &item) + { + item = strtol(buffer, NULL, 10); + return true; + } +}; +template <> +struct WStrOps<QT3DSF32> +{ + QT3DSU32 ToStr(QT3DSF32 item, NVDataRef<wchar_t> buffer) + { + QString s = QLocale::c().toString(item); + wcsncpy(buffer.begin(), s.toStdWString().c_str(), buffer.size()); + return s.length(); + } + QT3DSU32 ToStr(QT3DSF32 item, NVDataRef<char8_t> buffer) + { + QString s = QLocale::c().toString(item); + strncpy(buffer.begin(), s.toStdString().c_str(), buffer.size()); + return s.length(); + } + bool StrTo(const char8_t *buffer, QT3DSF32 &item) + { + bool ok; + item = QLocale::c().toFloat(buffer, &ok); + return ok; + } +}; + +template <> +struct WStrOps<QT3DSF64> +{ + QT3DSU32 ToStr(QT3DSF64 item, NVDataRef<wchar_t> buffer) + { + QString s = QLocale::c().toString(item); + wcsncpy(buffer.begin(), s.toStdWString().c_str(), buffer.size()); + return s.length(); + } + bool StrTo(const char8_t *buffer, QT3DSF64 &item) + { + bool ok; + item = QLocale::c().toDouble(buffer, &ok); + return ok; + } +}; +#define QT3DS_WCHAR_T_None L"None" +#define QT3DS_WCHAR_T_Float L"Float" +#define QT3DS_WCHAR_T_Float2 L"Float2" +#define QT3DS_WCHAR_T_Float3 L"Float3" +#define QT3DS_WCHAR_T_Float4 L"Float4" +#define QT3DS_WCHAR_T_Long L"Long" +#define QT3DS_WCHAR_T_String L"String" +#define QT3DS_WCHAR_T_Bool L"Bool" +#define QT3DS_WCHAR_T_Long4 L"Long4" +#define QT3DS_WCHAR_T_StringRef L"StringRef" +#define QT3DS_WCHAR_T_ObjectRef L"ObjectRef" +#define QT3DS_WCHAR_T_StringOrInt L"StringOrInt" +#define QT3DS_WCHAR_T_FloatList L"FloatList" + +#define QT3DS_IMPORT_ITERATE_DMTYPE \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::None, None, QT3DSF32) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::Float, Float, QT3DSF32) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::Float2, Float2, SFloat2) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::Float3, Float3, SFloat3) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::Float4, Float4, SFloat4) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::Long, Long, QT3DSI32) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::String, String, TDataStrPtr) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::Bool, Bool, bool) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::Long4, Long4, SLong4) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::StringRef, StringRef, SStringRef) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::ObjectRef, ObjectRef, SObjectRefType) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::StringOrInt, StringOrInt, SStringOrInt) \ + QT3DS_IMPORT_HANDLE_DMTYPE(DataModelDataType::FloatList, FloatList, TFloatList) + +template <> +struct WStrOps<DataModelDataType::Value> +{ + QT3DSU32 ToStr(DataModelDataType::Value item, NVDataRef<wchar_t> buffer) + { + const wchar_t *data = NULL; + switch (item) { +#define QT3DS_IMPORT_HANDLE_DMTYPE(x, y, z) \ + case x: \ + data = QT3DS_WCHAR_T_##y; \ + break; + QT3DS_IMPORT_ITERATE_DMTYPE +#undef QT3DS_IMPORT_HANDLE_DMTYPE + default: + break; + } + if (data == NULL) { + QT3DS_ASSERT(false); + data = L"Unknown"; + } + return (QT3DSU32)swprintf(buffer.begin(), buffer.size(), L"%ls", data); + } + bool StrTo(const wchar_t *buffer, DataModelDataType::Value &item) + { +#define QT3DS_IMPORT_HANDLE_DMTYPE(x, y, z) \ + if (AreEqual(buffer, QT3DS_WCHAR_T_##y)) { \ + item = x; \ + return true; \ + } + QT3DS_IMPORT_ITERATE_DMTYPE +#undef QT3DS_IMPORT_HANDLE_DMTYPE + item = DataModelDataType::None; + return false; + } +}; +template <typename TBufferType> +struct WStrOpsDMWriter +{ + TBufferType &buf; + WStrOpsDMWriter(TBufferType &_buf) + : buf(_buf) + { + } + + void operator()(float val) { buf.Write(val); } + void operator()(const SFloat2 &val) { buf.Write(NVConstDataRef<QT3DSF32>(&val[0], 2)); } + void operator()(const SFloat3 &val) { buf.Write(NVConstDataRef<QT3DSF32>(&val[0], 3)); } + void operator()(const SFloat4 &val) { buf.Write(NVConstDataRef<QT3DSF32>(&val[0], 4)); } + void operator()(QT3DSI32 val) { buf.Write(val); } + void operator()(bool val) { buf.Write(val); } + void operator()(const TDataStrPtr &val) + { + if (val != NULL) + buf.Write(NVConstDataRef<wchar_t>(val->GetData(), (QT3DSU32)val->GetLength())); + } + void operator()(const SLong4 &val) + { + buf.Write(NVConstDataRef<QT3DSU32>(&val.m_Longs[0], 4), 4); + } + void operator()(const SStringRef &val) { buf.Write(val.m_Id, (QT3DSU32)wcslen(val.m_Id) + 1); } + void operator()(const SObjectRefType &val) { val.m_Value.visit<void>(*this); } + void operator()(const SStringOrInt &val) { val.m_Value.visit<void>(*this); } + void operator()(const TFloatList &val) + { + buf.Write(NVConstDataRef<float>(val.data(), (QT3DSU32)val.size())); + } + void operator()() { QT3DS_ASSERT(false); } +}; + +template <> +struct WStrOps<SValue> +{ + template <typename TBufferType> + void ToBuf(const SValue &item, TBufferType &outBuffer) + { + WStrOpsDMWriter<TBufferType> writer(outBuffer); + item.visit<void>(writer); + } + template <typename TBufferType> + SValue BufTo(DataModelDataType::Value type, TBufferType &inReader) + { + switch (type) { +#define QT3DS_IMPORT_HANDLE_DMTYPE(x, y, z) \ + case x: { \ + z retval; \ + Read(inReader, retval); \ + return retval; \ + } + QT3DS_IMPORT_ITERATE_DMTYPE +#undef QT3DS_IMPORT_HANDLE_DMTYPE + default: + break; + } + QT3DS_ASSERT(false); + return SValue(); + } + template <typename TBufferType> + void Read(TBufferType &reader, float &val) + { + reader.Read(val); + } + template <typename TBufferType> + void Read(TBufferType &reader, SFloat2 &val) + { + reader.ReadRef(NVDataRef<QT3DSF32>(&val[0], 2)); + } + template <typename TBufferType> + void Read(TBufferType &reader, SFloat3 &val) + { + reader.ReadRef(NVDataRef<QT3DSF32>(&val[0], 3)); + } + template <typename TBufferType> + void Read(TBufferType &reader, SFloat4 &val) + { + reader.ReadRef(NVDataRef<QT3DSF32>(&val[0], 4)); + } + template <typename TBufferType> + void Read(TBufferType &reader, QT3DSI32 &val) + { + reader.Read(val); + } + template <typename TBufferType> + void Read(TBufferType &reader, bool &val) + { + reader.Read(val); + } + template <typename TBufferType> + void Read(TBufferType &reader, TDataStrPtr &val) + { + NVConstDataRef<wchar_t> buffer; + reader.ReadBuffer(buffer); + val = std::make_shared<CDataStr>(buffer.begin(), buffer.size()); + } + template <typename TBufferType> + void Read(TBufferType &reader, SLong4 &val) + { + reader.ReadRef(NVDataRef<QT3DSU32>(&val.m_Longs[0], 4)); + } + template <typename TBufferType> + void Read(TBufferType &reader, SStringRef &val) + { + NVConstDataRef<wchar_t> buffer; + reader.ReadBuffer(buffer); + val = SStringRef(buffer.begin()); + } + template <typename TBufferType> + void Read(TBufferType &reader, TFloatList &val) + { + NVConstDataRef<QT3DSF32> buffer; + reader.ReadBuffer(buffer); + val.assign(buffer.begin(), buffer.end()); + } + template <typename TBufferType> + void Read(TBufferType &reader, SObjectRefType &val) + { + // Force the read to be as string; callers can always convert to a different + // format later if required. + TDataStrPtr theValue; + Read(reader, theValue); + val.m_Value = theValue; + } + template <typename TBufferType> + void Read(TBufferType &reader, SStringOrInt &val) + { + NVConstDataRef<char8_t> buffer; + reader.ReadBuffer(buffer); + if (buffer.size() == 0) + return; + + if ((buffer[0] >= '0' && buffer[0] <= '9') || buffer[0] == '-') { + QT3DSI32 theVal; + WStrOps<QT3DSI32>().StrTo(buffer.begin(), theVal); + val = SStringOrInt(theVal); + } else { + NVConstDataRef<wchar_t> wideBuffer; + reader.ReadBuffer(wideBuffer); + val = SStringOrInt(std::make_shared<CDataStr>(wideBuffer.begin())); + } + } +}; + +// Write the wchar_t but exlude the null terminator +// Meant to write data model values. +// Memory buffer contains a non-null-terminated +// wchar_t string +struct WCharTWriter +{ + MemoryBuffer<RawAllocator> &m_Buffer; + WCharTWriter(MemoryBuffer<RawAllocator> &buf) + : m_Buffer(buf) + { + } + void Write(const wchar_t *value, QT3DSU32 len = 0) + { + if (IsTrivial(value)) + return; + if (len == 0) + len = (QT3DSU32)wcslen(value); + m_Buffer.write(value, len); + } + void Write(wchar_t value) { m_Buffer.write(value); } + void Write(bool value) { Write(value ? L"True" : L"False"); } + + // Takes care of long and float + template <typename TDataType> + void Write(TDataType value) + { + wchar_t buf[256]; + QT3DSU32 numWritten = WStrOps<TDataType>().ToStr(value, NVDataRef<wchar_t>(buf, 256)); + if (numWritten) + Write((const wchar_t *)buf); + else { + QT3DS_ASSERT(false); + } + } + template <typename TDataType> + void Write(NVConstDataRef<TDataType> values, QT3DSU32 grouping = 6, QT3DSU32 tabCount = 0) + { + for (QT3DSU32 idx = 0; idx < values.size(); ++idx) { + if (idx) { + if ((idx % grouping) == 0) { + Write((wchar_t)'\n'); + for (QT3DSU32 tabIdx = 0; tabIdx < tabCount; ++tabIdx) + Write((wchar_t)'\t'); + } else + Write((wchar_t)' '); + } + Write(values[idx]); + } + } + + void Write(NVConstDataRef<wchar_t> values, QT3DSU32 ignored = 6) + { + (void)ignored; + if (values.size() && values[0] != 0) { + QT3DSU32 lastItem = values.size() - 1; + if (values[lastItem] == 0) + --lastItem; + Write(values.begin(), lastItem + 1); + } + } +}; + +inline bool IsWhite(wchar_t value) +{ + return value == '\n' || value == '\r' || value == ' ' || value == '\t'; +} + +// skip until we find whitespace. +inline wchar_t *FindNextWhitespace(wchar_t *input) +{ + if (input == NULL) + return input; + wchar_t *marker = input; + // Empty loop intentional + for (; *marker && !IsWhite(*marker); ++marker) + ; + return marker; +} + +// skip until we find whitespace. +inline char8_t *FindNextWhitespace(char8_t *input) +{ + if (input == NULL) + return input; + char8_t *marker = input; + // Empty loop intentional + for (; *marker && !IsWhite(*marker); ++marker) + ; + return marker; +} + +// skip until we find something that isn't whitespace. +inline wchar_t *FindNextNonWhitespace(wchar_t *input) +{ + if (input == NULL) + return input; + wchar_t *marker = input; + // Empty loop intentional + for (; *marker && IsWhite(*marker); ++marker) + ; + return marker; +} + +inline char8_t *FindNextNonWhitespace(char8_t *input) +{ + if (input == NULL) + return input; + char8_t *marker = input; + // Empty loop intentional + for (; *marker && IsWhite(*marker); ++marker) + ; + return marker; +} + +// Reading is destructive in the case of floating point lists, so we may +// destroy the incoming string. +// We are assuming the string is null-terminated at end ptr. +struct WCharTReader +{ + char8_t *m_StartPtr; + // Buffer used for temp storage + MemoryBuffer<RawAllocator> &m_Buffer; + IStringTable &m_StringTable; + WCharTReader(char8_t *sp, MemoryBuffer<RawAllocator> &buf, IStringTable &inStringTable) + : m_StartPtr(sp) + , m_Buffer(buf) + , m_StringTable(inStringTable) + { + } + void Read(const char8_t *&outPtr) { outPtr = m_StartPtr; } + void Read(const wchar_t *&outPtr) { outPtr = m_StringTable.GetWideStr(m_StartPtr); } + template <typename TDataType> + void Read(TDataType &data) + { + bool success = WStrOps<TDataType>().StrTo(m_StartPtr, data); + QT3DS_ASSERT(success); + (void)success; + } + // Destructive operation because we can't trust + // strtod to do the right thing. On windows, for long strings, + // it calls strlen every operation thus leading to basically N^2 + // behavior + template <typename TDataType> + void ReadRef(NVDataRef<TDataType> data) + { + QT3DSU32 idx = 0; + m_StartPtr = FindNextNonWhitespace(m_StartPtr); + for (; idx < data.size() && m_StartPtr && *m_StartPtr; ++idx) { + char8_t *nextPtr = FindNextWhitespace(m_StartPtr); + if (nextPtr && *nextPtr) + *nextPtr = 0; + else + nextPtr = NULL; + WStrOps<TDataType>().StrTo(m_StartPtr, data[idx]); + m_StartPtr = nextPtr; + if (m_StartPtr) + m_StartPtr = FindNextNonWhitespace(m_StartPtr + 1); + } + } + + void ReadBuffer(NVConstDataRef<char8_t> &outBuffer) + { + if (m_StartPtr && *m_StartPtr) { + QT3DSU32 len = (QT3DSU32)strlen(m_StartPtr); + outBuffer = NVConstDataRef<char8_t>(m_StartPtr, len + 1); + } + } + void ReadBuffer(NVConstDataRef<wchar_t> &outBuffer) + { + if (m_StartPtr && *m_StartPtr) { + QT3DSU32 len = (QT3DSU32)strlen(m_StartPtr); + outBuffer = NVConstDataRef<wchar_t>(m_StringTable.GetWideStr(m_StartPtr), len + 1); + } + } + + // Destructive operation because we can't trust + // strtod to do the right thing. On windows, for long strings, + // it calls strlen every operation thus leading to basically N^2 + // behavior + template <typename TDataType> + void ReadBuffer(NVConstDataRef<TDataType> &outBuffer) + { + m_Buffer.clear(); + m_StartPtr = FindNextNonWhitespace(m_StartPtr); + while (m_StartPtr && *m_StartPtr) { + char8_t *nextPtr = FindNextWhitespace(m_StartPtr); + if (nextPtr && *nextPtr) + *nextPtr = 0; + else + nextPtr = NULL; + TDataType temp; + WStrOps<TDataType>().StrTo(m_StartPtr, temp); + m_Buffer.write(temp); + m_StartPtr = nextPtr; + if (m_StartPtr) + m_StartPtr = FindNextNonWhitespace(m_StartPtr + 1); + } + QT3DSU32 numItems = m_Buffer.size() / sizeof(TDataType); + if (numItems) + outBuffer = NVConstDataRef<TDataType>((TDataType *)m_Buffer.begin(), numItems); + else + outBuffer = NVConstDataRef<TDataType>(); + } +}; + +template <> +struct WStrOps<CDataModelHandle> +{ + template <typename THandleType> + QT3DSU32 ToStr(THandleType item, NVDataRef<wchar_t> buffer) + { + int theValue(item); + return WStrOps<int>().ToStr(theValue, buffer); + } + template <typename THandleType> + bool StrTo(const char8_t *buffer, THandleType &item) + { + int theValue; + bool retval = WStrOps<int>().StrTo(buffer, theValue); + item = theValue; + return retval; + } +}; + +#define IMPLEMENT_HANDLE_WSTROPS(HandleType) \ + template <> \ + struct WStrOps<HandleType> : public WStrOps<CDataModelHandle> \ + { \ + }; +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMInstanceHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMPropertyHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMSlideHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMSlideGraphHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMAnimationHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMKeyframeHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMActionHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMHandlerArgHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMEventHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMHandlerHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMHandlerParamHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMMetaDataPropertyHandle); +IMPLEMENT_HANDLE_WSTROPS(Qt3DSDMCategoryHandle); +#undef IMPLEMENT_HANDLE_WSTROPS + +template <> +struct WStrOps<EAnimationType> +{ + QT3DSU32 ToStr(EAnimationType value, NVDataRef<wchar_t> buffer) + { + const wchar_t *animType = NULL; + switch (value) { + case EAnimationTypeLinear: + animType = L"Linear"; + break; + case EAnimationTypeBezier: + animType = L"Bezier"; + break; + case EAnimationTypeEaseInOut: + animType = L"EaseInOut"; + break; + default: + QT3DS_ASSERT(false); + break; + } + if (animType != NULL) + return swprintf(buffer.begin(), buffer.size(), L"%ls", animType); + else { + QT3DS_ASSERT(false); + return 0; + } + } + bool StrTo(const wchar_t *buffer, EAnimationType &item) + { + if (AreEqual(L"Linear", buffer)) { + item = EAnimationTypeLinear; + return true; + } + if (AreEqual(L"Bezier", buffer)) { + item = EAnimationTypeBezier; + return true; + } + if (AreEqual(L"EaseInOut", buffer)) { + item = EAnimationTypeEaseInOut; + return true; + } + return false; + } +}; + +// Implemented in UICDMMetaData.h +template <> +struct WStrOps<CompleteMetaDataType::Enum> +{ + QT3DSU32 ToStr(CompleteMetaDataType::Enum item, NVDataRef<wchar_t> buffer); + bool StrTo(const wchar_t *buffer, CompleteMetaDataType::Enum &item); +}; + +template <> +struct WStrOps<HandlerArgumentType::Value> +{ + QT3DSU32 ToStr(HandlerArgumentType::Value item, NVDataRef<wchar_t> buffer); + bool StrTo(const wchar_t *buffer, HandlerArgumentType::Value &item); +}; + +#ifndef __clang__ +#ifndef __INTEGRITY +// IDOMReader implementations +template <typename TDataType> +bool IDOMReader::ValueList(NVDataRef<TDataType> data) +{ + const wchar_t *value; + if (Value(value)) { + WCharTReader reader(const_cast<wchar_t *>(value), m_TempBuf); + reader.ReadRef(data); + } + return true; +} + +// Destructive operation because we can't trust +// strtod to do the right thing. On windows, for long strings, +// it calls strlen every operation thus leading to basically N^2 +// behavior +template <typename TDataType> +NVConstDataRef<TDataType> IDOMReader::ChildValueList(TWideXMLCharPtr listName) +{ + NVConstDataRef<TDataType> retval; + TWideXMLCharPtr childValue = NULL; + if (ChildValue(listName, childValue)) { + WCharTReader reader(const_cast<wchar_t *>(childValue), m_TempBuf); + reader.ReadBuffer(retval); + } + return retval; +} +#endif +#endif +} + +#endif diff --git a/src/dm/systems/Qt3DSDMWindowsCompatibility.h b/src/dm/systems/Qt3DSDMWindowsCompatibility.h new file mode 100644 index 0000000..0a53c71 --- /dev/null +++ b/src/dm/systems/Qt3DSDMWindowsCompatibility.h @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DSDM_WINDOWS_COMPATIBILITY_H +#define QT3DSDM_WINDOWS_COMPATIBILITY_H +#include "EABase/config/eaplatform.h" +#include "EABase/eabase.h" +#include <string> +#ifndef __INTEGRITY +#include <memory.h> +#endif +#include <string.h> +#include <stdio.h> + +#if defined QT3DS_PLATFORM_NEEDS_WCHAR_T + +inline size_t wcslen(const wchar_t *inStr) +{ + size_t retval = 0; + while (inStr && *inStr) { + ++retval; + ++inStr; + } + return retval; +} + +inline int wmemcmp(const wchar_t *lhs, const wchar_t *rhs, size_t count) +{ + return memcmp(lhs, rhs, count * sizeof(wchar_t)); +} + +inline wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count) +{ + memcpy(dest, src, count * sizeof(wchar_t)); + return dest; +} + +inline const wchar_t *wmemchr(const wchar_t *inFirst, size_t count, const wchar_t val) +{ + size_t idx; + // empty loop intentional + for (idx = 0; idx < count && inFirst[idx] != val; ++idx) { + } + if (idx < count) + return inFirst + idx; + return NULL; +} + +inline wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t count) +{ + memmove(dest, src, count * sizeof(wchar_t)); + return dest; +} + +inline wchar_t *wmemset(wchar_t *dest, size_t count, wchar_t val) +{ + for (size_t idx = 0; idx < count; ++idx) + dest[idx] = val; + return dest; +} + +#endif + +inline size_t WideToNarrow(char *inDest, size_t inDestLen, const wchar_t *inWideStr); +template <unsigned int N> +inline size_t WideToNarrow(char (&inDest)[N], const wchar_t *inWideStr); + +#if !defined EA_PLATFORM_WINDOWS + +inline void wcscpy_s(wchar_t *inDest, size_t destLen, const wchar_t *inMessage) +{ + if (destLen) { + size_t idx = 0; + while (inMessage && *inMessage && idx < destLen) { + inDest[idx] = *inMessage; + ++inMessage; + ++idx; + } + + idx = idx < destLen ? idx : destLen - 1; + inDest[idx] = 0; + } +} + +template <unsigned int N> +inline void wcscpy_s(wchar_t (&inDest)[N], const wchar_t *inMessage) +{ + wcscpy_s(inDest, N, inMessage); +} + +inline FILE *_wfopen(const wchar_t *inFname, const wchar_t *inFlags) +{ + char name[1024] = { 0 }; + WideToNarrow(name, inFname); + char flags[24] = { 0 }; + WideToNarrow(flags, inFlags); + return fopen(name, flags); +} + +inline int _fseeki64(FILE *inFile, int64_t pos, int seekFlags) +{ + return fseek(inFile, (int32_t)pos, seekFlags); +} + +inline int64_t _ftelli64(FILE *inFile) +{ + return ftell(inFile); +} + +#define _snprintf snprintf + +#endif + +template <typename TLHS, typename TRHS> +inline size_t ConvertStr(TLHS *inDest, size_t inDestLen, const TRHS *inWideStr) +{ + if (inDestLen == 0) + return 0; + + size_t nameLen = 0; + + // empty loop intentional. + for (const TRHS *tempPtr = inWideStr; tempPtr && *tempPtr; ++tempPtr, ++nameLen) { + } + + if (nameLen > inDestLen - 1) + nameLen = inDestLen - 1; + for (size_t idx = 0; idx < nameLen; ++idx) + inDest[idx] = (char)inWideStr[idx]; + inDest[nameLen] = 0; + return nameLen; +} + +inline size_t WideToNarrow(char *inDest, size_t inDestLen, const wchar_t *inWideStr) +{ + return ConvertStr(inDest, inDestLen, inWideStr); +} + +template <unsigned int N> +inline size_t WideToNarrow(char (&inDest)[N], const wchar_t *inWideStr) +{ + return WideToNarrow(inDest, N, inWideStr); +} + +inline size_t WideToNarrow(char *inDest, size_t inDestLen, const char16_t *inWideStr) +{ + return ConvertStr(inDest, inDestLen, inWideStr); +} + +template <unsigned int N> +inline size_t WideToNarrow(char (&inDest)[N], const char16_t *inWideStr) +{ + return WideToNarrow(inDest, N, inWideStr); +} + +#endif
\ No newline at end of file diff --git a/src/dm/systems/Qt3DSDMXML.cpp b/src/dm/systems/Qt3DSDMXML.cpp new file mode 100644 index 0000000..2055adf --- /dev/null +++ b/src/dm/systems/Qt3DSDMXML.cpp @@ -0,0 +1,1253 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "Qt3DSDMXML.h" +#include "foundation/Qt3DSPool.h" +#include "foundation/Qt3DSAtomic.h" +#include "foundation/Qt3DSRefCounted.h" +#include "Qt3DSDMStringTable.h" +#include "Qt3DSDMWStrOpsImpl.h" +#include <memory> +#include "foundation/StrConvertUTF.h" +#include "foundation/StringTable.h" +#ifdef QT3DS_VC +#include <winsock2.h> +#include <windows.h> //output debug string +#endif + +#include <QtCore/qxmlstream.h> + +typedef char XML_Char; +typedef char XML_LChar; + +using namespace qt3dsdm; +using std::shared_ptr; +using namespace qt3ds::foundation; +using qt3ds::foundation::Pool; + +#define QT3DSXML_FOREACH(idxnm, val) \ + for (QT3DSU32 idxnm = 0, __numItems = (QT3DSU32)val; idxnm < __numItems; ++idxnm) + +namespace qt3dsdm { + +// All names are string table values so we can do straight +// pointer comparisons on them, we don't have the compare their +// values. +struct SDOMAttribute +{ + TXMLCharPtr m_Name; + TXMLCharPtr m_Value; + SDOMAttribute *m_NextAttribute; + + SDOMAttribute(TXMLCharPtr nm, TXMLCharPtr val) + : m_Name(nm) + , m_Value(val) + , m_NextAttribute(NULL) + { + } +}; + +struct SDOMElement +{ + TXMLCharPtr m_Name; + SDOMAttribute *m_FirstAttribute; + SDOMAttribute *m_LastAttribute; + SDOMElement *m_Parent; + SDOMElement *m_FirstChild; + SDOMElement *m_LastChild; + SDOMElement *m_NextSibling; + TXMLCharPtr m_Value; + + SDOMElement(TXMLCharPtr nm) + : m_Name(nm) + , m_FirstAttribute(NULL) + , m_LastAttribute(NULL) + , m_Parent(NULL) + , m_FirstChild(NULL) + , m_LastChild(NULL) + , m_NextSibling(NULL) + , m_Value("") + { + } + + void AddAttribute(SDOMAttribute &att) + { + if (m_LastAttribute) { + m_LastAttribute->m_NextAttribute = &att; + m_LastAttribute = &att; + } else { + QT3DS_ASSERT(m_FirstAttribute == NULL); + m_FirstAttribute = m_LastAttribute = &att; + } + } + // Used to ensure duplicate attributes can't happen + void SetAttributeValue(TXMLCharPtr inName, TXMLCharPtr inValue, IDOMFactory &inFactory, + const SDOMFlags &inFlags) + { + inName = inFactory.GetStringTable()->RegisterStr(inName); + SDOMAttribute *att = FindAttribute(inName, inFlags); + if (att) { + att->m_Value = inFactory.RegisterValue(inValue); + } else { + AddAttribute(*inFactory.NextAttribute(inName, inValue)); + } + } + void SetAttributeValue(TWideXMLCharPtr inName, TWideXMLCharPtr inValue, IDOMFactory &inFactory, + const SDOMFlags &inFlags) + { + TXMLCharPtr theName = inFactory.GetStringTable()->GetNarrowStr(inName); + SDOMAttribute *att = FindAttribute(theName, inFlags); + if (att) { + att->m_Value = inFactory.RegisterValue(inValue); + } else { + AddAttribute( + *inFactory.NextAttribute(inFactory.GetStringTable()->GetWideStr(inName), inValue)); + } + } + const SDOMAttribute *FindAttribute(TXMLCharPtr nm, const SDOMFlags &inFlags) const + { + return const_cast<SDOMElement *>(this)->FindAttribute(nm, inFlags); + } + SDOMAttribute *FindAttribute(TXMLCharPtr nm, const SDOMFlags &inFlags) + { + for (SDOMAttribute *att = m_FirstAttribute; att != NULL; att = att->m_NextAttribute) { + if (att->m_Name == nm) + return att; + else if (inFlags.CaselessAttributes() && AreEqualCaseless(nm, att->m_Name)) + return att; + } + return NULL; + } + void RemoveAttribute(TXMLCharPtr nm, const SDOMFlags &inFlags) + { + SDOMAttribute *preatt = m_FirstAttribute; + for (SDOMAttribute *att = m_FirstAttribute; att != NULL; + preatt = att, att = att->m_NextAttribute) { + if (att->m_Name == nm + || (inFlags.CaselessAttributes() && AreEqualCaseless(nm, att->m_Name))) { + if (att == m_FirstAttribute) { + m_FirstAttribute = att->m_NextAttribute; + } else { + preatt->m_NextAttribute = att->m_NextAttribute; + if (att == m_LastAttribute) + m_LastAttribute = preatt; + } + + att->m_NextAttribute = NULL; + } + } + } + TXMLCharPtr GetAttributeValue(TXMLCharPtr nm, SDOMFlags &inFlags) const + { + const SDOMAttribute *att = FindAttribute(nm, inFlags); + if (att) + return att->m_Value; + return NULL; + } + void AddChild(SDOMElement &elem) + { + elem.m_Parent = this; + if (m_LastChild) { + m_LastChild->m_NextSibling = &elem; + m_LastChild = &elem; + } else { + QT3DS_ASSERT(m_FirstChild == NULL); + m_FirstChild = m_LastChild = &elem; + } + } + SDOMElement *FindPreviousChild(SDOMElement &elem) + { + if (&elem == m_FirstChild) + return NULL; + // Find the previous sibling. + SDOMElement *theChild = m_FirstChild; + // Empty loop intentional + for (; theChild && theChild->m_NextSibling != &elem; theChild = theChild->m_NextSibling) { + } + + return theChild; + } + void RemoveChild(SDOMElement &elem) + { + if (elem.m_Parent != this) { + QT3DS_ASSERT(false); + return; + } + elem.m_Parent = NULL; + if (&elem == m_FirstChild) { + m_FirstChild = elem.m_NextSibling; + } else { + SDOMElement *theChild(FindPreviousChild(elem)); + QT3DS_ASSERT(theChild); + if (theChild) { + theChild->m_NextSibling = elem.m_NextSibling; + if (&elem == m_LastChild) + m_LastChild = theChild; + } + } + elem.m_NextSibling = NULL; + } + + void ReplaceChild(SDOMElement &inChild, SDOMElement &inReplacement) + { + inChild.m_Parent = NULL; + if (&inChild == m_FirstChild) + m_FirstChild = &inReplacement; + else { + SDOMElement *theChild(FindPreviousChild(inChild)); + QT3DS_ASSERT(theChild); + if (theChild) { + theChild->m_NextSibling = &inReplacement; + if (&inChild == m_LastChild) + m_LastChild = &inReplacement; + } + } + inReplacement.m_NextSibling = inChild.m_NextSibling; + inReplacement.m_Parent = this; + inChild.m_NextSibling = NULL; + } + + void InsertChildBefore(SDOMElement &elem, SDOMElement &theSibling) + { + // Ensure elem isn't in the graph. + QT3DS_ASSERT(elem.m_Parent == NULL); + QT3DS_ASSERT(elem.m_NextSibling == NULL); + elem.m_Parent = this; + if (&theSibling == m_FirstChild) + m_FirstChild = &elem; + else { + SDOMElement *thePrevious = FindPreviousChild(theSibling); + QT3DS_ASSERT(thePrevious); + if (thePrevious) + thePrevious->m_NextSibling = &elem; + } + + elem.m_NextSibling = &theSibling; + } + QT3DSU32 GetNumChildren(TXMLCharPtr inChildName, const SDOMFlags &inFlags) const + { + QT3DSU32 idx = 0; + for (SDOMElement *elem = m_FirstChild; elem != NULL; elem = elem->m_NextSibling) { + if (elem->m_Name == inChildName) + ++idx; + else if (inFlags.CaselessElements() && AreEqualCaseless(inChildName, elem->m_Name)) + ++idx; + } + return idx; + } + QT3DSU32 GetNumChildren() const + { + QT3DSU32 idx = 0; + for (SDOMElement *elem = m_FirstChild; elem != NULL; elem = elem->m_NextSibling) + ++idx; + return idx; + } + SDOMElement *FindChildByName(TXMLCharPtr nm, const SDOMFlags &inFlags) const + { + for (SDOMElement *elem = m_FirstChild; elem != NULL; elem = elem->m_NextSibling) { + if (elem->m_Name == nm) + return elem; + else if (inFlags.CaselessElements() && AreEqualCaseless(nm, elem->m_Name)) + return elem; + } + return NULL; + } + SDOMElement *FindNextSiblingByName(TXMLCharPtr nm, const SDOMFlags &inFlags) const + { + for (SDOMElement *elem = m_NextSibling; elem != NULL; elem = elem->m_NextSibling) { + if (elem->m_Name == nm) + return elem; + else if (inFlags.CaselessElements() && AreEqualCaseless(nm, elem->m_Name)) + return elem; + } + return NULL; + } +}; +} + +namespace { + +const QT3DSU16 g_BOMMarker = (QT3DSU16)0xFEFF; + +struct SElemPointer : eastl::pair<SDOMElement *, SDOMAttribute *> +{ + SElemPointer(SDOMElement *elem = NULL) + : eastl::pair<SDOMElement *, SDOMAttribute *>(elem, NULL) + { + } + SElemPointer &operator=(SDOMElement *elem) + { + first = elem; + second = NULL; + return *this; + } + SElemPointer &operator=(SDOMAttribute *att) + { + second = att; + return *this; + } + SElemPointer &operator=(const eastl::pair<SDOMElement *, SDOMAttribute *> &other) + { + eastl::pair<SDOMElement *, SDOMAttribute *>::operator=(other); + return *this; + } + operator SDOMElement *() const { return first; } + SDOMElement *operator->() const { return first; } +}; + +// Some DOM parsing operations are destructive. If you need +// them to not be destructive, then we need to modify +// the reader. Specifically parsing lists of floats, due +// to a bug in strtod, is destructive. +struct SDOMReader : public IDOMReader +{ + SElemPointer m_TopElement; + eastl::vector<eastl::pair<SDOMElement *, SDOMAttribute *>> m_ScopeStack; + std::shared_ptr<IDOMFactory> m_Factory; + SDOMFlags m_Flags; + eastl::basic_string<TWCharEASTLConverter::TCharType> m_TempBuffer; + + SDOMReader(SDOMElement &te, std::shared_ptr<qt3dsdm::IStringTable> s, + std::shared_ptr<IDOMFactory> inFactory = std::shared_ptr<IDOMFactory>()) + : IDOMReader(s) + , m_TopElement(&te) + , m_Factory(inFactory) + { + } + + SDOMElement *Current() const { return m_TopElement.first; } + void SetDOMFlags(SDOMFlags inFlags) override { m_Flags = inFlags; } + SDOMFlags GetDOMFlags() const override { return m_Flags; } + + void PushScope() override { m_ScopeStack.push_back(m_TopElement); } + void PopScope() override + { + if (m_ScopeStack.size()) { + m_TopElement = m_ScopeStack.back(); + m_ScopeStack.pop_back(); + } else + m_TopElement = eastl::pair<SDOMElement *, SDOMAttribute *>(NULL, NULL); + } + + void *GetScope() override { return m_TopElement.first; } + + void SetScope(void *inScope) override + { + m_TopElement = + eastl::make_pair(reinterpret_cast<SDOMElement *>(inScope), (SDOMAttribute *)NULL); + } + + TWideXMLCharPtr GetElementName() const override + { + return m_StringTable->GetWideStr(GetNarrowElementName()); + } + + TXMLCharPtr GetNarrowElementName() const override + { + if (!Current()) { + QT3DS_ASSERT(false); + return NULL; + } + return Current()->m_Name; + } + + bool UnregisteredAtt(TWideXMLCharPtr name, TWideXMLCharPtr &outValue) override + { + outValue = L""; + SDOMElement *current(Current()); + if (current) { + TXMLCharPtr theValue = + current->GetAttributeValue(m_StringTable->GetNarrowStr(name), m_Flags); + if (theValue && *theValue) { + qt3ds::foundation::ConvertUTF(theValue, 0, m_TempBuffer); + outValue = reinterpret_cast<const wchar_t *>(m_TempBuffer.c_str()); + return true; + } + } else { + QT3DS_ASSERT(false); + } + return false; + } + + bool UnregisteredAtt(TXMLCharPtr name, TXMLCharPtr &outValue) override + { + outValue = ""; + SDOMElement *current(Current()); + if (current) { + outValue = current->GetAttributeValue(m_StringTable->GetNarrowStr(name), m_Flags); + if (outValue) + return true; + } else { + QT3DS_ASSERT(false); + } + return false; + } + + bool Att(TWideXMLCharPtr name, TWideXMLCharPtr &outValue) override + { + if (UnregisteredAtt(name, outValue)) { + outValue = m_StringTable->RegisterStr(outValue); + return true; + } + return false; + } + bool Att(TXMLCharPtr name, TXMLCharPtr &outValue) override + { + if (UnregisteredAtt(name, outValue)) { + outValue = m_StringTable->RegisterStr(outValue); + return true; + } + return false; + } + + QT3DSU32 CountChildren() override + { + SDOMElement *elem = Current(); + if (elem == NULL) { + QT3DS_ASSERT(false); + return 0; + } + return elem->GetNumChildren(); + } + + QT3DSU32 CountChildren(TWideXMLCharPtr childName) override + { + return CountChildren(m_StringTable->GetNarrowStr(childName)); + } + + QT3DSU32 CountChildren(TXMLCharPtr childName) override + { + SDOMElement *elem = Current(); + if (elem == NULL) { + QT3DS_ASSERT(false); + return 0; + } + return elem->GetNumChildren(m_StringTable->GetNarrowStr(childName), m_Flags); + } + + eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> + ToWide(const eastl::pair<TXMLCharPtr, TXMLCharPtr> &att) + { + return eastl::make_pair(m_StringTable->GetWideStr(att.first), + m_StringTable->GetWideStr(att.second)); + } + eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> CurrentAtt() + { + return ToWide(CurrentAttNarrow()); + } + + eastl::pair<TXMLCharPtr, TXMLCharPtr> CurrentAttNarrow() + { + if (m_TopElement.second) + return eastl::make_pair(m_TopElement.second->m_Name, m_TopElement.second->m_Value); + return eastl::make_pair("", ""); + } + eastl::pair<TXMLCharPtr, TXMLCharPtr> GetNarrowFirstAttribute() override + { + if (m_TopElement.first == NULL) { + QT3DS_ASSERT(false); + eastl::make_pair("", ""); + } + m_TopElement.second = m_TopElement.first->m_FirstAttribute; + return CurrentAttNarrow(); + } + + eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> GetFirstAttribute() override + { + return ToWide(GetNarrowFirstAttribute()); + } + eastl::pair<TXMLCharPtr, TXMLCharPtr> GetNarrowNextAttribute() override + { + if (m_TopElement.second) + m_TopElement.second = m_TopElement.second->m_NextAttribute; + return CurrentAttNarrow(); + } + + eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> GetNextAttribute() override + { + return ToWide(GetNarrowNextAttribute()); + } + + bool MoveToFirstChild() override + { + SDOMElement *elem = Current(); + if (elem == NULL) { + QT3DS_ASSERT(false); + return false; + } + if (elem->m_FirstChild) { + m_TopElement = elem->m_FirstChild; + return true; + } + return false; + } + bool MoveToFirstChild(TXMLCharPtr childName) override + { + SDOMElement *elem = Current(); + if (elem == NULL) { + QT3DS_ASSERT(false); + return false; + } + SDOMElement *child = elem->FindChildByName(m_StringTable->RegisterStr(childName), m_Flags); + if (child != NULL) { + m_TopElement = child; + return true; + } + return false; + } + + bool MoveToFirstChild(TWideXMLCharPtr childName) override + { + return MoveToFirstChild(m_StringTable->GetNarrowStr(childName)); + } + + bool MoveToNextSibling() override + { + SDOMElement *elem = Current(); + if (elem == NULL) { + QT3DS_ASSERT(false); + return false; + } + if (elem->m_NextSibling) { + m_TopElement = elem->m_NextSibling; + return true; + } + return false; + } + bool MoveToNextSibling(TXMLCharPtr childName) override + { + SDOMElement *elem = Current(); + if (elem == NULL) { + QT3DS_ASSERT(false); + return false; + } + SDOMElement *nextSibling = + elem->FindNextSiblingByName(m_StringTable->RegisterStr(childName), m_Flags); + if (nextSibling) { + m_TopElement = nextSibling; + return true; + } + return false; + } + bool MoveToNextSibling(TWideXMLCharPtr childName) override + { + return MoveToNextSibling(m_StringTable->GetNarrowStr(childName)); + } + // Leave element means go to its parent. + void Leave() override + { + if (m_TopElement) + m_TopElement = m_TopElement->m_Parent; + + QT3DS_ASSERT(m_TopElement); + } + bool Value(TXMLCharPtr &outValue) override + { + SDOMElement *current(Current()); + if (!current) { + QT3DS_ASSERT(false); + return false; + } + outValue = current->m_Value; + return true; + } + + bool Value(TWideXMLCharPtr &outValue) override + { + outValue = L""; + TXMLCharPtr theValue; + if (Value(theValue)) { + qt3ds::foundation::ConvertUTF(theValue, 0, m_TempBuffer); + outValue = reinterpret_cast<const wchar_t *>(m_TempBuffer.c_str()); + return true; + } + return false; + } + + SDOMElement *GetTopElement() override + { + SDOMElement *current(Current()); + while (current && current->m_Parent) + current = current->m_Parent; + return current; + } + + virtual std::shared_ptr<IDOMFactory> GetFactory() { return m_Factory; } +}; + +struct SDOMWriter : public IDOMWriter, public SDOMReader +{ + std::shared_ptr<IDOMFactory> m_FactoryPtr; + IDOMFactory &m_Factory; + + SDOMWriter(std::shared_ptr<IDOMFactory> inDOMFactory, + std::shared_ptr<qt3dsdm::IStringTable> inStringTable, SDOMElement &inTopElem) + : m_FactoryPtr(inDOMFactory) + , m_Factory(*inDOMFactory) + , SDOMReader(inTopElem, inStringTable) + { + } + void SetDOMFlags(SDOMFlags inFlags) override { m_Flags = inFlags; } + SDOMFlags GetDOMFlags() const override { return m_Flags; } + + void Begin(TXMLCharPtr inElemName) override + { + if (!m_TopElement) { + QT3DS_ASSERT(false); + return; + } + SDOMElement *current(Current()); + SDOMElement *newElement(m_Factory.NextElement(inElemName)); + current->AddChild(*newElement); + m_TopElement = newElement; + } + + void Begin(TWideXMLCharPtr inElemName) override + { + Begin(m_FactoryPtr->GetStringTable()->GetNarrowStr(inElemName)); + } + + void Att(TXMLCharPtr name, TXMLCharPtr value) override + { + if (!m_TopElement) { + QT3DS_ASSERT(false); + return; + } + m_TopElement->SetAttributeValue(name, value, m_Factory, m_Flags); + } + // Attributes. They may be sorted just before write + void Att(TWideXMLCharPtr name, TWideXMLCharPtr value) override + { + if (!m_TopElement) { + QT3DS_ASSERT(false); + return; + } + m_TopElement->SetAttributeValue(name, value, m_Factory, m_Flags); + } + + void Value(TWideXMLCharPtr value) override + { + if (!m_TopElement) { + QT3DS_ASSERT(false); + return; + } + if (value == NULL) + value = L""; + size_t len = wcslen(value); + m_Factory.AppendStrBuf(value, (QT3DSU32)len); + m_TopElement->m_Value = m_Factory.FinalizeStrBuf(); + } + void Value(TXMLCharPtr value) override + { + if (!m_TopElement) { + QT3DS_ASSERT(false); + return; + } + if (value == NULL) + value = ""; + size_t len = strlen(value); + m_Factory.AppendStrBuf(value, (QT3DSU32)len); + m_TopElement->m_Value = m_Factory.FinalizeStrBuf(); + } + + void End() override + { + if (!m_TopElement) { + QT3DS_ASSERT(false); + return; + } + Leave(); + } + void RemoveCurrent() override + { + SDOMElement *current(Current()); + if (!current) { + QT3DS_ASSERT(false); + return; + } + if (current->m_Parent) { + m_TopElement = current->m_Parent; + m_TopElement->RemoveChild(*current); + } + } + void ReplaceCurrent(SDOMElement &inElement) override + { + SDOMElement *current(Current()); + if (!current) { + QT3DS_ASSERT(false); + return; + } + if (current->m_Parent) { + current->m_Parent->ReplaceChild(*current, inElement); + m_TopElement = &inElement; + } else { + m_TopElement = &inElement; + inElement.m_Parent = NULL; + inElement.m_NextSibling = NULL; + } + } + void AppendChildren(SDOMElement &inElement) override + { + SDOMElement *current(Current()); + if (!current) { + QT3DS_ASSERT(false); + return; + } + SDOMElement *theChild = inElement.m_FirstChild; + inElement.m_FirstChild = inElement.m_LastChild = NULL; + while (theChild) { + SDOMElement *theCurrentChild = theChild; + theChild = theChild->m_NextSibling; + + theCurrentChild->m_Parent = NULL; + theCurrentChild->m_NextSibling = NULL; + current->AddChild(*theCurrentChild); + } + } + void RemoveAttribute(TXMLCharPtr inItem) override + { + SDOMElement *current(Current()); + if (!current) { + QT3DS_ASSERT(false); + return; + } + current->RemoveAttribute(m_StringTable->RegisterStr(inItem), m_Flags); + } + void RemoveAttribute(TWideXMLCharPtr inItem) override + { + RemoveAttribute(m_StringTable->GetNarrowStr(inItem)); + } + + void MoveBefore(TXMLCharPtr inItem, TXMLCharPtr inSibling) override + { + SDOMElement *current(Current()); + if (!current) { + QT3DS_ASSERT(false); + return; + } + + SDOMElement *theItem = + current->FindChildByName(m_StringTable->RegisterStr(inItem), m_Flags); + SDOMElement *theSibling = + current->FindChildByName(m_StringTable->RegisterStr(inSibling), m_Flags); + QT3DS_ASSERT(theItem && theSibling); + if (theItem && theSibling) { + current->RemoveChild(*theItem); + current->InsertChildBefore(*theItem, *theSibling); + } + } + + void MoveBefore(TWideXMLCharPtr inItem, TWideXMLCharPtr inSibling) override + { + MoveBefore(m_StringTable->GetNarrowStr(inItem), m_StringTable->GetNarrowStr(inSibling)); + } + + // If current has no parent, then we are at the top + // of the tree and we should return 0. Or if there is no + // current. + // If there is one parent, we should return 1. + QT3DSU32 GetTabs() override + { + QT3DSU32 retval = 0; + SDOMElement *current(Current()); + do { + if (current) + current = current->m_Parent; + if (current) + ++retval; + } while (current); + return retval; + } + + SDOMElement *GetTopElement() override { return SDOMReader::GetTopElement(); } + + std::shared_ptr<IDOMFactory> GetFactory() override { return m_FactoryPtr; } +}; + +struct SimpleXmlWriter +{ + IOutStream &m_Stream; + eastl::vector<eastl::pair<TXMLCharPtr, bool>> m_OpenElements; + bool m_ElementOpen; + wchar_t m_PrintBuf[256]; + QT3DSU32 m_Tabs; + eastl::basic_string<char8_t> m_ConvertBuf; + eastl::basic_string<TWCharEASTLConverter::TCharType> m_WideBuffer; + + SimpleXmlWriter(IOutStream &stream, QT3DSU32 inTabs = 0) + : m_Stream(stream) + , m_ElementOpen(false) + , m_Tabs(inTabs) + { + } + void Write(TWideXMLCharPtr data) + { + if (!IsTrivial(data)) { + qt3ds::foundation::ConvertUTF( + reinterpret_cast<const TWCharEASTLConverter::TCharType *>(data), 0, + m_ConvertBuf); + m_Stream.Write(m_ConvertBuf.begin(), m_ConvertBuf.size()); + } + } + void Write(const char8_t *data) + { + if (!IsTrivial(data)) { + m_Stream.Write(data, (QT3DSU32)strlen(data)); + } + } + void BeginWideWrite() { m_WideBuffer.clear(); } + void WriteTemp(wchar_t data) { m_WideBuffer.append(1, data); } + void WriteTemp(const wchar_t *data) + { + m_WideBuffer.append(reinterpret_cast<const TWCharEASTLConverter::TCharType *>(data)); + } + void EndWideWrite() { Write(reinterpret_cast<const wchar_t *>(m_WideBuffer.c_str())); } + void Write(char8_t data) { m_Stream.Write(data); } + void Tabs() + { + QT3DSXML_FOREACH(idx, (m_OpenElements.size() + m_Tabs)) + Write('\t'); + } + void Close(bool newline) + { + if (m_ElementOpen) { + Write(L" >"); + if (newline) + Write('\n'); + } + m_ElementOpen = false; + } + void Begin(TXMLCharPtr name) + { + Close(true); + Tabs(); + Write('<'); + Write(name); + m_OpenElements.push_back(eastl::pair<TXMLCharPtr, bool>(name, false)); + m_ElementOpen = true; + } + TWideXMLCharPtr ToStr(char8_t val) + { + m_PrintBuf[0] = val; + m_PrintBuf[1] = 0; + return m_PrintBuf; + } + template <typename TDataType> + TWideXMLCharPtr ToStr(TDataType val) + { + WStrOps<TDataType>().ToStr(val, NVDataRef<wchar_t>(m_PrintBuf, 256)); + return m_PrintBuf; + } + void Att(TXMLCharPtr name, TXMLCharPtr value) + { + QT3DS_ASSERT(m_ElementOpen); + Write(' '); + Write(name); + Write("=\""); + QString str = QString::fromUtf8(nonNull(value)).toHtmlEscaped(); + Write(str.toUtf8().constData()); + Write("\""); + } + template <typename TData> + void Att(TXMLCharPtr name, TData value) + { + Att(name, ToStr(value)); + } + + void Value(TXMLCharPtr value) + { + if (!IsTrivial(value)) { + Close(false); + QString str = QString::fromUtf8(nonNull(value)).toHtmlEscaped(); + Write(str.toUtf8().constData()); + m_OpenElements.back().second = true; + } + } + void ChildValue(TXMLCharPtr name, TXMLCharPtr value) + { + Begin(name); + Value(value); + End(); + } + void End(bool newlineAfterClose = true) + { + QT3DS_ASSERT(m_OpenElements.size()); + eastl::pair<TXMLCharPtr, bool> topElem = m_OpenElements.back(); + m_OpenElements.pop_back(); + if (m_ElementOpen) + Write(" />"); + else { + if (topElem.second == false) + Tabs(); + Write("</"); + Write(topElem.first); + Write(">"); + } + m_ElementOpen = false; + if (newlineAfterClose == true) + Write('\n'); + } +}; + +struct DOMParser +{ + typedef eastl::basic_string<TWCharEASTLConverter::TCharType> TStrType; + IDOMFactory &m_Factory; + SDOMElement *m_TopElement; + SDOMElement *m_FirstElement; + + DOMParser(IDOMFactory &factory) + : m_Factory(factory) + , m_FirstElement(NULL) + { + } + + template <QT3DSU32 THeaderLen> + struct SHeaderInStream : public IInStream + { + QT3DSU8 m_Header[THeaderLen]; + QT3DSU32 m_BytesRead; + IInStream &m_InStream; + SHeaderInStream(IInStream &inStream) + : m_InStream(inStream) + , m_BytesRead(0) + { + } + bool readHeader() + { + QT3DSU32 amountRead = m_InStream.Read(NVDataRef<QT3DSU8>(m_Header, THeaderLen)); + return amountRead == THeaderLen; + } + QT3DSU32 Read(NVDataRef<QT3DSU8> data) override + { + if (data.size() == 0) + return 0; + QT3DSU8 *writePtr(data.begin()); + QT3DSU32 amountToRead(data.size()); + QT3DSU32 amountRead = 0; + if (m_BytesRead < THeaderLen) { + QT3DSU32 headerLeft = qMin(THeaderLen - m_BytesRead, amountToRead); + memCopy(writePtr, m_Header + m_BytesRead, headerLeft); + writePtr += headerLeft; + amountToRead -= headerLeft; + amountRead += headerLeft; + } + if (amountToRead) + amountRead += m_InStream.Read(NVDataRef<QT3DSU8>(writePtr, amountToRead)); + m_BytesRead += amountRead; + return amountRead; + } + }; + + static SDOMElement *ParseXMLFile(IDOMFactory &factory, IInStream &inStream, + CXmlErrorHandler *handler = NULL) + { + QXmlStreamReader sreader; + + DOMParser domParser(factory); + QT3DSU8 dataBuf[2048]; + QT3DSU32 amountRead = 0; + do { + amountRead = inStream.Read(toDataRef(dataBuf, 2048)); + if (amountRead) { + QByteArray tmp = QByteArray::fromRawData((char*)dataBuf,amountRead); + sreader.addData(tmp); + } + } while (amountRead > 0); + + while (!sreader.atEnd()) { + QXmlStreamReader::TokenType token = sreader.readNext(); + + if (token == QXmlStreamReader::StartElement) { + domParser.m_Factory.IgnoreStrBuf(); + SDOMElement *newElem = domParser.m_Factory.NextElement( + (TXMLCharPtr)sreader.name().toUtf8().data()); + if (domParser.m_FirstElement == NULL) { + domParser.m_FirstElement = newElem; + domParser.m_TopElement = newElem; + } else { + domParser.m_TopElement->AddChild(*newElem); + domParser.m_TopElement = newElem; + } + const QXmlStreamAttributes& attributes = sreader.attributes(); + for (auto attrib : attributes) { + SDOMAttribute *att = domParser.m_Factory.NextAttribute( + (TXMLCharPtr)attrib.name().toUtf8().data(), + (TXMLCharPtr)attrib.value().toUtf8().data()); + newElem->AddAttribute(*att); + } + } else if (token == QXmlStreamReader::Characters) { + QByteArray text = sreader.text().toUtf8(); + domParser.m_Factory.AppendStrBuf(text.data(),text.length()); + } else if (token == QXmlStreamReader::EndElement) { + domParser.m_TopElement->m_Value = domParser.m_Factory.FinalizeStrBuf(); + domParser.m_TopElement = domParser.m_TopElement->m_Parent; + } + if (sreader.hasError()) { + if (handler) { + handler->OnXmlError(sreader.errorString(), sreader.lineNumber(), + sreader.columnNumber()); + } else { + qWarning() << "XML parse error:" << sreader.errorString() + << "line:" << sreader.lineNumber() + << "column:" << sreader.columnNumber(); + } + return nullptr; + } + } + return domParser.m_FirstElement; + } +}; + +class SimpleDomFactory : public IDOMFactory +{ + typedef eastl::basic_string<char8_t> TNarrowStr; + Pool<SDOMElement> m_ElementPool; + Pool<SDOMAttribute> m_AttributePool; + eastl::vector<char8_t *> m_BigStrings; + eastl::vector<char8_t> m_StringBuilder; + TNarrowStr m_ConvertBuffer; + std::shared_ptr<qt3dsdm::IStringTable> m_StringTable; + +public: + SimpleDomFactory(std::shared_ptr<qt3dsdm::IStringTable> strt) + : m_StringTable(strt) + { + } + ~SimpleDomFactory() + { + QT3DSXML_FOREACH(idx, m_BigStrings.size()) + free(m_BigStrings[idx]); + } + + TWideXMLCharPtr RegisterStr(TWideXMLCharPtr str) + { + if (str == NULL || *str == 0) + return L""; + return m_StringTable->RegisterStr(str); + } + + TXMLCharPtr RegisterStr(TXMLCharPtr str) + { + if (str == NULL || *str == 0) + return ""; + return m_StringTable->RegisterStr(str); + } + + void Release() override { delete this; } + void AppendStrBuf(TXMLCharPtr str, QT3DSU32 len) override + { + if (len && *str) { + QT3DSU32 offset = m_StringBuilder.size(); + m_StringBuilder.resize(offset + len); + memCopy(&m_StringBuilder[0] + offset, str, len * sizeof(char8_t)); + } + } + // Str does not need to be null terminated. + void AppendStrBuf(TWideXMLCharPtr str, QT3DSU32 len) override + { + if (len && *str) { + const TWCharEASTLConverter::TCharType *bufPtr = + reinterpret_cast<const TWCharEASTLConverter::TCharType *>(str); + qt3ds::foundation::ConvertUTF(bufPtr, len, m_ConvertBuffer); + AppendStrBuf(m_ConvertBuffer.data(), m_ConvertBuffer.size()); + } + } + + // Null terminate what is there and return the buffer. + // This pointer needs to be persistent. + TXMLCharPtr FinalizeStrBuf() override + { + if (m_StringBuilder.size() == 0) + return ""; + m_StringBuilder.push_back(0); + QT3DSU32 len = m_StringBuilder.size(); + QT3DSU32 numBytes = len * sizeof(char8_t); + char8_t *newMem = (char8_t *)malloc(numBytes); + memCopy(newMem, &m_StringBuilder[0], numBytes); + m_BigStrings.push_back(newMem); + m_StringBuilder.clear(); + return newMem; + } + void IgnoreStrBuf() override { m_StringBuilder.clear(); } + + SDOMAttribute *NextAttribute(TXMLCharPtr name, TXMLCharPtr val) override + { + TXMLCharPtr n(m_StringTable->GetNarrowStr(name)); + TXMLCharPtr v(RegisterValue(val)); + return m_AttributePool.construct(n, v, __FILE__, __LINE__); + } + + SDOMAttribute *NextAttribute(TWideXMLCharPtr name, TWideXMLCharPtr val) override + { + TXMLCharPtr n(m_StringTable->GetNarrowStr(name)); + TXMLCharPtr v(RegisterValue(val)); + return m_AttributePool.construct(n, v, __FILE__, __LINE__); + } + + SDOMElement *NextElement(TXMLCharPtr name) override + { + IgnoreStrBuf(); + TXMLCharPtr n(m_StringTable->GetNarrowStr(name)); + return m_ElementPool.construct(n, __FILE__, __LINE__); + } + SDOMElement *NextElement(TWideXMLCharPtr name) override + { + IgnoreStrBuf(); + TXMLCharPtr n(m_StringTable->GetNarrowStr(name)); + return m_ElementPool.construct(n, __FILE__, __LINE__); + } + + std::shared_ptr<qt3dsdm::IStringTable> GetStringTable() override { return m_StringTable; } +}; +} + +bool IDOMReader::Value(DataModelDataType::Value type, SValue &outValue) +{ + TXMLCharPtr value; + if (Value(value)) { + WCharTReader reader(const_cast<char8_t *>(value), m_TempBuf, *GetStringTable()); + outValue = WStrOps<SValue>().BufTo(type, reader); + return true; + } + return false; +} + +std::shared_ptr<IDOMReader> +IDOMReader::CreateDOMReader(SDOMElement &inRootElement, + std::shared_ptr<qt3dsdm::IStringTable> inStringTable, + std::shared_ptr<IDOMFactory> inFactory) +{ + return std::make_shared<SDOMReader>(std::ref(inRootElement), std::ref(inStringTable), + inFactory); +} + +eastl::pair<std::shared_ptr<IDOMWriter>, std::shared_ptr<IDOMReader>> +IDOMWriter::CreateDOMWriter(std::shared_ptr<IDOMFactory> inFactory, SDOMElement &inRootElement, + std::shared_ptr<qt3dsdm::IStringTable> inStringTable) +{ + std::shared_ptr<SDOMWriter> writer(std::make_shared<SDOMWriter>( + inFactory, std::ref(inStringTable), std::ref(inRootElement))); + return eastl::make_pair(writer, writer); +} + +TXMLCharPtr IDOMFactory::RegisterValue(TWideXMLCharPtr inValue) +{ + if (IsTrivial(inValue)) + return ""; + IgnoreStrBuf(); + AppendStrBuf(inValue, (QT3DSU32)wcslen(inValue)); + return FinalizeStrBuf(); +} + +TXMLCharPtr IDOMFactory::RegisterValue(TXMLCharPtr inValue) +{ + if (IsTrivial(inValue)) + return ""; + IgnoreStrBuf(); + AppendStrBuf(inValue, (QT3DSU32)strlen(inValue)); + return FinalizeStrBuf(); +} + +std::shared_ptr<IDOMFactory> +IDOMFactory::CreateDOMFactory(std::shared_ptr<qt3dsdm::IStringTable> inStrTable) +{ + return std::make_shared<SimpleDomFactory>(std::ref(inStrTable)); +} + +void CDOMSerializer::WriteXMLHeader(IOutStream &inStream) +{ + SimpleXmlWriter writer(inStream); + writer.Write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); +} + +// Lexigraphically sort the attributes. +struct SAttributeComparator +{ + bool operator()(const SDOMAttribute *lhs, const SDOMAttribute *rhs) + { + return strcmp(lhs->m_Name, rhs->m_Name) < 0; + } +}; + +// Write an element with attributes sorted by name so a file diff is effective. +void WriteElement(SDOMElement &inElement, SimpleXmlWriter &inWriter, + std::vector<SDOMAttribute *> &inAttSorter) +{ + inAttSorter.clear(); + for (SDOMAttribute *att = inElement.m_FirstAttribute; att; att = att->m_NextAttribute) + inAttSorter.push_back(att); + // We decided that we don't want attribute sorting; the code that adds attributes needs + // to be consistent. + // std::sort( inAttSorter.begin(), inAttSorter.end(), SAttributeComparator() ); + // This element doesn't add anything to the system in this case. + if (inElement.m_FirstAttribute == NULL && inElement.m_FirstChild == NULL + && IsTrivial(inElement.m_Value)) + return; + + inWriter.Begin(inElement.m_Name); + + const char8_t *theLastAttName = 0; + for (size_t idx = 0, end = inAttSorter.size(); idx < end; ++idx) { + SDOMAttribute *theAtt(inAttSorter[idx]); + if (theAtt->m_Name != theLastAttName) + inWriter.Att(theAtt->m_Name, theAtt->m_Value); + else { + QT3DS_ASSERT(false); + } + theLastAttName = theAtt->m_Name; + } + // Elements can either have children or values but not both at this point. + if (inElement.m_FirstChild) { + for (SDOMElement *theChild = inElement.m_FirstChild; theChild; + theChild = theChild->m_NextSibling) + WriteElement(*theChild, inWriter, inAttSorter); + inWriter.End(); + } else { + if (!IsTrivial(inElement.m_Value)) + inWriter.Value(inElement.m_Value); + + inWriter.End(); + } +} + +void CDOMSerializer::Write(SDOMElement &inElement, IOutStream &inStream, QT3DSU32 inTabs) +{ + // TODO: QXmlStreamWriter here? + std::vector<SDOMAttribute *> theAttributes; + SimpleXmlWriter writer(inStream, inTabs); + std::vector<SDOMAttribute *> theAttSorter; + WriteElement(inElement, writer, theAttSorter); +} + +SDOMElement *CDOMSerializer::Read(IDOMFactory &inFactory, IInStream &inStream, + CXmlErrorHandler *inErrorHandler) +{ + return DOMParser::ParseXMLFile(inFactory, inStream, inErrorHandler); +} diff --git a/src/dm/systems/Qt3DSDMXML.h b/src/dm/systems/Qt3DSDMXML.h new file mode 100644 index 0000000..5fe722f --- /dev/null +++ b/src/dm/systems/Qt3DSDMXML.h @@ -0,0 +1,506 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_IMPORT_XML_H +#define QT3DS_IMPORT_XML_H +#include "foundation/Qt3DS.h" +#include "foundation/Qt3DSMemoryBuffer.h" +#include "Qt3DSDMDataTypes.h" +#include <string> +#include "Qt3DSDMWStrOps.h" //Conversion between string and various datatypes. +#include "foundation/Qt3DSFlags.h" +#include "EASTL/algorithm.h" +#include "foundation/Qt3DSSimpleTypes.h" +#include "foundation/IOStreams.h" +#include "Qt3DSDMValue.h" +#include <memory> + +namespace qt3dsdm { +using qt3ds::foundation::MemoryBuffer; +using qt3ds::foundation::RawAllocator; +class IStringTable; + +class IDOMFactory; +struct SDOMAttribute; +struct SDOMElement; + +typedef const char8_t *TXMLCharPtr; +typedef const wchar_t *TWideXMLCharPtr; + +typedef TCharStr TXMLWideStr; +typedef eastl::basic_string<char8_t> TXMLStr; + +using qt3ds::QT3DSU32; +using qt3ds::NVFlags; +using qt3ds::foundation::NVDataRef; +using qt3ds::foundation::NVConstDataRef; +using qt3ds::foundation::IOutStream; + +class IDOMFactory +{ +protected: + virtual ~IDOMFactory() {} +public: + friend class std::shared_ptr<IDOMFactory>; + + virtual void Release() = 0; + // Str does not need to be null terminated. + virtual void AppendStrBuf(TXMLCharPtr str, QT3DSU32 len) = 0; + virtual void AppendStrBuf(TWideXMLCharPtr str, QT3DSU32 len) = 0; + // Null terminate what is there and return the buffer. + // This pointer needs to be persistent. + virtual TXMLCharPtr FinalizeStrBuf() = 0; + virtual void IgnoreStrBuf() = 0; + + virtual std::shared_ptr<IStringTable> GetStringTable() = 0; + + virtual SDOMAttribute *NextAttribute(TWideXMLCharPtr name, TWideXMLCharPtr val) = 0; + virtual SDOMElement *NextElement(TWideXMLCharPtr name) = 0; + + virtual SDOMAttribute *NextAttribute(TXMLCharPtr name, TXMLCharPtr val) = 0; + virtual SDOMElement *NextElement(TXMLCharPtr name) = 0; + + TXMLCharPtr RegisterValue(TXMLCharPtr inValue); + TXMLCharPtr RegisterValue(TWideXMLCharPtr inValue); + + static std::shared_ptr<IDOMFactory> + CreateDOMFactory(std::shared_ptr<IStringTable> inStrTable); +}; + +struct DOMFlagValues +{ + enum Enum { + CaselessElementNames = 1 << 0, + CaselessAttributeNames = 1 << 1, + }; +}; + +struct SDOMFlags : NVFlags<DOMFlagValues::Enum, int> +{ + SDOMFlags() + : NVFlags<DOMFlagValues::Enum, int>(DOMFlagValues::CaselessElementNames + | DOMFlagValues::CaselessAttributeNames) + { + } + bool CaselessAttributes() const { return *this & DOMFlagValues::CaselessAttributeNames; } + bool CaselessElements() const { return *this & DOMFlagValues::CaselessElementNames; } +}; + +class IDOMReader +{ +protected: + virtual ~IDOMReader() {} +public: + friend class std::shared_ptr<IDOMReader>; + + // Stack object to save the reader's state. + struct Scope + { + IDOMReader &m_Reader; + Scope(IDOMReader &reader) + : m_Reader(reader) + { + m_Reader.PushScope(); + } + ~Scope() { m_Reader.PopScope(); } + }; + + // Parse buffer + MemoryBuffer<RawAllocator> m_TempBuf; + std::shared_ptr<IStringTable> m_StringTable; + + IDOMReader(std::shared_ptr<IStringTable> inStringTable) + : m_StringTable(inStringTable) + { + } + + std::shared_ptr<IStringTable> GetStringTable() { return m_StringTable; } + + // DOM reader flags change the nature of the DOM reader. + // see DOMFlagValues + // Defaults to caseless comparisons for attributes and for + // element names. + virtual void SetDOMFlags(SDOMFlags inFlags) = 0; + virtual SDOMFlags GetDOMFlags() const = 0; + + // Pushing scope saves your state so no matter where you are when + // you next pop scope, you come back to the same state. + virtual void PushScope() = 0; + virtual void PopScope() = 0; + + // Sometimes pushing and popping scope isn't enough and you need + // somewhat random access to scope. + // This scope does not remember the current attribute. + virtual void *GetScope() = 0; + virtual void SetScope(void *inScope) = 0; + // Return an attribute whose value is *not* registered with the string table. + // You can't hold onto this value for any length of time, but when you need to + // immediately convert to a different value this is the most efficient way. + virtual bool UnregisteredAtt(TWideXMLCharPtr name, TWideXMLCharPtr &outValue) = 0; + virtual bool UnregisteredAtt(TXMLCharPtr name, TXMLCharPtr &outValue) = 0; + // Return an attribute whose value *is* registered with the string table. + virtual bool Att(TWideXMLCharPtr name, TWideXMLCharPtr &outValue) = 0; + virtual bool Att(TXMLCharPtr name, TXMLCharPtr &outValue) = 0; + virtual eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> GetFirstAttribute() = 0; + virtual eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> GetNextAttribute() = 0; + virtual eastl::pair<TXMLCharPtr, TXMLCharPtr> GetNarrowFirstAttribute() = 0; + virtual eastl::pair<TXMLCharPtr, TXMLCharPtr> GetNarrowNextAttribute() = 0; + virtual QT3DSU32 CountChildren() = 0; + virtual QT3DSU32 CountChildren(TWideXMLCharPtr childName) = 0; + virtual QT3DSU32 CountChildren(TXMLCharPtr childName) = 0; + virtual bool MoveToFirstChild(TWideXMLCharPtr childName) = 0; + virtual bool MoveToFirstChild(TXMLCharPtr childName) = 0; + virtual bool MoveToFirstChild() = 0; + virtual bool MoveToNextSibling(TWideXMLCharPtr siblingName) = 0; + virtual bool MoveToNextSibling(TXMLCharPtr siblingName) = 0; + virtual bool MoveToNextSibling() = 0; + // Leave element means go to its parent. + virtual void Leave() = 0; + virtual TWideXMLCharPtr GetElementName() const = 0; + virtual TXMLCharPtr GetNarrowElementName() const = 0; + + // Value is the concatentated text node values inside the element + virtual bool Value(TWideXMLCharPtr &outValue) = 0; + virtual bool Value(TXMLCharPtr &outValue) = 0; + + // Get the element this reader was created with + virtual SDOMElement *GetTopElement() = 0; + + bool Att(TWideXMLCharPtr name, TXMLWideStr &outValue) + { + TWideXMLCharPtr temp; + if (UnregisteredAtt(name, temp)) { + outValue.assign(temp); + return true; + } + return false; + } + + bool Att(TXMLCharPtr name, TXMLStr &outValue) + { + TXMLCharPtr temp; + if (UnregisteredAtt(name, temp)) { + outValue.assign(temp); + return true; + } + return false; + } + + // Helpers to help make the parsing a bit easier. + template <typename TDataType> + bool Att(TWideXMLCharPtr name, TDataType &outValue) + { + TWideXMLCharPtr temp; + if (UnregisteredAtt(name, temp)) { + WStrOps<TDataType>().StrTo(temp, outValue); + return true; + } else { + return false; + } + } + template <typename TDataType> + bool Att(TXMLCharPtr name, TDataType &outValue) + { + TXMLCharPtr temp; + if (UnregisteredAtt(name, temp)) { + WStrOps<TDataType>().StrTo(temp, outValue); + return true; + } else { + return false; + } + } + + bool ChildValue(TXMLCharPtr name, TXMLCharPtr &value) + { + if (MoveToFirstChild(name)) { + Value(value); + Leave(); + return true; + } + return false; + } + + bool ChildValue(TWideXMLCharPtr name, TWideXMLCharPtr &value) + { + if (MoveToFirstChild(name)) { + Value(value); + Leave(); + return true; + } + return false; + } + + bool RegisteredChildValue(TWideXMLCharPtr name, TWideXMLCharPtr &value) + { + if (MoveToFirstChild(name)) { + RegisteredValue(value); + Leave(); + return true; + } + return false; + } + bool RegisteredChildValue(TXMLCharPtr name, TXMLCharPtr &value) + { + if (MoveToFirstChild(name)) { + RegisteredValue(value); + Leave(); + return true; + } + return false; + } + bool RegisteredValue(TWideXMLCharPtr &outValue) + { + bool retval = Value(outValue); + if (retval) + outValue = m_StringTable->RegisterStr(outValue); + return retval; + } + bool RegisteredValue(TXMLCharPtr &outValue) + { + bool retval = Value(outValue); + if (retval) + outValue = m_StringTable->RegisterStr(outValue); + return retval; + } + bool Value(DataModelDataType::Value type, SValue &outValue); + + template <typename TDataType> + bool Value(TDataType &outValue) + { + TXMLCharPtr value; + if (Value(value)) { + WStrOps<TDataType>().StrTo(value, outValue); + return true; + } + return false; + } + + // Functions below implemented in WStrOpsImpl + // to avoid circular dependencies + // Returns the number of items read + // Destructive parsing + template <typename TDataType> + bool ValueList(NVDataRef<TDataType> data); + + // Destructive operation because we can't trust + // strtod to do the right thing. On windows, for long strings, + // it calls strlen every operation thus leading to basically N^2 + // behavior + template <typename TDataType> + NVConstDataRef<TDataType> ChildValueList(TWideXMLCharPtr listName); + + template <typename TDataType> + NVConstDataRef<TDataType> ChildValueList(TXMLCharPtr listName); + + template <typename TSerializer> + void Serialize(const wchar_t *elemName, TSerializer &serializer) + { + IDOMReader::Scope __theScope(*this); + if (MoveToFirstChild(elemName)) { + serializer.Serialize(*this); + } + } + // Optionally hold on to the factory to keep our elements in memory as long as we are. + static std::shared_ptr<IDOMReader> + CreateDOMReader(SDOMElement &inRootElement, std::shared_ptr<IStringTable> inStringTable, + std::shared_ptr<IDOMFactory> inFactory = std::shared_ptr<IDOMFactory>()); +}; + +// Write out data in an xml-like fasion without specifying exactly +// where that data is being written. +class IDOMWriter +{ +protected: + virtual ~IDOMWriter() {} +public: + friend class std::shared_ptr<IDOMWriter>; + + // Control the element scope. + struct Scope + { + IDOMWriter &m_Writer; + Scope(IDOMWriter &writer, TWideXMLCharPtr inElemName) + : m_Writer(writer) + { + m_Writer.Begin(inElemName); + } + Scope(IDOMWriter &writer, TXMLCharPtr inElemName) + : m_Writer(writer) + { + m_Writer.Begin(inElemName); + } + ~Scope() { m_Writer.End(); } + }; + + wchar_t m_PrintBuf[256]; + char8_t m_NarrowBuf[256]; + + virtual void SetDOMFlags(SDOMFlags inFlags) = 0; + virtual SDOMFlags GetDOMFlags() const = 0; + // There tend to be two types of elements. + // Containers (<a>\n\t<b/><b/>\n</a>) + // and Values <b>onetwothree</b> + virtual void Begin(TWideXMLCharPtr inElemName) = 0; + virtual void Begin(TXMLCharPtr inElemName) = 0; + // Attributes. They may be sorted just before write + virtual void Att(TWideXMLCharPtr name, TWideXMLCharPtr value) = 0; + virtual void Att(TXMLCharPtr name, TXMLCharPtr value) = 0; + virtual void Value(TWideXMLCharPtr value) = 0; + virtual void Value(TXMLCharPtr value) = 0; + virtual void End() = 0; + virtual void RemoveCurrent() = 0; + virtual void ReplaceCurrent(SDOMElement &inElement) = 0; + // Append all the children of inElement to the child list of the current items. + virtual void AppendChildren(SDOMElement &inElement) = 0; + virtual void RemoveAttribute(TWideXMLCharPtr inItem) = 0; + virtual void RemoveAttribute(TXMLCharPtr inItem) = 0; + // Get the number of tabs required to line up the next line + // with the opening of the previous line + virtual QT3DSU32 GetTabs() = 0; + virtual SDOMElement *GetTopElement() = 0; + virtual std::shared_ptr<IDOMFactory> GetFactory() = 0; + // Move this item before this sibling. Function does not rearrange the + // tree in any major way and will not work if inItem and inSibling aren't + // siblings. + virtual void MoveBefore(TWideXMLCharPtr inItem, TWideXMLCharPtr inSibling) = 0; + virtual void MoveBefore(TXMLCharPtr inItem, TXMLCharPtr inSibling) = 0; + + virtual void ChildValue(TWideXMLCharPtr name, TWideXMLCharPtr value) + { + Begin(name); + Value(value); + End(); + } + + virtual void ChildValue(TXMLCharPtr name, TXMLCharPtr value) + { + Begin(name); + Value(value); + End(); + } + + TWideXMLCharPtr ToStr(wchar_t val) + { + m_PrintBuf[0] = val; + m_PrintBuf[1] = 0; + return m_PrintBuf; + } + TXMLCharPtr ToStr(char8_t val) + { + m_NarrowBuf[0] = val; + m_NarrowBuf[1] = 0; + return m_NarrowBuf; + } + template <typename TDataType> + TWideXMLCharPtr ToStr(TDataType val) + { + WStrOps<TDataType>().ToStr(val, NVDataRef<wchar_t>(m_PrintBuf, 256)); + return m_PrintBuf; + } + + template <typename TDataType> + TXMLCharPtr ToNarrowStr(TDataType val) + { + WStrOps<TDataType>().ToStr(val, NVDataRef<char8_t>(m_NarrowBuf, 256)); + return m_NarrowBuf; + } + + void Att(TWideXMLCharPtr name, const TXMLWideStr &inValue) + { + return Att(name, inValue.wide_str()); + } + + void Att(TXMLCharPtr name, const TXMLStr &inValue) { return Att(name, inValue.c_str()); } + + template <typename TData> + void Att(TWideXMLCharPtr name, TData value) + { + Att(name, ToStr(value)); + } + + template <typename TData> + void Att(TXMLCharPtr name, TData value) + { + Att(name, ToNarrowStr(value)); + } + + template <typename TSerializer> + void Serialize(const wchar_t *elemName, TSerializer &serializer) + { + IDOMWriter::Scope __theScope(*this, elemName); + serializer.Serialize(*this); + } + + template <typename TSerializer> + void Serialize(const char8_t *elemName, TSerializer &serializer) + { + IDOMWriter::Scope __theScope(*this, elemName); + serializer.Serialize(*this); + } + + std::shared_ptr<IDOMReader> CreateDOMReader() + { + std::shared_ptr<IDOMFactory> theFactory(GetFactory()); + return IDOMReader::CreateDOMReader(*GetTopElement(), theFactory->GetStringTable(), + theFactory); + } + + // Note that the default method of creating a writer also creates a reader; they can + // both manipulation the DOM hierarch. + static eastl::pair<std::shared_ptr<IDOMWriter>, std::shared_ptr<IDOMReader>> + CreateDOMWriter(std::shared_ptr<IDOMFactory> inFactory, SDOMElement &inRootElement, + std::shared_ptr<IStringTable> inStringTable); + + static eastl::pair<std::shared_ptr<IDOMWriter>, std::shared_ptr<IDOMReader>> + CreateDOMWriter(const wchar_t *inTopElemName, std::shared_ptr<IStringTable> inStringTable) + { + std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(inStringTable)); + SDOMElement *theRoot = theFactory->NextElement(inTopElemName); + return CreateDOMWriter(theFactory, *theRoot, inStringTable); + } +}; + +class CXmlErrorHandler +{ +protected: + virtual ~CXmlErrorHandler() {} +public: + virtual void OnXmlError(const QString &errorName, int line, int column) = 0; +}; + +class CDOMSerializer +{ +public: + static void WriteXMLHeader(IOutStream &inStream); + static void Write(SDOMElement &inElement, IOutStream &inStream, QT3DSU32 inTabs = 0); + static SDOMElement *Read(IDOMFactory &inFactory, qt3ds::foundation::IInStream &inStream, + CXmlErrorHandler *inErrorHandler = NULL); +}; +} +#endif diff --git a/src/dm/systems/SignalsImpl.cpp b/src/dm/systems/SignalsImpl.cpp new file mode 100644 index 0000000..6f42516 --- /dev/null +++ b/src/dm/systems/SignalsImpl.cpp @@ -0,0 +1,1565 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#ifdef WIN32 +#pragma warning(disable : 4103 4512 4503) +#endif +#include "SignalsImpl.h" + +using namespace std; + +namespace { +bool g_DataModelSignalsEnabled = true; + +#define CHECK_SIGNALS_ENABLED() \ + { \ + if (g_DataModelSignalsEnabled == false) \ + return; \ + } +} + +namespace qt3dsdm { +void SetDataModelSignalsEnabled(bool inEnabled) +{ + g_DataModelSignalsEnabled = inEnabled; +} +// Defaults to true +bool AreDataModelSignalsEnabled() +{ + return g_DataModelSignalsEnabled; +} + +#define CONNECT_QT(x) TSignalConnectionPtr(new QtSignalConnection(x)) +#define CONNECT_SIGNAL_QT(x) CONNECT_QT(QObject::connect(this, x, inCallback)) + +class CPropertyCoreSignaller : public QObject, public IInstancePropertyCoreSignalProvider, + public IInstancePropertyCoreSignalSender +{ + Q_OBJECT +Q_SIGNALS: + void propertySignal(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, const SValue); +public: + TSignalConnectionPtr ConnectInstancePropertyValue( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, const SValue &)> + &inCallback) override + { + return CONNECT_QT(QObject::connect(this, &CPropertyCoreSignaller::propertySignal, + inCallback)); + } + void SignalInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT propertySignal(inInstance, inProperty, inValue); + } +}; + +TSignalItemPtr CreatePropertyCoreSignaller() +{ + return TSignalItemPtr( + static_cast<IInstancePropertyCoreSignalProvider *>(new CPropertyCoreSignaller())); +} + +class CDataCoreSignaller : public QObject, public IDataCoreSignalProvider, + public IDataCoreSignalSender +{ + Q_OBJECT +Q_SIGNALS: + void instanceCreated(Qt3DSDMInstanceHandle handle); + void beforeInstanceDeleted(Qt3DSDMInstanceHandle handle); + void instanceDeleted(Qt3DSDMInstanceHandle handle); + void instanceDerived(Qt3DSDMInstanceHandle handle, Qt3DSDMInstanceHandle handle2); + void instanceParentRemoved(Qt3DSDMInstanceHandle handle, Qt3DSDMInstanceHandle handle2); + void propertyAdded(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, TCharPtr, + DataModelDataType::Value); + void propertyRemoved(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, TCharPtr, + DataModelDataType::Value); + +public: + virtual TSignalConnectionPtr + ConnectInstanceCreated(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_QT(QObject::connect(this, &CDataCoreSignaller::instanceCreated, + inCallback)); + } + virtual TSignalConnectionPtr + ConnectBeforeInstanceDeleted(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_QT(QObject::connect(this, &CDataCoreSignaller::beforeInstanceDeleted, + inCallback)); + } + virtual TSignalConnectionPtr + ConnectInstanceDeleted(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_QT(QObject::connect(this, &CDataCoreSignaller::instanceDeleted, + inCallback)); + } + TSignalConnectionPtr ConnectInstanceDerived( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_QT(QObject::connect(this, &CDataCoreSignaller::instanceDerived, + inCallback)); + } + TSignalConnectionPtr ConnectInstanceParentRemoved( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_QT(QObject::connect(this, &CDataCoreSignaller::instanceParentRemoved, + inCallback)); + } + virtual TSignalConnectionPtr + ConnectPropertyAdded(const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + TCharPtr, DataModelDataType::Value)> &inCallback) override + { + return CONNECT_QT(QObject::connect(this, &CDataCoreSignaller::propertyAdded, inCallback)); + } + virtual TSignalConnectionPtr + ConnectPropertyRemoved(const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + TCharPtr, DataModelDataType::Value)> &inCallback) override + { + return CONNECT_QT(QObject::connect(this, &CDataCoreSignaller::propertyRemoved, + inCallback)); + } + + void SignalInstanceCreated(Qt3DSDMInstanceHandle inInstance) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instanceCreated(inInstance); + } + void SignalBeforeInstanceDeleted(Qt3DSDMInstanceHandle inInstance) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT beforeInstanceDeleted(inInstance); + } + void SignalInstanceDeleted(Qt3DSDMInstanceHandle inInstance) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instanceDeleted(inInstance); + } + void SignalInstanceDerived(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instanceDerived(inInstance, inParent); + } + void SignalInstanceParentRemoved(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instanceParentRemoved(inInstance, inParent); + } + void SignalPropertyAdded(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, TCharPtr inName, + DataModelDataType::Value inDataType) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT propertyAdded(inInstance, inProperty, inName, inDataType); + } + void SignalPropertyRemoved(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, TCharPtr inName, + DataModelDataType::Value inDataType) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT propertyRemoved(inInstance, inProperty, inName, inDataType); + } +}; + +TSignalItemPtr CreateDataCoreSignaller() +{ + return TSignalItemPtr(static_cast<IDataCoreSignalProvider *>(new CDataCoreSignaller())); +} + +class CSlideCoreSignaller : public QObject, public ISlideCoreSignalProvider, + public ISlideCoreSignalSender +{ + Q_OBJECT +Q_SIGNALS: + + void slideCreated(Qt3DSDMSlideHandle); + void beforeSlideDeleted(Qt3DSDMSlideHandle); + void slideDeleted(Qt3DSDMSlideHandle); + void slideDerived(Qt3DSDMSlideHandle, Qt3DSDMSlideHandle, int); + void instancePropertyValueSet(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &); + qt3dsdm::SValue instancePropertyValueAdded(Qt3DSDMSlideHandle, Qt3DSDMSlideHandle, + Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &); + void instancePropertyValueRemoved(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, const SValue &); + void slideTimeChanged(Qt3DSDMSlideHandle); + +public: + virtual TSignalConnectionPtr + ConnectSlideCreated(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideCoreSignaller::slideCreated); + } + virtual TSignalConnectionPtr + ConnectBeforeSlideDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideCoreSignaller::beforeSlideDeleted); + } + virtual TSignalConnectionPtr + ConnectSlideDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideCoreSignaller::slideDeleted); + } + TSignalConnectionPtr ConnectSlideDerived( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMSlideHandle, int)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideCoreSignaller::slideDerived); + } + TSignalConnectionPtr ConnectInstancePropertyValueSet( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideCoreSignaller::instancePropertyValueSet); + } + virtual TSignalConnectionPtr ConnectInstancePropertyValueAdded( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, const SValue &)> &inCallback) + { + return CONNECT_SIGNAL_QT(&CSlideCoreSignaller::instancePropertyValueAdded); + } + TSignalConnectionPtr ConnectInstancePropertyValueRemoved( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideCoreSignaller::instancePropertyValueRemoved); + } + virtual TSignalConnectionPtr + ConnectSlideTimeChanged(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideCoreSignaller::slideTimeChanged); + } + + void SendSlideCreated(Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT slideCreated(inSlide); + } + void SendBeforeSlideDeleted(Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT beforeSlideDeleted(inSlide); + } + void SendSlideDeleted(Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT slideDeleted(inSlide); + } + void SendSlideDerived(Qt3DSDMSlideHandle inSlide, Qt3DSDMSlideHandle inParent, + int inIndex) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT slideDerived(inSlide, inParent, inIndex); + } + void SendPropertyValueSet(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instancePropertyValueSet(inSlide, inInstance, inProperty, inValue); + } + virtual SValue SendPropertyValueAdded(Qt3DSDMSlideHandle inSource, Qt3DSDMSlideHandle inDest, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) + { + if (!g_DataModelSignalsEnabled) return SValue(); + + // check that we have one and only one slot connected to + // instancePropertyValueAdded signal as it returns a value. + Q_ASSERT( + receivers( + SIGNAL( + instancePropertyValueAdded( + Qt3DSDMSlideHandle, Qt3DSDMSlideHandle, + Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle,const SValue &))) == 1); + // emit instancePropertyValueAdded + return instancePropertyValueAdded(inSource, inDest, inInstance, inProperty, inValue); + } + void SendPropertyValueRemoved(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instancePropertyValueRemoved(inSlide, inInstance, inProperty, inValue); + } + void SendSlideTimeChanged(Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT slideTimeChanged(inSlide); + } +}; + +TSignalItemPtr CreateSlideCoreSignaller() +{ + return TSignalItemPtr(static_cast<ISlideCoreSignalProvider *>(new CSlideCoreSignaller())); +} + +class CSlideGraphCoreSignaller : public QObject, public ISlideGraphCoreSignalProvider, + public ISlideGraphCoreSignalSender +{ + Q_OBJECT +Q_SIGNALS: + void graphCreated(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle); + void graphDeleted(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle); + void instanceAssociated(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle); + void instanceDissociated(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle); + void graphActiveSlide(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle); + void graphSeconds(Qt3DSDMSlideGraphHandle, float); + +public: + TSignalConnectionPtr ConnectGraphCreated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideGraphCoreSignaller::graphCreated); + } + TSignalConnectionPtr ConnectGraphDeleted( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideGraphCoreSignaller::graphDeleted); + } + TSignalConnectionPtr ConnectInstanceAssociated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideGraphCoreSignaller::instanceAssociated); + } + TSignalConnectionPtr ConnectInstanceDissociated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideGraphCoreSignaller::instanceDissociated); + } + TSignalConnectionPtr ConnectGraphActiveSlide( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideGraphCoreSignaller::graphActiveSlide); + } + virtual TSignalConnectionPtr + ConnectGraphSeconds(const std::function<void(Qt3DSDMSlideGraphHandle, float)> &inCallback) + { + return CONNECT_SIGNAL_QT(&CSlideGraphCoreSignaller::graphSeconds); + } + + void SendGraphCreated(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT graphCreated(inGraph, inSlide); + } + void SendGraphDeleted(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT graphDeleted(inGraph, inSlide); + } + void SendInstanceAssociated(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instanceAssociated(inGraph, inSlide, inInstance); + } + void SendInstanceDissociated(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instanceDissociated(inGraph, inSlide, inInstance); + } + void SendGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT graphActiveSlide(inGraph, inSlide); + } + virtual void SendGraphSeconds(Qt3DSDMSlideGraphHandle inGraph, float inSeconds) + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT graphSeconds(inGraph, inSeconds); + } +}; + +TSignalItemPtr CreateSlideGraphCoreSignaller() +{ + return TSignalItemPtr( + static_cast<ISlideGraphCoreSignalProvider *>(new CSlideGraphCoreSignaller())); +} + +class CAnimationCoreSignaller : public QObject, public IAnimationCoreSignalProvider, + public IAnimationCoreSignalSender +{ + Q_OBJECT +Q_SIGNALS: + void animationCreated(Qt3DSDMAnimationHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType); + void beforeAnimationDeleted(Qt3DSDMAnimationHandle); + void animationDeleted(Qt3DSDMAnimationHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType); + void keyframeInserted(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle, const TKeyframe &); + void beforeKeyframeErased(Qt3DSDMKeyframeHandle); + void keyframeErased(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle, const TKeyframe &); + void beforeAllKeyframesErased(Qt3DSDMAnimationHandle); + void keyframeUpdated(Qt3DSDMKeyframeHandle, const TKeyframe &); + void firstKeyframeDynamic(Qt3DSDMAnimationHandle, bool); + +public: + TSignalConnectionPtr ConnectAnimationCreated( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CAnimationCoreSignaller::animationCreated); + } + virtual TSignalConnectionPtr + ConnectBeforeAnimationDeleted(const std::function<void(Qt3DSDMAnimationHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CAnimationCoreSignaller::beforeAnimationDeleted); + } + TSignalConnectionPtr ConnectAnimationDeleted( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CAnimationCoreSignaller::animationDeleted); + } + TSignalConnectionPtr ConnectKeyframeInserted( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle, const TKeyframe &)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CAnimationCoreSignaller::keyframeInserted); + } + virtual TSignalConnectionPtr + ConnectBeforeKeyframeErased(const std::function<void(Qt3DSDMKeyframeHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CAnimationCoreSignaller::beforeKeyframeErased); + } + TSignalConnectionPtr ConnectKeyframeErased( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle, const TKeyframe &)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CAnimationCoreSignaller::keyframeErased); + } + virtual TSignalConnectionPtr + ConnectBeforeAllKeyframesErased(const std::function<void(Qt3DSDMAnimationHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CAnimationCoreSignaller::beforeAllKeyframesErased); + } + TSignalConnectionPtr ConnectKeyframeUpdated( + const std::function<void(Qt3DSDMKeyframeHandle, const TKeyframe &)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CAnimationCoreSignaller::keyframeUpdated); + } + TSignalConnectionPtr ConnectFirstKeyframeDynamicSet( + const std::function<void(Qt3DSDMAnimationHandle, bool)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CAnimationCoreSignaller::firstKeyframeDynamic); + } + + void SendAnimationCreated(Qt3DSDMAnimationHandle inAnimation, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT animationCreated(inAnimation, inSlide, inInstance, inProperty, inIndex, + inAnimationType); + } + void SendBeforeAnimationDeleted(Qt3DSDMAnimationHandle inAnimation) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT beforeAnimationDeleted(inAnimation); + } + void SendAnimationDeleted(Qt3DSDMAnimationHandle inAnimation, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT animationDeleted(inAnimation, inSlide, inInstance, inProperty, inIndex, + inAnimationType); + } + void SendKeyframeInserted(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT keyframeInserted(inAnimation, inKeyframe, inData); + } + void SendBeforeKeyframeErased(Qt3DSDMKeyframeHandle inKeyframe) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT beforeKeyframeErased(inKeyframe); + } + void SendKeyframeErased(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT keyframeErased(inAnimation, inKeyframe, inData); + } + void SendBeforeAllKeyframesErased(Qt3DSDMAnimationHandle inAnimation) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT beforeAllKeyframesErased(inAnimation); + } + void SendKeyframeUpdated(Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT keyframeUpdated(inKeyframe, inData); + } + void SendFirstKeyframeDynamicSet(Qt3DSDMAnimationHandle inAnimation, + bool inKeyframeDynamic) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT firstKeyframeDynamic(inAnimation, inKeyframeDynamic); + } +}; + +TSignalItemPtr CreateAnimationCoreSignaller() +{ + return TSignalItemPtr( + static_cast<IAnimationCoreSignalProvider *>(new CAnimationCoreSignaller())); +} + +class CActionCoreSignaller : public QObject, public IActionCoreSignalProvider, + public IActionCoreSignalSender +{ + Q_OBJECT +Q_SIGNALS: + void triggerObjectSet(Qt3DSDMActionHandle, SObjectRefType &); + void targetObjectSet(Qt3DSDMActionHandle, SObjectRefType &); + void eventHandleSet(Qt3DSDMActionHandle, const wstring &); + void handlerHandleSet(Qt3DSDMActionHandle, const wstring &); + + void handlerArgumentAdded(Qt3DSDMActionHandle, Qt3DSDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value); + void handlerArgumentRemoved(Qt3DSDMActionHandle, Qt3DSDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value); + void handlerArgumentValueSet(Qt3DSDMHandlerArgHandle, const SValue &); + +public: + TSignalConnectionPtr ConnectTriggerObjectSet( + const std::function<void(Qt3DSDMActionHandle, SObjectRefType &)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CActionCoreSignaller::triggerObjectSet); + } + TSignalConnectionPtr ConnectTargetObjectSet( + const std::function<void(Qt3DSDMActionHandle, SObjectRefType &)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CActionCoreSignaller::targetObjectSet); + } + virtual TSignalConnectionPtr + ConnectEventSet(const std::function<void(Qt3DSDMActionHandle, const wstring &)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CActionCoreSignaller::eventHandleSet); + } + virtual TSignalConnectionPtr + ConnectHandlerSet(const std::function<void(Qt3DSDMActionHandle, const wstring &)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CActionCoreSignaller::handlerHandleSet); + } + + TSignalConnectionPtr ConnectHandlerArgumentAdded( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CActionCoreSignaller::handlerArgumentAdded); + } + TSignalConnectionPtr ConnectHandlerArgumentRemoved( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CActionCoreSignaller::handlerArgumentRemoved); + } + TSignalConnectionPtr ConnectHandlerArgumentValueSet( + const std::function<void(Qt3DSDMHandlerArgHandle, const SValue &)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CActionCoreSignaller::handlerArgumentValueSet); + } + + void SendTriggerObjectSet(Qt3DSDMActionHandle inAction, SObjectRefType &inTriggerObject) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT triggerObjectSet(inAction, inTriggerObject); + } + void SendTargetObjectSet(Qt3DSDMActionHandle inAction, SObjectRefType &inTargetObject) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT targetObjectSet(inAction, inTargetObject); + } + void SendEventSet(Qt3DSDMActionHandle inAction, const wstring &inEventHandle) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT eventHandleSet(inAction, inEventHandle); + } + void SendHandlerSet(Qt3DSDMActionHandle inAction, const wstring &inHandlerHandle) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT handlerHandleSet(inAction, inHandlerHandle); + } + + void SendHandlerArgumentAdded(Qt3DSDMActionHandle inAction, + Qt3DSDMHandlerArgHandle inHandlerArgument, + const TCharStr &inName, HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT handlerArgumentAdded(inAction, inHandlerArgument, inName, inArgType, inValueType); + } + void SendHandlerArgumentRemoved(Qt3DSDMActionHandle inAction, + Qt3DSDMHandlerArgHandle inHandlerArgument, + const TCharStr &inName, HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT handlerArgumentRemoved(inAction, inHandlerArgument, inName, inArgType, inValueType); + } + void SendHandlerArgumentValueSet(Qt3DSDMHandlerArgHandle inHandlerArgument, + const SValue &inValue) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT handlerArgumentValueSet(inHandlerArgument, inValue); + } +}; + +TSignalItemPtr CreateActionCoreSignaller() +{ + return TSignalItemPtr(static_cast<IActionCoreSignalProvider *>(new CActionCoreSignaller())); +} + +class CActionSystemSignaller : public QObject, public IActionSystemSignalProvider, + public IActionSystemSignalSender +{ + Q_OBJECT +Q_SIGNALS: + void actionCreated(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle); + void actionDeleted(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle); + +public: + TSignalConnectionPtr ConnectActionCreated( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CActionSystemSignaller::actionCreated); + } + TSignalConnectionPtr ConnectActionDeleted( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CActionSystemSignaller::actionDeleted); + } + + void SendActionCreated(Qt3DSDMActionHandle inAction, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT actionCreated(inAction, inSlide, inOwner); + } + void SendActionDeleted(Qt3DSDMActionHandle inAction, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT actionDeleted(inAction, inSlide, inOwner); + } +}; + +TSignalItemPtr CreateActionSystemSignaller() +{ + return TSignalItemPtr(static_cast<IActionSystemSignalProvider *>(new CActionSystemSignaller())); +} + +class CSlideSystemSignaller : public QObject, public ISlideSystemSignalProvider, + public ISlideSystemSignalSender +{ + Q_OBJECT +Q_SIGNALS: + void masterCreated(Qt3DSDMSlideHandle); + void masterDeleted(Qt3DSDMSlideHandle); + void slideCreated(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle); + void slideDeleted(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle); + void slideRearranged(Qt3DSDMSlideHandle, int, int); + void componentSeconds(Qt3DSDMSlideHandle, float); + void instanceAssociated(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle); + void instanceDissociated(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle); + void propertyLinked(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle); + void propertyUnlinked(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle); + void activeSlide(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle, Qt3DSDMSlideHandle); + + qt3dsdm::SValue valueCreated(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue); + void valueDestroyed(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue); + +public: + virtual TSignalConnectionPtr + ConnectMasterCreated(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::masterCreated); + } + virtual TSignalConnectionPtr + ConnectMasterDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::masterDeleted); + } + TSignalConnectionPtr ConnectSlideCreated( + const std::function<void(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::slideCreated); + } + TSignalConnectionPtr ConnectSlideDeleted( + const std::function<void(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::slideDeleted); + } + virtual TSignalConnectionPtr + ConnectSlideRearranged(const std::function<void(Qt3DSDMSlideHandle, int, int)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::slideRearranged); + } + virtual TSignalConnectionPtr + ConnectComponentSeconds(const std::function<void(Qt3DSDMSlideHandle, float)> &inCallback) + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::componentSeconds); + } + TSignalConnectionPtr ConnectInstanceAssociated( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::instanceAssociated); + } + TSignalConnectionPtr ConnectInstanceDissociated( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::instanceDissociated); + } + TSignalConnectionPtr ConnectPropertyLinked( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::propertyLinked); + } + TSignalConnectionPtr ConnectPropertyUnlinked( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::propertyUnlinked); + } + TSignalConnectionPtr ConnectActiveSlide( + const std::function<void(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle, Qt3DSDMSlideHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::activeSlide); + } + virtual TSignalConnectionPtr ConnectPropertyValueCreated( + const std::function<SValue(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::valueCreated); + } + virtual TSignalConnectionPtr ConnectPropertyValueDestroyed( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) + { + return CONNECT_SIGNAL_QT(&CSlideSystemSignaller::valueDestroyed); + } + + void SendMasterCreated(Qt3DSDMSlideHandle inMaster) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT masterCreated(inMaster); + } + void SendMasterDeleted(Qt3DSDMSlideHandle inMaster) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT masterDeleted(inMaster); + } + void SendSlideCreated(Qt3DSDMSlideHandle inMaster, int inIndex, + Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT slideCreated(inMaster, inIndex, inSlide); + } + void SendSlideDeleted(Qt3DSDMSlideHandle inMaster, int inIndex, + Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT slideDeleted(inMaster, inIndex, inSlide); + } + void SendSlideRearranged(Qt3DSDMSlideHandle inMaster, int inOldIndex, int inNewIndex) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT slideRearranged(inMaster, inOldIndex, inNewIndex); + } + virtual void SendComponentSeconds(Qt3DSDMSlideHandle inMaster, float inSeconds) + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT componentSeconds(inMaster, inSeconds); + } + void SendInstanceAssociated(Qt3DSDMSlideHandle inMaster, Qt3DSDMInstanceHandle inInstance) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instanceAssociated(inMaster, inInstance); + } + void SendInstanceDissociated(Qt3DSDMSlideHandle inMaster, + Qt3DSDMInstanceHandle inInstance) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instanceDissociated(inMaster, inInstance); + } + void SendPropertyLinked(Qt3DSDMSlideHandle inMaster, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT propertyLinked(inMaster, inInstance, inProperty); + } + void SendPropertyUnlinked(Qt3DSDMSlideHandle inMaster, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT propertyUnlinked(inMaster, inInstance, inProperty); + } + void SendActiveSlide(Qt3DSDMSlideHandle inMaster, int inIndex, + Qt3DSDMSlideHandle inOldSlide, Qt3DSDMSlideHandle inNewSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT activeSlide(inMaster, inIndex, inOldSlide, inNewSlide); + } + + virtual SValue SendPropertyValueCreated(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) + { + if (!g_DataModelSignalsEnabled) return SValue(); + + // check that we have one and only one slot connected to + // valueCreated signal as it returns a value. + Q_ASSERT( + receivers( + SIGNAL( + valueCreated(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, const SValue &))) == 1); + // emit valueCreated + return valueCreated(inSlide, inInstance, inProperty, inValue); + } + virtual void SendPropertyValueDestroyed(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT valueDestroyed(inSlide, inInstance, inProperty, inValue); + } +}; + +TSignalItemPtr CreateSlideSystemSignaller() +{ + return TSignalItemPtr(static_cast<ISlideSystemSignalProvider *>(new CSlideSystemSignaller())); +} + +class CCustomPropCoreSignaller : public QObject, public ICustomPropCoreSignalProvider, + public ICustomPropCoreSignalSender +{ + Q_OBJECT +Q_SIGNALS: + void customPropertyCreated(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle); + void customPropertyDeleted(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle); + void customPropertyModified(Qt3DSDMPropertyHandle); + void customEventCreated(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle); + void customEventDeleted(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle); + void customEventModified(Qt3DSDMEventHandle); + void customHandlerCreated(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle); + void customHandlerDeleted(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle); + void customHandlerModified(Qt3DSDMHandlerHandle); + void customHandlerParamCreated(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle); + void customHandlerParamDeleted(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle); + void customHandlerParamModified(Qt3DSDMHandlerParamHandle); + void customReferencesModified(Qt3DSDMInstanceHandle, const TCharStr &); + +public: + TSignalConnectionPtr ConnectCustomPropertyCreated( + const std::function<void(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customPropertyCreated); + } + TSignalConnectionPtr ConnectCustomPropertyDeleted( + const std::function<void(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customPropertyDeleted); + } + virtual TSignalConnectionPtr + ConnectCustomPropertyModified(const std::function<void(Qt3DSDMPropertyHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customPropertyModified); + } + TSignalConnectionPtr ConnectCustomEventCreated( + const std::function<void(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customEventCreated); + } + TSignalConnectionPtr ConnectCustomEventDeleted( + const std::function<void(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customEventDeleted); + } + virtual TSignalConnectionPtr + ConnectCustomEventModified(const std::function<void(Qt3DSDMEventHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customEventModified); + } + TSignalConnectionPtr ConnectCustomHandlerCreated( + const std::function<void(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customHandlerCreated); + } + TSignalConnectionPtr ConnectCustomHandlerDeleted( + const std::function<void(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customHandlerDeleted); + } + virtual TSignalConnectionPtr + ConnectCustomHandlerModified(const std::function<void(Qt3DSDMHandlerHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customHandlerModified); + } + TSignalConnectionPtr ConnectCustomHandlerParamCreated( + const std::function<void(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customHandlerParamCreated); + } + TSignalConnectionPtr ConnectCustomHandlerParamDeleted( + const std::function<void(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customHandlerParamDeleted); + } + TSignalConnectionPtr ConnectCustomHandlerParamModified( + const std::function<void(Qt3DSDMHandlerParamHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customHandlerParamModified); + } + TSignalConnectionPtr ConnectCustomReferencesModified( + const std::function<void(Qt3DSDMInstanceHandle, const TCharStr &)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CCustomPropCoreSignaller::customReferencesModified); + } + + void SendCustomPropertyCreated(Qt3DSDMPropertyHandle inProp, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customPropertyCreated(inProp, inOwner); + } + void SendCustomPropertyDeleted(Qt3DSDMPropertyHandle inProp, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customPropertyDeleted(inProp, inOwner); + } + void SendCustomPropertyModified(Qt3DSDMPropertyHandle inProp) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customPropertyModified(inProp); + } + void SendCustomEventCreated(Qt3DSDMEventHandle inEvent, Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customEventCreated(inEvent, inOwner); + } + void SendCustomEventDeleted(Qt3DSDMEventHandle inEvent, Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customEventDeleted(inEvent, inOwner); + } + void SendCustomEventModified(Qt3DSDMEventHandle inEvent) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customEventModified(inEvent); + } + void SendCustomHandlerCreated(Qt3DSDMHandlerHandle inHandler, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerCreated(inHandler, inOwner); + } + void SendCustomHandlerDeleted(Qt3DSDMHandlerHandle inHandler, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerDeleted(inHandler, inOwner); + } + void SendCustomHandlerModified(Qt3DSDMHandlerHandle inHandler) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerModified(inHandler); + } + void SendCustomHandlerParamCreated(Qt3DSDMHandlerParamHandle inParameter, + Qt3DSDMHandlerHandle inHandler) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerParamCreated(inParameter, inHandler); + } + void SendCustomHandlerParamDeleted(Qt3DSDMHandlerParamHandle inParameter, + Qt3DSDMHandlerHandle inHandler) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerParamDeleted(inParameter, inHandler); + } + void SendCustomHandlerParamModified(Qt3DSDMHandlerParamHandle inParameter) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerParamModified(inParameter); + } + void SendCustomReferencesModified(Qt3DSDMInstanceHandle inOwner, + const TCharStr &inString) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customReferencesModified(inOwner, inString); + } +}; + +TSignalItemPtr CreateCustomPropCoreSignaller() +{ + return TSignalItemPtr( + static_cast<ICustomPropCoreSignalProvider *>(new CCustomPropCoreSignaller())); +} + +class CStudioFullSystemSignaller : public QObject, public IStudioFullSystemSignalProvider, + public IStudioFullSystemSignalSender +{ + Q_OBJECT +Q_SIGNALS: + void changeSetBegin(); + void changeSetEnd(); + void animationBegin(); + void animationEnd(); + void slideCreated(Qt3DSDMSlideHandle); + void slideDeleted(Qt3DSDMSlideHandle); + void slideRearranged(Qt3DSDMSlideHandle, int, int); + void componentSeconds(Qt3DSDMSlideHandle); + void beginComponentSeconds(Qt3DSDMSlideHandle); + void propertyLinked(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle); + void propertyUnlinked(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle); + void activeSlide(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle); + void instanceCreated(Qt3DSDMInstanceHandle); + void instanceDeleted(Qt3DSDMInstanceHandle); + void animationCreated(Qt3DSDMAnimationHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle); + void animationDeleted(Qt3DSDMAnimationHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle); + void controlledToggled(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle); + void keyframeInserted(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle); + void keyframeErased(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle); + void keyframeUpdated(Qt3DSDMKeyframeHandle); + void connectFirstKeyframeDynamicSet(Qt3DSDMAnimationHandle, bool); + void instancePropertyValue(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle); + void actionCreated(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle); + void actionDeleted(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle); + void triggerObjectSet(Qt3DSDMActionHandle); + void targetObjectSet(Qt3DSDMActionHandle); + void eventHandleSet(Qt3DSDMActionHandle); + void handlerHandleSet(Qt3DSDMActionHandle); + void handlerArgumentValueSet(Qt3DSDMHandlerArgHandle); + void customPropertyCreated(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle); + void customPropertyDeleted(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle); + void customPropertyModified(Qt3DSDMPropertyHandle); + void customEventCreated(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle); + void customEventDeleted(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle); + void customEventModified(Qt3DSDMEventHandle); + void customHandlerCreated(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle); + void customHandlerDeleted(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle); + void customHandlerModified(Qt3DSDMHandlerHandle); + void customHandlerParamCreated(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle); + void customHandlerParamDeleted(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle); + void customHandlerParamModified(Qt3DSDMHandlerParamHandle); + void customReferencesModified(Qt3DSDMInstanceHandle, const TCharStr &); +private: + ISlideSystemSignalProvider *m_SlideSystemSignalProvider; + +public: + CStudioFullSystemSignaller(ISlideSystemSignalProvider *inProvider) + : m_SlideSystemSignalProvider(inProvider) + { + } + + virtual TSignalConnectionPtr ConnectChangeSetBegin(const std::function<void()> &inCallback) + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::changeSetBegin); + } + virtual TSignalConnectionPtr ConnectChangeSetEnd(const std::function<void()> &inCallback) + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::changeSetEnd); + } + + // Used when people start to set component times. + virtual TSignalConnectionPtr ConnectAnimationSetBegin(const std::function<void()> &inCallback) + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::animationBegin); + } + virtual TSignalConnectionPtr ConnectAnimationSetEnd(const std::function<void()> &inCallback) + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::animationEnd); + } + + virtual TSignalConnectionPtr + ConnectSlideCreated(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::slideCreated); + } + virtual TSignalConnectionPtr + ConnectSlideDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::slideDeleted); + } + virtual TSignalConnectionPtr + ConnectSlideRearranged(const std::function<void(Qt3DSDMSlideHandle, int, int)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::slideRearranged); + } + virtual TSignalConnectionPtr + ConnectBeginComponentSeconds(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::beginComponentSeconds); + } + virtual TSignalConnectionPtr + ConnectComponentSeconds(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::componentSeconds); + } + TSignalConnectionPtr ConnectPropertyLinked( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::propertyLinked); + } + TSignalConnectionPtr ConnectPropertyUnlinked( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::propertyUnlinked); + } + TSignalConnectionPtr ConnectActiveSlide( + const std::function<void(Qt3DSDMSlideHandle, int, Qt3DSDMSlideHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::activeSlide); + } + + virtual TSignalConnectionPtr + ConnectInstanceCreated(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::instanceCreated); + } + virtual TSignalConnectionPtr + ConnectInstanceDeleted(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::instanceDeleted); + } + virtual TSignalConnectionPtr + ConnectAnimationCreated(const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::animationCreated); + } + virtual TSignalConnectionPtr + ConnectAnimationDeleted(const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::animationDeleted); + } + TSignalConnectionPtr ConnectKeyframeInserted( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::keyframeInserted); + } + TSignalConnectionPtr ConnectKeyframeErased( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::keyframeErased); + } + virtual TSignalConnectionPtr + ConnectKeyframeUpdated(const std::function<void(Qt3DSDMKeyframeHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::keyframeUpdated); + } + TSignalConnectionPtr ConnectInstancePropertyValue( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::instancePropertyValue); + } + TSignalConnectionPtr ConnectFirstKeyframeDynamicSet( + const std::function<void(Qt3DSDMAnimationHandle, bool)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::connectFirstKeyframeDynamicSet); + } + + TSignalConnectionPtr ConnectActionCreated( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::actionCreated); + } + TSignalConnectionPtr ConnectActionDeleted( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::actionDeleted); + } + virtual TSignalConnectionPtr + ConnectTriggerObjectSet(const std::function<void(Qt3DSDMActionHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::triggerObjectSet); + } + virtual TSignalConnectionPtr + ConnectTargetObjectSet(const std::function<void(Qt3DSDMActionHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::targetObjectSet); + } + virtual TSignalConnectionPtr + ConnectEventSet(const std::function<void(Qt3DSDMActionHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::eventHandleSet); + } + virtual TSignalConnectionPtr + ConnectHandlerSet(const std::function<void(Qt3DSDMActionHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::handlerHandleSet); + } + virtual TSignalConnectionPtr + ConnectHandlerArgumentValueSet(const std::function<void(Qt3DSDMHandlerArgHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::handlerArgumentValueSet); + } + + TSignalConnectionPtr ConnectCustomPropertyCreated( + const std::function<void(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customPropertyCreated); + } + TSignalConnectionPtr ConnectCustomPropertyDeleted( + const std::function<void(Qt3DSDMPropertyHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customPropertyDeleted); + } + virtual TSignalConnectionPtr + ConnectCustomPropertyModified(const std::function<void(Qt3DSDMPropertyHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customPropertyModified); + } + TSignalConnectionPtr ConnectCustomEventCreated( + const std::function<void(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customEventCreated); + } + TSignalConnectionPtr ConnectCustomEventDeleted( + const std::function<void(Qt3DSDMEventHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customEventDeleted); + } + virtual TSignalConnectionPtr + ConnectCustomEventModified(const std::function<void(Qt3DSDMEventHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customEventModified); + } + TSignalConnectionPtr ConnectCustomHandlerCreated( + const std::function<void(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customHandlerCreated); + } + TSignalConnectionPtr ConnectCustomHandlerDeleted( + const std::function<void(Qt3DSDMHandlerHandle, Qt3DSDMInstanceHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customHandlerDeleted); + } + virtual TSignalConnectionPtr + ConnectCustomHandlerModified(const std::function<void(Qt3DSDMHandlerHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customHandlerModified); + } + TSignalConnectionPtr ConnectCustomHandlerParamCreated( + const std::function<void(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customHandlerParamCreated); + } + TSignalConnectionPtr ConnectCustomHandlerParamDeleted( + const std::function<void(Qt3DSDMHandlerParamHandle, Qt3DSDMHandlerHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customHandlerParamDeleted); + } + TSignalConnectionPtr ConnectCustomHandlerParamModified( + const std::function<void(Qt3DSDMHandlerParamHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customHandlerParamModified); + } + TSignalConnectionPtr ConnectCustomReferencesModified( + const std::function<void(Qt3DSDMInstanceHandle, const TCharStr &)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::customReferencesModified); + } + TSignalConnectionPtr ConnectControlledToggled( + const std::function<void( + Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> &inCallback) override + { + return CONNECT_SIGNAL_QT(&CStudioFullSystemSignaller::controlledToggled); + } + + virtual void SendChangeSetBegin() + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT changeSetBegin(); + } + virtual void SendChangeSetEnd() + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT changeSetEnd(); + } + + virtual void SendAnimationSetBegin() + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT animationBegin(); + } + virtual void SendAnimationSetEnd() + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT animationEnd(); + } + + void SendSlideCreated(Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT slideCreated(inSlide); + } + void SendSlideDeleted(Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT slideDeleted(inSlide); + } + void SendSlideRearranged(Qt3DSDMSlideHandle inMaster, int inOldIndex, int inNewIndex) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT slideRearranged(inMaster, inOldIndex, inNewIndex); + } + void SendBeginComponentSeconds(Qt3DSDMSlideHandle inMaster) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT beginComponentSeconds(inMaster); + } + void SendComponentSeconds(Qt3DSDMSlideHandle inMaster) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT componentSeconds(inMaster); + } + void SendPropertyLinked(Qt3DSDMSlideHandle inMaster, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT propertyLinked(inMaster, inInstance, inProperty); + } + void SendPropertyUnlinked(Qt3DSDMSlideHandle inMaster, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT propertyUnlinked(inMaster, inInstance, inProperty); + } + void SendActiveSlide(Qt3DSDMSlideHandle inMaster, int inIndex, Qt3DSDMSlideHandle inSlide) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT activeSlide(inMaster, inIndex, inSlide); + } + + void SendInstanceCreated(Qt3DSDMInstanceHandle inInstance) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instanceCreated(inInstance); + } + void SendInstanceDeleted(Qt3DSDMInstanceHandle inInstance) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instanceDeleted(inInstance); + } + + void SendAnimationCreated(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT animationCreated(inAnimation, inInstance, inProperty); + } + void SendAnimationDeleted(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT animationDeleted(inAnimation, inInstance, inProperty); + } + void SendKeyframeInserted(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMKeyframeHandle inKeyframe) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT keyframeInserted(inAnimation, inKeyframe); + } + void SendKeyframeErased(Qt3DSDMAnimationHandle inAnimation, + Qt3DSDMKeyframeHandle inKeyframe) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT keyframeErased(inAnimation, inKeyframe); + } + void SendKeyframeUpdated(Qt3DSDMKeyframeHandle inKeyframe) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT keyframeUpdated(inKeyframe); + } + void SendConnectFirstKeyframeDynamicSet(Qt3DSDMAnimationHandle inAnimation, + bool inDynamic) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT connectFirstKeyframeDynamicSet(inAnimation, inDynamic); + } + + void SendInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT instancePropertyValue(inInstance, inProperty); + } + + void SendActionCreated(Qt3DSDMActionHandle inAction, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT actionCreated(inAction, inSlide, inOwner); + } + void SendActionDeleted(Qt3DSDMActionHandle inAction, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT actionDeleted(inAction, inSlide, inOwner); + } + void SendTriggerObjectSet(Qt3DSDMActionHandle inAction) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT triggerObjectSet(inAction); + } + void SendTargetObjectSet(Qt3DSDMActionHandle inAction) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT targetObjectSet(inAction); + } + void SendEventSet(Qt3DSDMActionHandle inAction) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT eventHandleSet(inAction); + } + void SendHandlerSet(Qt3DSDMActionHandle inAction) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT handlerHandleSet(inAction); + } + void SendHandlerArgumentValueSet(Qt3DSDMHandlerArgHandle inHandlerArgument) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT handlerArgumentValueSet(inHandlerArgument); + } + + void SendCustomPropertyCreated(Qt3DSDMPropertyHandle inProp, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customPropertyCreated(inProp, inOwner); + } + void SendCustomPropertyDeleted(Qt3DSDMPropertyHandle inProp, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customPropertyDeleted(inProp, inOwner); + } + void SendCustomPropertyModified(Qt3DSDMPropertyHandle inProp) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customPropertyModified(inProp); + } + void SendCustomEventCreated(Qt3DSDMEventHandle inEvent, Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customEventCreated(inEvent, inOwner); + } + void SendCustomEventDeleted(Qt3DSDMEventHandle inEvent, Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customEventDeleted(inEvent, inOwner); + } + void SendCustomEventModified(Qt3DSDMEventHandle inEvent) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customEventModified(inEvent); + } + void SendCustomHandlerCreated(Qt3DSDMHandlerHandle inHandler, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerCreated(inHandler, inOwner); + } + void SendCustomHandlerDeleted(Qt3DSDMHandlerHandle inHandler, + Qt3DSDMInstanceHandle inOwner) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerDeleted(inHandler, inOwner); + } + void SendCustomHandlerModified(Qt3DSDMHandlerHandle inHandler) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerModified(inHandler); + } + void SendCustomHandlerParamCreated(Qt3DSDMHandlerParamHandle inParameter, + Qt3DSDMHandlerHandle inHandler) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerParamCreated(inParameter, inHandler); + } + void SendCustomHandlerParamDeleted(Qt3DSDMHandlerParamHandle inParameter, + Qt3DSDMHandlerHandle inHandler) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerParamDeleted(inParameter, inHandler); + } + void SendCustomHandlerParamModified(Qt3DSDMHandlerParamHandle inParameter) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customHandlerParamModified(inParameter); + } + void SendCustomReferencesModified(Qt3DSDMInstanceHandle inOwner, + const TCharStr &inString) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT customReferencesModified(inOwner, inString); + } + + void SendControlledToggled(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) override + { + CHECK_SIGNALS_ENABLED(); + Q_EMIT controlledToggled(inInstance, inProperty); + } +}; + +TSignalItemPtr +CreateStudioFullSystemSignaller(ISlideSystemSignalProvider *inSlideSystemSignalProvider) +{ + return TSignalItemPtr(static_cast<IStudioFullSystemSignalProvider *>( + new CStudioFullSystemSignaller(inSlideSystemSignalProvider))); +} +} + +#include "SignalsImpl.moc" diff --git a/src/dm/systems/SignalsImpl.h b/src/dm/systems/SignalsImpl.h new file mode 100644 index 0000000..988270e --- /dev/null +++ b/src/dm/systems/SignalsImpl.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef SIGNALSIMPLH +#define SIGNALSIMPLH +#include "Qt3DSDMSignals.h" + +namespace qt3dsdm { +class ISlideSystemSignalProvider; + +TSignalItemPtr CreatePropertyCoreSignaller(); +TSignalItemPtr CreateDataCoreSignaller(); +TSignalItemPtr CreateSlideCoreSignaller(); +TSignalItemPtr CreateSlideGraphCoreSignaller(); +TSignalItemPtr CreateAnimationCoreSignaller(); +TSignalItemPtr CreateActionCoreSignaller(); +TSignalItemPtr CreateActionSystemSignaller(); +TSignalItemPtr CreateSlideSystemSignaller(); +TSignalItemPtr CreateCustomPropCoreSignaller(); +TSignalItemPtr +CreateStudioFullSystemSignaller(ISlideSystemSignalProvider *inSlideSystemSignalProvider); +} + +#endif
\ No newline at end of file diff --git a/src/dm/systems/SlideSystem.cpp b/src/dm/systems/SlideSystem.cpp new file mode 100644 index 0000000..d6d8893 --- /dev/null +++ b/src/dm/systems/SlideSystem.cpp @@ -0,0 +1,867 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#ifdef WIN32 +#pragma warning(disable : 4503) +#endif +#include "SlideSystem.h" +#include "SimpleSlideCore.h" + +using namespace std; + +namespace qt3dsdm { + +SSlideSystem::SSlideSystem(TDataCorePtr inDataCore, TSlideCorePtr inSlideCore, + TSlideGraphCorePtr inSlideGraphCore, TAnimationCorePtr inAnimationCore, + Qt3DSDMInstanceHandle inSlideInstance, + Qt3DSDMPropertyHandle inComponentGuidProperty) + : m_DataCore(inDataCore) + , m_SlideCore(inSlideCore) + , m_SlideGraphCore(inSlideGraphCore) + , m_AnimationCore(inAnimationCore) + , m_SlideInstance(inSlideInstance) + , m_ComponentGuid(inComponentGuidProperty) +{ + m_Signaller = CreateSlideSystemSignaller(); +} +void SSlideSystem::SetPropertySystem(TPropertySystemPtr inPropertySystem) +{ + m_PropertySystem = inPropertySystem; +} + +Qt3DSDMSlideHandle SSlideSystem::CreateMasterSlide() +{ + Qt3DSDMInstanceHandle theSlideInstance = m_DataCore->CreateInstance(); + m_DataCore->DeriveInstance(theSlideInstance, m_SlideInstance); + Qt3DSDMSlideHandle retval = m_SlideCore->CreateSlide(theSlideInstance); + m_SlideGraphCore->CreateSlideGraph(retval); + GetSignalSender()->SendMasterCreated(retval); + return retval; +} + +inline bool PropertyHandlePairEquals(const TPropertyHandlePropertyInfoPair &inPair, + Qt3DSDMPropertyHandle inProperty) +{ + return (inProperty == inPair.first); +} + +void AddReferencedInstance(const TSlideEntry &inEntry, + const TPropertyHandlePropertyInfoPairList &inInfoPairList, + Qt3DSDMSlideHandle inSourceSlide, Qt3DSDMSlideHandle inDestSlide, + TInstanceHandleList &outInstances, TSlideEntryList &outReferencedEntries) +{ + TPropertyHandlePropertyInfoPairList::const_iterator theFind = + find_if<TPropertyHandlePropertyInfoPairList::const_iterator>( + inInfoPairList, std::bind(PropertyHandlePairEquals, + std::placeholders::_1, get<1>(inEntry))); + if (theFind != inInfoPairList.end()) { + TPropertyInstanceInfoPtr theInfo(theFind->second); + Qt3DSDMInstanceHandle theReferenced(theInfo->GetInstanceForProperty(get<2>(inEntry))); + if (theReferenced.Valid() + && !exists(outInstances, std::bind(equal_to<int>(), theReferenced, + std::placeholders::_1))) { + insert_unique(outInstances, theReferenced); + SValue theNewValue( + theInfo->CreateInstanceForProperty(inSourceSlide, inDestSlide, theReferenced)); + outReferencedEntries.push_back( + make_tuple(get<0>(inEntry), get<1>(inEntry), theNewValue)); + } + } +} + +void CopySpecificAnimation(Qt3DSDMSlideHandle inMaster, Qt3DSDMSlideHandle inTarget, + TInstancePropertyPair inPropertyPair, TAnimationCorePtr inAnimationCore, + size_t inIndex) +{ + Qt3DSDMAnimationHandle theAnimation = inAnimationCore->GetAnimation( + inMaster, inPropertyPair.first, inPropertyPair.second, inIndex); + if (theAnimation.Valid()) + CopyAnimation(inAnimationCore, theAnimation, inTarget, inPropertyPair.first, + inPropertyPair.second, inIndex); +} + +void CopyAnimationIfExist(Qt3DSDMSlideHandle inMaster, Qt3DSDMSlideHandle inTarget, + TInstancePropertyPair inPropertyPair, TPropertySystemPtr inPropertySystem, + TAnimationCorePtr inAnimationCore) +{ + DataModelDataType::Value thePropertyType = inPropertySystem->GetDataType(inPropertyPair.second); + std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(thePropertyType); + if (std::get<0>(theArity)) + do_times(std::get<1>(theArity), std::bind(CopySpecificAnimation, inMaster, inTarget, + inPropertyPair, inAnimationCore, + std::placeholders::_1)); +} + +void SetEntryValueIfNotReferenced(const TSlideEntry &inEntry, + const TInstanceHandleList &inReferencedInstances, + const TSlideEntryList &inReferencedEntries, + Qt3DSDMSlideHandle inSource, Qt3DSDMSlideHandle inDestSlide, + TPropertySystemPtr inPropertySystem, TSlideCorePtr inDestCore, + TAnimationCorePtr inAnimationCore) +{ + // Don't copy referenced instance properties. + if (exists(inReferencedInstances, std::bind(equal_to<int>(), get<0>(inEntry), + std::placeholders::_1))) + return; + TSlideEntryList::const_iterator theFind = find_if<TSlideEntryList::const_iterator>( + inReferencedEntries, + std::bind(CSimpleSlideCore::PropertyFound, get<0>(inEntry), get<1>(inEntry), + std::placeholders::_1)); + if (theFind != inReferencedEntries.end()) + inDestCore->ForceSetInstancePropertyValue(inDestSlide, get<0>(inEntry), get<1>(inEntry), + get<2>(*theFind)); + else + inDestCore->ForceSetInstancePropertyValue(inDestSlide, get<0>(inEntry), get<1>(inEntry), + get<2>(inEntry)); + CopyAnimationIfExist(inSource, inDestSlide, make_pair(get<0>(inEntry), get<1>(inEntry)), + inPropertySystem, inAnimationCore); +} + +Qt3DSDMSlideHandle SSlideSystem::CreateSlide(Qt3DSDMSlideHandle inMaster, int inIndex) +{ + return DuplicateSlide(inMaster, inIndex); +} + +Qt3DSDMSlideHandle SSlideSystem::DuplicateSlide(Qt3DSDMSlideHandle inSourceSlide, int inIndex) +{ + Qt3DSDMSlideHandle theMaster = GetMasterSlide(inSourceSlide); + Qt3DSDMInstanceHandle theSlideInstance = m_DataCore->CreateInstance(); + m_DataCore->DeriveInstance(theSlideInstance, m_SlideInstance); + Qt3DSDMSlideHandle retval = m_SlideCore->CreateSlide(theSlideInstance); + + TSlideHandleList theChildren; + m_SlideCore->GetChildSlides(theMaster, theChildren); + m_SlideCore->DeriveSlide(retval, theMaster, inIndex - 1); + int finalIndex = m_SlideCore->GetChildIndex(theMaster, retval) + 1; + if (!theChildren.empty()) { + // If the master was passed in, we get the intersecting properties + // of the master and first child. + // if another slide was passed in, we again do the intersection but we + // take the values from the source slide instead of the master. + TSlideEntryList theIntersectingEntries; + if (inSourceSlide == theMaster) + m_SlideCore->GetIntersectingProperties(theMaster, theChildren.at(0), + theIntersectingEntries); + else + m_SlideCore->GetIntersectingProperties(inSourceSlide, theMaster, + theIntersectingEntries); + + // duplicates the instance properties, from source slide (could be master (a new slide + // command) or another other slides (duplicate slide) to the newly created slide + m_DataCore->CopyInstanceProperties(this->GetSlideInstance(inSourceSlide), theSlideInstance); + + TInstanceHandleList theReferencedInstances; + TSlideEntryList theReferencedEntries; + do_all(theIntersectingEntries, + std::bind(AddReferencedInstance, std::placeholders::_1, + std::cref(m_PropertyInfoPairList), + inSourceSlide, retval, std::ref(theReferencedInstances), + std::ref(theReferencedEntries))); + do_all(theIntersectingEntries, + std::bind(SetEntryValueIfNotReferenced, std::placeholders::_1, + std::cref(theReferencedInstances), + std::cref(theReferencedEntries), inSourceSlide, retval, + m_PropertySystem, m_SlideCore, m_AnimationCore)); + } + GetSignalSender()->SendSlideCreated(theMaster, finalIndex, retval); + return retval; +} + +Qt3DSDMSlideHandle SSlideSystem::GetMasterSlide(Qt3DSDMSlideHandle inSlide) const +{ + if (inSlide.Valid() && m_SlideCore->IsSlide(inSlide)) { + Qt3DSDMSlideHandle theParent = m_SlideCore->GetParentSlide(inSlide); + if (theParent.Valid()) + return theParent; + return inSlide; + } + return 0; +} + +bool SSlideSystem::IsMasterSlide(Qt3DSDMSlideHandle inSlide) const +{ + Qt3DSDMSlideHandle theParent = m_SlideCore->GetParentSlide(inSlide); + if (!theParent.Valid()) + return true; + else + return false; +} + +inline bool GraphGuidMatches(Qt3DSDMSlideGraphHandle inGraph, TSlideGraphCorePtr inSlideGraph, + TSlideCorePtr inSlideCore, TDataCorePtr inDataCore, + Qt3DSDMPropertyHandle inProperty, SValue inValue) +{ + Qt3DSDMSlideHandle theMaster = inSlideGraph->GetGraphRoot(inGraph); + Qt3DSDMInstanceHandle theInstance = inSlideCore->GetSlideInstance(theMaster); + SValue theValue; + if (inDataCore->GetInstancePropertyValue(theInstance, inProperty, theValue) + && Equals(inValue, theValue.toOldSkool())) + return true; + return false; +} + +Qt3DSDMSlideHandle SSlideSystem::GetMasterSlideByComponentGuid(SLong4 inGuid) const +{ + TSlideGraphHandleList theGraphs; + m_SlideGraphCore->GetSlideGraphs(theGraphs); + TSlideGraphHandleList::iterator theFind = find_if<TSlideGraphHandleList::iterator>( + theGraphs, std::bind(GraphGuidMatches, + std::placeholders::_1, m_SlideGraphCore, m_SlideCore, m_DataCore, + m_ComponentGuid, inGuid)); + if (theFind != theGraphs.end()) + return m_SlideGraphCore->GetGraphRoot(*theFind); + return 0; +} + +void InsertIfReferencedProperty(const TSlideEntry &inEntry, + const TPropertyHandlePropertyInfoPairList &inRefProperties, + TInstanceHandleList &inInstances) +{ + TPropertyHandlePropertyInfoPairList::const_iterator theFind = + find_if<TPropertyHandlePropertyInfoPairList::const_iterator>( + inRefProperties, std::bind(PropertyHandlePairEquals, std::placeholders::_1, get<1>(inEntry))); + if (theFind != inRefProperties.end()) { + Qt3DSDMInstanceHandle theInstance(theFind->second->GetInstanceForProperty(get<2>(inEntry))); + if (theInstance.Valid()) + inInstances.push_back(theInstance); + } +} + +void SSlideSystem::InsertEntryAndPropertyInstance(const TSlideEntry &inEntry, + TInstanceHandleList &inInstances, + Qt3DSDMSlideHandle inSlide) +{ + Qt3DSDMInstanceHandle theEntryInstance = get<0>(inEntry); + if (find(inInstances.begin(), inInstances.end(), theEntryInstance) == inInstances.end()) { + TGraphSlidePair thePair = m_SlideGraphCore->GetAssociatedGraph(theEntryInstance); + if (thePair.second == inSlide) // if this instance belongs to this slide + { + // get all references belong to this instance (ex: image instances that belong to this + // material instance) + qt3dsdm::SValue theValue; + for (TPropertyHandlePropertyInfoPairList::iterator theIter = + m_PropertyInfoPairList.begin(); + theIter != m_PropertyInfoPairList.end(); ++theIter) { + if (m_DataCore->HasAggregateInstanceProperty( + theEntryInstance, + theIter->first) // check if the property exists before querying the value + && m_DataCore->GetInstancePropertyValue( + theEntryInstance, theIter->first, + theValue)) // this function may throw error if the property doesn't exist + { + Qt3DSDMInstanceHandle theInstance( + theIter->second->GetInstanceForProperty(theValue.toOldSkool())); + if (theInstance.Valid()) + inInstances.push_back(theInstance); + } + } + // get this instance as well + inInstances.push_back(theEntryInstance); + } + } +} + +// Delete the referenced instances of this slide +// This function is very similar to GetReferencedInstances +// You change one function, you need to change the other function +void SSlideSystem::DeleteReferencedInstances(Qt3DSDMSlideHandle inSlide) +{ + // Recursively delete the children of this slide + // Usually the slide has children if it is a Master slide (for example when deleting a + // Component) + TSlideHandleList theChildren; + m_SlideCore->GetChildSlides(inSlide, theChildren); + do_all(theChildren, std::bind(&SSlideSystem::DeleteReferencedInstances, this, + std::placeholders::_1)); + + // Delete the referenced instances from this slide + TSlideEntryList theEntries; + m_SlideCore->GetSlidePropertyEntries(inSlide, theEntries); + + // Run through all entries, if you find a reference property delete the associated instance. + // This is for properties that are set on this slide (because you can set property on slide or + // on instance) + TInstanceHandleList theReferencedInstances; + do_all(theEntries, + std::bind(InsertIfReferencedProperty, std::placeholders::_1, + std::cref(m_PropertyInfoPairList), + std::ref(theReferencedInstances))); + do_all(theReferencedInstances, std::bind(&IDataCore::DeleteInstance, m_DataCore, + std::placeholders::_1)); + + // Run through all entries, delete all instances that belong to this slide and its reference + // property instances + // This is for properties that are set on instance + theReferencedInstances.clear(); + do_all(theEntries, std::bind(&SSlideSystem::InsertEntryAndPropertyInstance, this, + std::placeholders::_1, + std::ref(theReferencedInstances), inSlide)); + do_all(theReferencedInstances, std::bind(&IDataCore::DeleteInstance, m_DataCore, + std::placeholders::_1)); +} + +// Get the referenced instances of this slide +// This function is very similar to DeleteReferencedInstances +// You change one function, you need to change the other function +void SSlideSystem::GetReferencedInstances(Qt3DSDMSlideHandle inSlide, + TInstanceHandleList &outReferencedInstances) +{ + // Recursively get the children of this slide + // Usually the slide has children if it is a Master slide (for example Component) + TSlideHandleList theChildren; + m_SlideCore->GetChildSlides(inSlide, theChildren); + do_all(theChildren, std::bind(&SSlideSystem::GetReferencedInstances, this, + std::placeholders::_1, + std::ref(outReferencedInstances))); + + // Get the referenced instances from this slide + TSlideEntryList theEntries; + m_SlideCore->GetSlidePropertyEntries(inSlide, theEntries); + + // Run through all entries, if you find a reference property get the associated instance. + // This is for properties that are set on this slide (because you can set property on slide or + // on instance) + do_all(theEntries, + std::bind(InsertIfReferencedProperty, std::placeholders::_1, + std::cref(m_PropertyInfoPairList), + std::ref(outReferencedInstances))); + + // Run through all entries, get all instances that belong to this slide and its reference + // property instances + // This is for properties that are set on instance + do_all(theEntries, std::bind(&SSlideSystem::InsertEntryAndPropertyInstance, this, + std::placeholders::_1, + std::ref(outReferencedInstances), inSlide)); +} + +void SSlideSystem::DeleteSlideByIndex(Qt3DSDMSlideHandle inMaster, size_t inIndex) +{ + Qt3DSDMSlideHandle theChild = GetSlideByIndex(inMaster, inIndex); + TInstanceHandleList theInstances; + if (theChild.Valid()) { + DeleteReferencedInstances(theChild); + m_SlideCore->DeleteSlide(theChild, theInstances); + do_all(theInstances, std::bind(&IDataCore::DeleteInstance, m_DataCore, + std::placeholders::_1)); + } + if (inIndex == 0) + GetSignalSender()->SendMasterDeleted(inMaster); + else + GetSignalSender()->SendSlideDeleted(inMaster, (int)inIndex, theChild); +} + +void SSlideSystem::GetSlideReferencedInstances(Qt3DSDMSlideHandle inMaster, size_t inIndex, + TInstanceHandleList &outReferencedInstances) +{ + outReferencedInstances.clear(); + Qt3DSDMSlideHandle theChild = GetSlideByIndex(inMaster, inIndex); + if (theChild.Valid()) { + GetReferencedInstances(theChild, outReferencedInstances); + } +} + +Qt3DSDMSlideHandle SSlideSystem::GetSlideByIndex(Qt3DSDMSlideHandle inMaster, size_t inIndex) const +{ + if (inIndex == 0) + return inMaster; + --inIndex; + TSlideHandleList theChildren; + m_SlideCore->GetChildSlides(inMaster, theChildren); + if (inIndex < theChildren.size()) + return theChildren[inIndex]; + return Qt3DSDMSlideHandle(); +} + +void SSlideSystem::SetActiveSlide(Qt3DSDMSlideHandle inMaster, size_t inIndex) +{ + Qt3DSDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(inMaster); + Qt3DSDMSlideHandle theActiveSlide = inMaster; + if (inIndex > 0) + theActiveSlide = GetSlideByIndex(inMaster, inIndex); + Qt3DSDMSlideHandle theOldSlide = m_SlideGraphCore->GetGraphActiveSlide(theGraph); + m_SlideGraphCore->SetGraphActiveSlide(theGraph, theActiveSlide); + GetSignalSender()->SendActiveSlide(inMaster, (int)inIndex, theOldSlide, theActiveSlide); +} + +size_t SSlideSystem::GetSlideCount(Qt3DSDMSlideHandle inMaster) const +{ + TSlideHandleList theChildren; + m_SlideCore->GetChildSlides(inMaster, theChildren); + return 1 + theChildren.size(); +} + +void SSlideSystem::RearrangeSlide(Qt3DSDMSlideHandle inMaster, size_t inOldIndex, size_t inNewIndex) +{ + if (inOldIndex == 0) + throw RearrangeSlideArgumentsMustNotBeZero(L""); + TSlideHandleList theChildren; + m_SlideCore->GetChildSlides(inMaster, theChildren); + Qt3DSDMSlideHandle theChild = theChildren.at(inOldIndex - 1); + m_SlideCore->DeriveSlide(theChild, inMaster, (int)inNewIndex - 1); + GetSignalSender()->SendSlideRearranged(inMaster, (int)inOldIndex, (int)inNewIndex); +} + +void SSlideSystem::SetComponentSeconds(Qt3DSDMSlideHandle inSlide, float inSeconds) +{ + Qt3DSDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(GetMasterSlide(inSlide)); + m_SlideCore->SetSlideTime(m_SlideGraphCore->GetGraphActiveSlide(theGraph), inSeconds); +} + +float SSlideSystem::GetComponentSeconds(Qt3DSDMSlideHandle inSlide) const +{ + Qt3DSDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(GetMasterSlide(inSlide)); + return m_SlideCore->GetSlideTime(m_SlideGraphCore->GetGraphActiveSlide(theGraph)); +} + +long SSlideSystem::GetComponentSecondsLong(Qt3DSDMSlideHandle inSlide) const +{ + float seconds(GetComponentSeconds(inSlide)); + return static_cast<long>((seconds * 1000) + .5f); +} + +long SSlideSystem::GetComponentSecondsLong(Qt3DSDMInstanceHandle inInstance) const +{ + Qt3DSDMSlideGraphHandle theGraph = m_SlideGraphCore->GetAssociatedGraph(inInstance).first; + float seconds = m_SlideCore->GetSlideTime(m_SlideGraphCore->GetGraphActiveSlide(theGraph)); + return static_cast<long>((seconds * 1000) + .5f); +} + +SInstanceSlideInformation +SSlideSystem::GetInstanceSlideInformation(Qt3DSDMInstanceHandle inInstance) const +{ + TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance); + Qt3DSDMSlideHandle theAssociatedSlide(theGraphSlidePair.second); + if (theAssociatedSlide.Valid() == false) + return SInstanceSlideInformation(); + Qt3DSDMSlideHandle theMasterSlide(GetMasterSlide(theGraphSlidePair.second)); + Qt3DSDMSlideHandle theActiveSlide( + m_SlideGraphCore->GetGraphActiveSlide(theGraphSlidePair.first)); + float seconds = m_SlideCore->GetSlideTime(theActiveSlide); + long theMilliseconds = static_cast<long>((seconds * 1000) + .5f); + return SInstanceSlideInformation(theAssociatedSlide, theMasterSlide, theActiveSlide, + theMilliseconds); +} + +/** + * Use the instance for storing information such as name, or the GUID of the object + * this slide links to. + */ +Qt3DSDMInstanceHandle SSlideSystem::GetSlideInstance(Qt3DSDMSlideHandle inSlide) const +{ + return m_SlideCore->GetSlideInstance(inSlide); +} +/** + * Reverse lookup into the slide system so you can match slides to instances. + */ +Qt3DSDMSlideHandle SSlideSystem::GetSlideByInstance(Qt3DSDMInstanceHandle inSlide) const +{ + return m_SlideCore->GetSlideByInstance(inSlide); +} + +/** + * Slide may be either a master slide + */ +void SSlideSystem::AssociateInstanceWithSlide(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) +{ + Qt3DSDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(GetMasterSlide(inSlide)); + m_SlideGraphCore->AssociateInstance(theGraph, inSlide, inInstance); + GetSignalSender()->SendInstanceAssociated(inSlide, inInstance); +} + +Qt3DSDMSlideHandle SSlideSystem::GetAssociatedSlide(Qt3DSDMInstanceHandle inInstance) const +{ + return m_SlideGraphCore->GetAssociatedGraph(inInstance).second; +} + +/** + * This gets the instances that resides int the SlideGraph, i.e. all the instances in all the + *slides for this component/scene + * TODO rename this to make it more clear + */ +void SSlideSystem::GetAssociatedInstances(Qt3DSDMSlideHandle inMaster, + TSlideInstancePairList &outAssociations) const +{ + m_SlideGraphCore->GetAssociatedInstances( + m_SlideGraphCore->GetSlideGraph(GetMasterSlide(inMaster)), outAssociations); +} + +/** + * Gets all the instances in this slide + */ +void SSlideSystem::GetAssociatedInstances(Qt3DSDMSlideHandle inSlide, + TInstanceHandleList &outAssociations) const +{ + Qt3DSDMSlideHandle theMasterSlide = GetMasterSlide(inSlide); + TSlideInstancePairList theGraphInstances; + m_SlideGraphCore->GetAssociatedInstances(m_SlideGraphCore->GetSlideGraph(theMasterSlide), + theGraphInstances); + for (TSlideInstancePairList::const_iterator theIter = theGraphInstances.begin(); + theIter != theGraphInstances.end(); ++theIter) { + if (theIter->first == inSlide || theIter->first == theMasterSlide) { + // in the current slide or master slide + outAssociations.push_back(theIter->second); + } + } +} + +void DeleteInstanceIfExistsAsProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, TSlideCorePtr inSlideCore, + TPropertyInstanceInfoPtr inPropertyInfoPtr, + TDataCorePtr inDataCore) +{ + SValue theValue; + if (inSlideCore->GetSpecificInstancePropertyValue(inSlide, inInstance, inProperty, theValue)) { + Qt3DSDMInstanceHandle theInstance(inPropertyInfoPtr->GetInstanceForProperty(theValue)); + if (theInstance.Valid()) + inDataCore->DeleteInstance(theInstance); + } +} + +void SSlideSystem::LinkProperty(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) +{ + Qt3DSDMSlideGraphHandle theGraph = m_SlideGraphCore->GetAssociatedGraph(inInstance).first; + Qt3DSDMSlideHandle theSlide = m_SlideGraphCore->GetGraphRoot(theGraph); + TPropertyHandlePropertyInfoPairList::const_iterator theFind = + find_if<TPropertyHandlePropertyInfoPairList::const_iterator>( + m_PropertyInfoPairList, std::bind(PropertyHandlePairEquals, + std::placeholders::_1, inProperty)); + if (theFind != m_PropertyInfoPairList.end()) { + TSlideHandleList theChildren; + m_SlideCore->GetChildSlides(theSlide, theChildren); + do_all(theChildren, std::bind(DeleteInstanceIfExistsAsProperty, std::placeholders::_1, inInstance, + inProperty, m_SlideCore, theFind->second, m_DataCore)); + } + m_SlideCore->ClearChildrenPropertyValues(theSlide, inInstance, inProperty); + GetSignalSender()->SendPropertyLinked(theSlide, inInstance, inProperty); +} + +void ClearPropertyValueIfLinked(Qt3DSDMSlideHandle inMaster, const TSlideHandleList &inChildren, + Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + TSlideCorePtr inSlideCore) +{ + if (inChildren.empty()) + return; + + if (inSlideCore->ContainsProperty(inChildren.at(0), inInstance, + inProperty)) // if property is linked, + inSlideCore->ClearChildrenPropertyValues(inMaster, inInstance, + inProperty); // get it off non-master slides +} + +void SetReferencedEntryValue(Qt3DSDMSlideHandle inMaster, Qt3DSDMSlideHandle inDestSlide, + TPropertyInstanceInfoPtr inInfo, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + Qt3DSDMInstanceHandle inReferencedInstance, TSlideCorePtr inSlideCore) +{ + SValue theNewValue( + inInfo->CreateInstanceForProperty(inMaster, inDestSlide, inReferencedInstance)); + inSlideCore->ForceSetInstancePropertyValue(inDestSlide, inInstance, inProperty, theNewValue); +} + +void SSlideSystem::UnlinkProperty(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) +{ + Qt3DSDMSlideGraphHandle theGraph = m_SlideGraphCore->GetAssociatedGraph(inInstance).first; + Qt3DSDMSlideHandle theSlide = m_SlideGraphCore->GetGraphRoot(theGraph); + SValue theValue; + SValue theTempValue; + if (!m_SlideCore->GetInstancePropertyValue(theSlide, inInstance, inProperty, theValue)) { + if (!m_PropertySystem->GetInstancePropertyValue(inInstance, inProperty, theTempValue)) + throw PropertyLinkError(L""); + theValue = theTempValue.toOldSkool(); + } + + m_SlideCore->ForceSetInstancePropertyValue(theSlide, inInstance, inProperty, theValue); + TSlideHandleList theChildren; + m_SlideCore->GetChildSlides(theSlide, theChildren); + + Qt3DSDMInstanceHandle theReferenced; + TPropertyHandlePropertyInfoPairList::const_iterator theFind = + find_if<TPropertyHandlePropertyInfoPairList::const_iterator>( + m_PropertyInfoPairList, std::bind(PropertyHandlePairEquals, + std::placeholders::_1, inProperty)); + TPropertyInstanceInfoPtr theInfo; + if (theFind != m_PropertyInfoPairList.end()) { + theInfo = theFind->second; + theReferenced = theInfo->GetInstanceForProperty(theValue); + } + if (theReferenced.Valid()) { + TPropertyHandleList theProperties; + m_PropertySystem->GetAggregateInstanceProperties( + theReferenced, + theProperties); // TODO: We should make the method return the custom properties. + // Remove the property instance's unlinked properties from non-master slides. + do_all(theProperties, + std::bind(ClearPropertyValueIfLinked, theSlide, std::cref(theChildren), + theReferenced, std::placeholders::_1, m_SlideCore)); + // Remove all property values from the children from that instance. + do_all(theChildren, std::bind(SetReferencedEntryValue, theSlide, + std::placeholders::_1, theInfo, inInstance, + inProperty, theReferenced, m_SlideCore)); + } else { + do_all(theChildren, std::bind(&ISlideCore::ForceSetInstancePropertyValue, m_SlideCore, + std::placeholders::_1, + inInstance, inProperty, theValue)); + do_all(theChildren, + std::bind(CopyAnimationIfExist, theSlide, std::placeholders::_1, make_pair(inInstance, inProperty), + m_PropertySystem, m_AnimationCore)); + } + GetSignalSender()->SendPropertyUnlinked(theSlide, inInstance, inProperty); +} + +bool SSlideSystem::IsPropertyLinked(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance); + Qt3DSDMSlideGraphHandle theGraph = theGraphSlidePair.first; + if (!theGraph.Valid()) + return false; + + Qt3DSDMSlideHandle theSlide = m_SlideGraphCore->GetGraphRoot(theGraph); + if (theGraphSlidePair.second != theSlide) + return false; + + TSlideHandleList theChildren; + m_SlideCore->GetChildSlides(theSlide, theChildren); + bool containsProperty = false; + for (TSlideHandleList::iterator theIter = theChildren.begin(); + theIter != theChildren.end() && !containsProperty; ++theIter) { + containsProperty = + containsProperty || m_SlideCore->ContainsProperty(*theIter, inInstance, inProperty); + } + + return !containsProperty; +} + +bool SSlideSystem::CanPropertyBeLinked(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance); + if (theGraphSlidePair.first.Valid() + && theGraphSlidePair.second == m_SlideGraphCore->GetGraphRoot(theGraphSlidePair.first)) + return true; + return false; +} + +bool SSlideSystem::GetSlidePropertyValue(size_t inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) +{ + TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance); + Qt3DSDMSlideGraphHandle theGraph = theGraphSlidePair.first; + if (!theGraph.Valid()) + return false; + Qt3DSDMSlideHandle theSlide = GetSlideByIndex(m_SlideGraphCore->GetGraphRoot(theGraph), inSlide); + if (!theSlide.Valid()) + return false; + return m_SlideCore->GetSpecificInstancePropertyValue(theSlide, inInstance, inProperty, + outValue); +} + +void AddEntriesToHash(const TSlideEntryList &theSlideEntries, TSlideEntryHash &theEntryHash, + TInstancePropertyPairList &outProperties) +{ + for (size_t idx = 0, end = theSlideEntries.size(); idx < end; ++idx) { + const TSlideEntry &theEntry(theSlideEntries[idx]); + pair<TSlideEntryHash::iterator, bool> insertRecord(theEntryHash.insert( + make_pair(TSlideInstancePropertyPair(get<0>(theEntry), get<1>(theEntry)), + SInternValue::ISwearThisHasAlreadyBeenInternalized(get<2>(theEntry))))); + if (insertRecord.second) + outProperties.push_back(insertRecord.first->first); + } +} + +void SSlideSystem::GetUnionOfProperties(Qt3DSDMSlideHandle inSlide1, Qt3DSDMSlideHandle inSlide2, + TInstancePropertyPairList &outProperties) const +{ + TSlideEntryHash theEntryHash; + TSlideEntryList theSlideEntries; + if (m_SlideCore->IsSlide(inSlide1)) { + m_SlideCore->GetSlidePropertyEntries(inSlide1, theSlideEntries); + AddEntriesToHash(theSlideEntries, theEntryHash, outProperties); + } + if (m_SlideCore->IsSlide(inSlide2)) { + m_SlideCore->GetSlidePropertyEntries(inSlide2, theSlideEntries); + AddEntriesToHash(theSlideEntries, theEntryHash, outProperties); + } +} + +void SSlideSystem::SetActiveSlide(Qt3DSDMSlideHandle inSlide) +{ + Qt3DSDMSlideHandle theMaster = GetMasterSlide(inSlide); + int theIndex = GetSlideIndex(inSlide); + SetActiveSlide(theMaster, theIndex); +} + +Qt3DSDMSlideHandle SSlideSystem::GetAssociatedSlide(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance); + Qt3DSDMSlideGraphHandle theGraph = theGraphSlidePair.first; + if (!theGraph.Valid()) + return 0; + Qt3DSDMSlideHandle theSlide = m_SlideGraphCore->GetGraphActiveSlide(theGraph); + if (theSlide.Valid()) { + if (m_SlideCore->ContainsProperty(theSlide, inInstance, inProperty)) + return theSlide; + theSlide = m_SlideCore->GetParentSlide(theSlide); + if (theSlide.Valid() && m_SlideCore->ContainsProperty(theSlide, inInstance, inProperty)) + return theSlide; + return theGraphSlidePair.second; + } + return 0; +} + +bool SSlideSystem::SlideValid(Qt3DSDMSlideHandle inSlide) const +{ + return m_SlideCore->HandleValid(inSlide); +} + +int SSlideSystem::GetSlideIndex(Qt3DSDMSlideHandle inSlide) const +{ + Qt3DSDMSlideHandle theMaster = GetMasterSlide(inSlide); + if (inSlide.Valid() && inSlide != theMaster) + return m_SlideCore->GetChildIndex(theMaster, inSlide) + 1; + return 0; +} + +int SSlideSystem::GetActiveSlideIndex(Qt3DSDMSlideHandle inMaster) const +{ + Qt3DSDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(inMaster); + Qt3DSDMSlideHandle theActiveSlide = m_SlideGraphCore->GetGraphActiveSlide(theGraph); + if (theActiveSlide == inMaster) + return 0; + return GetSlideIndex(theActiveSlide); +} + +Qt3DSDMSlideHandle SSlideSystem::GetActiveSlide(Qt3DSDMSlideHandle inMaster) const +{ + Qt3DSDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(inMaster); + return m_SlideGraphCore->GetGraphActiveSlide(theGraph); +} + +Qt3DSDMInstanceHandle SSlideSystem::GetSlideSelectedInstance(Qt3DSDMSlideHandle inSlide) const +{ + TIntIntMap::const_iterator theIter = m_SlideSelectedInstances.find(inSlide); + if (theIter != m_SlideSelectedInstances.end() && m_DataCore->IsInstance(theIter->second)) + return theIter->second; + return 0; +} + +void SSlideSystem::SetSlideSelectedInstance(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) +{ + m_SlideSelectedInstances[inSlide] = inInstance; +} + +void SSlideSystem::RegisterPropertyInstance(Qt3DSDMPropertyHandle inPropertyHandle, + TPropertyInstanceInfoPtr inPropertyInfo) +{ + m_PropertyInfoPairList.push_back(make_pair(inPropertyHandle, inPropertyInfo)); +} + +ISlideSystemSignalProvider *SSlideSystem::GetSignalProvider() +{ + return dynamic_cast<ISlideSystemSignalProvider *>(m_Signaller.get()); +} + +ISlideSystemSignalSender *SSlideSystem::GetSignalSender() +{ + return dynamic_cast<ISlideSystemSignalSender *>(m_Signaller.get()); +} + +qt3dsdm::Qt3DSDMSlideHandle SSlideSystem::GetApplicableSlide(Qt3DSDMInstanceHandle inHandle) +{ + TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inHandle); + if (!theGraphSlidePair.first.Valid()) + return Qt3DSDMSlideHandle(); + + Qt3DSDMSlideHandle theMaster = m_SlideGraphCore->GetGraphRoot(theGraphSlidePair.first); + if (theGraphSlidePair.second != theMaster) + return theGraphSlidePair.second; + + return theMaster; +} + +qt3dsdm::Qt3DSDMSlideHandle SSlideSystem::GetApplicableSlide(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) +{ + TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inHandle); + if (!theGraphSlidePair.first.Valid()) + return Qt3DSDMSlideHandle(); + + Qt3DSDMSlideHandle theMaster = m_SlideGraphCore->GetGraphRoot(theGraphSlidePair.first); + if (theGraphSlidePair.second != theMaster) + return theGraphSlidePair.second; + + Qt3DSDMSlideHandle theActive = m_SlideGraphCore->GetGraphActiveSlide(theGraphSlidePair.first); + if (m_SlideCore->ContainsProperty(theActive, inHandle, inProperty)) + return theActive; + + return theMaster; +} + +bool SSlideSystem::GetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const +{ + return m_SlideCore->GetInstancePropertyValue(inSlide, inInstance, inProperty, outValue); +} + +bool SSlideSystem::GetCanonicalInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance); + if (theGraphSlidePair.first.Valid()) { + // Check to see if the object is on the master slide; + if (theGraphSlidePair.second == m_SlideGraphCore->GetGraphRoot(theGraphSlidePair.first)) { + TSlideHandleList theChildren; + m_SlideCore->GetChildSlides(theGraphSlidePair.second, theChildren); + // See if the value exists on slide 1. + if (!theChildren.empty() + && m_SlideCore->GetSpecificInstancePropertyValue(theChildren.at(0), inInstance, + inProperty, outValue)) + return true; + } + + if (m_SlideCore->GetSpecificInstancePropertyValue(theGraphSlidePair.second, inInstance, + inProperty, outValue)) + return true; + } + return false; +} + +void SSlideSystem::ForceSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + m_SlideCore->ForceSetInstancePropertyValue(inSlide, inInstance, inProperty, inValue); +} +} diff --git a/src/dm/systems/SlideSystem.h b/src/dm/systems/SlideSystem.h new file mode 100644 index 0000000..1ea3f81 --- /dev/null +++ b/src/dm/systems/SlideSystem.h @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef SLIDESYSTEMH +#define SLIDESYSTEMH +#include "Qt3DSDMDataCore.h" +#include "Qt3DSDMSlideCore.h" +#include "Qt3DSDMSlideGraphCore.h" +#include "Qt3DSDMTransactions.h" +#include "Qt3DSDMSlides.h" +#include "Qt3DSDMAnimation.h" +#include "StudioPropertySystem.h" +#include "SignalsImpl.h" + +/** + * The systems aggregate the various cores and provide further information or + * integrity checking taking the various cores into account. + */ + +namespace qt3dsdm { + +typedef std::pair<Qt3DSDMPropertyHandle, TPropertyInstanceInfoPtr> TPropertyHandlePropertyInfoPair; +typedef std::vector<TPropertyHandlePropertyInfoPair> TPropertyHandlePropertyInfoPairList; +/** + * Provides more thorough checking and will return an appropriate + * slide graph when calling GetSlideGraph + */ +struct SSlideSystem : public ISlideSystem +{ + Q_DISABLE_COPY(SSlideSystem) + + TDataCorePtr m_DataCore; // TODO: We might want to throw this away and use the PropertySystem, + // unless we have a clean seperate of IPropertySystem and IDataCore + TPropertySystemPtr m_PropertySystem; + TSlideCorePtr m_SlideCore; + TSlideGraphCorePtr m_SlideGraphCore; + TAnimationCorePtr m_AnimationCore; + Qt3DSDMInstanceHandle m_SlideInstance; + Qt3DSDMPropertyHandle m_ComponentGuid; + std::shared_ptr<ISignalItem> m_Signaller; + TPropertyHandlePropertyInfoPairList m_PropertyInfoPairList; + typedef std::unordered_map<int, int> TIntIntMap; + TIntIntMap m_SlideSelectedInstances; + + SSlideSystem(TDataCorePtr inDataCore, TSlideCorePtr inSlideCore, + TSlideGraphCorePtr inSlideGraphCore, TAnimationCorePtr inAnimationCore, + Qt3DSDMInstanceHandle inSlideInstance, + Qt3DSDMPropertyHandle inComponentGuidProperty); + + void SetPropertySystem(TPropertySystemPtr inPropertySystem); + + Qt3DSDMSlideHandle CreateMasterSlide() override; + Qt3DSDMSlideHandle CreateSlide(Qt3DSDMSlideHandle inMaster, int inIndex = -1) override; + Qt3DSDMSlideHandle DuplicateSlide(Qt3DSDMSlideHandle inSourceSlide, int inDestIndex = -1) override; + Qt3DSDMSlideHandle GetMasterSlide(Qt3DSDMSlideHandle inSlide) const override; + bool IsMasterSlide(Qt3DSDMSlideHandle inSlide) const override; + Qt3DSDMSlideHandle GetMasterSlideByComponentGuid(SLong4 inGuid) const override; + // Indexes are 1 based. Index 0 refers to the master slide; you can't delete this. + void DeleteSlideByIndex(Qt3DSDMSlideHandle inMaster, size_t inIndex) override; + void GetSlideReferencedInstances(Qt3DSDMSlideHandle inMaster, size_t inIndex, + TInstanceHandleList &outReferencedInstances) override; + Qt3DSDMSlideHandle GetSlideByIndex(Qt3DSDMSlideHandle inMaster, size_t inIndex) const override; + void SetActiveSlide(Qt3DSDMSlideHandle inMaster, size_t inIndex) override; + size_t GetSlideCount(Qt3DSDMSlideHandle inMaster) const override; + void RearrangeSlide(Qt3DSDMSlideHandle inMaster, size_t inOldIndex, size_t inNewIndex) override; + + void SetComponentSeconds(Qt3DSDMSlideHandle inSlide, float inSeconds) override; + float GetComponentSeconds(Qt3DSDMSlideHandle inSlide) const override; + long GetComponentSecondsLong(Qt3DSDMSlideHandle inSlide) const override; + // For any given instance, find the current seconds via backtracking to the graph, finding the + // active + // slide, and return. + long GetComponentSecondsLong(Qt3DSDMInstanceHandle inInstance) const override; + virtual SInstanceSlideInformation + GetInstanceSlideInformation(Qt3DSDMInstanceHandle inInstance) const override; + /** + * Use the instance for storing information such as name, or the GUID of the object + * this slide links to. + */ + Qt3DSDMInstanceHandle GetSlideInstance(Qt3DSDMSlideHandle inInstance) const override; + /** + * Reverse lookup into the slide system so you can match slides to instances. + */ + Qt3DSDMSlideHandle GetSlideByInstance(Qt3DSDMInstanceHandle inInstance) const override; + + /** + * Slide may be either a master slide or a normal slide. This will associate this instance + * with this set of slides. Property lookups (using the above IInstancePropertyCore interface) + * will now run through the slide set before hitting the main data core database. + */ + void AssociateInstanceWithSlide(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) override; + Qt3DSDMSlideHandle GetAssociatedSlide(Qt3DSDMInstanceHandle inInstance) const override; + void GetAssociatedInstances( + Qt3DSDMSlideHandle inMaster, + std::vector<std::pair<Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle>> &outAssociations) const override; + void GetAssociatedInstances(Qt3DSDMSlideHandle inSlide, + TInstanceHandleList &outAssociations) const override; + void LinkProperty(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) override; + void UnlinkProperty(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) override; + bool IsPropertyLinked(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + bool CanPropertyBeLinked(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + bool GetSlidePropertyValue(size_t inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) override; + void GetUnionOfProperties(Qt3DSDMSlideHandle inSlide1, Qt3DSDMSlideHandle inSlide, + TInstancePropertyPairList &outProperties) const override; + + void SetActiveSlide(Qt3DSDMSlideHandle inSlide) override; + Qt3DSDMSlideHandle GetAssociatedSlide(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + + bool SlideValid(Qt3DSDMSlideHandle inSlide) const override; + int GetSlideIndex(Qt3DSDMSlideHandle inSlide) const override; + int GetActiveSlideIndex(Qt3DSDMSlideHandle inMaster) const override; + Qt3DSDMSlideHandle GetActiveSlide(Qt3DSDMSlideHandle inMaster) const override; + Qt3DSDMInstanceHandle GetSlideSelectedInstance(Qt3DSDMSlideHandle inSlide) const override; + void SetSlideSelectedInstance(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance) override; + + Qt3DSDMSlideHandle GetApplicableSlide(Qt3DSDMInstanceHandle inHandle) override; + Qt3DSDMSlideHandle GetApplicableSlide(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) override; + + bool GetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + bool GetCanonicalInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const override; + void ForceSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) override; + + void RegisterPropertyInstance(Qt3DSDMPropertyHandle inPropertyHandle, + TPropertyInstanceInfoPtr inPropertyInfo) override; + + virtual ISlideSystemSignalProvider *GetSignalProvider(); + +private: + virtual ISlideSystemSignalSender *GetSignalSender(); + // helper method + void InsertEntryAndPropertyInstance(const TSlideEntry &inEntry, + TInstanceHandleList &inInstances, + Qt3DSDMSlideHandle inSlide); + void DeleteReferencedInstances(Qt3DSDMSlideHandle inSlide); + void GetReferencedInstances(Qt3DSDMSlideHandle inSlide, + TInstanceHandleList &outReferencedInstances); +}; +} + +#endif diff --git a/src/dm/systems/StandardExtensions.h b/src/dm/systems/StandardExtensions.h new file mode 100644 index 0000000..a994600 --- /dev/null +++ b/src/dm/systems/StandardExtensions.h @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef STANDARDEXTENSIONSH +#define STANDARDEXTENSIONSH +#include <algorithm> + +namespace qt3dsdm { +template <typename TContainer, typename TPred> +inline void erase_if(TContainer &inContainer, TPred inPred) +{ + inContainer.erase(std::remove_if(inContainer.begin(), inContainer.end(), inPred), + inContainer.end()); +} + +template <typename TRetType, typename TContainerType, typename TPred> +inline TRetType find_if(TContainerType &inContainer, TPred inPred) +{ + return std::find_if(inContainer.begin(), inContainer.end(), inPred); +} + +template <typename TContainer, typename TTransaction> +inline void do_all(TContainer &inContainer, TTransaction inTransaction) +{ + std::for_each(inContainer.begin(), inContainer.end(), inTransaction); +} + +template <typename TNumType, typename TTransaction> +inline void do_times(TNumType numberOfTimes, TTransaction inTransaction) +{ + for (TNumType index = 0; index < numberOfTimes; ++index) + inTransaction(index); +} + +template <typename TCountFunc, typename TItemByIndexFunc, typename TTransaction> +inline void for_each_item(TCountFunc inCountFunc, TItemByIndexFunc inItemByIndex, + TTransaction inTransaction) +{ + int theEnd = static_cast<int>(inCountFunc()); + for (int index = 0; index < theEnd; ++index) + inTransaction(inItemByIndex(index)); +} + +template <typename TContainerType, typename TItemType> +inline void insert_unique(TContainerType &inContainer, const TItemType &inItem) +{ + if (find(inContainer.begin(), inContainer.end(), inItem) == inContainer.end()) + inContainer.insert(inContainer.end(), inItem); +} + +template <typename TContainerType, typename TItemType, typename TPred> +inline void insert_unique_if(TContainerType &inContainer, const TItemType &inItem, TPred inPred) +{ + if (find_if(inContainer.begin(), inContainer.end(), inPred) == inContainer.end()) + inContainer.insert(inContainer.end(), inItem); +} + +template <typename TItemType> +inline TItemType identity(const TItemType &inValue) +{ + return inValue; +} + +template <typename TItemType, typename TOutContainerType> +inline void transformv_all(const std::vector<TItemType> &inSource, TOutContainerType &outDest) +{ + outDest.resize(inSource.size()); + std::transform(inSource.begin(), inSource.end(), outDest.begin(), identity<TItemType>); +} + +template <typename TContainerType, typename Pred> +inline bool exists(TContainerType &inContainer, Pred inPredicate) +{ + return std::find_if(inContainer.begin(), inContainer.end(), inPredicate) != inContainer.end(); +} + +// Always return a default value (useful for default true for false) +template <typename TRetType> +inline TRetType always(TRetType inValue) +{ + return inValue; +} + +template <typename TRetType, typename TIgnoreType> +inline TRetType always_ignore(TIgnoreType, TRetType inValue) +{ + return inValue; +} + +template <typename TArgument, typename TTransaction, typename TPredicate> +inline void predicate_apply(TArgument inArgument, TTransaction inTransaction, + TPredicate inPredicate) +{ + if (inPredicate(inArgument)) + inTransaction(inArgument); +} + +template <typename TItemType> +inline void assign_to(const TItemType &inSource, TItemType &inDest) +{ + inDest = inSource; +} + +template <typename TPredType, typename TArgType> +bool complement(TPredType inPredicate, TArgType inArgument) +{ + return !(inPredicate(inArgument)); +} + +template <typename TItemType, typename TPredicate> +void insert_or_update(const TItemType &inItem, std::vector<TItemType> &inItems, + TPredicate inPredicate) +{ + typename std::vector<TItemType>::iterator theIter = + find_if<typename std::vector<TItemType>::iterator>(inItems, inPredicate); + if (theIter == inItems.end()) + inItems.push_back(inItem); + else + *theIter = inItem; +} + +template <typename TItemType> +typename std::vector<TItemType>::iterator binary_sort_find(std::vector<TItemType> &inItems, + const TItemType &inItem) +{ + typedef typename std::vector<TItemType>::iterator TIterType; + TIterType insertPos = std::lower_bound(inItems.begin(), inItems.end(), inItem); + if (insertPos != inItems.end() && *insertPos == inItem) + return insertPos; + return inItems.end(); +} + +template <typename TItemType, typename TPredicate> +std::pair<typename std::vector<TItemType>::iterator, bool> +binary_sort_insert_unique(std::vector<TItemType> &inItems, const TItemType &inItem, + TPredicate inPredicate) +{ + typedef typename std::vector<TItemType>::iterator TIterType; + TIterType insertPos = std::lower_bound(inItems.begin(), inItems.end(), inItem, inPredicate); + // OK, insertPos can equal begin, it can equal end, or somewhere in between. + // If it doesn't equal end, then we may be pointing at the object and we let + // the caller figure out what to do. Else we insert + if (insertPos != inItems.end() && *insertPos == inItem) + return std::make_pair(insertPos, false); + size_t diff = insertPos - inItems.begin(); + inItems.insert(insertPos, inItem); + return std::make_pair(inItems.begin() + diff, true); +} + +template <typename TItemType> +std::pair<typename std::vector<TItemType>::iterator, bool> +binary_sort_insert_unique(std::vector<TItemType> &inItems, const TItemType &inItem) +{ + return binary_sort_insert_unique(inItems, inItem, std::less<TItemType>()); +} + +template <typename TItemType> +bool binary_sort_erase(std::vector<TItemType> &inItems, const TItemType &inItem) +{ + typedef typename std::vector<TItemType>::iterator TIterType; + TIterType insertPos = binary_sort_find(inItems, inItem); + if (insertPos != inItems.end()) { + inItems.erase(insertPos); + return true; + } + return false; +} +} + +#endif diff --git a/src/dm/systems/StudioAnimationSystem.cpp b/src/dm/systems/StudioAnimationSystem.cpp new file mode 100644 index 0000000..2b78888 --- /dev/null +++ b/src/dm/systems/StudioAnimationSystem.cpp @@ -0,0 +1,610 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "StudioAnimationSystem.h" +#include "StudioPropertySystem.h" + +using namespace std; + +namespace qt3dsdm { + +bool AnimationFloatPairContainsAnimation(Qt3DSDMAnimationHandle inAnimation, + const TAnimationFloatPair &inPair) +{ + return inAnimation == inPair.first; +} + +CStudioAnimationSystem::CStudioAnimationSystem(TPropertySystemPtr inPropertySystem, + TSlideSystemPtr inSlideSystem, + TSlideCorePtr inSlideCore, + TSlideGraphCorePtr inSlideGraphCore, + TAnimationCorePtr inAnimationCore) + : m_PropertySystem(inPropertySystem) + , m_SlideSystem(inSlideSystem) + , m_SlideCore(inSlideCore) + , m_SlideGraphCore(inSlideGraphCore) + , m_AnimationCore(inAnimationCore) + , m_AutoKeyframe(false) + , m_SmoothInterpolation(false) +{ + IAnimationCoreSignalProvider *theAnimationSignals = + dynamic_cast<IAnimationCoreSignalProvider *>(m_AnimationCore.get()); + m_Connections.push_back(theAnimationSignals->ConnectAnimationDeleted( + std::bind(&CStudioAnimationSystem::OnAnimationDeleted, this, std::placeholders::_1))); +} + +void CStudioAnimationSystem::OnAnimationDeleted(Qt3DSDMAnimationHandle inAnimation) +{ + ClearTemporaryAnimationValues(inAnimation); +} + +void CStudioAnimationSystem::ClearTemporaryAnimationValues() +{ + m_AnimationFloatPairs.clear(); +} + +void CStudioAnimationSystem::ClearTemporaryAnimationValues(Qt3DSDMAnimationHandle inAnimation) +{ + erase_if(m_AnimationFloatPairs, + std::bind(AnimationFloatPairContainsAnimation, inAnimation, std::placeholders::_1)); +} + +inline bool IsAnimationInfoEqual(const SAnimationInfo &inInfo, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) +{ + if (inInfo.m_Slide == inSlide && inInfo.m_Instance == inInstance + && inInfo.m_Property == inProperty) + return true; + return false; +} +inline bool IsAnimationInfoEqual(const SAnimationInfo &inInfo, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + size_t inIndex) +{ + if (IsAnimationInfoEqual(inInfo, inSlide, inInstance, inProperty) && inInfo.m_Index == inIndex) + return true; + return false; +} + +inline bool ApplyIfAnimationMatches(TAnimationFloatPair inAnimationFloatPair, + Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + TAnimationCorePtr inAnimationCore, SValue &outValue) +{ + SAnimationInfo theInfo = inAnimationCore->GetAnimationInfo(inAnimationFloatPair.first); + if (IsAnimationInfoEqual(theInfo, inSlide, inInstance, inProperty)) { + SetAnimationValue(inAnimationFloatPair.second, theInfo.m_Index, outValue); + return true; + } + return false; +} + +void CStudioAnimationSystem::OverrideChannelIfAnimated(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + size_t inIndex, float inSeconds, + bool &ioAnimated, SValue &outValue) const +{ + Qt3DSDMAnimationHandle theAnimation = + m_AnimationCore->GetAnimation(inSlide, inInstance, inProperty, inIndex); + if (theAnimation.Valid() && m_AnimationCore->GetKeyframeCount(theAnimation)) { + float theValue = m_AnimationCore->EvaluateAnimation(theAnimation, inSeconds); + SetAnimationValue(theValue, inIndex, outValue); + ioAnimated |= true; + } +} + +// Value must be *primed* first. +bool CStudioAnimationSystem::GetAnimatedInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + bool retval = false; + + tuple<bool, size_t> arity = GetVariantAnimatableAndArity(outValue); + if (get<0>(arity)) { + for (size_t index = 0; index < m_AnimationFloatPairs.size(); ++index) + retval |= ApplyIfAnimationMatches(m_AnimationFloatPairs.at(index), inSlide, inInstance, + inProperty, m_AnimationCore, outValue); + } + + if (!retval) { + bool animatable; + size_t numChannels; + bool animated = false; + + std::tie(animatable, numChannels) = GetVariantAnimatableAndArity(outValue); + if (animatable) { + TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance); + float theSeconds = m_SlideCore->GetSlideTime( + m_SlideGraphCore->GetGraphActiveSlide(theGraphSlidePair.first)); + + do_times(numChannels, std::bind(&CStudioAnimationSystem::OverrideChannelIfAnimated, + this, inSlide, inInstance, inProperty, + std::placeholders::_1, theSeconds, + std::ref(animated), std::ref(outValue))); + } + + if (animated) + retval = true; + } + + return retval; +} + +bool KeyframeNear(const TKeyframe &inKeyframe, float inSeconds) +{ + return fabs(KeyframeTime(inKeyframe) - inSeconds) < .01; +} +Qt3DSDMKeyframeHandle CreateKeyframeExplicit(Qt3DSDMAnimationHandle inAnimation, float inValue, + float inSeconds, TAnimationCorePtr inAnimationCore, + float inEaseIn, float inEaseOut) +{ + TKeyframeHandleList theKeyframes; + float theValue = inValue; + inAnimationCore->GetKeyframes(inAnimation, theKeyframes); + function<TKeyframe(Qt3DSDMKeyframeHandle)> theConverter( + std::bind(&IAnimationCore::GetKeyframeData, inAnimationCore, std::placeholders::_1)); + + TKeyframeHandleList::iterator theFind = + std::find_if(theKeyframes.begin(), theKeyframes.end(), + [theConverter, inSeconds](const Qt3DSDMKeyframeHandle &handle) + { return KeyframeNear(theConverter(handle), inSeconds); }); + + float theEaseIn = inEaseIn; + float theEaseOut = inEaseOut; + Qt3DSDMKeyframeHandle theKeyframe; + if (theFind != theKeyframes.end()) { + theKeyframe = *theFind; + + inAnimationCore->SetKeyframeData( + theKeyframe, CreateEaseInEaseOutKeyframe(inSeconds, theValue, theEaseIn, theEaseOut)); + } else { + theKeyframe = inAnimationCore->InsertKeyframe( + inAnimation, CreateEaseInEaseOutKeyframe(inSeconds, theValue, theEaseIn, theEaseOut)); + } + return theKeyframe; +} + +Qt3DSDMKeyframeHandle CreateKeyframe(Qt3DSDMAnimationHandle inAnimation, const SValue &inValue, + float inSeconds, TAnimationCorePtr inAnimationCore, + float inEaseIn, float inEaseOut) +{ + SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation)); + return CreateKeyframeExplicit(inAnimation, GetAnimationValue(theInfo.m_Index, inValue), + inSeconds, inAnimationCore, inEaseIn, inEaseOut); +} + +void MaybeAddAnimation(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, Qt3DSDMAnimationHandle inAnimation, + TAnimationCorePtr inAnimationCore, TAnimationHandleList &outAnimations) +{ + SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation)); + if (IsAnimationInfoEqual(theInfo, inSlide, inInstance, inProperty)) + outAnimations.push_back(inAnimation); +} + +bool SortAnimationHandlesByIndex(Qt3DSDMAnimationHandle lhs, Qt3DSDMAnimationHandle rhs, + TAnimationCorePtr inCore) +{ + return inCore->GetAnimationInfo(lhs).m_Index < inCore->GetAnimationInfo(rhs).m_Index; +} + +void GetPresentAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const TAnimationFloatPairList &inAnimationPairs, + TAnimationCorePtr inAnimationCore, TAnimationHandleList &outAnimations) +{ + function<void(Qt3DSDMAnimationHandle)> theOperation( + std::bind(MaybeAddAnimation, inSlide, inInstance, inProperty, + std::placeholders::_1, inAnimationCore, + std::ref(outAnimations))); + + for (auto animation : inAnimationPairs) { + MaybeAddAnimation(inSlide, inInstance, inProperty, animation.first, inAnimationCore, + std::ref(outAnimations)); + } + + if (outAnimations.empty()) { + TAnimationHandleList theAnimationHandles; + inAnimationCore->GetAnimations(theAnimationHandles); + do_all(theAnimationHandles, theOperation); + } + std::sort(outAnimations.begin(), outAnimations.end(), + std::bind(SortAnimationHandlesByIndex, + std::placeholders::_1, std::placeholders::_2, inAnimationCore)); +} + +void CreateAnimationAndAdd(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + TAnimationCorePtr inAnimationCore, TAnimationHandleList &outAnimations) +{ + outAnimations.push_back(inAnimationCore->CreateAnimation( + inSlide, inInstance, inProperty, inIndex, EAnimationTypeEaseInOut, false)); +} + +bool AnimationValueDiffers(Qt3DSDMAnimationHandle inAnimation, const SValue &inValue, + float inSeconds, TAnimationCorePtr inAnimationCore) +{ + SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation)); + if (inAnimationCore->GetKeyframeCount(inAnimation) == 0) + return true; // currently there is no keyframe, so return true + float theValue = GetAnimationValue(theInfo.m_Index, inValue); + float theAnimatedValue = inAnimationCore->EvaluateAnimation(inAnimation, inSeconds); + return fabs(theValue - theAnimatedValue) > .001; +} + +bool AnimationExistsInPresentAnimations(const TAnimationFloatPair &inAnimation, + TAnimationHandleList &inPresentAnimations) +{ + return exists(inPresentAnimations, + std::bind(equal_to<Qt3DSDMAnimationHandle>(), inAnimation.first, + std::placeholders::_1)); +} + +void DoKeyframeProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue, float inTimeInSecs, + bool inDoDiffValue, TAnimationCorePtr inAnimationCore, + TAnimationFloatPairList &inAnimationFloatPairs, float inEaseIn, + float inEaseOut) +{ + tuple<bool, size_t> arity = GetVariantAnimatableAndArity(inValue); + TAnimationHandleList thePresentAnimations; + GetPresentAnimations(inSlide, inInstance, inProperty, std::cref(inAnimationFloatPairs), + inAnimationCore, thePresentAnimations); + if (thePresentAnimations.empty()) + do_times(get<1>(arity), std::bind(CreateAnimationAndAdd, inSlide, inInstance, inProperty, + std::placeholders::_1, + inAnimationCore, std::ref(thePresentAnimations))); + if (!inDoDiffValue + || find_if(thePresentAnimations.begin(), thePresentAnimations.end(), + std::bind(AnimationValueDiffers, + std::placeholders::_1, inValue, inTimeInSecs, inAnimationCore)) + != thePresentAnimations.end()) { + do_all(thePresentAnimations, + std::bind(CreateKeyframe, std::placeholders::_1, + std::cref(inValue), inTimeInSecs, inAnimationCore, + inEaseIn, inEaseOut)); + erase_if(inAnimationFloatPairs, std::bind(AnimationExistsInPresentAnimations, + std::placeholders::_1, + std::ref(thePresentAnimations))); + } +} + +void DoKeyframeProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue, bool inDoDiffValue, + TAnimationCorePtr inAnimationCore, TSlideGraphCorePtr inSlideGraphCore, + TSlideCorePtr inSlideCore, TAnimationFloatPairList &inAnimationFloatPairs, + float inEaseIn, float inEaseOut) +{ + TGraphSlidePair theGraphSlidePair = inSlideGraphCore->GetAssociatedGraph(inInstance); + float theCurrentTime = + inSlideCore->GetSlideTime(inSlideGraphCore->GetGraphActiveSlide(theGraphSlidePair.first)); + DoKeyframeProperty(inSlide, inInstance, inProperty, inValue, theCurrentTime, inDoDiffValue, + inAnimationCore, inAnimationFloatPairs, inEaseIn, inEaseOut); +} + +void DoKeyframeProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue, bool inDoDiffValue, + TAnimationCorePtr inAnimationCore, TSlideGraphCorePtr inSlideGraphCore, + TSlideCorePtr inSlideCore, TAnimationFloatPairList &inAnimationFloatPairs, + bool inSmoothInterpolation) +{ + float theEaseIn = 0.0f, theEaseOut = 0.0f; + if (inSmoothInterpolation) + theEaseIn = theEaseOut = 100.f; + DoKeyframeProperty(inSlide, inInstance, inProperty, inValue, inDoDiffValue, inAnimationCore, + inSlideGraphCore, inSlideCore, inAnimationFloatPairs, theEaseIn, theEaseOut); +} + +TAnimationFloatPair CreateAnimationFloatPair(Qt3DSDMAnimationHandle inAnimation, + const SValue &inValue, + TAnimationCorePtr inAnimationCore) +{ + SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation)); + float theValue = GetAnimationValue(theInfo.m_Index, inValue); + return make_pair(inAnimation, theValue); +} + +void InsertUniqueAnimationFloatPair(Qt3DSDMAnimationHandle inAnimation, + TAnimationFloatPairList &inList, const SValue &inValue, + TAnimationCorePtr inAnimationCore) +{ + TAnimationFloatPair thePair = CreateAnimationFloatPair(inAnimation, inValue, inAnimationCore); + insert_or_update(thePair, inList, + std::bind(AnimationFloatPairContainsAnimation, inAnimation, std::placeholders::_1)); +} + +bool CStudioAnimationSystem::SetAnimatedInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + tuple<bool, size_t> arity = GetVariantAnimatableAndArity(inValue); + if (get<0>(arity)) { + if (m_AutoKeyframe && IsPropertyAnimated(inInstance, inProperty)) // prerequisite for + // autoset-keyframes is + // that the property is + // already animated. + { + DoKeyframeProperty(inSlide, inInstance, inProperty, inValue, true, m_AnimationCore, + m_SlideGraphCore, m_SlideCore, m_AnimationFloatPairs, + m_SmoothInterpolation); + return true; + } + + TAnimationHandleList thePresentAnimations; + GetPresentAnimations(inSlide, inInstance, inProperty, std::cref(m_AnimationFloatPairs), + m_AnimationCore, thePresentAnimations); + if (!thePresentAnimations.empty()) { + TAnimationFloatPairList thePreList(m_AnimationFloatPairs); + do_all(thePresentAnimations, std::bind(InsertUniqueAnimationFloatPair, std::placeholders::_1, + std::ref(m_AnimationFloatPairs), + std::cref(inValue), m_AnimationCore)); + + + if (m_Consumer && m_refreshCallback) { + // Only create a single refresh per transaction stack + if (((CTransactionConsumer *)m_Consumer.get())->m_TransactionList.size() == 0) { + CreateGenericTransactionWithConsumer( + __FILE__, __LINE__, m_Consumer, + std::bind(m_refreshCallback, inInstance), + std::bind(m_refreshCallback, inInstance)); + } + } + + CreateGenericTransactionWithConsumer( + __FILE__, __LINE__, m_Consumer, + std::bind(assign_to<TAnimationFloatPairList>, m_AnimationFloatPairs, + std::ref(m_AnimationFloatPairs)), + std::bind(assign_to<TAnimationFloatPairList>, thePreList, + std::ref(m_AnimationFloatPairs))); + return true; + } + } + return false; +} + +void CStudioAnimationSystem::SetAutoKeyframe(bool inAutoKeyframe) +{ + m_AutoKeyframe = inAutoKeyframe; +} +bool CStudioAnimationSystem::GetAutoKeyframe() const +{ + return m_AutoKeyframe; +} + +Qt3DSDMSlideHandle CStudioAnimationSystem::GetApplicableGraphAndSlide( + Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, const SValue &inValue) +{ + Qt3DSDMSlideHandle theApplicableSlide; + tuple<bool, size_t> arity = GetVariantAnimatableAndArity(inValue); + if (get<0>(arity)) + theApplicableSlide = m_SlideSystem->GetApplicableSlide(inInstance, inProperty); + return theApplicableSlide; +} + +void InsertUniqueAnimationKeyframesPair(TAnimationKeyframesPairList &ioList, SAnimationInfo &inInfo, + TKeyframeList &inKeyframes) +{ + bool theFound = false; + for (TAnimationKeyframesPairList::iterator theAnimationKeyframeIter = ioList.begin(); + theAnimationKeyframeIter < ioList.end(); ++theAnimationKeyframeIter) { + if (IsAnimationInfoEqual(theAnimationKeyframeIter->first, inInfo.m_Slide, inInfo.m_Instance, + inInfo.m_Property, inInfo.m_Index)) { + theFound = true; + // Overwrite the existing value + SAnimationInfo &theInfo = theAnimationKeyframeIter->first; + theInfo.m_AnimationType = inInfo.m_AnimationType; + theInfo.m_DynamicFirstKeyframe = inInfo.m_DynamicFirstKeyframe; + theAnimationKeyframeIter->second = inKeyframes; + break; + } + } + if (!theFound) { + ioList.push_back(std::make_pair(inInfo, inKeyframes)); + } +} + +void CStudioAnimationSystem::Animate(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) +{ + SValue theValue; + m_PropertySystem->GetInstancePropertyValue(inInstance, inProperty, theValue); + Qt3DSDMSlideHandle theApplicableSlide = + GetApplicableGraphAndSlide(inInstance, inProperty, theValue.toOldSkool()); + if (theApplicableSlide.Valid()) { + // Check if previously we have set animation & keyframes + DataModelDataType::Value theDataType = m_PropertySystem->GetDataType(inProperty); + std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(theDataType); + bool theFound = false; + for (size_t i = 0; i < std::get<1>(theArity); ++i) { + TAnimationKeyframesPairList::iterator theAnimationKeyframeIter = + m_DeletedAnimationData.begin(); + for (; theAnimationKeyframeIter < m_DeletedAnimationData.end(); + ++theAnimationKeyframeIter) { + if (IsAnimationInfoEqual(theAnimationKeyframeIter->first, theApplicableSlide, + inInstance, inProperty, i)) { + theFound = true; + + // We use previously set animation & keyframes to create new animation & + // keyframe + SAnimationInfo &theInfo = theAnimationKeyframeIter->first; + Qt3DSDMAnimationHandle theAnimation = m_AnimationCore->CreateAnimation( + theInfo.m_Slide, theInfo.m_Instance, theInfo.m_Property, theInfo.m_Index, + theInfo.m_AnimationType, theInfo.m_DynamicFirstKeyframe); + + TKeyframeList theKeyframes = theAnimationKeyframeIter->second; + for (TKeyframeList::const_iterator theKeyframeIter = theKeyframes.begin(); + theKeyframeIter < theKeyframes.end(); ++theKeyframeIter) + m_AnimationCore->InsertKeyframe(theAnimation, *theKeyframeIter); + + break; + } + } + } + + if (!theFound) + DoKeyframeProperty(theApplicableSlide, inInstance, inProperty, theValue.toOldSkool(), + true, m_AnimationCore, m_SlideGraphCore, m_SlideCore, + m_AnimationFloatPairs, m_SmoothInterpolation); + } +} + +void CStudioAnimationSystem::Deanimate(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) +{ + DataModelDataType::Value theDataType = m_PropertySystem->GetDataType(inProperty); + std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(theDataType); + for (size_t i = 0; i < std::get<1>(theArity); ++i) { + Qt3DSDMAnimationHandle theAnimationHandle = + GetControllingAnimation(inInstance, inProperty, i); + + if (theAnimationHandle.Valid()) { + // Get animation & keyframe data and save it + SAnimationInfo theInfo(m_AnimationCore->GetAnimationInfo(theAnimationHandle)); + TKeyframeHandleList theKeyframeHandles; + m_AnimationCore->GetKeyframes(theAnimationHandle, theKeyframeHandles); + TKeyframeList theKeyframeList; + for (TKeyframeHandleList::const_iterator theKeyframeIter = theKeyframeHandles.begin(); + theKeyframeIter < theKeyframeHandles.end(); ++theKeyframeIter) + theKeyframeList.push_back(m_AnimationCore->GetKeyframeData(*theKeyframeIter)); + InsertUniqueAnimationKeyframesPair(m_DeletedAnimationData, theInfo, theKeyframeList); + + // Delete the animation + m_AnimationCore->DeleteAnimation(theAnimationHandle); + } + } +} + +void CStudioAnimationSystem::KeyframeProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, bool inDoDiffValue) +{ + SValue theValue; + m_PropertySystem->GetInstancePropertyValue(inInstance, inProperty, theValue); + Qt3DSDMSlideHandle theApplicableSlide = + GetApplicableGraphAndSlide(inInstance, inProperty, theValue.toOldSkool()); + if (theApplicableSlide.Valid()) + DoKeyframeProperty(theApplicableSlide, inInstance, inProperty, theValue.toOldSkool(), + inDoDiffValue, m_AnimationCore, m_SlideGraphCore, m_SlideCore, + m_AnimationFloatPairs, m_SmoothInterpolation); +} +void CStudioAnimationSystem::SetOrCreateKeyframe(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + float inTimeInSeconds, + SGetOrSetKeyframeInfo *inKeyframeInfo, + size_t inNumInfos) +{ + qt3dsdm::DataModelDataType::Value thePropertyType = m_PropertySystem->GetDataType(inProperty); + Qt3DSDMSlideHandle theApplicableSlide; + std::tuple<bool, size_t> arity = GetDatatypeAnimatableAndArity(thePropertyType); + if (std::get<0>(arity)) { + theApplicableSlide = m_SlideSystem->GetApplicableSlide(inInstance, inProperty); + if (theApplicableSlide.Valid()) { + + TAnimationHandleList thePresentAnimations; + GetPresentAnimations(theApplicableSlide, inInstance, inProperty, + std::cref(m_AnimationFloatPairs), m_AnimationCore, + thePresentAnimations); + size_t numIterations = std::min(inNumInfos, get<1>(arity)); + if (thePresentAnimations.empty()) { + for (size_t idx = 0, end = numIterations; idx < end; ++idx) { + CreateAnimationAndAdd(theApplicableSlide, inInstance, inProperty, idx, + m_AnimationCore, thePresentAnimations); + } + } + for (size_t idx = 0, end = numIterations; idx < end; ++idx) { + CreateKeyframeExplicit(thePresentAnimations[idx], inKeyframeInfo[idx].m_Value, + inTimeInSeconds, m_AnimationCore, + inKeyframeInfo[idx].m_EaseIn, inKeyframeInfo[idx].m_EaseOut); + if (inKeyframeInfo[idx].m_AnimationTrackIsDynamic) + m_AnimationCore->SetFirstKeyframeDynamic(thePresentAnimations[idx], true); + } + erase_if(m_AnimationFloatPairs, std::bind(AnimationExistsInPresentAnimations, + std::placeholders::_1, + std::ref(thePresentAnimations))); + } + } +} + +inline bool FindMatchingAnimation(Qt3DSDMAnimationHandle inAnimation, + TAnimationCorePtr inAnimationCore, size_t inIndex) +{ + return inAnimationCore->GetAnimationInfo(inAnimation).m_Index == inIndex; +} + +Qt3DSDMAnimationHandle CStudioAnimationSystem::GetControllingAnimation( + Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, size_t inIndex) const +{ + Qt3DSDMSlideHandle theApplicableSlide = + m_SlideSystem->GetApplicableSlide(inInstance, inProperty); + // first check our anim float pairs + for (size_t idx = 0, end = m_AnimationFloatPairs.size(); idx < end; ++idx) { + const SAnimationInfo &theInfo = + m_AnimationCore->GetAnimationInfo(m_AnimationFloatPairs[idx].first); + if (IsAnimationInfoEqual(theInfo, theApplicableSlide, inInstance, inProperty, inIndex)) + return m_AnimationFloatPairs[idx].first; + } + // Use the cache lookup instead of linear search algorithm + return m_AnimationCore->GetAnimation(theApplicableSlide, inInstance, inProperty, inIndex); +} + +bool CStudioAnimationSystem::IsPropertyAnimatable(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + DataModelDataType::Value theDataType = m_PropertySystem->GetDataType(inProperty); + std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(theDataType); + if (std::get<0>(theArity)) + return m_SlideGraphCore->GetAssociatedGraph(inInstance).first.Valid(); + return false; +} + +bool CStudioAnimationSystem::IsPropertyAnimated(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + DataModelDataType::Value theDataType = m_PropertySystem->GetDataType(inProperty); + std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(theDataType); + for (size_t i = 0; i < std::get<1>(theArity); ++i) { + if (GetControllingAnimation(inInstance, inProperty, i).Valid()) + return true; + } + return false; +} + +void CStudioAnimationSystem::SetConsumer(TTransactionConsumerPtr inConsumer) +{ + m_Consumer = inConsumer; +} + +void CStudioAnimationSystem::setRefreshCallback(TRefreshCallbackFunc func) +{ + m_refreshCallback = func; +} +} diff --git a/src/dm/systems/StudioAnimationSystem.h b/src/dm/systems/StudioAnimationSystem.h new file mode 100644 index 0000000..e6fdf75 --- /dev/null +++ b/src/dm/systems/StudioAnimationSystem.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef STUDIOANIMATIONSYSTEMIMPLH +#define STUDIOANIMATIONSYSTEMIMPLH + +#include "Qt3DSDMAnimation.h" +#include "Qt3DSDMSlides.h" +#include "Qt3DSDMSlideCore.h" +#include "Qt3DSDMSlideGraphCore.h" +#include "Qt3DSDMTransactions.h" +#include "Qt3DSDMDataCore.h" +#include "Qt3DSDMSignals.h" + +namespace qt3dsdm { + +typedef std::pair<Qt3DSDMAnimationHandle, float> TAnimationFloatPair; +typedef std::vector<TAnimationFloatPair> TAnimationFloatPairList; + +class CStudioAnimationSystem : public IStudioAnimationSystem, + public ITransactionProducer +{ + Q_DISABLE_COPY(CStudioAnimationSystem) + + TPropertySystemPtr m_PropertySystem; + TSlideSystemPtr m_SlideSystem; + TSlideCorePtr m_SlideCore; + TSlideGraphCorePtr m_SlideGraphCore; + TAnimationCorePtr m_AnimationCore; + TRefreshCallbackFunc m_refreshCallback = nullptr; + + bool m_AutoKeyframe; + // When a property has an animation associated with it, then writes + // do not go all the way down to the db. They stay on this object. + TAnimationFloatPairList m_AnimationFloatPairs; + bool m_SmoothInterpolation; + + TAnimationKeyframesPairList m_DeletedAnimationData; // list to store deanimated animation & + // keyframe data. This will be use if user + // wants to animate the same property again + + TTransactionConsumerPtr m_Consumer; + + std::vector<std::shared_ptr<ISignalConnection>> m_Connections; + +public: + CStudioAnimationSystem(TPropertySystemPtr inPropertySystem, TSlideSystemPtr inSlideSystem, + TSlideCorePtr inSlideCore, TSlideGraphCorePtr inSlideGraphCore, + TAnimationCorePtr inAnimationCore); + + void ClearTemporaryAnimationValues(); + void ClearTemporaryAnimationValues(Qt3DSDMAnimationHandle inAnimation); + + void SetPropertySystem(TPropertySystemPtr inPropertySystem) + { + m_PropertySystem = inPropertySystem; + } // HACK: TODO: We should really consider having all the subsytem know everyone else without + // passing in so many things in the constructor + + //==================================================================== + // IStudioAnimationSystem implementation + //==================================================================== + void SetAutoKeyframe(bool inAutoKeyframe) override; + bool GetAutoKeyframe() const override; + void Animate(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) override; + void Deanimate(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty) override; + void KeyframeProperty(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + bool inDoDiffValue) override; + void SetOrCreateKeyframe(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, float inTimeInSeconds, + SGetOrSetKeyframeInfo *inKeyframeInfo, size_t inNumInfos) override; + Qt3DSDMAnimationHandle GetControllingAnimation(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + size_t inIndex) const override; + bool IsPropertyAnimatable(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + bool IsPropertyAnimated(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + void SetInterpolation(bool inSmooth) override { m_SmoothInterpolation = inSmooth; } + + bool GetAnimatedInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const override; + bool SetAnimatedInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) override; + //==================================================================== + + void SetConsumer(TTransactionConsumerPtr inConsumer) override; + + void setRefreshCallback(TRefreshCallbackFunc func) override; + +private: + void OnAnimationDeleted(Qt3DSDMAnimationHandle inAnimation); + + Qt3DSDMSlideHandle GetApplicableGraphAndSlide(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue); + + void OverrideChannelIfAnimated(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, float inSeconds, + bool &ioAnimated, SValue &outValue) const; +}; +} + +#endif diff --git a/src/dm/systems/StudioCoreSystem.cpp b/src/dm/systems/StudioCoreSystem.cpp new file mode 100644 index 0000000..f9f0e2c --- /dev/null +++ b/src/dm/systems/StudioCoreSystem.cpp @@ -0,0 +1,409 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "StudioCoreSystem.h" +#include "SlideCoreProducer.h" +#include "SlideGraphCoreProducer.h" +#include "DataCoreProducer.h" +#include "AnimationCoreProducer.h" +#include "ActionCoreProducer.h" +#include "Qt3DSDMSignals.h" +#include "Qt3DSDMMetaData.h" +#include "Qt3DSDMGuides.h" + +using namespace std; + +namespace qt3dsdm { + +inline bool AnimationInstanceMatches(Qt3DSDMAnimationHandle inAnimation, + TAnimationCorePtr inAnimationCore, + Qt3DSDMInstanceHandle inInstance) +{ + return inInstance == inAnimationCore->GetAnimationInfo(inAnimation).m_Instance; +} + +inline bool AnimationPropertyMatches(Qt3DSDMAnimationHandle inAnimation, + TAnimationCorePtr inAnimationCore, + Qt3DSDMPropertyHandle inProperty) +{ + return inProperty == inAnimationCore->GetAnimationInfo(inAnimation).m_Property; +} + +inline bool AnimationSlideMatches(Qt3DSDMAnimationHandle inAnimation, + TAnimationCorePtr inAnimationCore, Qt3DSDMSlideHandle inSlide) +{ + return inSlide == inAnimationCore->GetAnimationInfo(inAnimation).m_Slide; +} + +inline bool AnimationSlideInstancePropertyMatch(Qt3DSDMAnimationHandle inAnimation, + TAnimationCorePtr inAnimationCore, + Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) +{ + SAnimationInfo theInfo = inAnimationCore->GetAnimationInfo(inAnimation); + return theInfo.m_Slide == inSlide && theInfo.m_Instance == inInstance + && theInfo.m_Property == inProperty; +} + +inline bool AnimationInstancesPropertiesMatch(Qt3DSDMAnimationHandle inAnimation, + TAnimationCorePtr inAnimationCore, + const TInstanceHandleList &inInstances, + const TPropertyHandleList &inProperties) +{ + SAnimationInfo theInfo = inAnimationCore->GetAnimationInfo(inAnimation); + return exists(inInstances, std::bind(equal_to<int>(), theInfo.m_Instance, + std::placeholders::_1)) + && exists(inProperties, std::bind(equal_to<int>(), theInfo.m_Property, + std::placeholders::_1)); +} + +void EraseAnimationsThatMatch(TAnimationCorePtr inAnimationCore, + function<bool(Qt3DSDMAnimationHandle)> inPredicate) +{ + TAnimationHandleList theAnimations; + inAnimationCore->GetAnimations(theAnimations); + function<bool(Qt3DSDMAnimationHandle)> theComp(std::bind( + complement<function<bool(Qt3DSDMAnimationHandle)>, Qt3DSDMAnimationHandle>, inPredicate, + std::placeholders::_1)); + TAnimationHandleList::iterator theRemovals = + remove_if(theAnimations.begin(), theAnimations.end(), theComp); + for_each(theAnimations.begin(), theRemovals, + std::bind(&IAnimationCore::DeleteAnimation, inAnimationCore, std::placeholders::_1)); +} + +void EraseActions(TDataCorePtr inDataCore, TActionCorePtr inActionCore, + const TActionHandleList &inActions) +{ + for (TActionHandleList::const_iterator theActionIter = inActions.begin(); + theActionIter != inActions.end(); ++theActionIter) { + Qt3DSDMInstanceHandle theActionInstance; + inActionCore->DeleteAction(*theActionIter, theActionInstance); + inDataCore->DeleteInstance(theActionInstance); + } +} + +void CascadeInstanceDelete(Qt3DSDMInstanceHandle inInstance, TDataCorePtr inDataCore, + TSlideCorePtr inSlideCore, TSlideGraphCorePtr inSlideGraphCore, + TAnimationCorePtr inAnimationCore, TActionCorePtr inActionCore) +{ + inSlideCore->DeleteAllInstanceEntries(inInstance); + + inSlideGraphCore->DissociateInstance(inInstance); + + function<bool(Qt3DSDMAnimationHandle)> thePredicate( + std::bind(AnimationInstanceMatches, std::placeholders::_1, inAnimationCore, inInstance)); + EraseAnimationsThatMatch(inAnimationCore, thePredicate); + + TActionHandleList theActions; + inActionCore->GetActions(inInstance, theActions); + EraseActions(inDataCore, inActionCore, theActions); +} + +void CascadePropertyRemove(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + TSlideCorePtr inSlideCore, TSlideGraphCorePtr inSlideGraphCore, + TAnimationCorePtr inAnimationCore) +{ + inSlideCore->DeleteAllPropertyEntries(inProperty); + function<bool(Qt3DSDMAnimationHandle)> thePredicate( + std::bind(AnimationPropertyMatches, std::placeholders::_1, inAnimationCore, inProperty)); + EraseAnimationsThatMatch(inAnimationCore, thePredicate); +} + +void CascadeSlideDelete(Qt3DSDMSlideHandle inSlide, TDataCorePtr inDataCore, + TSlideCorePtr inSlideCore, TSlideGraphCorePtr inSlideGraphCore, + TAnimationCorePtr inAnimationCore, TActionCorePtr inActionCore) +{ + Qt3DSDMSlideGraphHandle theGraph = inSlideGraphCore->GetSlideGraph(inSlide); + if (theGraph.Valid()) { + TSlideHandleList theChildren; + inSlideCore->GetChildSlides(inSlide, theChildren); + TInstanceHandleList instances; + for (size_t idx = 0, end = theChildren.size(); idx < end; ++idx) { + instances.clear(); + inSlideCore->DeleteSlide(theChildren[idx], instances); + for (size_t instIdx = 0, instEnd = instances.size(); instIdx < instEnd; ++instIdx) + inDataCore->DeleteInstance(instances[instIdx]); + } + inSlideGraphCore->DeleteSlideGraph(theGraph); + } + + else { + Qt3DSDMSlideHandle theMaster(inSlideCore->GetParentSlide(inSlide)); + if (theMaster.Valid()) { + Qt3DSDMSlideGraphHandle theGraph = inSlideGraphCore->GetSlideGraph(theMaster); + if (theGraph.Valid()) { + /* + tricky stuff. The slide change was recorded in the transaction system when the + slide was created. But since there didn't *have* to be a slide change when the + slide was destroyed there was no slide change recorded at that point. + + Then on the first redo, the system quietly switched the active slide to the new + slide. On the second redo the system crashed due to attempting to access the + new slide after it had been deleted (as nothing switched the system back to the + current slide). + + So the correct answer is that the cascading system needs to *always* set the + active slide, even if it seems like it would be, at the moment, unnecessary + because the slide getting deleted is not currently active. This is the mirror + of the fact that new slide *always* sets the active slide so it does make + logical sense.*/ + Qt3DSDMSlideHandle theNewActiveSlide = + inSlideGraphCore->GetGraphActiveSlide(theGraph); + if (theNewActiveSlide == inSlide) { + TSlideHandleList theChildren; + inSlideCore->GetChildSlides(theMaster, theChildren); + size_t idx = 0; + for (size_t end = theChildren.size(); idx < end; ++idx) { + if (theChildren[idx] != inSlide) { + theNewActiveSlide = theChildren[idx]; + break; + } + } + if (theNewActiveSlide == inSlide) + theNewActiveSlide = theMaster; + } + inSlideGraphCore->SetGraphActiveSlide(theGraph, theNewActiveSlide); + } + } + } + EraseAnimationsThatMatch(inAnimationCore, + std::bind(AnimationSlideMatches, + std::placeholders::_1, inAnimationCore, inSlide)); + + TActionHandleList theActions; + inActionCore->GetActions(inSlide, theActions); + EraseActions(inDataCore, inActionCore, theActions); +} + +void CascadeSlidePropertyRemove(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, TAnimationCorePtr inAnimationCore) +{ + EraseAnimationsThatMatch(inAnimationCore, + std::bind(AnimationSlideInstancePropertyMatch, + std::placeholders::_1, inAnimationCore, + inSlide, inInstance, inProperty)); +} + +void CascadeInstanceParentRemoved(Qt3DSDMInstanceHandle inInstance, Qt3DSDMInstanceHandle inParent, + TDataCorePtr inDataCore, TSlideCorePtr inSlideCore, + TAnimationCorePtr inAnimationCore) +{ + TPropertyHandleList theProperties; + inDataCore->GetInstanceProperties(inParent, theProperties); + TInstanceHandleList allInstances; + inDataCore->GetInstances(allInstances); + function<bool(Qt3DSDMInstanceHandle)> InstanceOrDerived( + std::bind(&IDataCore::IsInstanceOrDerivedFrom, inDataCore, + std::placeholders::_1, inInstance)); + function<bool(Qt3DSDMInstanceHandle)> DerivedComplement( + std::bind(complement<function<bool(Qt3DSDMInstanceHandle)>, Qt3DSDMInstanceHandle>, + InstanceOrDerived, std::placeholders::_1)); + TInstanceHandleList::iterator all_derived = + remove_if(allInstances.begin(), allInstances.end(), DerivedComplement); + TInstanceHandleList derivedInstances(allInstances.begin(), all_derived); + inSlideCore->DeleteAllInstancePropertyEntries(derivedInstances, theProperties); + EraseAnimationsThatMatch( + inAnimationCore, std::bind(AnimationInstancesPropertiesMatch, + std::placeholders::_1, inAnimationCore, + std::cref(derivedInstances), std::cref(theProperties))); +} + +void CascadeBeforeAnimationDeleted(Qt3DSDMAnimationHandle inAnimation, + TAnimationCorePtr inAnimationCore, TDataCorePtr inDataCore, + TSlideCorePtr inSlideCore) +{ + SAnimationInfo theInfo = inAnimationCore->GetAnimationInfo(inAnimation); + SValue theSlideValue; + if (inDataCore->IsInstance(theInfo.m_Instance) && inSlideCore->IsSlide(theInfo.m_Slide) + && inSlideCore->GetSpecificInstancePropertyValue(theInfo.m_Slide, theInfo.m_Instance, + theInfo.m_Property, theSlideValue) + && inAnimationCore->GetKeyframeCount(inAnimation)) { + float theTime = inSlideCore->GetSlideTime(theInfo.m_Slide); + float theValue = inAnimationCore->EvaluateAnimation(inAnimation, theTime); + SetAnimationValue(theValue, theInfo.m_Index, theSlideValue); + inSlideCore->ForceSetInstancePropertyValue(theInfo.m_Slide, theInfo.m_Instance, + theInfo.m_Property, theSlideValue); + } +} + +void CascadeBeforeKeyframeErased(Qt3DSDMKeyframeHandle inKeyframe, TAnimationCorePtr inAnimationCore, + TDataCorePtr inDataCore, TSlideCorePtr inSlideCore) +{ + Qt3DSDMAnimationHandle theAnimation = inAnimationCore->GetAnimationForKeyframe(inKeyframe); + if (inAnimationCore->GetKeyframeCount(theAnimation) == 1) + CascadeBeforeAnimationDeleted(theAnimation, inAnimationCore, inDataCore, inSlideCore); +} + +CStudioCoreSystem::CStudioCoreSystem(TStringTablePtr strTable) + : m_StringTable(strTable.get() != NULL ? strTable : IStringTable::CreateStringTable()) + , m_DataCore(new CDataCoreProducer(m_StringTable)) + , m_SlideCore(new CSlideCoreProducer(m_StringTable)) + , m_SlideGraphCore(new CSlideGraphCoreProducer()) + , m_AnimationCore(new CAnimationCoreProducer()) + , m_ActionCore(new CActionCoreProducer(m_StringTable)) + , m_NewMetaData( + IMetaData::CreateNewMetaData(dynamic_pointer_cast<CDataCoreProducer>(m_DataCore))) + , m_GuideSystem(IGuideSystem::CreateGuideSystem()) +{ + IDataCoreSignalProvider *theProvider = + dynamic_cast<IDataCoreSignalProvider *>(m_DataCore.get()); + m_Connections.push_back(theProvider->ConnectInstanceDeleted( + std::bind(CascadeInstanceDelete, std::placeholders::_1, m_DataCore, m_SlideCore, + m_SlideGraphCore, m_AnimationCore, m_ActionCore))); + m_Connections.push_back(theProvider->ConnectPropertyRemoved(std::bind( + CascadePropertyRemove, std::placeholders::_1, + std::placeholders::_2, m_SlideCore, m_SlideGraphCore, m_AnimationCore))); + m_Connections.push_back(theProvider->ConnectInstanceParentRemoved(std::bind( + CascadeInstanceParentRemoved, std::placeholders::_1, + std::placeholders::_2, m_DataCore, m_SlideCore, m_AnimationCore))); + ISlideCoreSignalProvider *theSlideCoreSignalProvider = + dynamic_cast<ISlideCoreSignalProvider *>(m_SlideCore.get()); + m_Connections.push_back(theSlideCoreSignalProvider->ConnectBeforeSlideDeleted( + std::bind(CascadeSlideDelete, std::placeholders::_1, m_DataCore, m_SlideCore, + m_SlideGraphCore, m_AnimationCore, m_ActionCore))); + m_Connections.push_back(theSlideCoreSignalProvider->ConnectInstancePropertyValueRemoved( + std::bind(CascadeSlidePropertyRemove, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, m_AnimationCore))); + IAnimationCoreSignalProvider *theAnimProvider = + dynamic_cast<IAnimationCoreSignalProvider *>(m_AnimationCore.get()); + m_Connections.push_back(theAnimProvider->ConnectBeforeAnimationDeleted( + std::bind(CascadeBeforeAnimationDeleted, std::placeholders::_1, + m_AnimationCore, m_DataCore, m_SlideCore))); + m_Connections.push_back(theAnimProvider->ConnectBeforeKeyframeErased( + std::bind(CascadeBeforeKeyframeErased, std::placeholders::_1, + m_AnimationCore, m_DataCore, m_SlideCore))); + m_Connections.push_back(theAnimProvider->ConnectBeforeAllKeyframesErased( + std::bind(CascadeBeforeAnimationDeleted, std::placeholders::_1, + m_AnimationCore, m_DataCore, m_SlideCore))); +} + +CStudioCoreSystem::~CStudioCoreSystem() +{ +} + +std::shared_ptr<IDataCore> CStudioCoreSystem::GetDataCore() +{ + return m_DataCore; +} +std::shared_ptr<ISlideCore> CStudioCoreSystem::GetSlideCore() +{ + return m_SlideCore; +} +std::shared_ptr<ISlideGraphCore> CStudioCoreSystem::GetSlideGraphCore() +{ + return m_SlideGraphCore; +} +std::shared_ptr<IAnimationCore> CStudioCoreSystem::GetAnimationCore() +{ + return m_AnimationCore; +} +std::shared_ptr<IActionCore> CStudioCoreSystem::GetActionCore() +{ + return m_ActionCore; +} +std::shared_ptr<ICustomPropCore> CStudioCoreSystem::GetCustomPropCore() +{ + return m_CustomPropCore; +} +std::shared_ptr<IMetaData> CStudioCoreSystem::GetNewMetaData() +{ + return m_NewMetaData; +} +std::shared_ptr<IGuideSystem> CStudioCoreSystem::GetGuideSystem() +{ + return m_GuideSystem; +} + +std::shared_ptr<IDataCore> CStudioCoreSystem::GetTransactionlessDataCore() +{ + return dynamic_cast<CDataCoreProducer *>(m_DataCore.get())->GetTransactionlessDataCore(); +} +std::shared_ptr<ISlideCore> CStudioCoreSystem::GetTransactionlessSlideCore() +{ + return dynamic_cast<CSlideCoreProducer *>(m_SlideCore.get())->GetTransactionlessSlideCore(); +} +std::shared_ptr<ISlideGraphCore> CStudioCoreSystem::GetTransactionlessSlideGraphCore() +{ + return dynamic_cast<CSlideGraphCoreProducer *>(m_SlideGraphCore.get()) + ->GetTransactionlessSlideGraphCore(); +} +std::shared_ptr<IAnimationCore> CStudioCoreSystem::GetTransactionlessAnimationCore() +{ + return dynamic_cast<CAnimationCoreProducer *>(m_AnimationCore.get()) + ->GetTransactionlessAnimationCore(); +} +std::shared_ptr<IActionCore> CStudioCoreSystem::GetTransactionlessActionCore() +{ + return dynamic_cast<CActionCoreProducer *>(m_ActionCore.get())->GetTransactionlessActionCore(); +} + +inline bool InstanceSpecificNameMatches(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const TCharStr &inName, + const CSimpleDataCore &inData) +{ + TPropertyHandleList theProperties; + inData.GetAggregateInstanceProperties(inInstance, theProperties); + SValue theValue; + if (exists(theProperties, std::bind(equal_to<int>(), inProperty, std::placeholders::_1)) + && inData.GetSpecificInstancePropertyValue(inInstance, inProperty, theValue)) { + return inName == get<TDataStrPtr>(theValue)->GetData(); + } + return false; +} + +Qt3DSDMInstanceHandle CStudioCoreSystem::FindInstanceByName(Qt3DSDMPropertyHandle inNameProperty, + const TCharStr &inName) const +{ + TInstanceHandleList theInstances; + m_DataCore->GetInstances(theInstances); + TInstanceHandleList::iterator theFind = find_if<TInstanceHandleList::iterator>( + theInstances, + std::bind(InstanceSpecificNameMatches, std::placeholders::_1, inNameProperty, std::cref(inName), + std::cref(*dynamic_cast<CDataCoreProducer *>(m_DataCore.get()) + ->GetTransactionlessDataCore()))); + if (theFind != theInstances.end()) + return *theFind; + return 0; +} + +void CStudioCoreSystem::SetConsumer(TTransactionConsumerPtr inConsumer) +{ + DoSetConsumer(inConsumer, m_DataCore); + DoSetConsumer(inConsumer, m_SlideCore); + DoSetConsumer(inConsumer, m_SlideGraphCore); + DoSetConsumer(inConsumer, m_AnimationCore); + DoSetConsumer(inConsumer, m_ActionCore); + DoSetConsumer(inConsumer, m_GuideSystem); + // In general the meta data doesn't participate in the undo/redo system except + // in special cases. + if (!inConsumer) + DoSetConsumer(inConsumer, m_NewMetaData); +} +} diff --git a/src/dm/systems/StudioCoreSystem.h b/src/dm/systems/StudioCoreSystem.h new file mode 100644 index 0000000..18f1dad --- /dev/null +++ b/src/dm/systems/StudioCoreSystem.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef STUDIOCORESYSTEMH +#define STUDIOCORESYSTEMH +#include "Qt3DSDMTransactions.h" +#include "Qt3DSDMHandles.h" + +namespace qt3dsdm { +class IDataCore; +class ISlideCore; +class ISlideGraphCore; +class IAnimationCore; +class IActionCore; +class ICustomPropCore; +class ISignalConnection; +class IMetaData; +class IGuideSystem; + +// Manages cascading operations between cores so that the entire group of +// cores stays up to date. +class CStudioCoreSystem : public ITransactionProducer +{ + Q_DISABLE_COPY(CStudioCoreSystem) + + TStringTablePtr m_StringTable; + std::shared_ptr<IDataCore> m_DataCore; + std::shared_ptr<ISlideCore> m_SlideCore; + std::shared_ptr<ISlideGraphCore> m_SlideGraphCore; + std::shared_ptr<IAnimationCore> m_AnimationCore; + std::shared_ptr<IActionCore> m_ActionCore; + std::shared_ptr<ICustomPropCore> m_CustomPropCore; + std::shared_ptr<IMetaData> m_NewMetaData; + std::shared_ptr<IGuideSystem> m_GuideSystem; + + std::vector<std::shared_ptr<ISignalConnection>> m_Connections; + +public: + CStudioCoreSystem(TStringTablePtr strTable = TStringTablePtr()); + virtual ~CStudioCoreSystem(); + TStringTablePtr GetStringTablePtr() const { return m_StringTable; } + + std::shared_ptr<IDataCore> GetDataCore(); + std::shared_ptr<ISlideCore> GetSlideCore(); + std::shared_ptr<ISlideGraphCore> GetSlideGraphCore(); + std::shared_ptr<IAnimationCore> GetAnimationCore(); + std::shared_ptr<IActionCore> GetActionCore(); + std::shared_ptr<ICustomPropCore> GetCustomPropCore(); + std::shared_ptr<IMetaData> GetNewMetaData(); + std::shared_ptr<IGuideSystem> GetGuideSystem(); + + std::shared_ptr<IDataCore> GetTransactionlessDataCore(); + std::shared_ptr<ISlideCore> GetTransactionlessSlideCore(); + std::shared_ptr<ISlideGraphCore> GetTransactionlessSlideGraphCore(); + std::shared_ptr<IAnimationCore> GetTransactionlessAnimationCore(); + std::shared_ptr<IActionCore> GetTransactionlessActionCore(); + std::shared_ptr<ICustomPropCore> GetTransactionlessCustomPropCore(); + + Qt3DSDMInstanceHandle FindInstanceByName(Qt3DSDMPropertyHandle inNameProperty, + const TCharStr &inName) const; + + void SetConsumer(TTransactionConsumerPtr inConsumer) override; +}; + +typedef std::shared_ptr<CStudioCoreSystem> TStudioCoreSystemPtr; +} + +#endif diff --git a/src/dm/systems/StudioFullSystem.cpp b/src/dm/systems/StudioFullSystem.cpp new file mode 100644 index 0000000..c98f8a8 --- /dev/null +++ b/src/dm/systems/StudioFullSystem.cpp @@ -0,0 +1,647 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "StudioFullSystem.h" +#include "StudioCoreSystem.h" +#include "StudioPropertySystem.h" +#include "SlideSystem.h" +#include "StudioAnimationSystem.h" +#include "ActionSystem.h" +#include "SignalsImpl.h" +#include "SimpleDataCore.h" +#include "SimpleSlideCore.h" +#include "SimpleSlideGraphCore.h" +#include "SimpleAnimationCore.h" +#include "DataCoreProducer.h" +#include "SlideCoreProducer.h" +#include "SlideGraphCoreProducer.h" +#include "ActionCoreProducer.h" + +using namespace std; + +namespace qt3dsdm { + +template <typename TDoTransaction, typename TUndoTransaction> +inline void NotifyConsumer(TTransactionConsumerPtr inConsumer, TDoTransaction inDoNotification, + TUndoTransaction inUndoNotification) +{ + if (inConsumer) { + inConsumer->OnDoNotification(inDoNotification); + inConsumer->OnUndoNotification(inUndoNotification); + } else { + inDoNotification(); // No consumer, send notification right away + } +} + +void NotifySlideCreated(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, Qt3DSDMSlideHandle inSlide) +{ + NotifyConsumer(inConsumer, + bind(&IStudioFullSystemSignalSender::SendSlideCreated, inSender, inSlide), + bind(&IStudioFullSystemSignalSender::SendSlideDeleted, inSender, inSlide)); +} + +void NotifySlideDeleted(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, Qt3DSDMSlideHandle inSlide) +{ + NotifyConsumer(inConsumer, + bind(&IStudioFullSystemSignalSender::SendSlideDeleted, inSender, inSlide), + bind(&IStudioFullSystemSignalSender::SendSlideCreated, inSender, inSlide)); +} + +void NotifySlideRearranged(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, Qt3DSDMSlideHandle inSlide, + int inOldIndex, int inNewIndex) +{ + NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendSlideRearranged, inSender, + inSlide, inOldIndex, inNewIndex), + bind(&IStudioFullSystemSignalSender::SendSlideRearranged, inSender, inSlide, + inNewIndex, inOldIndex)); +} + +void SendInstancePropertyValueChanged(TDataCorePtr inCore, IStudioFullSystemSignalSender *inSender, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) +{ + // Ignore when the instance is not an instance (undoing an add operation may create this, as + // transactions are run first and notifications second). + if (inCore->IsInstance(inInstance)) + inSender->SendInstancePropertyValue(inInstance, inProperty); +} + +void NotifyInstancePropertyChanged(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore, + IStudioFullSystemSignalSender *inSender, + Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + bool inIsAggregate) +{ + if (inConsumer) { + if (inIsAggregate == false) { + NotifyConsumer( + inConsumer, + bind(SendInstancePropertyValueChanged, inCore, inSender, inInstance, inProperty), + bind(SendInstancePropertyValueChanged, inCore, inSender, inInstance, inProperty)); + } + } else { + SendInstancePropertyValueChanged(inCore, inSender, inInstance, inProperty); + } +} + +void RunAnimations(IStudioFullSystemSignalSender *inSender, Qt3DSDMSlideHandle inMaster, + Qt3DSDMSlideHandle inSlide, TAnimationCorePtr inAnimationCore, + TDataCorePtr inDataCore, TTransactionConsumerPtr &inConsumer) +{ + TAnimationInfoList theAnimations; + inAnimationCore->GetAnimations(theAnimations, inMaster, inSlide); + size_t theEnd = theAnimations.size(); + for (size_t theIndex = 0; theIndex < theEnd; ++theIndex) { + SAnimationInfo &theInfo(theAnimations[theIndex]); + NotifyInstancePropertyChanged(inConsumer, inDataCore, inSender, theInfo.m_Instance, + theInfo.m_Property, false); + } +} + +void NotifyComponentSeconds(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, Qt3DSDMSlideHandle inSlide, + TDataCorePtr inCore, TAnimationCorePtr inAnimationCore, + TStudioAnimationSystemPtr inAnimationSystem, + TSlideSystemPtr inSlideSystem) +{ + Qt3DSDMSlideHandle theMaster = inSlideSystem->GetMasterSlide(inSlide); + NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendBeginComponentSeconds, + inSender, theMaster), + bind(&IStudioFullSystemSignalSender::SendComponentSeconds, inSender, theMaster)); + RunAnimations(inSender, theMaster, inSlide, inAnimationCore, inCore, inConsumer); + dynamic_cast<CStudioAnimationSystem *>(inAnimationSystem.get()) + ->ClearTemporaryAnimationValues(); + NotifyConsumer( + inConsumer, bind(&IStudioFullSystemSignalSender::SendComponentSeconds, inSender, theMaster), + bind(&IStudioFullSystemSignalSender::SendBeginComponentSeconds, inSender, theMaster)); +} + +void NotifyPropertyLinked(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore, + IStudioFullSystemSignalSender *inSender, Qt3DSDMSlideHandle inMaster, + Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + bool inAggregate) +{ + if (inAggregate == false) { + NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendPropertyLinked, + inSender, inMaster, inInstance, inProperty), + bind(&IStudioFullSystemSignalSender::SendPropertyUnlinked, inSender, + inMaster, inInstance, inProperty)); + NotifyInstancePropertyChanged(inConsumer, inCore, inSender, inInstance, inProperty, + inAggregate); + } +} + +void NotifyPropertyUnlinked(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore, + IStudioFullSystemSignalSender *inSender, Qt3DSDMSlideHandle inMaster, + Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + bool inAggregate) +{ + if (inAggregate == false) { + NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendPropertyUnlinked, + inSender, inMaster, inInstance, inProperty), + bind(&IStudioFullSystemSignalSender::SendPropertyLinked, inSender, inMaster, + inInstance, inProperty)); + NotifyInstancePropertyChanged(inConsumer, inCore, inSender, inInstance, inProperty, + inAggregate); + } +} + +void NotifyActiveSlide(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore, + IStudioFullSystemSignalSender *inSender, Qt3DSDMSlideHandle inMaster, + int /*inIndex*/, Qt3DSDMSlideHandle inOldSlide, Qt3DSDMSlideHandle inNewSlide, + TAnimationCorePtr inAnimationCore, TSlideSystemPtr inSlideSystem) +{ + TInstancePropertyPairList thePropertyList; + inSlideSystem->GetUnionOfProperties(inOldSlide, inNewSlide, thePropertyList); + for (size_t idx = 0, end = thePropertyList.size(); idx < end; ++idx) + NotifyInstancePropertyChanged(inConsumer, inCore, inSender, thePropertyList[idx].first, + thePropertyList[idx].second, false); + + RunAnimations(inSender, inMaster, inNewSlide, inAnimationCore, inCore, inConsumer); +} + +void NotifyAnimationCreated(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, + Qt3DSDMAnimationHandle inAnimation, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, bool inIsAggregate) +{ + if (!inIsAggregate) { + NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendAnimationCreated, + inSender, inAnimation, inInstance, inProperty), + bind(&IStudioFullSystemSignalSender::SendAnimationDeleted, inSender, + inAnimation, inInstance, inProperty)); + } +} + +void NotifyAnimationDeleted(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore, + IStudioFullSystemSignalSender *inSender, + Qt3DSDMAnimationHandle inAnimation, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) +{ + NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendAnimationDeleted, inSender, + inAnimation, inInstance, inProperty), + bind(&IStudioFullSystemSignalSender::SendAnimationCreated, inSender, inAnimation, + inInstance, inProperty)); + NotifyInstancePropertyChanged(inConsumer, inCore, inSender, inInstance, inProperty, false); +} + +void NotifyAnimationChanged(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore, + IStudioFullSystemSignalSender *inSender, + Qt3DSDMAnimationHandle inAnimation, TAnimationCorePtr inAnimationCore, + bool inIsAggregate) +{ + if (!inIsAggregate) { + SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation)); + NotifyInstancePropertyChanged(inConsumer, inCore, inSender, theInfo.m_Instance, + theInfo.m_Property, inIsAggregate); + } +} + +void NotifyKeyframeInserted(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore, + IStudioFullSystemSignalSender *inSender, + Qt3DSDMAnimationHandle inAnimation, Qt3DSDMKeyframeHandle inKeyframe, + TAnimationCorePtr inAnimationCore, bool inIsAggregate) +{ + if (!inIsAggregate) { + NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendKeyframeInserted, + inSender, inAnimation, inKeyframe), + bind(&IStudioFullSystemSignalSender::SendKeyframeErased, inSender, + inAnimation, inKeyframe)); + NotifyAnimationChanged(inConsumer, inCore, inSender, inAnimation, inAnimationCore, false); + } +} + +void NotifyKeyframeErased(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore, + IStudioFullSystemSignalSender *inSender, + Qt3DSDMAnimationHandle inAnimation, Qt3DSDMKeyframeHandle inKeyframe, + TAnimationCorePtr inAnimationCore) +{ + NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendKeyframeErased, inSender, + inAnimation, inKeyframe), + bind(&IStudioFullSystemSignalSender::SendKeyframeInserted, inSender, inAnimation, + inKeyframe)); + NotifyAnimationChanged(inConsumer, inCore, inSender, inAnimation, inAnimationCore, false); +} + +void NotifyKeyframeUpdated(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore, + IStudioFullSystemSignalSender *inSender, Qt3DSDMKeyframeHandle inKeyframe, + TAnimationCorePtr inAnimationCore) +{ + NotifyConsumer(inConsumer, + bind(&IStudioFullSystemSignalSender::SendKeyframeUpdated, inSender, inKeyframe), + bind(&IStudioFullSystemSignalSender::SendKeyframeUpdated, inSender, inKeyframe)); + Qt3DSDMAnimationHandle theAnimation(inAnimationCore->GetAnimationForKeyframe(inKeyframe)); + NotifyAnimationChanged(inConsumer, inCore, inSender, theAnimation, inAnimationCore, false); +} + +void NotifyConnectFirstKeyframeDynamicSet(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore, + IStudioFullSystemSignalSender *inSender, + Qt3DSDMAnimationHandle inAnimation, bool inDynamic, + TAnimationCorePtr inAnimationCore) +{ + NotifyConsumer(inConsumer, + bind(&IStudioFullSystemSignalSender::SendConnectFirstKeyframeDynamicSet, + inSender, inAnimation, inDynamic), + bind(&IStudioFullSystemSignalSender::SendConnectFirstKeyframeDynamicSet, + inSender, inAnimation, inDynamic)); + NotifyAnimationChanged(inConsumer, inCore, inSender, inAnimation, inAnimationCore, false); +} + +inline ISlideCoreSignalProvider *GetSlideSignaller(TSlideCorePtr inSlideCore) +{ + return dynamic_cast<CSlideCoreProducer *>(inSlideCore.get()); +} + +void NotifyInstanceCreated(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, Qt3DSDMInstanceHandle instance) +{ + NotifyConsumer(inConsumer, + bind(&IStudioFullSystemSignalSender::SendInstanceCreated, inSender, instance), + bind(&IStudioFullSystemSignalSender::SendInstanceDeleted, inSender, instance)); +} + +void NotifyInstanceDeleted(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, Qt3DSDMInstanceHandle instance) +{ + NotifyConsumer(inConsumer, + bind(&IStudioFullSystemSignalSender::SendInstanceDeleted, inSender, instance), + bind(&IStudioFullSystemSignalSender::SendInstanceCreated, inSender, instance)); +} + +void NotifyActionCreated(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, Qt3DSDMActionHandle inAction, + Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance) +{ + NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendActionCreated, inSender, + inAction, inSlide, inInstance), + bind(&IStudioFullSystemSignalSender::SendActionDeleted, inSender, inAction, + inSlide, inInstance)); +} + +void NotifyActionDestroyed(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, Qt3DSDMActionHandle inAction, + Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance) +{ + NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendActionDeleted, inSender, + inAction, inSlide, inInstance), + bind(&IStudioFullSystemSignalSender::SendActionCreated, inSender, inAction, + inSlide, inInstance)); +} + +void SendActionEvent(Qt3DSDMActionHandle inAction, TActionCorePtr inCore, + function<void()> inFunction) +{ + if (inCore->HandleValid(inAction)) + inFunction(); +} + +void NotifyTriggerObjectSet(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, Qt3DSDMActionHandle inAction, + TActionCorePtr inCore) +{ + function<void()> theFunc( + bind(&IStudioFullSystemSignalSender::SendTriggerObjectSet, inSender, inAction)); + NotifyConsumer(inConsumer, bind(SendActionEvent, inAction, inCore, theFunc), + bind(SendActionEvent, inAction, inCore, theFunc)); +} + +void NotifyTargetObjectSet(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, Qt3DSDMActionHandle inAction, + TActionCorePtr inCore) +{ + function<void()> theFunc( + bind(&IStudioFullSystemSignalSender::SendTargetObjectSet, inSender, inAction)); + NotifyConsumer(inConsumer, bind(SendActionEvent, inAction, inCore, theFunc), + bind(SendActionEvent, inAction, inCore, theFunc)); +} + +void NotifyEventSet(TTransactionConsumerPtr &inConsumer, IStudioFullSystemSignalSender *inSender, + Qt3DSDMActionHandle inAction, TActionCorePtr inCore) +{ + function<void()> theFunc( + bind(&IStudioFullSystemSignalSender::SendEventSet, inSender, inAction)); + NotifyConsumer(inConsumer, bind(SendActionEvent, inAction, inCore, theFunc), + bind(SendActionEvent, inAction, inCore, theFunc)); +} + +void NotifyHandlerSet(TTransactionConsumerPtr &inConsumer, IStudioFullSystemSignalSender *inSender, + Qt3DSDMActionHandle inAction, TActionCorePtr inCore) +{ + function<void()> theFunc( + bind(&IStudioFullSystemSignalSender::SendHandlerSet, inSender, inAction)); + NotifyConsumer(inConsumer, bind(SendActionEvent, inAction, inCore, theFunc), + bind(SendActionEvent, inAction, inCore, theFunc)); +} + +void NotifyHandlerArgumentValueSet(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, + Qt3DSDMHandlerArgHandle inAction, TActionCorePtr inCore) +{ + function<void()> theFunc( + bind(&IStudioFullSystemSignalSender::SendHandlerArgumentValueSet, inSender, inAction)); + Qt3DSDMActionHandle theActionHdl(inCore->GetHandlerArgumentInfo(inAction).m_Action); + NotifyConsumer(inConsumer, bind(SendActionEvent, theActionHdl, inCore, theFunc), + bind(SendActionEvent, theActionHdl, inCore, theFunc)); +} + +void NotifyAllKeyframesErased(TTransactionConsumerPtr &inConsumer, + IStudioFullSystemSignalSender *inSender, + TAnimationCorePtr inAnimationCore, Qt3DSDMAnimationHandle inAnimation) +{ + if (inConsumer) { + TKeyframeHandleList theKeyframes; + inAnimationCore->GetKeyframes(inAnimation, theKeyframes); + for (size_t idx = 0, end = theKeyframes.size(); idx < end; ++idx) { + inConsumer->OnDoNotification(bind(&IStudioFullSystemSignalSender::SendKeyframeErased, + inSender, inAnimation, theKeyframes[idx])); + inConsumer->OnUndoNotification( + bind(&IStudioFullSystemSignalSender::SendKeyframeInserted, inSender, inAnimation, + theKeyframes[idx])); + } + } +} + +CStudioFullSystem::CStudioFullSystem(std::shared_ptr<CStudioCoreSystem> inCoreSystem, + Qt3DSDMInstanceHandle inSlideInstance, + Qt3DSDMPropertyHandle inComponentGuidProperty, + Qt3DSDMInstanceHandle inActionInstance, + Qt3DSDMPropertyHandle inActionEyeball) + : m_CoreSystem(inCoreSystem) + , m_SlideSystem(new SSlideSystem(m_CoreSystem->GetDataCore(), m_CoreSystem->GetSlideCore(), + m_CoreSystem->GetSlideGraphCore(), + m_CoreSystem->GetAnimationCore(), inSlideInstance, + inComponentGuidProperty)) + , m_ActionSystem(new CActionSystem(m_CoreSystem->GetDataCore(), m_CoreSystem->GetSlideCore(), + m_CoreSystem->GetSlideGraphCore(), + m_CoreSystem->GetActionCore(), m_SlideSystem, + inActionInstance, inActionEyeball)) + , m_AggregateOperation(false) +{ + // TODO: Too many parameters passed in to the subsystem. Just make them know about FullSystem so + // they can get whatever they want + CStudioAnimationSystem *theAnimationSystem = new CStudioAnimationSystem( + m_PropertySystem, m_SlideSystem, m_CoreSystem->GetSlideCore(), + m_CoreSystem->GetSlideGraphCore(), m_CoreSystem->GetAnimationCore()); + m_AnimationSystem = std::shared_ptr<qt3dsdm::IStudioAnimationSystem>(theAnimationSystem); + + m_PropertySystem = std::shared_ptr<qt3dsdm::IPropertySystem>( + new CStudioPropertySystem(m_CoreSystem->GetNewMetaData(), m_CoreSystem->GetDataCore(), + m_SlideSystem, m_AnimationSystem)); + theAnimationSystem->SetPropertySystem(m_PropertySystem); + + TDataCorePtr dataCore(m_CoreSystem->GetDataCore()); + + static_cast<SSlideSystem *>(m_SlideSystem.get())->SetPropertySystem(m_PropertySystem); + + ISlideSystemSignalProvider *theSlideSignaller = + dynamic_cast<SSlideSystem *>(m_SlideSystem.get())->GetSignalProvider(); + m_Signaller = CreateStudioFullSystemSignaller(theSlideSignaller); + IStudioFullSystemSignalSender *theSystemSender = + dynamic_cast<IStudioFullSystemSignalSender *>(m_Signaller.get()); + m_Connections.push_back(theSlideSignaller->ConnectSlideRearranged( + bind(NotifySlideRearranged, ref(m_Consumer), theSystemSender, + std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3))); + m_Connections.push_back(theSlideSignaller->ConnectPropertyLinked( + bind(NotifyPropertyLinked, ref(m_Consumer), dataCore, theSystemSender, + std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, + std::cref(m_AggregateOperation)))); + m_Connections.push_back(theSlideSignaller->ConnectPropertyUnlinked( + bind(NotifyPropertyUnlinked, ref(m_Consumer), dataCore, theSystemSender, + std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, + std::cref(m_AggregateOperation)))); + + m_Connections.push_back(theSlideSignaller->ConnectActiveSlide( + bind(NotifyActiveSlide, ref(m_Consumer), dataCore, theSystemSender, + std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, + GetAnimationCore(), GetSlideSystem()))); + + IDataCoreSignalProvider *theDataSignals = + dynamic_cast<IDataCoreSignalProvider *>(m_CoreSystem->GetDataCore().get()); + m_Connections.push_back(theDataSignals->ConnectInstanceCreated( + bind(NotifyInstanceCreated, ref(m_Consumer), theSystemSender, std::placeholders::_1))); + m_Connections.push_back(theDataSignals->ConnectInstanceDeleted( + bind(NotifyInstanceDeleted, ref(m_Consumer), theSystemSender, std::placeholders::_1))); + + ISlideCoreSignalProvider *theSlideCoreSignaller = + dynamic_cast<ISlideCoreSignalProvider *>(m_CoreSystem->GetSlideCore().get()); + m_Connections.push_back(theSlideCoreSignaller->ConnectInstancePropertyValueSet( + bind(NotifyInstancePropertyChanged, ref(m_Consumer), dataCore, theSystemSender, + std::placeholders::_2, std::placeholders::_3, + std::cref(m_AggregateOperation)))); + m_Connections.push_back(theSlideCoreSignaller->ConnectSlideTimeChanged( + bind(NotifyComponentSeconds, ref(m_Consumer), theSystemSender, std::placeholders::_1, + dataCore, GetAnimationCore(), GetAnimationSystem(), GetSlideSystem()))); + m_Connections.push_back(theSlideCoreSignaller->ConnectSlideCreated( + bind(NotifySlideCreated, ref(m_Consumer), theSystemSender, std::placeholders::_1))); + m_Connections.push_back(theSlideCoreSignaller->ConnectSlideDeleted( + bind(NotifySlideDeleted, ref(m_Consumer), theSystemSender, std::placeholders::_1))); + + IAnimationCoreSignalProvider *theAnimationSignals = + dynamic_cast<IAnimationCoreSignalProvider *>(GetAnimationCore().get()); + m_Connections.push_back(theAnimationSignals->ConnectAnimationCreated( + bind(NotifyAnimationCreated, ref(m_Consumer), theSystemSender, + std::placeholders::_1, std::placeholders::_3, std::placeholders::_4, + std::cref(m_AggregateOperation)))); + m_Connections.push_back(theAnimationSignals->ConnectAnimationDeleted( + bind(NotifyAnimationDeleted, ref(m_Consumer), dataCore, theSystemSender, + std::placeholders::_1, std::placeholders::_3, std::placeholders::_4))); + m_Connections.push_back(theAnimationSignals->ConnectKeyframeInserted( + bind(NotifyKeyframeInserted, ref(m_Consumer), dataCore, theSystemSender, + std::placeholders::_1, std::placeholders::_2, + GetAnimationCore(), std::cref(m_AggregateOperation)))); + m_Connections.push_back(theAnimationSignals->ConnectKeyframeErased( + bind(NotifyKeyframeErased, ref(m_Consumer), dataCore, theSystemSender, + std::placeholders::_1, std::placeholders::_2, + GetAnimationCore()))); + m_Connections.push_back(theAnimationSignals->ConnectKeyframeUpdated( + bind(NotifyKeyframeUpdated, ref(m_Consumer), dataCore, theSystemSender, + std::placeholders::_1, GetAnimationCore()))); + m_Connections.push_back(theAnimationSignals->ConnectFirstKeyframeDynamicSet( + bind(NotifyConnectFirstKeyframeDynamicSet, ref(m_Consumer), dataCore, + theSystemSender, std::placeholders::_1, + std::placeholders::_2, GetAnimationCore()))); + m_Connections.push_back(theAnimationSignals->ConnectBeforeAllKeyframesErased( + bind(NotifyAllKeyframesErased, ref(m_Consumer), theSystemSender, + GetAnimationCore(), std::placeholders::_1))); + + IInstancePropertyCoreSignalProvider *thePropertyCoreSignaller = + dynamic_cast<CStudioPropertySystem *>(m_PropertySystem.get()) + ->GetPropertyCoreSignalProvider(); + m_Connections.push_back(thePropertyCoreSignaller->ConnectInstancePropertyValue( + bind(NotifyInstancePropertyChanged, ref(m_Consumer), dataCore, theSystemSender, + std::placeholders::_1, std::placeholders::_2, std::cref(m_AggregateOperation)))); + + thePropertyCoreSignaller = dynamic_cast<CStudioPropertySystem *>(m_PropertySystem.get()) + ->GetImmediatePropertyCoreSignalProvider(); + m_Connections.push_back(thePropertyCoreSignaller->ConnectInstancePropertyValue( + bind(&IStudioFullSystemSignalSender::SendInstancePropertyValue, theSystemSender, + std::placeholders::_1, std::placeholders::_2))); + + thePropertyCoreSignaller = + dynamic_cast<IInstancePropertyCoreSignalProvider *>(m_CoreSystem->GetDataCore().get()); + m_Connections.push_back(thePropertyCoreSignaller->ConnectInstancePropertyValue( + bind(NotifyInstancePropertyChanged, ref(m_Consumer), dataCore, theSystemSender, + std::placeholders::_1, std::placeholders::_2, std::cref(m_AggregateOperation)))); + + IActionCoreSignalProvider *theActionSignals = + dynamic_cast<IActionCoreSignalProvider *>(m_CoreSystem->GetActionCore().get()); + m_Connections.push_back(theActionSignals->ConnectTriggerObjectSet( + bind(NotifyTriggerObjectSet, ref(m_Consumer), theSystemSender, + std::placeholders::_1, GetActionCore()))); + m_Connections.push_back(theActionSignals->ConnectTargetObjectSet( + bind(NotifyTargetObjectSet, ref(m_Consumer), theSystemSender, + std::placeholders::_1, GetActionCore()))); + m_Connections.push_back(theActionSignals->ConnectEventSet( + bind(NotifyEventSet, ref(m_Consumer), theSystemSender, + std::placeholders::_1, GetActionCore()))); + m_Connections.push_back(theActionSignals->ConnectHandlerSet( + bind(NotifyHandlerSet, ref(m_Consumer), theSystemSender, + std::placeholders::_1, GetActionCore()))); + m_Connections.push_back(theActionSignals->ConnectHandlerArgumentValueSet(bind( + NotifyHandlerArgumentValueSet, ref(m_Consumer), theSystemSender, + std::placeholders::_1, GetActionCore()))); + + IActionSystemSignalProvider *theActionSystemSignals = + dynamic_cast<CActionSystem *>(m_ActionSystem.get())->GetSignalProvider(); + m_Connections.push_back(theActionSystemSignals->ConnectActionCreated( + bind(NotifyActionCreated, ref(m_Consumer), theSystemSender, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))); + m_Connections.push_back(theActionSystemSignals->ConnectActionDeleted( + bind(NotifyActionDestroyed, ref(m_Consumer), theSystemSender, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))); +} + +CStudioFullSystem::~CStudioFullSystem() +{ +} + +std::shared_ptr<IPropertySystem> CStudioFullSystem::GetPropertySystem() +{ + return m_PropertySystem; +} +std::shared_ptr<ISlideSystem> CStudioFullSystem::GetSlideSystem() +{ + return m_SlideSystem; +} +std::shared_ptr<ISlideCore> CStudioFullSystem::GetSlideCore() +{ + return m_CoreSystem->GetSlideCore(); +} +std::shared_ptr<IAnimationCore> CStudioFullSystem::GetAnimationCore() +{ + return m_CoreSystem->GetAnimationCore(); +} +std::shared_ptr<IStudioAnimationSystem> CStudioFullSystem::GetAnimationSystem() +{ + return m_AnimationSystem; +} +std::shared_ptr<IActionCore> CStudioFullSystem::GetActionCore() +{ + return m_CoreSystem->GetActionCore(); +} +std::shared_ptr<IActionSystem> CStudioFullSystem::GetActionSystem() +{ + return m_ActionSystem; +} + +std::shared_ptr<IPropertySystem> CStudioFullSystem::GetPropertySystem() const +{ + return m_PropertySystem; +} +std::shared_ptr<ISlideSystem> CStudioFullSystem::GetSlideSystem() const +{ + return m_SlideSystem; +} +std::shared_ptr<ISlideCore> CStudioFullSystem::GetSlideCore() const +{ + return m_CoreSystem->GetSlideCore(); +} +std::shared_ptr<IAnimationCore> CStudioFullSystem::GetAnimationCore() const +{ + return m_CoreSystem->GetAnimationCore(); +} +std::shared_ptr<IStudioAnimationSystem> CStudioFullSystem::GetAnimationSystem() const +{ + return m_AnimationSystem; +} +std::shared_ptr<IActionCore> CStudioFullSystem::GetActionCore() const +{ + return m_CoreSystem->GetActionCore(); +} +std::shared_ptr<IActionSystem> CStudioFullSystem::GetActionSystem() const +{ + return m_ActionSystem; +} + +std::shared_ptr<CStudioCoreSystem> CStudioFullSystem::GetCoreSystem() +{ + return m_CoreSystem; +} + +bool CStudioFullSystem::GetCanonicalInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + SValue theTemp; + bool retval = dynamic_cast<const CStudioPropertySystem *>(m_PropertySystem.get()) + ->GetCanonicalInstancePropertyValue(inInstance, inProperty, theTemp); + if (retval) + outValue = theTemp.toOldSkool(); + return retval; +} + +Qt3DSDMInstanceHandle CStudioFullSystem::FindInstanceByName(Qt3DSDMPropertyHandle inNameProperty, + const TCharStr &inName) const +{ + return m_CoreSystem->FindInstanceByName(inNameProperty, inName); +} + +void CStudioFullSystem::SetConsumer(TTransactionConsumerPtr inConsumer) +{ + m_CoreSystem->SetConsumer(inConsumer); + DoSetConsumer(inConsumer, m_AnimationSystem); + m_Consumer = inConsumer; +} + +IStudioFullSystemSignalProvider *CStudioFullSystem::GetSignalProvider() +{ + return dynamic_cast<IStudioFullSystemSignalProvider *>(m_Signaller.get()); +} + +IStudioFullSystemSignalSender *CStudioFullSystem::GetSignalSender() +{ + return dynamic_cast<IStudioFullSystemSignalSender *>(m_Signaller.get()); +} +} diff --git a/src/dm/systems/StudioFullSystem.h b/src/dm/systems/StudioFullSystem.h new file mode 100644 index 0000000..9411e78 --- /dev/null +++ b/src/dm/systems/StudioFullSystem.h @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef STUDIOFULLSYSTEMH +#define STUDIOFULLSYSTEMH +#include "Qt3DSDMTransactions.h" +#include "Qt3DSDMHandles.h" +#include "Qt3DSDMSignals.h" +#include "Qt3DSDMDataTypes.h" + +namespace qt3dsdm { +class IPropertySystem; +class ISlideSystem; +class IStudioAnimationSystem; +class CStudioCoreSystem; +class IInstancePropertyCore; +class INotificationEngine; +class IAnimationCore; +class IActionCore; +class ISlideCore; +class IActionSystem; +class ISignalConnection; + +class IStudioFullSystemSerializeHelper +{ +public: + virtual ~IStudioFullSystemSerializeHelper() {} + /** + * Given an instance, set the name if possible. Called for parents of existing instances + * so we can find instances by name later. There is an implicit assumption for partial + * serialization that none of the instances that are serialized out are base instances + * for other serialized instances. There is another implicit assumption that the system + * can name any instances used a base. + */ + virtual bool GetInstanceName(Qt3DSDMInstanceHandle inInstance, TCharStr &outName) = 0; +}; + +typedef std::shared_ptr<IStudioFullSystemSerializeHelper> TStudioFullSystemSerializeHelperPtr; + +// The full studio system needs extra information in the deserialize stage. This information +// requires knowledge of the larger studio universe in order to work and thus clients need to +// pass in an interface. +class IStudioFullSystemDeserializeHelper +{ +public: + virtual ~IStudioFullSystemDeserializeHelper() {} + /** + * Return an instance by name. Whatever method was used above to name instances + * should be used to find a given instance by name. + */ + virtual Qt3DSDMInstanceHandle FindInstanceByName(const TCharStr &inName) = 0; + /** + * Translate a given guid. For pass 1, you should only translate ids and just return identity + * for anything that isn't an id. + */ + virtual void TranslateGuidPass1(Qt3DSDMPropertyHandle inProperty, SLong4 inValue) = 0; + /** + * Now translate guids that are used as data variables. These are links to other objects and + *the GUID + * information should come from what was created in pass 1. + */ + virtual SLong4 TranslateGuidPass2(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SLong4 inValue) = 0; +}; + +typedef std::shared_ptr<IStudioFullSystemDeserializeHelper> TStudioFullSystemDeserializeHelperPtr; + +class CStudioFullSystem : public ITransactionProducer +{ + Q_DISABLE_COPY(CStudioFullSystem) + + // Base that the other types are built upon + std::shared_ptr<CStudioCoreSystem> m_CoreSystem; + + // The data model exposed to studio + std::shared_ptr<IPropertySystem> m_PropertySystem; + std::shared_ptr<ISlideSystem> m_SlideSystem; + std::shared_ptr<IStudioAnimationSystem> m_AnimationSystem; + std::shared_ptr<IActionSystem> m_ActionSystem; + + std::vector<std::shared_ptr<ISignalConnection>> m_Connections; + + TTransactionConsumerPtr m_Consumer; + TSignalItemPtr m_Signaller; + bool m_AggregateOperation; + +public: + CStudioFullSystem(std::shared_ptr<CStudioCoreSystem> inCoreSystem, + Qt3DSDMInstanceHandle inSlideInstance, + Qt3DSDMPropertyHandle inComponentGuidProperty, + Qt3DSDMInstanceHandle inActionInstance, Qt3DSDMPropertyHandle inActionEyeball); + virtual ~CStudioFullSystem(); + + void BeginAggregateOperation() { m_AggregateOperation = true; } + void EndAggregateOperation() { m_AggregateOperation = false; } + + std::shared_ptr<IPropertySystem> GetPropertySystem(); + std::shared_ptr<ISlideSystem> GetSlideSystem(); + std::shared_ptr<ISlideCore> GetSlideCore(); + std::shared_ptr<IAnimationCore> GetAnimationCore(); + std::shared_ptr<IStudioAnimationSystem> GetAnimationSystem(); + std::shared_ptr<IActionCore> GetActionCore(); + std::shared_ptr<IActionSystem> GetActionSystem(); + + std::shared_ptr<IPropertySystem> GetPropertySystem() const; + std::shared_ptr<ISlideSystem> GetSlideSystem() const; + std::shared_ptr<ISlideCore> GetSlideCore() const; + std::shared_ptr<IAnimationCore> GetAnimationCore() const; + std::shared_ptr<IStudioAnimationSystem> GetAnimationSystem() const; + std::shared_ptr<IActionCore> GetActionCore() const; + std::shared_ptr<IActionSystem> GetActionSystem() const; + + // Don't use this unless you are a test harness or some other more-knowledgeable-than-ordinary + // entity. + std::shared_ptr<CStudioCoreSystem> GetCoreSystem(); + + // Ignoring animation and the currently active slide, get the canonical instance property value + // for this instance. + bool GetCanonicalInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const; + Qt3DSDMInstanceHandle FindInstanceByName(Qt3DSDMPropertyHandle inNameProperty, + const TCharStr &inName) const; + + void SetConsumer(TTransactionConsumerPtr inConsumer) override; + TTransactionConsumerPtr GetConsumer() { return m_Consumer; } + + // This signal provider sends signals during undo/redo and during + // animation runs. + IStudioFullSystemSignalProvider *GetSignalProvider(); + + // Return the signal sender so that we can activate/deactivate signals + IStudioFullSystemSignalSender *GetSignalSender(); +}; + +typedef std::shared_ptr<CStudioFullSystem> TStudioFullSystemPtr; +} + +#endif diff --git a/src/dm/systems/StudioPropertySystem.cpp b/src/dm/systems/StudioPropertySystem.cpp new file mode 100644 index 0000000..78fabc6 --- /dev/null +++ b/src/dm/systems/StudioPropertySystem.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "StudioPropertySystem.h" +#include "StudioAnimationSystem.h" +#include "SignalsImpl.h" + +using namespace std; + +namespace qt3dsdm { + +CStudioPropertySystem::CStudioPropertySystem(std::shared_ptr<IMetaData> inMetaData, + TDataCorePtr inDataCore, TSlideSystemPtr inSlideSystem, + TStudioAnimationSystemPtr inStudioAnimationSystem) + : m_MetaData(inMetaData) + , m_DataCore(inDataCore) + , m_SlideSystem(inSlideSystem) + , m_StudioAnimationSystem(inStudioAnimationSystem) +{ + m_PropertyCoreSignaller = CreatePropertyCoreSignaller(); + m_ImmediateModePropertyCoreSignaller = CreatePropertyCoreSignaller(); +} + +DataModelDataType::Value CStudioPropertySystem::GetDataType(Qt3DSDMPropertyHandle inProperty) const +{ + if (m_DataCore->IsProperty(inProperty)) + return m_DataCore->GetProperty(inProperty).m_Type; + return DataModelDataType::None; +} + +TCharStr CStudioPropertySystem::GetName(Qt3DSDMPropertyHandle inProperty) const +{ + if (m_DataCore->IsProperty(inProperty)) + return m_DataCore->GetProperty(inProperty).m_Name; + return TCharStr(); +} + +TCharStr CStudioPropertySystem::GetFormalName(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + if (inInstance.Valid() && inProperty.Valid()) + return m_MetaData->GetFormalName(inInstance, inProperty); + return TCharStr(); +} + +AdditionalMetaDataType::Value +CStudioPropertySystem::GetAdditionalMetaDataType(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + return m_MetaData->GetAdditionalMetaDataType(inInstance, inProperty); +} + +TMetaDataData +CStudioPropertySystem::GetAdditionalMetaDataData(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + return m_MetaData->GetAdditionalMetaDataData(inInstance, inProperty); +} + +Qt3DSDMInstanceHandle CStudioPropertySystem::GetPropertyOwner(Qt3DSDMPropertyHandle inProperty) const +{ + + qt3dsdm::Qt3DSDMPropertyDefinition thePropDef = m_DataCore->GetProperty(inProperty); + return thePropDef.m_Instance; +} + +Qt3DSDMPropertyHandle +CStudioPropertySystem::GetAggregateInstancePropertyByName(Qt3DSDMInstanceHandle inInstance, + const TCharStr &inStr) const +{ + return m_DataCore->GetAggregateInstancePropertyByName(inInstance, inStr); +} + +void CStudioPropertySystem::GetAggregateInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const +{ + m_DataCore->GetAggregateInstanceProperties(inInstance, outProperties); +} + +bool CStudioPropertySystem::HasAggregateInstanceProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + return m_DataCore->HasAggregateInstanceProperty(inInstance, inProperty); +} + +bool ApplyValueAndReturnTrue(const SValue &inValue, SValue &outValue) +{ + outValue = inValue; + return true; +} + +bool CStudioPropertySystem::GetInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + if (!m_DataCore->IsInstance(inInstance)) + return false; + if (!m_DataCore->IsProperty(inProperty)) + return false; + + Qt3DSDMSlideHandle theAnimationSlide; + theAnimationSlide = m_SlideSystem->GetApplicableSlide(inInstance, inProperty); + SValue theTemp; + bool retval = SetDefault(GetDataType(inProperty), theTemp); + if (retval && theAnimationSlide.Valid() + && m_StudioAnimationSystem->GetAnimatedInstancePropertyValue(theAnimationSlide, inInstance, + inProperty, theTemp)) + return ApplyValueAndReturnTrue(theTemp, outValue); + if (theAnimationSlide.Valid() + && m_SlideSystem->GetInstancePropertyValue(theAnimationSlide, inInstance, inProperty, + theTemp)) + return ApplyValueAndReturnTrue(theTemp, outValue); + return m_DataCore->GetInstancePropertyValue(inInstance, inProperty, outValue); +} + +void CStudioPropertySystem::SetInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + m_DataCore->CheckValue(inInstance, inProperty, inValue); + + Qt3DSDMSlideHandle theApplicableSlide; + theApplicableSlide = m_SlideSystem->GetApplicableSlide(inInstance, inProperty); + if (theApplicableSlide.Valid()) { + if (!m_StudioAnimationSystem->SetAnimatedInstancePropertyValue( + theApplicableSlide, inInstance, inProperty, inValue.toOldSkool())) { + // Force set on slide where item exists as it doesn't exist on the root. + m_SlideSystem->ForceSetInstancePropertyValue(theApplicableSlide, inInstance, inProperty, + inValue.toOldSkool()); + } + } else { + m_DataCore->SetInstancePropertyValue(inInstance, inProperty, inValue); + } +} + +Qt3DSDMInstanceHandle CStudioPropertySystem::CreateInstance() +{ + return m_DataCore->CreateInstance(); +} + +void CStudioPropertySystem::GetInstances(TInstanceHandleList &outInstances) const +{ + m_DataCore->GetInstances(outInstances); +} + +void CStudioPropertySystem::DeleteInstance(Qt3DSDMInstanceHandle inHandle) +{ + m_DataCore->DeleteInstance(inHandle); +} + +void CStudioPropertySystem::DeriveInstance(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) +{ + m_DataCore->DeriveInstance(inInstance, inParent); +} + +bool CStudioPropertySystem::IsInstanceOrDerivedFrom(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) const +{ + return m_DataCore->IsInstanceOrDerivedFrom(inInstance, inParent); +} + +QVector<Qt3DSDMPropertyHandle> +CStudioPropertySystem::GetControllableProperties(Qt3DSDMInstanceHandle inInst) const +{ + vector<Qt3DSDMMetaDataPropertyHandle> propList; + QVector<Qt3DSDMPropertyHandle> outList; + m_MetaData->GetMetaDataProperties(inInst, propList); + + for (const auto it : qAsConst(propList)) { + auto metadata = m_MetaData->GetMetaDataPropertyInfo(it).getValue(); + + if ((metadata.m_Controllable + || (metadata.m_Animatable + && m_StudioAnimationSystem->IsPropertyAnimatable(inInst, metadata.m_Property))) + && !metadata.m_IsHidden) { + outList.append(metadata.m_Property); + } + } + return outList; +} + +Qt3DSDMPropertyHandle CStudioPropertySystem::AddProperty(Qt3DSDMInstanceHandle inInstance, + TCharPtr inName, + DataModelDataType::Value inPropType) +{ + return m_DataCore->AddProperty(inInstance, inName, inPropType); +} + +bool CStudioPropertySystem::HandleValid(int inHandle) const +{ + return m_DataCore->HandleValid(inHandle); +} + +bool CStudioPropertySystem::GetCanonicalInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + SValue theTempValue; + if (m_SlideSystem->GetCanonicalInstancePropertyValue(inInstance, inProperty, theTempValue)) { + outValue = SValue(theTempValue); + return true; + } + return m_DataCore->GetInstancePropertyValue(inInstance, inProperty, outValue); +} +} diff --git a/src/dm/systems/StudioPropertySystem.h b/src/dm/systems/StudioPropertySystem.h new file mode 100644 index 0000000..67abcf9 --- /dev/null +++ b/src/dm/systems/StudioPropertySystem.h @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef INSTANCEPROPERTYCORESYSTEMH +#define INSTANCEPROPERTYCORESYSTEMH + +#include "Qt3DSDMSlides.h" +#include "Qt3DSDMAnimation.h" +#include "Qt3DSDMSignals.h" +#include "Qt3DSDMDataCore.h" + +namespace qt3dsdm { + +typedef std::tuple<Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, SValue> TTemporaryPropertyValue; +typedef std::vector<TTemporaryPropertyValue> TTemporaryPropertyValueList; + +/** + * Get/set instance properties taking the slide and slide graph, and animation systems into + *account. + * Also takes care of notifying external entities when a property changes. + */ +class CStudioPropertySystem : public IPropertySystem +{ + std::shared_ptr<IMetaData> m_MetaData; + TDataCorePtr m_DataCore; + + TSlideSystemPtr m_SlideSystem; + TStudioAnimationSystemPtr m_StudioAnimationSystem; + + TSignalItemPtr m_PropertyCoreSignaller; + TSignalItemPtr m_ImmediateModePropertyCoreSignaller; + +public: + CStudioPropertySystem(std::shared_ptr<IMetaData> inMetaData, TDataCorePtr inDataCore, + TSlideSystemPtr inSlideSystem, + TStudioAnimationSystemPtr inStudioAnimationSystem); + + IInstancePropertyCoreSignalProvider *GetPropertyCoreSignalProvider() + { + return dynamic_cast<IInstancePropertyCoreSignalProvider *>(m_PropertyCoreSignaller.get()); + } + // The immediate signaller is used before changes have been committed for very live feedback. + IInstancePropertyCoreSignalProvider *GetImmediatePropertyCoreSignalProvider() + { + return dynamic_cast<IInstancePropertyCoreSignalProvider *>( + m_ImmediateModePropertyCoreSignaller.get()); + } + + IInstancePropertyCoreSignalSender *GetPropertyCoreSignalSender() + { + return dynamic_cast<IInstancePropertyCoreSignalSender *>(m_PropertyCoreSignaller.get()); + } + + DataModelDataType::Value GetDataType(Qt3DSDMPropertyHandle inProperty) const override; + TCharStr GetName(Qt3DSDMPropertyHandle inProperty) const override; + TCharStr GetFormalName(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + virtual AdditionalMetaDataType::Value + GetAdditionalMetaDataType(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + TMetaDataData GetAdditionalMetaDataData(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + Qt3DSDMInstanceHandle GetPropertyOwner(Qt3DSDMPropertyHandle inProperty) const override; + + Qt3DSDMPropertyHandle GetAggregateInstancePropertyByName(Qt3DSDMInstanceHandle inInstance, + const TCharStr &inStr) const override; + void GetAggregateInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const override; + bool HasAggregateInstanceProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + + bool GetInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + void SetInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + + Qt3DSDMInstanceHandle CreateInstance() override; + void GetInstances(TInstanceHandleList &outInstances) const override; + void DeleteInstance(Qt3DSDMInstanceHandle inHandle) override; + + void DeriveInstance(Qt3DSDMInstanceHandle inInstance, Qt3DSDMInstanceHandle inParent) override; + bool IsInstanceOrDerivedFrom(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) const override; + + Qt3DSDMPropertyHandle AddProperty(Qt3DSDMInstanceHandle inInstance, TCharPtr inName, + DataModelDataType::Value inPropType) override; + bool HandleValid(int inHandle) const override; + + // Get the instance property value from the slide that owns the instance or the data core if the + // slide doesn't have the value + bool GetCanonicalInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const; + + QVector<Qt3DSDMPropertyHandle> GetControllableProperties( + Qt3DSDMInstanceHandle inInst) const override; + +private: + static bool DerivedGuidMatches(qt3dsdm::IDataCore &inDataCore, + qt3dsdm::Qt3DSDMInstanceHandle inInstance, + qt3dsdm::Qt3DSDMPropertyHandle inProperty, qt3dsdm::SLong4 inGuid); + CStudioPropertySystem(const CStudioPropertySystem&) = delete; + CStudioPropertySystem& operator=(const CStudioPropertySystem&) = delete; +}; +} + +#endif diff --git a/src/dm/systems/VectorTransactions.h b/src/dm/systems/VectorTransactions.h new file mode 100644 index 0000000..ff1fe2e --- /dev/null +++ b/src/dm/systems/VectorTransactions.h @@ -0,0 +1,235 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef VECTORTRANSACTIONSH +#define VECTORTRANSACTIONSH + +namespace qt3dsdm { +template <typename TItemType> +inline void VecInsert(std::vector<TItemType> &inItems, const TItemType &inItem, size_t inIndex) +{ + inItems.insert(inItems.begin() + inIndex, inItem); +} + +template <typename TItemType> +inline void VecErase(std::vector<TItemType> &inItems, const TItemType &inItem) +{ + erase_if(inItems, std::bind(std::equal_to<TItemType>(), inItem, std::placeholders::_1)); +} + +template <typename TItemType> +inline void VecInsertTransaction(const char *inFile, int inLine, std::vector<TItemType> &inItems, + size_t inIndex, TTransactionConsumerPtr &inConsumer) +{ + TItemType theItem = inItems.at(inIndex); + TTransactionPtr theTransaction(DoCreateGenericTransaction( + inFile, inLine, std::bind(VecInsert<TItemType>, std::ref(inItems), theItem, inIndex), + std::bind(VecErase<TItemType>, std::ref(inItems), theItem))); + inConsumer->OnTransaction(theTransaction); +} + +template <typename TItemType> +inline void VecEraseTransaction(const char *inFile, int inLine, std::vector<TItemType> &inItems, + size_t inIndex, const TItemType &inItem, + TTransactionConsumerPtr &inConsumer) +{ + TTransactionPtr theTransaction(DoCreateGenericTransaction( + inFile, inLine, std::bind(VecErase<TItemType>, std::ref(inItems), inItem), + std::bind(VecInsert<TItemType>, std::ref(inItems), inItem, inIndex))); + inConsumer->OnTransaction(theTransaction); +} + +template <typename TItemType> +inline void CreateVecInsertTransaction(const char *inFile, int inLine, + TTransactionConsumerPtr inConsumer, const TItemType &inItem, + std::vector<TItemType> &inItems) +{ + using namespace std; + size_t theDistance = distance(inItems.begin(), find(inItems.begin(), inItems.end(), inItem)); + RunWithConsumer(inConsumer, std::bind(VecInsertTransaction<TItemType>, inFile, inLine, + std::ref(inItems), theDistance, std::placeholders::_1)); +} + +template <typename TItemType> +inline void CreateVecEraseTransaction(const char *inFile, int inLine, + TTransactionConsumerPtr inConsumer, const TItemType &inItem, + std::vector<TItemType> &inItems) +{ + using namespace std; + size_t theDistance = distance(inItems.begin(), find(inItems.begin(), inItems.end(), inItem)); + RunWithConsumer(inConsumer, + std::bind(VecEraseTransaction<TItemType>, inFile, inLine, std::ref(inItems), + theDistance, std::ref(inItem), std::placeholders::_1)); +} + +template <typename TKeyType, typename TValueType, typename THashType> +struct HashMapAction +{ + std::unordered_map<TKeyType, TValueType, THashType> &m_HashMap; + std::pair<TKeyType, TValueType> m_Value; + + HashMapAction(std::unordered_map<TKeyType, TValueType, THashType> &map, + const std::pair<TKeyType, TValueType> &val) + : m_HashMap(map) + , m_Value(val) + { + } + bool Exists() { return m_HashMap.find(m_Value.first) != m_HashMap.end(); } + void Add() + { + Q_ASSERT(!Exists()); + m_HashMap.insert(m_Value); + } + void Remove() + { + Q_ASSERT(Exists()); + m_HashMap.erase(m_HashMap.find(m_Value.first)); + } +}; + +template <typename TKeyType, typename TValueType, typename THashType> +struct HashMapInsertTransaction : public HashMapAction<TKeyType, TValueType, THashType>, + public ITransaction, + public IMergeableTransaction<TValueType> +{ + typedef HashMapAction<TKeyType, TValueType, THashType> base; + HashMapInsertTransaction(const char *inFile, int inLine, + std::unordered_map<TKeyType, TValueType, THashType> &map, + const std::pair<TKeyType, TValueType> &val) + : HashMapAction<TKeyType, TValueType, THashType>(map, val) + , ITransaction(inFile, inLine) + { + } + void Do() override { base::Add(); } + void Undo() override { base::Remove(); } + void Update(const TValueType &inValue) override { base::m_Value.second = inValue; } +}; + +template <typename TKeyType, typename TValueType, typename THashType> +struct HashMapEraseTransaction : public HashMapAction<TKeyType, TValueType, THashType>, + public ITransaction +{ + typedef HashMapAction<TKeyType, TValueType, THashType> base; + HashMapEraseTransaction(const char *inFile, int inLine, + std::unordered_map<TKeyType, TValueType, THashType> &map, + const std::pair<TKeyType, TValueType> &val) + : HashMapAction<TKeyType, TValueType, THashType>(map, val) + , ITransaction(inFile, inLine) + { + } + void Do() override { base::Remove(); } + void Undo() override { base::Add(); } +}; + +template <typename TKeyType, typename TValueType, typename THashType> +inline std::shared_ptr<IMergeableTransaction<TValueType>> +CreateHashMapInsertTransaction(const char *inFile, int inLine, TTransactionConsumerPtr inConsumer, + const std::pair<TKeyType, TValueType> &inItem, + std::unordered_map<TKeyType, TValueType, THashType> &inItems) +{ + using namespace std; + std::shared_ptr<IMergeableTransaction<TValueType>> retval; + if (inConsumer) { + std::shared_ptr<HashMapInsertTransaction<TKeyType, TValueType, THashType>> transaction( + std::make_shared<HashMapInsertTransaction<TKeyType, TValueType, THashType>>( + inFile, inLine, std::ref(inItems), std::cref(inItem))); + retval = static_pointer_cast<IMergeableTransaction<TValueType>>(transaction); + inConsumer->OnTransaction(static_pointer_cast<ITransaction>(transaction)); + } + return retval; +} + +template <typename TKeyType, typename TValueType, typename THashType> +inline void +CreateHashMapEraseTransaction(const char *inFile, int inLine, TTransactionConsumerPtr inConsumer, + const std::pair<TKeyType, TValueType> &inItem, + std::unordered_map<TKeyType, TValueType, THashType> &inItems) +{ + using namespace std; + if (inConsumer) + inConsumer->OnTransaction(static_pointer_cast<ITransaction>( + std::make_shared<HashMapEraseTransaction<TKeyType, TValueType, THashType>>( + inFile, inLine, std::ref(inItems), std::cref(inItem)))); +} + +template <typename TKeyType, typename TValueType, typename THashType> +struct HashMapSwapTransaction : public ITransaction, public IMergeableTransaction<TValueType> +{ + typedef std::unordered_map<TKeyType, TValueType, THashType> TMapType; + + TMapType &m_HashMap; + TKeyType m_Key; + TValueType m_OldValue; + TValueType m_NewValue; + + HashMapSwapTransaction(const char *inFile, int inLine, TMapType &inMap, const TKeyType &inKey, + const TValueType &inOldVal, const TValueType &inNewVal) + : ITransaction(inFile, inLine) + , m_HashMap(inMap) + , m_Key(inKey) + , m_OldValue(inOldVal) + , m_NewValue(inNewVal) + { + } + + bool Exists() { return m_HashMap.find(m_Key) != m_HashMap.end(); } + void SetValue(const TValueType &inVal) + { + typename TMapType::iterator find(m_HashMap.find(m_Key)); + if (find != m_HashMap.end()) + find->second = inVal; + else + m_HashMap.insert(std::make_pair(m_Key, inVal)); + } + void Do() override { SetValue(m_NewValue); } + void Undo() override { SetValue(m_OldValue); } + void Update(const TValueType &inValue) override { m_NewValue = inValue; } +}; + +template <typename TKeyType, typename TValueType, typename THashType> +inline std::shared_ptr<IMergeableTransaction<TValueType>> +CreateHashMapSwapTransaction(const char *inFile, int inLine, TTransactionConsumerPtr inConsumer, + const TKeyType &inKey, const TValueType &inOldValue, + const TValueType &inNewValue, + std::unordered_map<TKeyType, TValueType, THashType> &inItems) +{ + using namespace std; + std::shared_ptr<IMergeableTransaction<TValueType>> retval; + if (inConsumer) { + std::shared_ptr<HashMapSwapTransaction<TKeyType, TValueType, THashType>> transaction = + std::make_shared<HashMapSwapTransaction<TKeyType, TValueType, THashType>>( + inFile, inLine, std::ref(inItems), inKey, inOldValue, inNewValue); + retval = static_pointer_cast<IMergeableTransaction<TValueType>>(transaction); + inConsumer->OnTransaction(static_pointer_cast<ITransaction>(transaction)); + } + return retval; +} +} + +#endif diff --git a/src/dm/systems/cores/ActionCoreProducer.cpp b/src/dm/systems/cores/ActionCoreProducer.cpp new file mode 100644 index 0000000..c262c23 --- /dev/null +++ b/src/dm/systems/cores/ActionCoreProducer.cpp @@ -0,0 +1,289 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "ActionCoreProducer.h" +#include "HandleSystemTransactions.h" +#include "VectorTransactions.h" +#include "SignalsImpl.h" + +using namespace std; + +namespace qt3dsdm { + +Qt3DSDMActionHandle CActionCoreProducer::CreateAction(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner, + SLong4 inTriggerTargetObjects) +{ + Qt3DSDMActionHandle retval = + m_Data->CreateAction(inInstance, inSlide, inOwner, inTriggerTargetObjects); + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + return retval; +} + +void CActionCoreProducer::DeleteAction(Qt3DSDMActionHandle inAction, + Qt3DSDMInstanceHandle &outInstance) +{ + // Ensure action exists + SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects); + CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inAction, m_Data->m_Objects); + do_all(theAction->m_ActionInfo.m_HandlerArgs, + std::bind(DoCreateHandleDeleteTransaction, __FILE__, __LINE__, m_Consumer, + std::placeholders::_1, std::ref(m_Data->m_Objects))); + m_Data->DeleteAction(inAction, outInstance); +} + +const SActionInfo &CActionCoreProducer::GetActionInfo(Qt3DSDMActionHandle inAction) const +{ + return m_Data->GetActionInfo(inAction); +} + +void CActionCoreProducer::GetActions(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const +{ + return m_Data->GetActions(inSlide, inOwner, outActions); +} + +void CActionCoreProducer::GetActions(Qt3DSDMSlideHandle inSlide, TActionHandleList &outActions) const +{ + return m_Data->GetActions(inSlide, outActions); +} + +void CActionCoreProducer::GetActions(Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const +{ + return m_Data->GetActions(inOwner, outActions); +} + +void CActionCoreProducer::GetActions(TActionHandleList &outActions) const +{ + return m_Data->GetActions(outActions); +} + +Qt3DSDMInstanceHandle CActionCoreProducer::GetActionInstance(Qt3DSDMActionHandle inAction) const +{ + return m_Data->GetActionInstance(inAction); +} + +Qt3DSDMActionHandle +CActionCoreProducer::GetActionByInstance(Qt3DSDMInstanceHandle inActionInstance) const +{ + return m_Data->GetActionByInstance(inActionInstance); +} + +void CActionCoreProducer::SetTriggerObject(Qt3DSDMActionHandle inAction, + const SObjectRefType &inTriggerObject) +{ + SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects); + if (m_Consumer) { + m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION( + std::bind(&CSimpleActionCore::SetTriggerObject, m_Data, inAction, inTriggerObject), + std::bind(&CSimpleActionCore::SetTriggerObject, m_Data, inAction, + theAction->m_ActionInfo.m_TriggerObject)))); + } + m_Data->SetTriggerObject(inAction, inTriggerObject); + GetSignalSender()->SendTriggerObjectSet(inAction, theAction->m_ActionInfo.m_TriggerObject); +} + +void CActionCoreProducer::SetTargetObject(Qt3DSDMActionHandle inAction, + const SObjectRefType &inTargetObject) +{ + SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects); + if (m_Consumer) { + m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION( + std::bind(&CSimpleActionCore::SetTargetObject, m_Data, inAction, inTargetObject), + std::bind(&CSimpleActionCore::SetTargetObject, m_Data, inAction, + theAction->m_ActionInfo.m_TargetObject)))); + } + m_Data->SetTargetObject(inAction, inTargetObject); + GetSignalSender()->SendTargetObjectSet(inAction, theAction->m_ActionInfo.m_TargetObject); +} + +void CActionCoreProducer::SetEvent(Qt3DSDMActionHandle inAction, const wstring &inEventHandle) +{ + SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects); + if (m_Consumer) { + m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION( + std::bind(&CSimpleActionCore::SetEvent, m_Data, inAction, inEventHandle), + std::bind(&CSimpleActionCore::SetEvent, m_Data, inAction, + theAction->m_ActionInfo.m_Event)))); + } + m_Data->SetEvent(inAction, inEventHandle); + GetSignalSender()->SendEventSet(inAction, inEventHandle); +} + +void CActionCoreProducer::SetHandler(Qt3DSDMActionHandle inAction, const wstring &inHandlerHandle) +{ + SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects); + if (m_Consumer) { + m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION( + std::bind(&CSimpleActionCore::SetHandler, m_Data, inAction, inHandlerHandle), + std::bind(&CSimpleActionCore::SetHandler, m_Data, inAction, + theAction->m_ActionInfo.m_Handler)))); + } + m_Data->SetHandler(inAction, inHandlerHandle); + GetSignalSender()->SendHandlerSet(inAction, inHandlerHandle); +} + +Qt3DSDMHandlerArgHandle CActionCoreProducer::AddHandlerArgument(Qt3DSDMActionHandle inAction, + const TCharStr &inName, + HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) +{ + Qt3DSDMHandlerArgHandle retval = + m_Data->AddHandlerArgument(inAction, inName, inArgType, inValueType); + SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects); + CreateVecInsertTransaction<Qt3DSDMHandlerArgHandle>(__FILE__, __LINE__, m_Consumer, retval, + theAction->m_ActionInfo.m_HandlerArgs); + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + GetSignalSender()->SendHandlerArgumentAdded(inAction, retval, inName, inArgType, inValueType); + return retval; +} + +void CActionCoreProducer::RemoveHandlerArgument(Qt3DSDMHandlerArgHandle inHandlerArgument) +{ + SHandlerArgument *theHandlerArgument = + CSimpleActionCore::GetHandlerArgumentNF(inHandlerArgument, m_Data->m_Objects); + SAction *theAction = CSimpleActionCore::GetActionNF( + theHandlerArgument->m_HandlerArgInfo.m_Action, m_Data->m_Objects); + if (exists(theAction->m_ActionInfo.m_HandlerArgs, + std::bind(equal_to<Qt3DSDMHandlerArgHandle>(), inHandlerArgument, + std::placeholders::_1))) { + CreateVecEraseTransaction<Qt3DSDMHandlerArgHandle>(__FILE__, __LINE__, m_Consumer, + inHandlerArgument, + theAction->m_ActionInfo.m_HandlerArgs); + CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inHandlerArgument, m_Data->m_Objects); + } + m_Data->RemoveHandlerArgument(inHandlerArgument); + GetSignalSender()->SendHandlerArgumentRemoved(theAction->m_Handle, theHandlerArgument->m_Handle, + theHandlerArgument->m_HandlerArgInfo.m_Name, + theHandlerArgument->m_HandlerArgInfo.m_ArgType, + theHandlerArgument->m_HandlerArgInfo.m_ValueType); +} + +const SHandlerArgumentInfo & +CActionCoreProducer::GetHandlerArgumentInfo(Qt3DSDMHandlerArgHandle inHandlerArgument) const +{ + return m_Data->GetHandlerArgumentInfo(inHandlerArgument); +} + +void CActionCoreProducer::GetHandlerArguments(Qt3DSDMActionHandle inAction, + THandlerArgHandleList &outHandlerArguments) const +{ + return m_Data->GetHandlerArguments(inAction, outHandlerArguments); +} + +void CActionCoreProducer::GetHandlerArgumentValue(Qt3DSDMHandlerArgHandle inHandlerArgument, + SValue &outValue) const +{ + return m_Data->GetHandlerArgumentValue(inHandlerArgument, outValue); +} + +void CActionCoreProducer::SetHandlerArgumentValue(Qt3DSDMHandlerArgHandle inHandlerArgument, + const SValue &inValue) +{ + SHandlerArgument *theHandlerArgument = + CSimpleActionCore::GetHandlerArgumentNF(inHandlerArgument, m_Data->m_Objects); + if (m_Consumer) { + m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION( + std::bind(&CSimpleActionCore::SetHandlerArgumentValue, m_Data, inHandlerArgument, + inValue), + std::bind(&CSimpleActionCore::SetHandlerArgumentValue, m_Data, inHandlerArgument, + theHandlerArgument->m_HandlerArgInfo.m_Value)))); + } + m_Data->SetHandlerArgumentValue(inHandlerArgument, inValue); + GetSignalSender()->SendHandlerArgumentValueSet(inHandlerArgument, inValue); +} + +// CHandleBase +bool CActionCoreProducer::HandleValid(int inHandle) const +{ + return m_Data->HandleValid(inHandle); +} + +// ITransactionProducer implementation +void CActionCoreProducer::SetConsumer(TTransactionConsumerPtr inConsumer) +{ + m_Consumer = inConsumer; +} + +TSignalConnectionPtr CActionCoreProducer::ConnectTriggerObjectSet( + const std::function<void(Qt3DSDMActionHandle, SObjectRefType &)> &inCallback) +{ + return GetSignalProvider()->ConnectTriggerObjectSet(inCallback); +} +TSignalConnectionPtr CActionCoreProducer::ConnectTargetObjectSet( + const std::function<void(Qt3DSDMActionHandle, SObjectRefType &)> &inCallback) +{ + return GetSignalProvider()->ConnectTargetObjectSet(inCallback); +} +TSignalConnectionPtr CActionCoreProducer::ConnectEventSet( + const std::function<void(Qt3DSDMActionHandle, const wstring &)> &inCallback) +{ + return GetSignalProvider()->ConnectEventSet(inCallback); +} +TSignalConnectionPtr CActionCoreProducer::ConnectHandlerSet( + const std::function<void(Qt3DSDMActionHandle, const wstring &)> &inCallback) +{ + return GetSignalProvider()->ConnectHandlerSet(inCallback); +} + +TSignalConnectionPtr CActionCoreProducer::ConnectHandlerArgumentAdded( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) +{ + return GetSignalProvider()->ConnectHandlerArgumentAdded(inCallback); +} +TSignalConnectionPtr CActionCoreProducer::ConnectHandlerArgumentRemoved( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) +{ + return GetSignalProvider()->ConnectHandlerArgumentRemoved(inCallback); +} +TSignalConnectionPtr CActionCoreProducer::ConnectHandlerArgumentValueSet( + const std::function<void(Qt3DSDMHandlerArgHandle, const SValue &)> &inCallback) +{ + return GetSignalProvider()->ConnectHandlerArgumentValueSet(inCallback); +} + +void CActionCoreProducer::InitSignaller() +{ + m_Signaller = CreateActionCoreSignaller(); +} + +IActionCoreSignalProvider *CActionCoreProducer::GetSignalProvider() +{ + return dynamic_cast<IActionCoreSignalProvider *>(m_Signaller.get()); +} + +IActionCoreSignalSender *CActionCoreProducer::GetSignalSender() +{ + return dynamic_cast<IActionCoreSignalSender *>(m_Signaller.get()); +} +} diff --git a/src/dm/systems/cores/ActionCoreProducer.h b/src/dm/systems/cores/ActionCoreProducer.h new file mode 100644 index 0000000..bf65a38 --- /dev/null +++ b/src/dm/systems/cores/ActionCoreProducer.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef ACTIONCOREPRODUCERH +#define ACTIONCOREPRODUCERH + +#include "SimpleActionCore.h" +#include "Qt3DSDMTransactions.h" +#include "Qt3DSDMSignals.h" +#include "Qt3DSDMStringTable.h" + +namespace qt3dsdm { +class CActionCoreProducer : public IActionCore, + public ITransactionProducer, + public IActionCoreSignalProvider +{ + Q_DISABLE_COPY(CActionCoreProducer) + + TSimpleActionCorePtr m_Data; + TTransactionConsumerPtr m_Consumer; + TSignalItemPtr m_Signaller; + +public: + CActionCoreProducer(TStringTablePtr inStringTable) + : m_Data(new CSimpleActionCore(inStringTable)) + { + InitSignaller(); + } + + TSimpleActionCorePtr GetTransactionlessActionCore() const { return m_Data; } + + // IActionCore implementation + IStringTable &GetStringTable() const override { return m_Data->GetStringTable(); } + TStringTablePtr GetStringTablePtr() const override { return m_Data->GetStringTablePtr(); } + // Action + Qt3DSDMActionHandle CreateAction(Qt3DSDMInstanceHandle inInstance, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner, SLong4 inTriggerTargetObjects) override; + void DeleteAction(Qt3DSDMActionHandle inAction, Qt3DSDMInstanceHandle &outInstance) override; + const SActionInfo &GetActionInfo(Qt3DSDMActionHandle inAction) const override; + void GetActions(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const override; + void GetActions(Qt3DSDMSlideHandle inSlide, TActionHandleList &outActions) const override; + void GetActions(Qt3DSDMInstanceHandle inOwner, TActionHandleList &outActions) const override; + void GetActions(TActionHandleList &outActions) const override; + Qt3DSDMInstanceHandle GetActionInstance(Qt3DSDMActionHandle inAction) const override; + Qt3DSDMActionHandle GetActionByInstance(Qt3DSDMInstanceHandle inActionInstance) const override; + + // Action Properties + void SetTriggerObject(Qt3DSDMActionHandle inAction, const SObjectRefType &inTriggerObject) override; + void SetTargetObject(Qt3DSDMActionHandle inAction, const SObjectRefType &inTargetObject) override; + void SetEvent(Qt3DSDMActionHandle inAction, const wstring &inEventHandle) override; + void SetHandler(Qt3DSDMActionHandle inAction, const wstring &inHandlerHandle) override; + + // Action Argument + Qt3DSDMHandlerArgHandle AddHandlerArgument(Qt3DSDMActionHandle inAction, const TCharStr &inName, + HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) override; + void RemoveHandlerArgument(Qt3DSDMHandlerArgHandle inHandlerArgument) override; + const SHandlerArgumentInfo & + GetHandlerArgumentInfo(Qt3DSDMHandlerArgHandle inHandlerArgument) const override; + void GetHandlerArguments(Qt3DSDMActionHandle inAction, + THandlerArgHandleList &outHandlerArguments) const override; + + // Action Argument Properties + void GetHandlerArgumentValue(Qt3DSDMHandlerArgHandle inHandlerArgument, SValue &outValue) const override; + void SetHandlerArgumentValue(Qt3DSDMHandlerArgHandle inHandlerArgument, const SValue &inValue) override; + + // CHandleBase + bool HandleValid(int inHandle) const override; + + // ITransactionProducer implementation + void SetConsumer(TTransactionConsumerPtr inConsumer) override; + + TSignalConnectionPtr ConnectTriggerObjectSet( + const std::function<void(Qt3DSDMActionHandle, SObjectRefType &)> &inCallback) override; + TSignalConnectionPtr ConnectTargetObjectSet( + const std::function<void(Qt3DSDMActionHandle, SObjectRefType &)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectEventSet(const std::function<void(Qt3DSDMActionHandle, const wstring &)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectHandlerSet(const std::function<void(Qt3DSDMActionHandle, const wstring &)> &inCallback) override; + + TSignalConnectionPtr ConnectHandlerArgumentAdded( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) override; + TSignalConnectionPtr ConnectHandlerArgumentRemoved( + const std::function<void(Qt3DSDMActionHandle, Qt3DSDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) override; + TSignalConnectionPtr ConnectHandlerArgumentValueSet( + const std::function<void(Qt3DSDMHandlerArgHandle, const SValue &)> &inCallback) override; + +private: + void InitSignaller(); + IActionCoreSignalProvider *GetSignalProvider(); + IActionCoreSignalSender *GetSignalSender(); +}; +} + +#endif diff --git a/src/dm/systems/cores/AnimationCoreProducer.cpp b/src/dm/systems/cores/AnimationCoreProducer.cpp new file mode 100644 index 0000000..14d1824 --- /dev/null +++ b/src/dm/systems/cores/AnimationCoreProducer.cpp @@ -0,0 +1,488 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "AnimationCoreProducer.h" +#include "HandleSystemTransactions.h" +#include "VectorTransactions.h" +#include "SignalsImpl.h" +#ifdef _WIN32 +#pragma warning(disable : 4512) // assignment operator not generated +#endif + +using namespace std; + +namespace qt3dsdm { + +struct SArtistEditedUndoRedoScope +{ + TSimpleAnimationCorePtr m_AnimationCore; + Qt3DSDMAnimationHandle m_Animation; + TTransactionConsumerPtr m_Consumer; + bool m_ArtistEdited; + SArtistEditedUndoRedoScope(TSimpleAnimationCorePtr inAnimCore, Qt3DSDMAnimationHandle inAnim, + TTransactionConsumerPtr inConsumer) + : m_AnimationCore(inAnimCore) + , m_Animation(inAnim) + , m_Consumer(inConsumer) + , m_ArtistEdited(inAnimCore->IsArtistEdited(inAnim)) + { + } + ~SArtistEditedUndoRedoScope() + { + bool edited = m_AnimationCore->IsArtistEdited(m_Animation); + if (m_Consumer && edited != m_ArtistEdited) { + m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION( + std::bind(&CSimpleAnimationCore::SetIsArtistEdited, m_AnimationCore, m_Animation, + edited), + std::bind(&CSimpleAnimationCore::SetIsArtistEdited, m_AnimationCore, m_Animation, + m_ArtistEdited)))); + } + } +}; + +struct SLookupCacheDoUndoOp : public ITransaction +{ + std::shared_ptr<SAnimationTrack> m_Animation; + TSimpleAnimationCorePtr m_AnimationCore; + bool m_AddOnDo; + SLookupCacheDoUndoOp(const char *inFile, int inLine, Qt3DSDMAnimationHandle inAnimHandle, + TSimpleAnimationCorePtr inCore, bool addOnDo) + : ITransaction(inFile, inLine) + , m_AnimationCore(inCore) + , m_AddOnDo(addOnDo) + { + THandleObjectMap::const_iterator theIter(inCore->m_Objects.find(inAnimHandle)); + if (theIter != inCore->m_Objects.end()) + m_Animation = static_pointer_cast<SAnimationTrack>(theIter->second); + } + void Remove() + { + if (m_Animation) + m_AnimationCore->RemoveAnimationFromLookupCache(m_Animation); + } + void Add() + { + if (m_Animation) + m_AnimationCore->AddAnimationToLookupCache(m_Animation); + } + void Do() override + { + if (m_AddOnDo) + Add(); + else + Remove(); + } + void Undo() override + { + if (m_AddOnDo) + Remove(); + else + Add(); + } +}; + +Qt3DSDMAnimationHandle +CAnimationCoreProducer::CreateAnimation(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType, bool inFirstKeyframeDynamic) +{ + Qt3DSDMAnimationHandle retval = m_Data->CreateAnimation(inSlide, inInstance, inProperty, inIndex, + inAnimationType, inFirstKeyframeDynamic); + + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + if (m_Consumer) + m_Consumer->OnTransaction( + std::make_shared<SLookupCacheDoUndoOp>(__FILE__, __LINE__, retval, m_Data, true)); + GetSignalSender()->SendAnimationCreated(retval, inSlide, inInstance, inProperty, inIndex, + inAnimationType); + return retval; +} + +void CAnimationCoreProducer::DeleteAnimation(Qt3DSDMAnimationHandle inAnimation) +{ + // Ensure animation exists + SAnimationTrack *theAnimation = + CSimpleAnimationCore::GetAnimationNF(inAnimation, m_Data->m_Objects); + GetSignalSender()->SendBeforeAnimationDeleted(inAnimation); + if (m_Consumer) + m_Consumer->OnTransaction(std::make_shared<SLookupCacheDoUndoOp>( + __FILE__, __LINE__, inAnimation, m_Data, false)); + CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inAnimation, m_Data->m_Objects); + do_all(theAnimation->m_Keyframes, + std::bind(DoCreateHandleDeleteTransaction, __FILE__, __LINE__, m_Consumer, + std::placeholders::_1, std::ref(m_Data->m_Objects))); + SAnimationInfo theInfo = m_Data->GetAnimationInfo(inAnimation); + m_Data->DeleteAnimation(inAnimation); + GetSignalSender()->SendAnimationDeleted(inAnimation, theInfo.m_Slide, theInfo.m_Instance, + theInfo.m_Property, theInfo.m_Index, + theInfo.m_AnimationType); +} + +Qt3DSDMAnimationHandle CAnimationCoreProducer::GetAnimation(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + size_t inIndex) const +{ + return m_Data->GetAnimation(inSlide, inInstance, inProperty, inIndex); +} + +SAnimationInfo CAnimationCoreProducer::GetAnimationInfo(Qt3DSDMAnimationHandle inAnimation) const +{ + return m_Data->GetAnimationInfo(inAnimation); +} + +void CAnimationCoreProducer::GetAnimations(TAnimationHandleList &outAnimations) const +{ + return m_Data->GetAnimations(outAnimations); +} + +void CAnimationCoreProducer::GetAnimations(TAnimationInfoList &outAnimations, + Qt3DSDMSlideHandle inMaster, + Qt3DSDMSlideHandle inSlide) const +{ + return m_Data->GetAnimations(outAnimations, inMaster, inSlide); +} + +void CAnimationCoreProducer::SetFirstKeyframeDynamic(Qt3DSDMAnimationHandle inAnimation, + bool inValue) +{ + SAnimationInfo theInfo(m_Data->GetAnimationInfo(inAnimation)); + SArtistEditedUndoRedoScope __editedScope(m_Data, inAnimation, m_Consumer); + if (m_Consumer) { + m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION( + std::bind(&CSimpleAnimationCore::SetFirstKeyframeDynamic, m_Data, inAnimation, + inValue), + std::bind(&CSimpleAnimationCore::SetFirstKeyframeDynamic, m_Data, inAnimation, + theInfo.m_DynamicFirstKeyframe)))); + } + m_Data->SetFirstKeyframeDynamic(inAnimation, inValue); + GetSignalSender()->SendFirstKeyframeDynamicSet(inAnimation, inValue); +} + +inline void DirtyKeyframes(Qt3DSDMAnimationHandle inAnimation, THandleObjectMap &inObjects) +{ + SAnimationTrack *theAnimation = CSimpleAnimationCore::GetAnimationNF(inAnimation, inObjects); + theAnimation->m_KeyframesDirty = true; +} + +inline void CreateDirtyKeyframesTransaction(TTransactionConsumerPtr inConsumer, + Qt3DSDMAnimationHandle inAnimation, + THandleObjectMap &inObjects) +{ + if (inConsumer) { + inConsumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION( + std::bind(DirtyKeyframes, inAnimation, std::ref(inObjects)), + std::bind(DirtyKeyframes, inAnimation, std::ref(inObjects))))); + } +} + +Qt3DSDMKeyframeHandle CAnimationCoreProducer::InsertKeyframe(Qt3DSDMAnimationHandle inAnimation, + const TKeyframe &inKeyframe) +{ + SArtistEditedUndoRedoScope __editedScope(m_Data, inAnimation, m_Consumer); + Qt3DSDMKeyframeHandle retval = m_Data->InsertKeyframe(inAnimation, inKeyframe); + SAnimationTrack *theAnimation = + CSimpleAnimationCore::GetAnimationNF(inAnimation, m_Data->m_Objects); + CreateVecInsertTransaction<Qt3DSDMKeyframeHandle>(__FILE__, __LINE__, m_Consumer, retval, + theAnimation->m_Keyframes); + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + CreateDirtyKeyframesTransaction(m_Consumer, inAnimation, m_Data->m_Objects); + GetSignalSender()->SendKeyframeInserted(inAnimation, retval, inKeyframe); + return retval; +} + +void CAnimationCoreProducer::EraseKeyframe(Qt3DSDMKeyframeHandle inKeyframe) +{ + SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, m_Data->m_Objects); + SArtistEditedUndoRedoScope __editedScope(m_Data, theKeyframe->m_Animation, m_Consumer); + GetSignalSender()->SendBeforeKeyframeErased(inKeyframe); + SAnimationTrack *theAnimation = + CSimpleAnimationCore::GetAnimationNF(theKeyframe->m_Animation, m_Data->m_Objects); + if (exists(theAnimation->m_Keyframes, std::bind(equal_to<int>(), inKeyframe, + std::placeholders::_1))) { + CreateVecEraseTransaction<Qt3DSDMKeyframeHandle>(__FILE__, __LINE__, m_Consumer, inKeyframe, + theAnimation->m_Keyframes); + CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inKeyframe, m_Data->m_Objects); + CreateDirtyKeyframesTransaction(m_Consumer, theKeyframe->m_Animation, m_Data->m_Objects); + } + int theKeyframeHandle = theKeyframe->m_Handle; + TKeyframe theData = theKeyframe->m_Keyframe; + m_Data->EraseKeyframe(inKeyframe); + GetSignalSender()->SendKeyframeErased(theAnimation->m_Handle, theKeyframeHandle, theData); +} + +template <typename TDataType> +struct VectorSwapTransaction : public ITransaction +{ + vector<TDataType> m_Data; + vector<TDataType> &m_Target; + VectorSwapTransaction(const char *inFile, int inLine, vector<TDataType> &inTarget) + : ITransaction(inFile, inLine) + , m_Data(inTarget) + , m_Target(inTarget) + { + } + void Do() override { std::swap(m_Data, m_Target); } + void Undo() override { Do(); } +}; + +void CAnimationCoreProducer::DeleteAllKeyframes(Qt3DSDMAnimationHandle inAnimation) +{ + // Ensure animation exists + SAnimationTrack *theAnimation = + CSimpleAnimationCore::GetAnimationNF(inAnimation, m_Data->m_Objects); + SArtistEditedUndoRedoScope __editedScope(m_Data, inAnimation, m_Consumer); + GetSignalSender()->SendBeforeAllKeyframesErased(inAnimation); + do_all(theAnimation->m_Keyframes, + std::bind(DoCreateHandleDeleteTransaction, __FILE__, __LINE__, m_Consumer, + std::placeholders::_1, std::ref(m_Data->m_Objects))); + if (m_Consumer) + m_Consumer->OnTransaction(std::make_shared<VectorSwapTransaction<Qt3DSDMKeyframeHandle>>( + __FILE__, __LINE__, std::ref(theAnimation->m_Keyframes))); + theAnimation->m_Keyframes.clear(); +} + +Qt3DSDMAnimationHandle +CAnimationCoreProducer::GetAnimationForKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const +{ + return m_Data->GetAnimationForKeyframe(inKeyframe); +} + +struct KeyframeDataTransaction : public ITransaction, public IMergeableTransaction<TKeyframe> +{ + TSimpleAnimationCorePtr m_AnimationCore; + Qt3DSDMKeyframeHandle m_Keyframe; + TKeyframe m_OldData; + TKeyframe m_NewData; + + KeyframeDataTransaction(const char *inFile, int inLine, TSimpleAnimationCorePtr animCore, + Qt3DSDMKeyframeHandle keyframe, TKeyframe oldData, TKeyframe newData) + : ITransaction(inFile, inLine) + , m_AnimationCore(animCore) + , m_Keyframe(keyframe) + , m_OldData(oldData) + , m_NewData(newData) + { + } + + void Do() override { m_AnimationCore->DoSetKeyframeData(m_Keyframe, m_NewData); } + void Undo() override { m_AnimationCore->DoSetKeyframeData(m_Keyframe, m_OldData); } + + void Update(const TKeyframe &inKeyframe) override { m_NewData = inKeyframe; } +}; + +void CAnimationCoreProducer::SetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe, + const TKeyframe &inData) +{ + SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, m_Data->m_Objects); + SArtistEditedUndoRedoScope __editedScope(m_Data, theKeyframe->m_Animation, m_Consumer); + TKeyframe theNewData(inData); + TKeyframe theOldData = theKeyframe->m_Keyframe; + m_Data->SetKeyframeData(inKeyframe, inData); + TKeyframeDataMergeMap::iterator iter(m_KeyframeMergeMap.find(inKeyframe)); + if (iter != m_KeyframeMergeMap.end()) + iter->second->Update(theNewData); + else { + if (m_Consumer) { + std::shared_ptr<KeyframeDataTransaction> theKeyframeTransaction( + std::make_shared<KeyframeDataTransaction>(__FILE__, __LINE__, m_Data, inKeyframe, + theOldData, theNewData)); + m_Consumer->OnTransaction(static_pointer_cast<ITransaction>(theKeyframeTransaction)); + m_KeyframeMergeMap.insert(make_pair( + inKeyframe, + static_pointer_cast<IMergeableTransaction<TKeyframe>>(theKeyframeTransaction))); + } + GetSignalSender()->SendKeyframeUpdated(inKeyframe, inData); + } +} + +TKeyframe CAnimationCoreProducer::GetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe) const +{ + return m_Data->GetKeyframeData(inKeyframe); +} + +void CAnimationCoreProducer::GetKeyframes(Qt3DSDMAnimationHandle inAnimation, + TKeyframeHandleList &outKeyframes) const +{ + return m_Data->GetKeyframes(inAnimation, outKeyframes); +} + +size_t CAnimationCoreProducer::GetKeyframeCount(Qt3DSDMAnimationHandle inAnimation) const +{ + return m_Data->GetKeyframeCount(inAnimation); +} + +void CAnimationCoreProducer::OffsetAnimations(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + long inMillisecondOffset) +{ + float theOffsetSeconds = static_cast<float>(inMillisecondOffset) / 1000.f; + for (THandleObjectMap::const_iterator iter = m_Data->m_Objects.begin(), + end = m_Data->m_Objects.end(); + iter != end; ++iter) { + SAnimationTrack *theTrack = static_cast<SAnimationTrack *>(iter->second.get()); + if (theTrack->m_Slide == inSlide && theTrack->m_Instance == inInstance) { + for (size_t keyframeIdx = 0, keyframeEnd = theTrack->m_Keyframes.size(); + keyframeIdx < keyframeEnd; ++keyframeIdx) { + Qt3DSDMKeyframeHandle theKeyframeHandle(theTrack->m_Keyframes[keyframeIdx]); + TKeyframe theCurrentKeyframe = m_Data->GetKeyframeData(theKeyframeHandle); + + float seconds = qt3dsdm::GetKeyframeSeconds(theCurrentKeyframe); + + theCurrentKeyframe = + qt3dsdm::SetKeyframeSeconds(theCurrentKeyframe, seconds + theOffsetSeconds); + + SetKeyframeData(theKeyframeHandle, theCurrentKeyframe); + } + } + } +} + +void CAnimationCoreProducer::SetIsArtistEdited(Qt3DSDMAnimationHandle inAnimation, bool inEdited) +{ + SArtistEditedUndoRedoScope __editedScope(m_Data, inAnimation, m_Consumer); + m_Data->SetIsArtistEdited(inAnimation, inEdited); +} + +bool CAnimationCoreProducer::IsArtistEdited(Qt3DSDMAnimationHandle inAnimation) const +{ + return m_Data->IsArtistEdited(inAnimation); +} +// Animation Evaluation. +float CAnimationCoreProducer::EvaluateAnimation(Qt3DSDMAnimationHandle inAnimation, + float inSeconds) const +{ + return m_Data->EvaluateAnimation(inAnimation, inSeconds); +} + +bool CAnimationCoreProducer::KeyframeValid(Qt3DSDMKeyframeHandle inKeyframe) const +{ + return m_Data->KeyframeValid(inKeyframe); +} + +bool CAnimationCoreProducer::AnimationValid(Qt3DSDMAnimationHandle inAnimation) const +{ + return m_Data->AnimationValid(inAnimation); +} + +void CAnimationCoreProducer::CopyAnimations(Qt3DSDMSlideHandle inSourceSlide, + Qt3DSDMInstanceHandle inSourceInstance, + Qt3DSDMSlideHandle inDestSlide, + Qt3DSDMInstanceHandle inDestInstance) +{ + std::vector<SAnimationTrack *> theAnimations; + for (THandleObjectMap::const_iterator iter = m_Data->m_Objects.begin(), + end = m_Data->m_Objects.end(); + iter != end; ++iter) { + SAnimationTrack *theTrack = static_cast<SAnimationTrack *>(iter->second.get()); + if (theTrack->m_Instance == inSourceInstance && theTrack->m_Slide == inSourceSlide) + theAnimations.push_back(theTrack); + } + for (size_t idx = 0, end = theAnimations.size(); idx < end; ++idx) { + const SAnimationTrack &newTrack(*theAnimations[idx]); + Qt3DSDMAnimationHandle theNewAnimation( + CreateAnimation(inDestSlide, inDestInstance, newTrack.m_Property, newTrack.m_Index, + newTrack.m_AnimationType, newTrack.m_FirstKeyframeDynamic)); + for (size_t keyIdx = 0, keyEnd = newTrack.m_Keyframes.size(); keyIdx < keyEnd; ++keyIdx) + InsertKeyframe(theNewAnimation, GetKeyframeData(newTrack.m_Keyframes[keyIdx])); + } +} + +// ITransactionProducer implementation +void CAnimationCoreProducer::SetConsumer(TTransactionConsumerPtr inConsumer) +{ + m_Consumer = inConsumer; + m_KeyframeMergeMap.clear(); +} + +TSignalConnectionPtr CAnimationCoreProducer::ConnectAnimationCreated( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) +{ + return GetSignalProvider()->ConnectAnimationCreated(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectBeforeAnimationDeleted( + const std::function<void(Qt3DSDMAnimationHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectBeforeAnimationDeleted(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectAnimationDeleted( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) +{ + return GetSignalProvider()->ConnectAnimationDeleted(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectKeyframeInserted( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle, const TKeyframe &)> + &inCallback) +{ + return GetSignalProvider()->ConnectKeyframeInserted(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectBeforeKeyframeErased( + const std::function<void(Qt3DSDMKeyframeHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectBeforeKeyframeErased(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectKeyframeErased( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle, const TKeyframe &)> + &inCallback) +{ + return GetSignalProvider()->ConnectKeyframeErased(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectBeforeAllKeyframesErased( + const std::function<void(Qt3DSDMAnimationHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectBeforeAllKeyframesErased(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectKeyframeUpdated( + const std::function<void(Qt3DSDMKeyframeHandle, const TKeyframe &)> &inCallback) +{ + return GetSignalProvider()->ConnectKeyframeUpdated(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectFirstKeyframeDynamicSet( + const std::function<void(Qt3DSDMAnimationHandle, bool)> &inCallback) +{ + return GetSignalProvider()->ConnectFirstKeyframeDynamicSet(inCallback); +} + +void CAnimationCoreProducer::InitSignaller() +{ + m_Signaller = CreateAnimationCoreSignaller(); +} + +IAnimationCoreSignalProvider *CAnimationCoreProducer::GetSignalProvider() +{ + return dynamic_cast<IAnimationCoreSignalProvider *>(m_Signaller.get()); +} + +IAnimationCoreSignalSender *CAnimationCoreProducer::GetSignalSender() +{ + return dynamic_cast<IAnimationCoreSignalSender *>(m_Signaller.get()); +} +} diff --git a/src/dm/systems/cores/AnimationCoreProducer.h b/src/dm/systems/cores/AnimationCoreProducer.h new file mode 100644 index 0000000..17603d6 --- /dev/null +++ b/src/dm/systems/cores/AnimationCoreProducer.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef ANIMATIONCOREPRODUCERH +#define ANIMATIONCOREPRODUCERH +#include "SimpleAnimationCore.h" +#include "Qt3DSDMTransactions.h" +#include "Qt3DSDMSignals.h" + +namespace qt3dsdm { +class CAnimationCoreProducer : public IAnimationCore, + public ITransactionProducer, + public IAnimationCoreSignalProvider +{ + Q_DISABLE_COPY(CAnimationCoreProducer) + + typedef std::shared_ptr<IMergeableTransaction<TKeyframe>> TKeyframeDataMergeMapEntry; + typedef std::unordered_map<int, TKeyframeDataMergeMapEntry> TKeyframeDataMergeMap; + + TSimpleAnimationCorePtr m_Data; + TTransactionConsumerPtr m_Consumer; + TSignalItemPtr m_Signaller; + TKeyframeDataMergeMap m_KeyframeMergeMap; + +public: + CAnimationCoreProducer() + : m_Data(new CSimpleAnimationCore()) + { + InitSignaller(); + } + CAnimationCoreProducer(TStringTablePtr strTable) + : m_Data(new CSimpleAnimationCore(strTable)) + { + InitSignaller(); + } + + TSimpleAnimationCorePtr GetTransactionlessAnimationCore() const { return m_Data; } + + // IAnimationManger implementation + + Qt3DSDMAnimationHandle CreateAnimation(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType, + bool inFirstKeyframeDynamic) override; + void DeleteAnimation(Qt3DSDMAnimationHandle inAnimation) override; + Qt3DSDMAnimationHandle GetAnimation(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex) const override; + SAnimationInfo GetAnimationInfo(Qt3DSDMAnimationHandle inAnimation) const override; + void GetAnimations(TAnimationHandleList &outAnimations) const override; + void GetAnimations(TAnimationInfoList &outAnimations, Qt3DSDMSlideHandle inMaster, + Qt3DSDMSlideHandle inSlide) const override; + void GetSpecificInstanceAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + TAnimationHandleList &outAnimations) override + { + m_Data->GetSpecificInstanceAnimations(inSlide, inInstance, outAnimations); + } + + void SetFirstKeyframeDynamic(Qt3DSDMAnimationHandle inAnimation, bool inValue) override; + + Qt3DSDMKeyframeHandle InsertKeyframe(Qt3DSDMAnimationHandle inAnimation, + const TKeyframe &inKeyframe) override; + void EraseKeyframe(Qt3DSDMKeyframeHandle) override; + void DeleteAllKeyframes(Qt3DSDMAnimationHandle inAnimation) override; + Qt3DSDMAnimationHandle GetAnimationForKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const override; + TKeyframe GetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe) const override; + void SetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData) override; + void GetKeyframes(Qt3DSDMAnimationHandle inAnimation, TKeyframeHandleList &outKeyframes) const override; + size_t GetKeyframeCount(Qt3DSDMAnimationHandle inAnimation) const override; + bool IsFirstKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const override + { + return m_Data->IsFirstKeyframe(inKeyframe); + } + void OffsetAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + long inMillisecondOffset) override; + + void SetIsArtistEdited(Qt3DSDMAnimationHandle inAnimation, bool inEdited = true) override; + bool IsArtistEdited(Qt3DSDMAnimationHandle inAnimation) const override; + + // Animation Evaluation. + float EvaluateAnimation(Qt3DSDMAnimationHandle inAnimation, float inSeconds) const override; + + bool KeyframeValid(Qt3DSDMKeyframeHandle inKeyframe) const override; + bool AnimationValid(Qt3DSDMAnimationHandle inAnimation) const override; + + void CopyAnimations(Qt3DSDMSlideHandle inSourceSlide, Qt3DSDMInstanceHandle inSourceInstance, + Qt3DSDMSlideHandle inDestSlide, Qt3DSDMInstanceHandle inDestInstance) override; + + // ITransactionProducer implementation + void SetConsumer(TTransactionConsumerPtr inConsumer) override; + + TSignalConnectionPtr ConnectAnimationCreated( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectBeforeAnimationDeleted(const std::function<void(Qt3DSDMAnimationHandle)> &inCallback) override; + TSignalConnectionPtr ConnectAnimationDeleted( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) override; + TSignalConnectionPtr ConnectKeyframeInserted( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle, const TKeyframe &)> + &inCallback) override; + virtual TSignalConnectionPtr + ConnectBeforeKeyframeErased(const std::function<void(Qt3DSDMKeyframeHandle)> &inCallback) override; + TSignalConnectionPtr ConnectKeyframeErased( + const std::function<void(Qt3DSDMAnimationHandle, Qt3DSDMKeyframeHandle, const TKeyframe &)> + &inCallback) override; + virtual TSignalConnectionPtr + ConnectBeforeAllKeyframesErased(const std::function<void(Qt3DSDMAnimationHandle)> &inCallback) override; + TSignalConnectionPtr ConnectKeyframeUpdated( + const std::function<void(Qt3DSDMKeyframeHandle, const TKeyframe &)> &inCallback) override; + TSignalConnectionPtr ConnectFirstKeyframeDynamicSet( + const std::function<void(Qt3DSDMAnimationHandle, bool)> &inCallback) override; + +private: + void InitSignaller(); + IAnimationCoreSignalProvider *GetSignalProvider(); + IAnimationCoreSignalSender *GetSignalSender(); +}; +} + +#endif diff --git a/src/dm/systems/cores/DataCoreProducer.cpp b/src/dm/systems/cores/DataCoreProducer.cpp new file mode 100644 index 0000000..5c3cc92 --- /dev/null +++ b/src/dm/systems/cores/DataCoreProducer.cpp @@ -0,0 +1,457 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "DataCoreProducer.h" +#include "HandleSystemTransactions.h" +#include "VectorTransactions.h" +#include "SignalsImpl.h" +#ifdef _WIN32 +#pragma warning(disable : 4503) // decorated name length exceeded +#endif +namespace qt3dsdm { + +Qt3DSDMInstanceHandle CDataCoreProducer::CreateInstance(Qt3DSDMInstanceHandle inTargetId) +{ + Qt3DSDMInstanceHandle retval = m_Data->CreateInstance(inTargetId); + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + GetDataCoreSender()->SignalInstanceCreated(retval); + return retval; +} + +inline tuple<Qt3DSDMPropertyHandle, Qt3DSDMPropertyDefinition> +TransformProperty(Qt3DSDMPropertyHandle inProperty, CSimpleDataCore &inData) +{ + return make_tuple(inProperty, inData.GetProperty(inProperty)); +} + +inline void SignalPropertyRemoved(Qt3DSDMInstanceHandle inInstance, + tuple<Qt3DSDMPropertyHandle, Qt3DSDMPropertyDefinition> inData, + IDataCoreSignalSender *inSender) +{ + inSender->SignalPropertyRemoved(inInstance, get<0>(inData), get<1>(inData).m_Name.wide_str(), + get<1>(inData).m_Type); +} + +void CDataCoreProducer::DeleteInstance(Qt3DSDMInstanceHandle inInstance) +{ + TIntList theProperties; + TIntList theInstances; + + GetDataCoreSender()->SignalBeforeInstanceDeleted(inInstance); + // Ensure the instance exists + m_Data->GetInstanceNF(inInstance, m_Data->m_Objects); + do_all(m_Data->m_Objects, + std::bind(CSimpleDataCore::FindRelatedItemsForDelete, inInstance.GetHandleValue(), + std::ref(theProperties), std::ref(theInstances), std::placeholders::_1)); + + if (m_Consumer) { + CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inInstance, m_Data->m_Objects); + do_all(theProperties, std::bind(HandleDeleteTransaction, __FILE__, __LINE__, + std::placeholders::_1, + std::ref(m_Data->m_Objects), m_Consumer)); + } + + vector<tuple<Qt3DSDMPropertyHandle, Qt3DSDMPropertyDefinition>> theDefinitionList; + theDefinitionList.resize(theProperties.size()); + + function<tuple<Qt3DSDMPropertyHandle, Qt3DSDMPropertyDefinition>(Qt3DSDMPropertyHandle)> + thePropertyTransform(bind(TransformProperty, std::placeholders::_1, ref(*m_Data))); + transform(theProperties.begin(), theProperties.end(), theDefinitionList.begin(), + thePropertyTransform); + + GetDataCoreSender()->SignalInstanceDeleted(inInstance); + + m_Data->DeleteInstance(inInstance); + // Signal that these theProperties are no longer with us. + do_all(theDefinitionList, bind(SignalPropertyRemoved, inInstance, + std::placeholders::_1, GetDataCoreSender())); +} + +bool CDataCoreProducer::IsInstanceOrDerivedFrom(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) const +{ + return m_Data->IsInstanceOrDerivedFrom(inInstance, inParent); +} + +void CDataCoreProducer::GetInstances(TInstanceHandleList &outInstances) const +{ + m_Data->GetInstances(outInstances); +} +void CDataCoreProducer::GetInstancesDerivedFrom(TInstanceHandleList &outInstances, + Qt3DSDMInstanceHandle inParentHandle) const +{ + m_Data->GetInstancesDerivedFrom(outInstances, inParentHandle); +} + +struct ClearInstanceParentCacheTransaction : public ITransaction +{ + const CDataModelInstance &m_Instance; + ClearInstanceParentCacheTransaction(const char *inFile, int inLine, + const CDataModelInstance &inst) + : ITransaction(inFile, inLine) + , m_Instance(inst) + { + } + void Do() override { m_Instance.ClearParentCache(); } + void Undo() override { m_Instance.ClearParentCache(); } +}; + +void CDataCoreProducer::DeriveInstance(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) +{ + m_Data->DeriveInstance(inInstance, inParent); + TDataModelInstancePtr theInstance = + CSimpleDataCore::GetInstanceNF(inInstance, m_Data->m_Objects); + if (m_Consumer) { + CreateHashMapInsertTransaction( + __FILE__, __LINE__, m_Consumer, + make_pair(inParent.GetHandleValue(), + CSimpleDataCore::GetInstanceNF(inParent, m_Data->m_Objects)), + theInstance->m_Parents); + m_Consumer->OnTransaction(std::static_pointer_cast<ITransaction>( + std::make_shared<ClearInstanceParentCacheTransaction>(__FILE__, __LINE__, + *theInstance))); + } + GetDataCoreSender()->SignalInstanceDerived(inInstance, inParent); +} + +void CDataCoreProducer::GetInstanceParents(Qt3DSDMInstanceHandle inHandle, + TInstanceHandleList &outParents) const +{ + m_Data->GetInstanceParents(inHandle, outParents); +} + +Qt3DSDMPropertyHandle CDataCoreProducer::AddProperty(Qt3DSDMInstanceHandle inInstance, + TCharPtr inName, DataModelDataType::Value inPropType) +{ + Qt3DSDMPropertyHandle retval = m_Data->AddProperty(inInstance, inName, inPropType); + TDataModelInstancePtr theInstance = + CSimpleDataCore::GetInstanceNF(inInstance, m_Data->m_Objects); + CreateVecInsertTransaction<int>(__FILE__, __LINE__, m_Consumer, retval, + theInstance->m_Properties); + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + GetDataCoreSender()->SignalPropertyAdded(inInstance, retval, inName, inPropType); + return retval; +} + +void CDataCoreProducer::GetInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const +{ + m_Data->GetInstanceProperties(inInstance, outProperties); +} + +const Qt3DSDMPropertyDefinition & +CDataCoreProducer::GetProperty(Qt3DSDMPropertyHandle inProperty) const +{ + return m_Data->GetProperty(inProperty); +} + +void CDataCoreProducer::RemoveProperty(Qt3DSDMPropertyHandle inProperty) +{ + Qt3DSDMPropertyDefinition theDef = GetProperty(inProperty); + TDataModelInstancePtr theInstance = + CSimpleDataCore::GetInstanceNF(theDef.m_Instance, m_Data->m_Objects); + if (find_if<TIntList::iterator>(theInstance->m_Properties, + std::bind(equal_to<int>(), inProperty, std::placeholders::_1)) + != theInstance->m_Properties.end()) { + CreateVecEraseTransaction<int>(__FILE__, __LINE__, m_Consumer, inProperty, + theInstance->m_Properties); + CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inProperty, m_Data->m_Objects); + GetDataCoreSender()->SignalPropertyRemoved(theDef.m_Instance, inProperty, + theDef.m_Name.wide_str(), theDef.m_Type); + m_Data->RemoveProperty(inProperty); + } else { + throw PropertyNotFound(L""); + } +} + +inline void AddCopyInstancePropertyTransaction(int inProperty, const TIntList &inOriginalList, + CDataModelInstance &inInstance, + TTransactionConsumerPtr &inConsumer) +{ + // if this property was never in the original list + if (find_if<TIntList::const_iterator>(inOriginalList, + std::bind(equal_to<int>(), inProperty, + std::placeholders::_1)) + == inOriginalList.end()) + CreateVecInsertTransaction<int>(__FILE__, __LINE__, inConsumer, + Qt3DSDMPropertyHandle(inProperty), inInstance.m_Properties); +} + +inline void AddCopyInstanceValuePropertyTransaction(const TPropertyPair &inProperty, + const TPropertyPairHash &inOriginalList, + CDataModelInstance &inInstance, + TTransactionConsumerPtr &inConsumer) +{ + // if this property was never in the original list + if (inOriginalList.end() == inOriginalList.find(inProperty.first)) + CreateHashMapInsertTransaction(__FILE__, __LINE__, inConsumer, inProperty, + inInstance.m_PropertyValues); +} + +struct InstancePropertyValuesTransaction : public ITransaction +{ + CDataModelInstance &m_Instance; + TIntList m_OldProperties; + TPropertyPairList m_OldValues; + TIntList m_NewProperties; + TPropertyPairList m_NewValues; + + InstancePropertyValuesTransaction(const char *inFile, int inLine, + CDataModelInstance &inInstance) + : ITransaction(inFile, inLine) + , m_Instance(inInstance) + , m_OldProperties(inInstance.m_Properties) + { + inInstance.ToPropertyPairList(m_OldValues); + } + + void SetNew() + { + m_NewProperties = m_Instance.m_Properties; + m_Instance.ToPropertyPairList(m_NewValues); + } + + void Do() override + { + m_Instance.m_Properties = m_NewProperties; + m_Instance.FromPropertyPairList(m_NewValues); + } + + void Undo() override + { + m_Instance.m_Properties = m_OldProperties; + m_Instance.FromPropertyPairList(m_OldValues); + } +}; + +void CDataCoreProducer::CopyInstanceProperties(Qt3DSDMInstanceHandle inSrcInstance, + Qt3DSDMInstanceHandle inDestInstance) +{ + TDataModelInstancePtr theInstance = + CSimpleDataCore::GetInstanceNF(inDestInstance, m_Data->m_Objects); + if (m_Consumer) { + // Create the transaction object setting its 'old values' property to the current instance + // property values. + std::shared_ptr<InstancePropertyValuesTransaction> theTransaction( + std::make_shared<InstancePropertyValuesTransaction>(__FILE__, __LINE__, + ref(*theInstance))); + + // Change the current instance property values + m_Data->CopyInstanceProperties(inSrcInstance, inDestInstance); + + // Ask the transaction to copy the new values into it's new values datastructure. + theTransaction->SetNew(); + + m_Consumer->OnTransaction(std::static_pointer_cast<ITransaction>(theTransaction)); + } else { + m_Data->CopyInstanceProperties(inSrcInstance, inDestInstance); + } +} + +Qt3DSDMPropertyHandle +CDataCoreProducer::GetAggregateInstancePropertyByName(Qt3DSDMInstanceHandle inInstance, + const TCharStr &inStr) const +{ + return m_Data->GetAggregateInstancePropertyByName(inInstance, inStr); +} + +void CDataCoreProducer::GetAggregateInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const +{ + m_Data->GetAggregateInstanceProperties(inInstance, outProperties); +} + +void CDataCoreProducer::GetSpecificInstancePropertyValues(Qt3DSDMInstanceHandle inHandle, + TPropertyHandleValuePairList &outValues) +{ + m_Data->GetSpecificInstancePropertyValues(inHandle, outValues); +} + +bool CDataCoreProducer::HasAggregateInstanceProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + return m_Data->HasAggregateInstanceProperty(inInstance, inProperty); +} + +void CDataCoreProducer::CheckValue(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) const +{ + return m_Data->CheckValue(inInstance, inProperty, inValue); +} + +bool CDataCoreProducer::GetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + return m_Data->GetInstancePropertyValue(inHandle, inProperty, outValue); +} + +inline void EraseProperty(TPropertyPairHash &inProperties, int inProperty) +{ + inProperties.erase( + find_if(inProperties.begin(), inProperties.end(), + std::bind(CSimpleDataCore::InstancePropertyMatches, inProperty, + std::placeholders::_1))); +} + +void CDataCoreProducer::SetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + // Two possible courses of actions. The property exists, in which case + // we need to get its old value. + // If it doesn't exist, then we need to erase for undo. + TPropertyValuePair theOldValue(PropertyValueFlags(PropertyValueFlags::SetViaAutoPropagate), + SInternValue(0.0f, GetStringTable())); + TDataModelInstancePtr theInstance = CSimpleDataCore::GetInstanceNF(inHandle, m_Data->m_Objects); + TPropertyPairHash::iterator theItem = + theInstance->m_PropertyValues.find(inProperty.GetHandleValue()); + bool foundProp = theItem != theInstance->m_PropertyValues.end(); + if (foundProp) + theOldValue = theItem->second; + m_Data->SetInstancePropertyValue(inHandle, inProperty, inValue); + TPropertyValuePair theNewValue = + theInstance->m_PropertyValues.find(inProperty.GetHandleValue())->second; + if (m_Consumer) { + // Check if we already have the entry + TSlideInstancePropertyPair theKey(inHandle, inProperty); + TPropertyMergeMap::iterator iter = m_PropertyMergeMap.find(theKey); + // Then we merge the values in to the original event where they + // first happened. + if (iter != m_PropertyMergeMap.end()) { + iter->second->Update(theNewValue); + return; // don't send the signal if we just updated value + } else // Else we add a new merge entry. + { + TPropertyMergeMapEntry theEntry; + if (!foundProp) + theEntry = CreateHashMapInsertTransaction( + __FILE__, __LINE__, m_Consumer, + make_pair(inProperty.GetHandleValue(), theNewValue), + theInstance->m_PropertyValues); + else + theEntry = CreateHashMapSwapTransaction(__FILE__, __LINE__, m_Consumer, + inProperty.GetHandleValue(), theOldValue, + theNewValue, theInstance->m_PropertyValues); + m_PropertyMergeMap.insert(std::make_pair(theKey, theEntry)); + } + } + GetPropertyCoreSender()->SignalInstancePropertyValue(inHandle, inProperty, inValue); +} + +bool CDataCoreProducer::HandleValid(int inHandle) const +{ + return m_Data->HandleValid(inHandle); +} + +void CDataCoreProducer::SetConsumer(TTransactionConsumerPtr inConsumer) +{ + m_Consumer = inConsumer; + m_PropertyMergeMap.clear(); +} + +TSignalConnectionPtr CDataCoreProducer::ConnectInstancePropertyValue( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, const SValue &)> + &inCallback) +{ + return GetPropertyCoreProvider()->ConnectInstancePropertyValue(inCallback); +} + +TSignalConnectionPtr CDataCoreProducer::ConnectInstanceCreated( + const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) +{ + return GetDataCoreProvider()->ConnectInstanceCreated(inCallback); +} + +TSignalConnectionPtr CDataCoreProducer::ConnectInstanceDeleted( + const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) +{ + return GetDataCoreProvider()->ConnectInstanceDeleted(inCallback); +} + +TSignalConnectionPtr CDataCoreProducer::ConnectBeforeInstanceDeleted( + const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) +{ + return GetDataCoreProvider()->ConnectBeforeInstanceDeleted(inCallback); +} + +TSignalConnectionPtr CDataCoreProducer::ConnectInstanceDerived( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMInstanceHandle)> &inCallback) +{ + return GetDataCoreProvider()->ConnectInstanceDerived(inCallback); +} + +TSignalConnectionPtr CDataCoreProducer::ConnectInstanceParentRemoved( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMInstanceHandle)> &inCallback) +{ + return GetDataCoreProvider()->ConnectInstanceParentRemoved(inCallback); +} + +TSignalConnectionPtr CDataCoreProducer::ConnectPropertyAdded( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, TCharPtr, + DataModelDataType::Value)> &inCallback) +{ + return GetDataCoreProvider()->ConnectPropertyAdded(inCallback); +} + +TSignalConnectionPtr CDataCoreProducer::ConnectPropertyRemoved( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, TCharPtr, + DataModelDataType::Value)> &inCallback) +{ + return GetDataCoreProvider()->ConnectPropertyRemoved(inCallback); +} + +void CDataCoreProducer::InitSignallers() +{ + m_InstancePropertyCoreSignaller = CreatePropertyCoreSignaller(); + m_DataCoreSignaller = CreateDataCoreSignaller(); +} + +IInstancePropertyCoreSignalProvider *CDataCoreProducer::GetPropertyCoreProvider() +{ + return dynamic_cast<IInstancePropertyCoreSignalProvider *>( + m_InstancePropertyCoreSignaller.get()); +} + +IInstancePropertyCoreSignalSender *CDataCoreProducer::GetPropertyCoreSender() +{ + return dynamic_cast<IInstancePropertyCoreSignalSender *>(m_InstancePropertyCoreSignaller.get()); +} + +IDataCoreSignalProvider *CDataCoreProducer::GetDataCoreProvider() +{ + return dynamic_cast<IDataCoreSignalProvider *>(m_DataCoreSignaller.get()); +} + +IDataCoreSignalSender *CDataCoreProducer::GetDataCoreSender() +{ + return dynamic_cast<IDataCoreSignalSender *>(m_DataCoreSignaller.get()); +} +} diff --git a/src/dm/systems/cores/DataCoreProducer.h b/src/dm/systems/cores/DataCoreProducer.h new file mode 100644 index 0000000..8d89bfa --- /dev/null +++ b/src/dm/systems/cores/DataCoreProducer.h @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef DATACOREPRODUCERH +#define DATACOREPRODUCERH + +#include "Qt3DSDMTransactions.h" +#include "SimpleDataCore.h" +#include "Qt3DSDMSignals.h" +#include "SimpleSlideCore.h" + +namespace qt3dsdm { + +class CDataCoreProducer : public IDataCore, + public ITransactionProducer, + public IInstancePropertyCoreSignalProvider, + public IDataCoreSignalProvider +{ + typedef std::shared_ptr<IMergeableTransaction<TPropertyValuePair>> TPropertyMergeMapEntry; + typedef std::unordered_map<TSlideInstancePropertyPair, TPropertyMergeMapEntry> + TPropertyMergeMap; + + TTransactionConsumerPtr m_Consumer; + TSimpleDataCorePtr m_Data; + TSignalItemPtr m_InstancePropertyCoreSignaller; + TSignalItemPtr m_DataCoreSignaller; + + TPropertyMergeMap m_PropertyMergeMap; + +public: + CDataCoreProducer(TStringTablePtr inStringTable) + : m_Data(new CSimpleDataCore(inStringTable)) + { + InitSignallers(); + } + virtual ~CDataCoreProducer() {} + + IStringTable &GetStringTable() const override { return m_Data->GetStringTable(); } + std::shared_ptr<IStringTable> GetStringTablePtr() const override + { + return m_Data->GetStringTablePtr(); + } + + // IHandleBase + bool HandleValid(int inHandle) const override; + + // IInstancePropertyCore + //=============================================================== + Qt3DSDMPropertyHandle GetAggregateInstancePropertyByName(Qt3DSDMInstanceHandle inInstance, + const TCharStr &inStr) const override; + void GetAggregateInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const override; + void GetSpecificInstancePropertyValues(Qt3DSDMInstanceHandle inHandle, + TPropertyHandleValuePairList &outValues) override; + bool HasAggregateInstanceProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + + void CheckValue(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) const override; + bool GetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + void SetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + //=============================================================== + + // IDataCore + //=============================================================== + Qt3DSDMInstanceHandle CreateInstance(Qt3DSDMInstanceHandle hdl = Qt3DSDMInstanceHandle()) override; + void GetInstances(TInstanceHandleList &outInstances) const override; + void GetInstancesDerivedFrom(TInstanceHandleList &outInstances, + Qt3DSDMInstanceHandle inParent) const override; + void DeleteInstance(Qt3DSDMInstanceHandle inHandle) override; + + void DeriveInstance(Qt3DSDMInstanceHandle inInstance, Qt3DSDMInstanceHandle inParent) override; + void GetInstanceParents(Qt3DSDMInstanceHandle inHandle, + TInstanceHandleList &outParents) const override; + bool IsInstanceOrDerivedFrom(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) const override; + + Qt3DSDMPropertyHandle AddProperty(Qt3DSDMInstanceHandle inInstance, TCharPtr inName, + DataModelDataType::Value inPropType) override; + void GetInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const override; + const Qt3DSDMPropertyDefinition &GetProperty(Qt3DSDMPropertyHandle inProperty) const override; + void RemoveProperty(Qt3DSDMPropertyHandle inProperty) override; + void CopyInstanceProperties(Qt3DSDMInstanceHandle inSrcInstance, + Qt3DSDMInstanceHandle inDestInstance) override; + + void RemoveCachedValues(Qt3DSDMInstanceHandle inInstance) override + { + m_Data->RemoveCachedValues(inInstance); + } + bool IsInstance(int inHandle) const override { return m_Data->IsInstance(inHandle); } + bool IsProperty(int inHandle) const override { return m_Data->IsProperty(inHandle); } + //=============================================================== + + //=============================================================== + // Set the current consumer + //=============================================================== + void SetConsumer(TTransactionConsumerPtr inConsumer) override; + + //=============================================================== + // Return a serializable data model for load/save + //=============================================================== + virtual TSimpleDataCorePtr GetTransactionlessDataCore() { return m_Data; } + virtual TSimpleDataCorePtr GetTransactionlessDataCore() const { return m_Data; } + + //=============================================================== + // Signal provider implementation + //=============================================================== + TSignalConnectionPtr ConnectInstancePropertyValue( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, const SValue &)> + &inCallback) override; + virtual TSignalConnectionPtr + ConnectInstanceCreated(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectInstanceDeleted(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectBeforeInstanceDeleted(const std::function<void(Qt3DSDMInstanceHandle)> &inCallback) override; + TSignalConnectionPtr ConnectInstanceDerived( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMInstanceHandle)> &inCallback) override; + TSignalConnectionPtr ConnectInstanceParentRemoved( + const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMInstanceHandle)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectPropertyAdded(const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + TCharPtr, DataModelDataType::Value)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectPropertyRemoved(const std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + TCharPtr, DataModelDataType::Value)> &inCallback) override; + +private: + CDataCoreProducer(const CDataCoreProducer&) = delete; + CDataCoreProducer& operator=(const CDataCoreProducer&) = delete; + + template <typename TTransactionType> + inline void RunWithConsumer(TTransactionType inTransaction) + { + qt3dsdm::RunWithConsumer(m_Consumer, inTransaction); + } + + void InitSignallers(); + IInstancePropertyCoreSignalProvider *GetPropertyCoreProvider(); + IInstancePropertyCoreSignalSender *GetPropertyCoreSender(); + IDataCoreSignalProvider *GetDataCoreProvider(); + IDataCoreSignalSender *GetDataCoreSender(); +}; +} + +#endif diff --git a/src/dm/systems/cores/SimpleActionCore.cpp b/src/dm/systems/cores/SimpleActionCore.cpp new file mode 100644 index 0000000..b2f3553 --- /dev/null +++ b/src/dm/systems/cores/SimpleActionCore.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "SimpleActionCore.h" + +namespace qt3dsdm { + +Qt3DSDMActionHandle CSimpleActionCore::CreateAction(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner, + SLong4 inTriggerTargetObjects) +{ + int nextId = GetNextId(); + Qt3DSDMActionHandle retval = CreateActionWithHandle(nextId, inInstance, inSlide, inOwner); + SetTriggerObject(retval, inTriggerTargetObjects); + SetTargetObject(retval, inTriggerTargetObjects); + return retval; +} + +void CSimpleActionCore::DeleteAction(Qt3DSDMActionHandle inAction, Qt3DSDMInstanceHandle &outInstance) +{ + SAction *theAction = GetActionNF(inAction, m_Objects); + outInstance = theAction->m_ActionInfo.m_Instance; + do_all(theAction->m_ActionInfo.m_HandlerArgs, + std::bind(EraseHandle, std::placeholders::_1, std::ref(m_Objects))); + EraseHandle(inAction, m_Objects); +} + +const SActionInfo &CSimpleActionCore::GetActionInfo(Qt3DSDMActionHandle inAction) const +{ + const SAction *theAction = GetActionNF(inAction, m_Objects); + return theAction->m_ActionInfo; +} + +inline void AddIfActionMatches(const THandleObjectPair &inPair, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner, TActionHandleList &outActions) +{ + if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeAction) { + const SAction *theAction = static_cast<SAction *>(inPair.second.get()); + if ((!inSlide.Valid() || inSlide == theAction->m_ActionInfo.m_Slide) + && (!inOwner.Valid() || inOwner == theAction->m_ActionInfo.m_Owner)) + outActions.push_back(inPair.first); + } +} + +// Return all actions that belong to a certain instance in a certain slide +void CSimpleActionCore::GetActions(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const +{ + outActions.clear(); + do_all(m_Objects, + std::bind(AddIfActionMatches, + std::placeholders::_1, inSlide, inOwner, std::ref(outActions))); +} + +// Return all actions that exist in a certain slide +void CSimpleActionCore::GetActions(Qt3DSDMSlideHandle inSlide, TActionHandleList &outActions) const +{ + GetActions(inSlide, 0, outActions); +} + +// Return all actions that belong to a certain instance +void CSimpleActionCore::GetActions(Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const +{ + GetActions(0, inOwner, outActions); +} + +// Return all actions +void CSimpleActionCore::GetActions(TActionHandleList &outActions) const +{ + outActions.clear(); + outActions.reserve(m_Objects.size()); + do_all(m_Objects, + std::bind(MaybeAddObject<SAction, Qt3DSDMActionHandle>, + std::placeholders::_1, std::ref(outActions))); +} + +// Return the instance that was allocated for this action. +Qt3DSDMInstanceHandle CSimpleActionCore::GetActionInstance(Qt3DSDMActionHandle inAction) const +{ + return GetActionNF(inAction, m_Objects)->m_ActionInfo.m_Instance; +} + +inline bool ActionInstanceMatches(const THandleObjectPair &inPair, Qt3DSDMInstanceHandle inInstance) +{ + if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeAction) { + const SAction *theAction = static_cast<SAction *>(inPair.second.get()); + if (inInstance == theAction->m_ActionInfo.m_Instance) + return true; + } + return false; +} + +// Reverse lookup into the action system so you can match actions to instances. +Qt3DSDMActionHandle +CSimpleActionCore::GetActionByInstance(Qt3DSDMInstanceHandle inActionInstance) const +{ + THandleObjectMap::const_iterator theAction = + find_if(m_Objects.begin(), m_Objects.end(), + std::bind(ActionInstanceMatches, std::placeholders::_1, inActionInstance)); + if (theAction != m_Objects.end()) + return theAction->first; + throw ActionNotFound(L""); +} + +// Action Properties +void CSimpleActionCore::SetTriggerObject(Qt3DSDMActionHandle inAction, + const SObjectRefType &inTriggerObject) +{ + SAction *theAction = GetActionNF(inAction, m_Objects); + theAction->m_ActionInfo.m_TriggerObject = inTriggerObject; +} + +void CSimpleActionCore::SetTargetObject(Qt3DSDMActionHandle inAction, + const SObjectRefType &inTargetObject) +{ + SAction *theAction = GetActionNF(inAction, m_Objects); + theAction->m_ActionInfo.m_TargetObject = inTargetObject; +} + +void CSimpleActionCore::SetEvent(Qt3DSDMActionHandle inAction, const wstring &inEventHandle) +{ + SAction *theAction = GetActionNF(inAction, m_Objects); + theAction->m_ActionInfo.m_Event = inEventHandle; +} + +void CSimpleActionCore::SetHandler(Qt3DSDMActionHandle inAction, const wstring &inHandlerHandle) +{ + SAction *theAction = GetActionNF(inAction, m_Objects); + theAction->m_ActionInfo.m_Handler = inHandlerHandle; +} + +// Action Argument +Qt3DSDMHandlerArgHandle CSimpleActionCore::AddHandlerArgument(Qt3DSDMActionHandle inAction, + const TCharStr &inName, + HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) +{ + int nextId = GetNextId(); + return AddHandlerArgumentWithHandle(nextId, inAction, inName, inArgType, inValueType); +} + +void CSimpleActionCore::RemoveHandlerArgument(Qt3DSDMHandlerArgHandle inHandlerArgument) +{ + SHandlerArgument *theHandlerArgument = GetHandlerArgumentNF(inHandlerArgument, m_Objects); + SAction *theAction = GetActionNF(theHandlerArgument->m_HandlerArgInfo.m_Action, m_Objects); + EraseHandle(inHandlerArgument, m_Objects); + erase_if(theAction->m_ActionInfo.m_HandlerArgs, + std::bind(equal_to<int>(), std::placeholders::_1, inHandlerArgument.GetHandleValue())); +} + +const SHandlerArgumentInfo & +CSimpleActionCore::GetHandlerArgumentInfo(Qt3DSDMHandlerArgHandle inHandlerArgument) const +{ + if (HandleValid(inHandlerArgument)) { + const SHandlerArgument *theHandlerArgument = + GetHandlerArgumentNF(inHandlerArgument, m_Objects); + return theHandlerArgument->m_HandlerArgInfo; + } else { + static SHandlerArgumentInfo dummy; + return dummy; + } +} + +void CSimpleActionCore::GetHandlerArguments(Qt3DSDMActionHandle inAction, + THandlerArgHandleList &outHandlerArguments) const +{ + const SAction *theAction = GetActionNF(inAction, m_Objects); + outHandlerArguments = theAction->m_ActionInfo.m_HandlerArgs; +} + +// Action Argument Properties +void CSimpleActionCore::GetHandlerArgumentValue(Qt3DSDMHandlerArgHandle inHandlerArgument, + SValue &outValue) const +{ + const SHandlerArgument *theHandlerArgument = GetHandlerArgumentNF(inHandlerArgument, m_Objects); + outValue = theHandlerArgument->m_HandlerArgInfo.m_Value; +} + +void CSimpleActionCore::SetHandlerArgumentValue(Qt3DSDMHandlerArgHandle inHandlerArgument, + const SValue &inValue) +{ + SHandlerArgument *theHandlerArgument = GetHandlerArgumentNF(inHandlerArgument, m_Objects); + theHandlerArgument->m_HandlerArgInfo.m_Value = inValue; +} + +// Helper functions +Qt3DSDMActionHandle CSimpleActionCore::CreateActionWithHandle(int inHandle, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) +{ + if (HandleValid(inHandle)) + throw HandleExists(L""); + m_Objects.insert(make_pair( + inHandle, (THandleObjectPtr) new SAction(inHandle, inInstance, inSlide, inOwner))); + return inHandle; +} + +Qt3DSDMHandlerArgHandle +CSimpleActionCore::AddHandlerArgumentWithHandle(int inHandle, Qt3DSDMActionHandle inAction, + const TCharStr &inName, HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) +{ + if (HandleValid(inHandle)) + throw HandleExists(L""); + m_Objects.insert(make_pair(inHandle, (THandleObjectPtr) new SHandlerArgument( + inHandle, inAction, inName, inArgType, inValueType))); + SAction *theAction = GetActionNF(inAction, m_Objects); + theAction->m_ActionInfo.m_HandlerArgs.push_back(inHandle); + return inHandle; +} +} diff --git a/src/dm/systems/cores/SimpleActionCore.h b/src/dm/systems/cores/SimpleActionCore.h new file mode 100644 index 0000000..1e229f1 --- /dev/null +++ b/src/dm/systems/cores/SimpleActionCore.h @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef ACTIONCOREH +#define ACTIONCOREH + +#include "Qt3DSDMActionCore.h" +#include "HandleSystemBase.h" +#include "Qt3DSDMErrors.h" + +namespace qt3dsdm { +struct SAction : public CHandleObject +{ + SActionInfo m_ActionInfo; + + SAction() {} + + SAction(int inHandle, Qt3DSDMInstanceHandle inInstance, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) + : CHandleObject(inHandle) + , m_ActionInfo(inInstance, inSlide, inOwner) + { + } + + static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeAction; + EHandleObjectType GetType() override { return s_Type; } +}; + +struct SHandlerArgument : public CHandleObject +{ + SHandlerArgumentInfo m_HandlerArgInfo; + + SHandlerArgument() {} + + SHandlerArgument(int inHandle, Qt3DSDMActionHandle inAction, const TCharStr &inName, + HandlerArgumentType::Value inArgType, DataModelDataType::Value inValueType) + : CHandleObject(inHandle) + , m_HandlerArgInfo(inAction, inName, inArgType, inValueType) + { + } + + static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeActionHandlerArgument; + EHandleObjectType GetType() override { return s_Type; } +}; + +class CSimpleActionCore : public CHandleBase, public IActionCore +{ + mutable TStringTablePtr m_StringTable; + +public: // Use + CSimpleActionCore(TStringTablePtr strTable) + : m_StringTable(strTable) + { + } + + IStringTable &GetStringTable() const override { return *m_StringTable.get(); } + TStringTablePtr GetStringTablePtr() const override { return m_StringTable; } + // Action + Qt3DSDMActionHandle CreateAction(Qt3DSDMInstanceHandle inInstance, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner, SLong4 inTriggerTargetObjects) override; + void DeleteAction(Qt3DSDMActionHandle inAction, Qt3DSDMInstanceHandle &outInstance) override; + const SActionInfo &GetActionInfo(Qt3DSDMActionHandle inAction) const override; + void GetActions(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const override; + void GetActions(Qt3DSDMSlideHandle inSlide, TActionHandleList &outActions) const override; + void GetActions(Qt3DSDMInstanceHandle inOwner, TActionHandleList &outActions) const override; + void GetActions(TActionHandleList &outActions) const override; + + // Return the instance that was allocated for this action. + Qt3DSDMInstanceHandle GetActionInstance(Qt3DSDMActionHandle inAction) const override; + // Reverse lookup into the action system so you can match actions to instances. + Qt3DSDMActionHandle GetActionByInstance(Qt3DSDMInstanceHandle inActionInstance) const override; + + // Action Properties + void SetTriggerObject(Qt3DSDMActionHandle inAction, const SObjectRefType &inTriggerObject) override; + void SetTargetObject(Qt3DSDMActionHandle inAction, const SObjectRefType &inTargetObject) override; + void SetEvent(Qt3DSDMActionHandle inAction, const wstring &inEvent) override; + void SetHandler(Qt3DSDMActionHandle inAction, const wstring &inHandler) override; + + // Action Argument + Qt3DSDMHandlerArgHandle AddHandlerArgument(Qt3DSDMActionHandle inAction, const TCharStr &inName, + HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) override; + void RemoveHandlerArgument(Qt3DSDMHandlerArgHandle inHandlerArgument) override; + const SHandlerArgumentInfo & + GetHandlerArgumentInfo(Qt3DSDMHandlerArgHandle inHandlerArgument) const override; + void GetHandlerArguments(Qt3DSDMActionHandle inAction, + THandlerArgHandleList &outHandlerArguments) const override; + + // Action Argument Properties + void GetHandlerArgumentValue(Qt3DSDMHandlerArgHandle inHandlerArgument, SValue &outValue) const override; + void SetHandlerArgumentValue(Qt3DSDMHandlerArgHandle inHandlerArgument, const SValue &inValue) override; + + // CHandleBase + bool HandleValid(int inHandle) const override { return CHandleBase::HandleValid(inHandle); } + + // Helper functions + Qt3DSDMActionHandle CreateActionWithHandle(int inHandle, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner); + Qt3DSDMHandlerArgHandle AddHandlerArgumentWithHandle(int inHandle, Qt3DSDMActionHandle inAction, + const TCharStr &inName, + HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType); + + static SAction *GetActionNF(int inHandle, THandleObjectMap &inObjects) + { + return const_cast<SAction *>( + GetActionNF(inHandle, static_cast<const THandleObjectMap &>(inObjects))); + } + + static const SAction *GetActionNF(int inHandle, const THandleObjectMap &inObjects) + { + const SAction *theAction = GetHandleObject<SAction>(inHandle, inObjects); + if (theAction) + return theAction; + throw ActionNotFound(L""); + } + + static SHandlerArgument *GetHandlerArgumentNF(int inHandle, THandleObjectMap &inObjects) + { + return const_cast<SHandlerArgument *>( + GetHandlerArgumentNF(inHandle, static_cast<const THandleObjectMap &>(inObjects))); + } + + static const SHandlerArgument *GetHandlerArgumentNF(int inHandle, + const THandleObjectMap &inObjects) + { + const SHandlerArgument *theItem = GetHandleObject<SHandlerArgument>(inHandle, inObjects); + if (theItem) + return theItem; + throw HandlerArgumentNotFound(L""); + } +}; + +typedef std::shared_ptr<CSimpleActionCore> TSimpleActionCorePtr; +} + +#endif diff --git a/src/dm/systems/cores/SimpleAnimationCore.cpp b/src/dm/systems/cores/SimpleAnimationCore.cpp new file mode 100644 index 0000000..00d6df4 --- /dev/null +++ b/src/dm/systems/cores/SimpleAnimationCore.cpp @@ -0,0 +1,618 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "SimpleAnimationCore.h" + +#ifdef _WIN32 +#pragma warning(disable : 4503) // decorated name length exceeded +#endif + +typedef long INT32; +typedef float FLOAT; +#define DATALOGGER_CUBICROOT 0 + +struct SPerfLogEvent +{ + SPerfLogEvent(int) {} +}; + +typedef SPerfLogEvent TPerfLogMathEvent1; + +#include "Qt3DSCubicRoots.h" +#include "Qt3DSCubicRootsImpl.h" +#include "Qt3DSBezierEval.h" +using namespace std; + +namespace qt3dsdm { + +Qt3DSDMAnimationHandle +CSimpleAnimationCore::CreateAnimation(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType, bool inFirstKeyframeDynamic) +{ + if (GetAnimation(inSlide, inInstance, inProperty, inIndex).Valid()) + throw AnimationExists(L""); + + int nextId = GetNextId(); + Qt3DSDMAnimationHandle retval = CreateAnimationWithHandle( + nextId, inSlide, inInstance, inProperty, inIndex, inAnimationType, inFirstKeyframeDynamic); + AddAnimationToLookupCache(retval); + return retval; +} + +void CSimpleAnimationCore::DeleteAnimation(Qt3DSDMAnimationHandle inAnimation) +{ + RemoveAnimationFromLookupCache(inAnimation); + SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + do_all(theItem->m_Keyframes, std::bind(EraseHandle, + std::placeholders::_1, std::ref(m_Objects))); + EraseHandle(inAnimation, m_Objects); +} + +void CSimpleAnimationCore::EnsureAnimationCache() const +{ + if (m_AnimationMatchesCache.size() == 0) { + for (THandleObjectMap::const_iterator theIter = m_Objects.begin(), theEnd = m_Objects.end(); + theIter != theEnd; ++theIter) { + if (theIter->second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack) + AddAnimationToLookupCache(static_pointer_cast<SAnimationTrack>(theIter->second)); + } + } +} + +Qt3DSDMAnimationHandle CSimpleAnimationCore::GetAnimation(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + size_t inIndex) const +{ + EnsureAnimationCache(); + + pair<TStateInstanceAnimationMap::const_iterator, TStateInstanceAnimationMap::const_iterator> + theRange(m_AnimationMatchesCache.equal_range( + make_pair(inSlide.GetHandleValue(), inInstance.GetHandleValue()))); + for (TStateInstanceAnimationMap::const_iterator theIter = theRange.first; + theIter != theRange.second; ++theIter) { + std::shared_ptr<SAnimationTrack> theItem = theIter->second; + if (inSlide.GetHandleValue() == theItem->m_Slide + && inInstance.GetHandleValue() == theItem->m_Instance + && inProperty.GetHandleValue() == theItem->m_Property && inIndex == theItem->m_Index) + return theItem->m_Handle; + } + return 0; +} + +SAnimationInfo CSimpleAnimationCore::GetAnimationInfo(Qt3DSDMAnimationHandle inAnimation) const +{ + if (m_Objects.find(inAnimation) != m_Objects.end()) { + const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + return CreateAnimationInfo(theItem->m_Slide, theItem->m_Instance, theItem->m_Property, + theItem->m_Index, theItem->m_AnimationType, + theItem->m_FirstKeyframeDynamic, theItem->m_ArtistEdited); + } + return SAnimationInfo(); +} + +inline void AddIfAnimation(const THandleObjectPair &inPair, TAnimationHandleList &outAnimations) +{ + if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack) + outAnimations.push_back(inPair.first); +} + +void CSimpleAnimationCore::GetAnimations(TAnimationHandleList &outAnimations) const +{ + outAnimations.clear(); + do_all(m_Objects, std::bind(AddIfAnimation, std::placeholders::_1, std::ref(outAnimations))); +} + +void CSimpleAnimationCore::GetAnimations(TAnimationInfoList &outAnimations, + Qt3DSDMSlideHandle inMaster, + Qt3DSDMSlideHandle inSlide) const +{ + outAnimations.clear(); + for (THandleObjectMap::const_iterator iter = m_Objects.begin(), end = m_Objects.end(); + iter != end; ++iter) { + if (iter->second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack) { + const SAnimationTrack *theItem = + static_cast<const SAnimationTrack *>(iter->second.get()); + // If either master or slide is valid, then item slide must match. + // If item slide matches neither, then we ignore unless neither are valid. + bool keep = (theItem->m_Slide == inMaster || theItem->m_Slide == inSlide) + || (inMaster.Valid() == false && inSlide.Valid() == false); + if (keep) { + outAnimations.push_back( + CreateAnimationInfo(theItem->m_Slide, theItem->m_Instance, theItem->m_Property, + theItem->m_Index, theItem->m_AnimationType, + theItem->m_FirstKeyframeDynamic, theItem->m_ArtistEdited)); + } + } + } +} + +inline void AddSpecificAnimationsIf(const THandleObjectPair &inPair, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + TAnimationHandleList &outAnimations) +{ + if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack) { + const SAnimationTrack *theTrack = static_cast<const SAnimationTrack *>(inPair.second.get()); + if (theTrack->m_Slide == inSlide && theTrack->m_Instance == inInstance) + outAnimations.push_back(inPair.first); + } +} + +void CSimpleAnimationCore::GetSpecificInstanceAnimations(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + TAnimationHandleList &outAnimations) +{ + EnsureAnimationCache(); + pair<TStateInstanceAnimationMap::const_iterator, TStateInstanceAnimationMap::const_iterator> + theRange(m_AnimationMatchesCache.equal_range( + make_pair(inSlide.GetHandleValue(), inInstance.GetHandleValue()))); + for (TStateInstanceAnimationMap::const_iterator iter = theRange.first; iter != theRange.second; + ++iter) + outAnimations.push_back(iter->second->m_Handle); +} + +void CSimpleAnimationCore::SetFirstKeyframeDynamic(Qt3DSDMAnimationHandle inAnimation, bool inValue) +{ + SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + theItem->m_FirstKeyframeDynamic = inValue; + SetIsArtistEdited(inAnimation); +} + +inline void CheckKeyframeType(EAnimationType inExpected, const TKeyframe &inKeyframe) +{ + if (inExpected != GetKeyframeType(inKeyframe)) + throw AnimationKeyframeTypeError(L""); +} + +// keyframe manipulation +Qt3DSDMKeyframeHandle CSimpleAnimationCore::InsertKeyframe(Qt3DSDMAnimationHandle inAnimation, + const TKeyframe &inKeyframe) +{ + SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + CheckKeyframeType(theItem->m_AnimationType, inKeyframe); + int nextId = GetNextId(); + m_Objects.insert( + make_pair(nextId, (THandleObjectPtr) new SKeyframe(nextId, inAnimation, inKeyframe))); + theItem->m_Keyframes.push_back(nextId); + theItem->m_KeyframesDirty = true; + SetIsArtistEdited(inAnimation); + return nextId; +} + +void CSimpleAnimationCore::EraseKeyframe(Qt3DSDMKeyframeHandle inKeyframe) +{ + SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects); + int theAnimHandle(theKeyframe->m_Animation); + SAnimationTrack *theItem = GetAnimationNF(theAnimHandle, m_Objects); + EraseHandle(inKeyframe, m_Objects); + erase_if(theItem->m_Keyframes, std::bind(equal_to<int>(), + std::placeholders::_1, inKeyframe.GetHandleValue())); + SetIsArtistEdited(theAnimHandle); +} + +void CSimpleAnimationCore::DeleteAllKeyframes(Qt3DSDMAnimationHandle inAnimation) +{ + SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + do_all(theItem->m_Keyframes, std::bind(EraseHandle, + std::placeholders::_1, std::ref(m_Objects))); + theItem->m_Keyframes.clear(); + SetIsArtistEdited(inAnimation); +} + +Qt3DSDMAnimationHandle +CSimpleAnimationCore::GetAnimationForKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const +{ + const SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects); + return theKeyframe->m_Animation; +} + +TKeyframe CSimpleAnimationCore::GetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe) const +{ + const SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects); + return theKeyframe->m_Keyframe; +} + +void CSimpleAnimationCore::SetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData) +{ + DoSetKeyframeData(inKeyframe, inData); + SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects); + SetIsArtistEdited(theKeyframe->m_Animation); +} + +void CSimpleAnimationCore::DoSetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe, + const TKeyframe &inData) +{ + SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects); + CheckKeyframeType(GetKeyframeType(theKeyframe->m_Keyframe), inData); + theKeyframe->m_Keyframe = inData; + SAnimationTrack *theItem = GetAnimationNF(theKeyframe->m_Animation, m_Objects); + theItem->m_KeyframesDirty = true; +} + +bool KeyframeLessThan(int inLeftSide, int inRightSide, const THandleObjectMap &inObjects) +{ + const SKeyframe *theLeft = CSimpleAnimationCore::GetKeyframeNF(inLeftSide, inObjects); + const SKeyframe *theRight = CSimpleAnimationCore::GetKeyframeNF(inRightSide, inObjects); + return KeyframeTime(theLeft->m_Keyframe) < KeyframeTime(theRight->m_Keyframe); +} + +void SortKeyframes(TKeyframeHandleList &inKeyframes, const THandleObjectMap &inObjects) +{ + return stable_sort(inKeyframes.begin(), inKeyframes.end(), + std::bind(KeyframeLessThan, std::placeholders::_1, + std::placeholders::_2, std::ref(inObjects))); +} + +void CheckKeyframesSorted(const SAnimationTrack *theItem, const THandleObjectMap &inObjects) +{ + if (theItem->m_KeyframesDirty) { + SAnimationTrack *theNonConst = const_cast<SAnimationTrack *>(theItem); + SortKeyframes(theNonConst->m_Keyframes, inObjects); + theNonConst->m_KeyframesDirty = false; + } +} + +void CSimpleAnimationCore::GetKeyframes(Qt3DSDMAnimationHandle inAnimation, + TKeyframeHandleList &outKeyframes) const +{ + const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + CheckKeyframesSorted(theItem, m_Objects); + outKeyframes = theItem->m_Keyframes; +} + +size_t CSimpleAnimationCore::GetKeyframeCount(Qt3DSDMAnimationHandle inAnimation) const +{ + const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + return theItem->m_Keyframes.size(); +} + +bool CSimpleAnimationCore::IsFirstKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const +{ + Qt3DSDMAnimationHandle theAnimation = GetAnimationForKeyframe(inKeyframe); + if (theAnimation.Valid()) { + const SAnimationTrack *theItem = GetAnimationNF(theAnimation, m_Objects); + return theItem->m_Keyframes.size() && theItem->m_Keyframes[0] == inKeyframe; + } + return false; +} + +void CSimpleAnimationCore::OffsetAnimations(Qt3DSDMSlideHandle /*inSlide*/, + Qt3DSDMInstanceHandle /*inInstance*/, long /*inOffset*/) +{ + throw std::runtime_error("unimplemented"); +} + +void CSimpleAnimationCore::SetIsArtistEdited(Qt3DSDMAnimationHandle inAnimation, bool inEdited) +{ + if (m_Objects.find(inAnimation) == m_Objects.end()) { + Q_ASSERT(false); + return; + } + SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + if (theItem->m_ArtistEdited != inEdited) + theItem->m_ArtistEdited = inEdited; +} + +bool CSimpleAnimationCore::IsArtistEdited(Qt3DSDMAnimationHandle inAnimation) const +{ + if (m_Objects.find(inAnimation) == m_Objects.end()) { + return false; + } + const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + return theItem->m_ArtistEdited; +} + +inline bool KeyframeTimeLessThan(int inKeyframe, float inSeconds, const THandleObjectMap &inObjects) +{ + const SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, inObjects); + return KeyframeTime(theKeyframe->m_Keyframe) < inSeconds; +} + +inline bool KeyframeValueTimeLessThan(const TKeyframe &inLeft, const TKeyframe &inRight) +{ + return KeyframeTime(inLeft) < KeyframeTime(inRight); +} + +TKeyframe IntToKeyframe(int inKeyframe, const THandleObjectMap &inObjects) +{ + const SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, inObjects); + return theKeyframe->m_Keyframe; +} + +inline float KeyframeValue(int inKeyframe, const THandleObjectMap &inObjects) +{ + const SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, inObjects); + return KeyframeValueValue(theKeyframe->m_Keyframe); +} + +inline float EvaluateLinear(float inS1, float inS2, float inV1, float inV2, float inSeconds) +{ + float amount = (inSeconds - inS1) / (inS2 - inS1); + return inV1 + amount * (inV2 - inV1); +} + +inline float EvaluateLinearKeyframe(SLinearKeyframe &inK1, SLinearKeyframe &inK2, float inSeconds) +{ + return EvaluateLinear(inK1.m_KeyframeSeconds, inK2.m_KeyframeSeconds, inK1.m_KeyframeValue, + inK2.m_KeyframeValue, inSeconds); +} + +inline float DoBezierEvaluation(float inSeconds, const SBezierKeyframe &inK1, + const SBezierKeyframe &inK2) +{ + return Q3DStudio::EvaluateBezierKeyframe( + inSeconds, inK1.m_KeyframeSeconds, inK1.m_KeyframeValue, inK1.m_OutTangentTime, + inK1.m_OutTangentValue, inK2.m_InTangentTime, inK2.m_InTangentValue, inK2.m_KeyframeSeconds, + inK2.m_KeyframeValue); +} + +// Animation Evaluation. +float CSimpleAnimationCore::EvaluateAnimation(Qt3DSDMAnimationHandle inAnimation, + float inSeconds) const +{ + const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + if (theItem->m_Keyframes.empty()) + return 0.0f; + CheckKeyframesSorted(theItem, m_Objects); + // Default to linear for now. + SLinearKeyframe theKeyframe = { 0 }; + theKeyframe.m_KeyframeSeconds = inSeconds; + TKeyframe theSearchKey(theKeyframe); + function<TKeyframe(int)> theIntToKeyframe( + std::bind(IntToKeyframe, std::placeholders::_1, std::ref(m_Objects))); + + TKeyframeHandleList::const_iterator theBound = + lower_bound(theItem->m_Keyframes.begin(), theItem->m_Keyframes.end(), theSearchKey, + [theIntToKeyframe](const Qt3DSDMKeyframeHandle &inLeft, + const TKeyframe &inRight) + {return KeyframeTime(theIntToKeyframe(inLeft)) < KeyframeTime(inRight);}); + + if (theBound == theItem->m_Keyframes.end()) + return KeyframeValue(theItem->m_Keyframes.back(), m_Objects); + if (theBound == theItem->m_Keyframes.begin()) + return KeyframeValue(*theItem->m_Keyframes.begin(), m_Objects); + + TKeyframeHandleList::const_iterator theStartIter = theBound; + --theStartIter; + + // Both iterators must be valid at this point... + Qt3DSDMKeyframeHandle theStart = *theStartIter; + Qt3DSDMKeyframeHandle theFinish = *theBound; + switch (theItem->m_AnimationType) { + default: + throw AnimationEvaluationError(L""); + case EAnimationTypeLinear: { + SLinearKeyframe k1 = get<SLinearKeyframe>(theIntToKeyframe(theStart)); + SLinearKeyframe k2 = get<SLinearKeyframe>(theIntToKeyframe(theFinish)); + return EvaluateLinearKeyframe(k1, k2, inSeconds); + } + case EAnimationTypeBezier: { + SBezierKeyframe k1 = get<SBezierKeyframe>(theIntToKeyframe(theStart)); + SBezierKeyframe k2 = get<SBezierKeyframe>(theIntToKeyframe(theFinish)); + return DoBezierEvaluation(inSeconds, k1, k2); + } + case EAnimationTypeEaseInOut: { + SEaseInEaseOutKeyframe k1 = get<SEaseInEaseOutKeyframe>(theIntToKeyframe(theStart)); + SEaseInEaseOutKeyframe k2 = get<SEaseInEaseOutKeyframe>(theIntToKeyframe(theFinish)); + return DoBezierEvaluation( + inSeconds, CreateBezierKeyframeFromEaseInEaseOutKeyframe(NULL, k1, &k2.m_KeyframeValue), + CreateBezierKeyframeFromEaseInEaseOutKeyframe(&k1.m_KeyframeValue, k2, NULL)); + } + } +} + +bool CSimpleAnimationCore::KeyframeValid(Qt3DSDMKeyframeHandle inKeyframe) const +{ + return HandleObjectValid<SKeyframe>(inKeyframe, m_Objects); +} + +bool CSimpleAnimationCore::AnimationValid(Qt3DSDMAnimationHandle inAnimation) const +{ + return HandleObjectValid<SAnimationTrack>(inAnimation, m_Objects); +} + +Qt3DSDMAnimationHandle CSimpleAnimationCore::CreateAnimationWithHandle( + int inHandle, Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, EAnimationType inAnimationType, + bool inFirstKeyframeDynamic) +{ + if (HandleValid(inHandle)) + throw HandleExists(L""); + m_Objects.insert(make_pair(inHandle, (THandleObjectPtr) new SAnimationTrack( + inHandle, inSlide, inInstance, inProperty, inIndex, + inAnimationType, inFirstKeyframeDynamic, true))); + return inHandle; +} + +void CSimpleAnimationCore::AddAnimationToLookupCache(Qt3DSDMAnimationHandle inAnimation) const +{ + THandleObjectMap::const_iterator theAnim = m_Objects.find(inAnimation); + if (theAnim != m_Objects.end()) + AddAnimationToLookupCache(static_pointer_cast<SAnimationTrack>(theAnim->second)); +} +void CSimpleAnimationCore::RemoveAnimationFromLookupCache(Qt3DSDMAnimationHandle inAnimation) const +{ + THandleObjectMap::const_iterator theAnim = m_Objects.find(inAnimation); + if (theAnim != m_Objects.end()) + RemoveAnimationFromLookupCache(static_pointer_cast<SAnimationTrack>(theAnim->second)); +} + +// Ensure there is only one of these in the multimap. +void CSimpleAnimationCore::AddAnimationToLookupCache( + std::shared_ptr<SAnimationTrack> inAnimation) const +{ + Qt3DSDMSlideHandle theSlide = inAnimation->m_Slide; + Qt3DSDMInstanceHandle theInstance = inAnimation->m_Instance; + pair<TStateInstanceAnimationMap::iterator, TStateInstanceAnimationMap::iterator> theRange = + m_AnimationMatchesCache.equal_range( + make_pair(theSlide.GetHandleValue(), theInstance.GetHandleValue())); + for (TStateInstanceAnimationMap::iterator theIter = theRange.first; theIter != theRange.second; + ++theIter) { + if (theIter->second == inAnimation) + return; + } + m_AnimationMatchesCache.insert( + make_pair(make_pair(theSlide.GetHandleValue(), theInstance.GetHandleValue()), inAnimation)); +} + +// Remove this from the multimap +void CSimpleAnimationCore::RemoveAnimationFromLookupCache( + std::shared_ptr<SAnimationTrack> inAnimation) const +{ + TStateInstanceAnimationMap &theMap(m_AnimationMatchesCache); + Qt3DSDMSlideHandle theSlide = inAnimation->m_Slide; + Qt3DSDMInstanceHandle theInstance = inAnimation->m_Instance; + pair<TStateInstanceAnimationMap::iterator, TStateInstanceAnimationMap::iterator> theRange = + theMap.equal_range(make_pair(theSlide.GetHandleValue(), theInstance.GetHandleValue())); + for (TStateInstanceAnimationMap::iterator theIter = theRange.first; theIter != theRange.second; + ++theIter) { + if (theIter->second == inAnimation) { + theMap.erase(theIter); + break; + } + } +} + +//================================================================================ +// UICDMAnimation.h function implementations +//================================================================================ + +void CopyKeyframe(Qt3DSDMAnimationHandle inAnimation, Qt3DSDMKeyframeHandle inKeyframe, + const IAnimationCore &inSourceAnimationCore, IAnimationCore &inDestAnimationCore) +{ + TKeyframe theData = inSourceAnimationCore.GetKeyframeData(inKeyframe); + inDestAnimationCore.InsertKeyframe(inAnimation, theData); +} + +void CopyKeyframes(const IAnimationCore &inSourceAnimationCore, IAnimationCore &inDestAnimationCore, + Qt3DSDMAnimationHandle inDestAnimation, const TKeyframeHandleList &inKeyframes) +{ + do_all(inKeyframes, + std::bind(CopyKeyframe, inDestAnimation, std::placeholders::_1, + std::cref(inSourceAnimationCore), std::ref(inDestAnimationCore))); +} + +Qt3DSDMAnimationHandle CopyAnimation(TAnimationCorePtr inAnimationCore, + Qt3DSDMAnimationHandle inAnimation, Qt3DSDMSlideHandle inNewSlide, + Qt3DSDMInstanceHandle inNewInstance, + Qt3DSDMPropertyHandle inNewProperty, size_t inNewIndex) +{ + TKeyframeHandleList theKeyframes; + inAnimationCore->GetKeyframes(inAnimation, theKeyframes); + SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation)); + Qt3DSDMAnimationHandle theAnimation = + inAnimationCore->CreateAnimation(inNewSlide, inNewInstance, inNewProperty, inNewIndex, + theInfo.m_AnimationType, theInfo.m_DynamicFirstKeyframe); + CopyKeyframes(*inAnimationCore, *inAnimationCore, theAnimation, theKeyframes); + return theAnimation; +} + +SBezierKeyframe GetBezierKeyframeData(Qt3DSDMKeyframeHandle inKeyframe, + const IAnimationCore &inAnimationCore) +{ + return get<SBezierKeyframe>(inAnimationCore.GetKeyframeData(inKeyframe)); +} + +SEaseInEaseOutKeyframe GetEaseInEaseOutKeyframeData(Qt3DSDMKeyframeHandle inKeyframe, + const IAnimationCore &inAnimationCore) +{ + return get<SEaseInEaseOutKeyframe>(inAnimationCore.GetKeyframeData(inKeyframe)); +} + +TKeyframeHandleList::iterator SafeIncrementIterator(TKeyframeHandleList::iterator inIter, + const TKeyframeHandleList::iterator &inEnd) +{ + return inIter == inEnd ? inEnd : inIter + 1; +} + +void GetKeyframesAsBezier(Qt3DSDMAnimationHandle inAnimation, const IAnimationCore &inAnimationCore, + TBezierKeyframeList &outKeyframes) +{ + SAnimationInfo theInfo(inAnimationCore.GetAnimationInfo(inAnimation)); + TKeyframeHandleList theKeyframes; + inAnimationCore.GetKeyframes(inAnimation, theKeyframes); + outKeyframes.resize(theKeyframes.size()); + switch (theInfo.m_AnimationType) { + default: + throw invalid_argument("AnimationType"); + case EAnimationTypeBezier: + transform(theKeyframes.begin(), theKeyframes.end(), outKeyframes.begin(), + std::bind(GetBezierKeyframeData, std::placeholders::_1, + std::cref(inAnimationCore))); + break; + case EAnimationTypeEaseInOut: { + + TKeyframeHandleList::iterator theEndKeyframe = theKeyframes.end(); + + typedef std::function<SEaseInEaseOutKeyframe(Qt3DSDMKeyframeHandle)> TConvertFunc; + TConvertFunc theDataConverter( + std::bind(GetEaseInEaseOutKeyframeData, std::placeholders::_1, + std::cref(inAnimationCore))); + + TKeyframeHandleList::iterator thePreviousKeyframe = theKeyframes.begin(); + + TKeyframeHandleList::iterator theCurrentKeyframe = + SafeIncrementIterator(thePreviousKeyframe, theEndKeyframe); + + TKeyframeHandleList::iterator theNextKeyframe = + SafeIncrementIterator(theCurrentKeyframe, theEndKeyframe); + + TBezierKeyframeList::iterator theResult(outKeyframes.begin()); + + if (thePreviousKeyframe != theEndKeyframe) { + float *theNextValuePtr = NULL; + float theNextValue; + if (theCurrentKeyframe != theEndKeyframe) { + theNextValue = theDataConverter(*theCurrentKeyframe).m_KeyframeValue; + theNextValuePtr = &theNextValue; + } + *theResult = CreateBezierKeyframeFromEaseInEaseOutKeyframe( + NULL, theDataConverter(*thePreviousKeyframe), theNextValuePtr); + theResult = theResult + 1; + } + for (; theCurrentKeyframe != theEndKeyframe; + ++thePreviousKeyframe, + theCurrentKeyframe = SafeIncrementIterator(theCurrentKeyframe, theEndKeyframe), + theNextKeyframe = SafeIncrementIterator(theNextKeyframe, theEndKeyframe), + ++theResult) { + float theLastValue(theDataConverter(*thePreviousKeyframe).m_KeyframeValue); + float *theNextValuePtr = NULL; + float theNextValue; + if (theNextKeyframe != theEndKeyframe) { + theNextValue = theDataConverter(*theNextKeyframe).m_KeyframeValue; + theNextValuePtr = &theNextValue; + } + *theResult = CreateBezierKeyframeFromEaseInEaseOutKeyframe( + &theLastValue, theDataConverter(*theCurrentKeyframe), theNextValuePtr); + } + } break; + } +} +} diff --git a/src/dm/systems/cores/SimpleAnimationCore.h b/src/dm/systems/cores/SimpleAnimationCore.h new file mode 100644 index 0000000..cb4c415 --- /dev/null +++ b/src/dm/systems/cores/SimpleAnimationCore.h @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef ANIMATIONCOREH +#define ANIMATIONCOREH +#include "Qt3DSDMAnimation.h" +#include "HandleSystemBase.h" +#include <unordered_map> + +namespace { +struct pair_hash { + template <class T1, class T2> + std::size_t operator () (const std::pair<T1, T2> &p) const { + auto h1 = std::hash<T1>{}(p.first); + auto h2 = std::hash<T2>{}(p.second); + + return h1 ^ h2; + } + }; +} + +namespace qt3dsdm { +struct SAnimationTrack : public CHandleObject +{ + int m_Slide; + int m_Instance; + int m_Property; + EAnimationType m_AnimationType; + size_t m_Index; + TKeyframeHandleList m_Keyframes; + bool m_KeyframesDirty; + bool m_FirstKeyframeDynamic; + bool m_ArtistEdited; + + SAnimationTrack() + : m_Slide(0) + , m_Instance(0) + , m_Property(0) + , m_AnimationType(EAnimationTypeLinear) + , m_Index(0) + , m_KeyframesDirty(false) + , m_FirstKeyframeDynamic(false) + , m_ArtistEdited(true) + { + } + + SAnimationTrack(int inHandle, Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, EAnimationType inAnimationType, + bool inFirstKeyframeDynamic, bool inArtistEdited) + : CHandleObject(inHandle) + , m_Slide(inSlide) + , m_Instance(inInstance) + , m_Property(inProperty) + , m_AnimationType(inAnimationType) + , m_Index(inIndex) + , m_KeyframesDirty(false) + , m_FirstKeyframeDynamic(inFirstKeyframeDynamic) + , m_ArtistEdited(inArtistEdited) + { + } + + static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeSAnimationTrack; + EHandleObjectType GetType() override { return s_Type; } +}; + +struct SKeyframe : public CHandleObject +{ + TKeyframe m_Keyframe; + int m_Animation; + + SKeyframe(int inHandle, int inAnimation, const TKeyframe &inKeyframe) + : CHandleObject(inHandle) + , m_Keyframe(inKeyframe) + , m_Animation(inAnimation) + { + } + + static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeSKeyframe; + EHandleObjectType GetType() override { return s_Type; } +}; + +class CAnimationCoreProducer; + +class CSimpleAnimationCore : public CHandleBase, public IAnimationCore +{ + TStringTablePtr m_StringTable; + typedef std::unordered_multimap<std::pair<int, int>, + std::shared_ptr<SAnimationTrack>, pair_hash> TStateInstanceAnimationMap; + // state,instance pair map to animation handle to speed up querying if a particular + // property is animated. + mutable TStateInstanceAnimationMap m_AnimationMatchesCache; + +public: // Use + friend class CAnimationCoreProducer; + // We don't use the string table ptr we are constructed with + // but the testing system needs an unified interface to creating + // objects + CSimpleAnimationCore() {} + CSimpleAnimationCore(TStringTablePtr strTable) + : m_StringTable(strTable) + { + } + TStringTablePtr GetStringTablePtr() const { return m_StringTable; } + + Qt3DSDMAnimationHandle CreateAnimation(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType, + bool inFirstKeyframeDynamic) override; + void DeleteAnimation(Qt3DSDMAnimationHandle inAnimation) override; + Qt3DSDMAnimationHandle GetAnimation(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex) const override; + SAnimationInfo GetAnimationInfo(Qt3DSDMAnimationHandle inAnimation) const override; + void GetAnimations(TAnimationHandleList &outAnimations) const override; + void GetAnimations(TAnimationInfoList &outAnimations, Qt3DSDMSlideHandle inMaster, + Qt3DSDMSlideHandle inSlide) const override; + void GetSpecificInstanceAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + TAnimationHandleList &outAnimations) override; + + void SetFirstKeyframeDynamic(Qt3DSDMAnimationHandle inAnimation, bool inValue) override; + + // keyframe manipulation + Qt3DSDMKeyframeHandle InsertKeyframe(Qt3DSDMAnimationHandle inAnimation, + const TKeyframe &inKeyframe) override; + void EraseKeyframe(Qt3DSDMKeyframeHandle inKeyframe) override; + void DeleteAllKeyframes(Qt3DSDMAnimationHandle inAnimation) override; + Qt3DSDMAnimationHandle GetAnimationForKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const override; + TKeyframe GetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe) const override; + void SetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData) override; + // Set the keyframe data, but don't set the artist edited flag. Used for undo/redo operations + // where the artist edited flag has handeled by a different transaction + void DoSetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData); + void GetKeyframes(Qt3DSDMAnimationHandle inAnimation, TKeyframeHandleList &outKeyframes) const override; + size_t GetKeyframeCount(Qt3DSDMAnimationHandle inAnimation) const override; + bool IsFirstKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const override; + // Only implemented in the producer for now. + void OffsetAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + long inOffset) override; + + void SetIsArtistEdited(Qt3DSDMAnimationHandle inAnimation, bool inEdited = true) override; + bool IsArtistEdited(Qt3DSDMAnimationHandle inAnimation) const override; + + // Animation Evaluation. + float EvaluateAnimation(Qt3DSDMAnimationHandle inAnimation, float inSeconds) const override; + + bool KeyframeValid(Qt3DSDMKeyframeHandle inKeyframe) const override; + bool AnimationValid(Qt3DSDMAnimationHandle inAnimation) const override; + + // Only implemented at the producer level, not at the simple core level. + void CopyAnimations(Qt3DSDMSlideHandle /*inSourceSlide*/, + Qt3DSDMInstanceHandle /*inSourceInstance*/, + Qt3DSDMSlideHandle /*inDestSlide*/, Qt3DSDMInstanceHandle /*inDestInstance*/) override + { + throw AnimationNotFound(L""); + } + + // Lookup cache management so we can find particular animations quickly. + void ClearAnimationMatchesLookupCache() const { m_AnimationMatchesCache.clear(); } + void AddAnimationToLookupCache(Qt3DSDMAnimationHandle inAnimation) const; + void RemoveAnimationFromLookupCache(Qt3DSDMAnimationHandle inAnimation) const; + void AddAnimationToLookupCache(std::shared_ptr<SAnimationTrack> inAnimation) const; + void RemoveAnimationFromLookupCache(std::shared_ptr<SAnimationTrack> inAnimation) const; + + void EnsureAnimationCache() const; + + Qt3DSDMAnimationHandle CreateAnimationWithHandle(int inHandle, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType, + bool inFirstKeyframeDynamic); + + static SAnimationTrack *GetAnimationNF(int inHandle, THandleObjectMap &inObjects) + { + return const_cast<SAnimationTrack *>( + GetAnimationNF(inHandle, static_cast<const THandleObjectMap &>(inObjects))); + } + + static const SAnimationTrack *GetAnimationNF(int inHandle, const THandleObjectMap &inObjects) + { + const SAnimationTrack *theAnimation = GetHandleObject<SAnimationTrack>(inHandle, inObjects); + if (theAnimation) + return theAnimation; + throw AnimationNotFound(L""); + } + + static SKeyframe *GetKeyframeNF(int inHandle, THandleObjectMap &inObjects) + { + return const_cast<SKeyframe *>( + GetKeyframeNF(inHandle, static_cast<const THandleObjectMap &>(inObjects))); + } + + static const SKeyframe *GetKeyframeNF(int inHandle, const THandleObjectMap &inObjects) + { + const SKeyframe *theItem = GetHandleObject<SKeyframe>(inHandle, inObjects); + if (theItem) + return theItem; + throw AnimationKeyframeNotFound(L""); + } +}; + +typedef std::shared_ptr<CSimpleAnimationCore> TSimpleAnimationCorePtr; +} + +#endif diff --git a/src/dm/systems/cores/SimpleDataCore.cpp b/src/dm/systems/cores/SimpleDataCore.cpp new file mode 100644 index 0000000..d6a1470 --- /dev/null +++ b/src/dm/systems/cores/SimpleDataCore.cpp @@ -0,0 +1,574 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "SimpleDataCore.h" + +namespace qt3dsdm { +Qt3DSDMDebugLogFunction g_DataModelDebugLogger = NULL; +// Instances +Qt3DSDMInstanceHandle CSimpleDataCore::CreateInstance(Qt3DSDMInstanceHandle hdl) +{ + int nextId = hdl; + if (hdl.Valid() == false) + nextId = GetNextId(); + + return CreateInstanceWithHandle(nextId); +} + +inline void RemoveParentFromClass(int inParent, int inChild, THandleObjectMap &inMap) +{ + TDataModelInstancePtr theInstance = CSimpleDataCore::GetInstanceNF(inChild, inMap); + theInstance->m_Parents.erase(theInstance->m_Parents.find(inParent)); + // Cascade the delete operation +} + +void CSimpleDataCore::DeleteInstance(Qt3DSDMInstanceHandle inHandle) +{ + // Ensure it exists in the first place. + CSimpleDataCore::GetInstanceNF(inHandle, m_Objects); // Check for instance existance + CSimpleDataCore::EraseHandle(inHandle, m_Objects); + TIntList properties; + TIntList instances; + do_all(m_Objects, std::bind(FindRelatedItemsForDelete, inHandle.GetHandleValue(), + std::ref(properties), std::ref(instances), std::placeholders::_1)); + do_all(instances, std::bind(RemoveParentFromClass, inHandle.GetHandleValue(), + std::placeholders::_1, std::ref(m_Objects))); + do_all(properties, std::bind(EraseHandle, std::placeholders::_1, std::ref(m_Objects))); +} + +void CSimpleDataCore::GetInstances(TInstanceHandleList &outInstances) const +{ + // reserve the vector to m_Objects.size() to prevent vector reallocation + // m_Objects.size() is the upper bound of the no of instances + // the exact no of instances = m_Objects.size() - the no of properties as added by + // CClientDataModelBridge::InitializeDataCore (as of now, we have 31 properties) + outInstances.reserve(m_Objects.size()); + do_all(m_Objects, std::bind(MaybeAddObject<CDataModelInstance, Qt3DSDMInstanceHandle>, + std::placeholders::_1, std::ref(outInstances))); +} + +// Get instances that are derived from a specific parent +void CSimpleDataCore::GetInstancesDerivedFrom(TInstanceHandleList &outInstances, + Qt3DSDMInstanceHandle inParentHandle) const +{ + do_all(m_Objects, std::bind(&CSimpleDataCore::AddInstanceIfDerivedFrom, this, + std::placeholders::_1, + std::ref(outInstances), inParentHandle)); +} + +// add instance that is derived from a specific parent +void CSimpleDataCore::AddInstanceIfDerivedFrom(const std::pair<int, THandleObjectPtr> &inItem, + TInstanceHandleList &outInstances, + Qt3DSDMInstanceHandle inParentHandle) const +{ + if (inItem.second->GetType() == CHandleObject::EHandleObjectTypeCDataModelInstance) { + TDataModelInstancePtr theInstance = static_pointer_cast<CDataModelInstance>(inItem.second); + if (IsInstanceOrDerivedFromHelper(theInstance, inParentHandle)) + outInstances.push_back(inItem.first); + } +} + +// Derivation +void CSimpleDataCore::DeriveInstance(Qt3DSDMInstanceHandle inInstance, Qt3DSDMInstanceHandle inParent) +{ + if (g_DataModelDebugLogger) + g_DataModelDebugLogger("CSimpleDataCore::DeriveInstance Enter"); + TDataModelInstancePtr theInstance = CSimpleDataCore::GetInstanceNF(inInstance, m_Objects); + if (theInstance->m_Parents.find(inParent) == theInstance->m_Parents.end()) { + std::shared_ptr<CDataModelInstance> theParent(GetInstanceNF(inParent, m_Objects)); + theInstance->m_Parents.insert(make_pair(inParent, theParent)); + } + if (g_DataModelDebugLogger) + g_DataModelDebugLogger("CSimpleDataCore::DeriveInstance Leave"); +} + +void CSimpleDataCore::GetInstanceParents(Qt3DSDMInstanceHandle inHandle, + TInstanceHandleList &outParents) const +{ + const TDataModelInstancePtr theInstance = GetInstanceNF(inHandle, m_Objects); + for (CDataModelInstance::TInstancePairList::const_iterator theParent = + theInstance->m_Parents.begin(); + theParent != theInstance->m_Parents.end(); ++theParent) + outParents.push_back(theParent->first); +} + +inline bool ComparePropertyNames(const TCharStr &inName, int inPropHandle, + const THandleObjectMap &inObjects) +{ + if (CSimpleDataCore::GetPropertyDefinitionNF(inPropHandle, inObjects)->m_Definition.m_Name + == inName) + return true; + return false; +} + +inline const wchar_t *SafeStrPtr(const wchar_t *inData) +{ + return inData == NULL ? L"" : inData; +} + +// Properties +Qt3DSDMPropertyHandle CSimpleDataCore::AddProperty(Qt3DSDMInstanceHandle inInstance, TCharPtr inName, + DataModelDataType::Value inPropType) +{ + QT3DSDM_LOG_FUNCTION("CSimpleDataCore::AddProperty"); + QT3DSDM_DEBUG_LOG(m_StringTable->GetNarrowStr(inName)); + TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects); + TCharStr theName(inName); + if (find_if<TIntList::iterator>( + theInstance->m_Properties, + std::bind(ComparePropertyNames, std::ref(theName), + std::placeholders::_1, std::ref(m_Objects))) + != theInstance->m_Properties.end()) { + QT3DSDM_DEBUG_LOG("Property Exists!!"); + throw PropertyExists(L""); + } + + int nextId = GetNextId(); + return AddPropertyWithHandle(nextId, inInstance, inName, inPropType); +} + +void CSimpleDataCore::GetInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const +{ + transformv_all(GetInstanceNF(inInstance, m_Objects)->m_Properties, outProperties); +} + +const Qt3DSDMPropertyDefinition &CSimpleDataCore::GetProperty(Qt3DSDMPropertyHandle inProperty) const +{ + const CDataModelPropertyDefinitionObject *theProp = + GetPropertyDefinitionNF(inProperty, m_Objects); + return theProp->m_Definition; +} + +void CSimpleDataCore::RemoveProperty(Qt3DSDMPropertyHandle inProperty) +{ + CDataModelPropertyDefinitionObject *theProp = + CSimpleDataCore::GetPropertyDefinitionNF(inProperty, m_Objects); + TDataModelInstancePtr theInstance = + CSimpleDataCore::GetInstanceNF(theProp->m_Definition.m_Instance, m_Objects); + erase_if(theInstance->m_Properties, + std::bind(equal_to<int>(), inProperty.GetHandleValue(), std::placeholders::_1)); + CSimpleDataCore::EraseHandle(inProperty, m_Objects); +} + +inline bool PropertyMatches(int inProperty, Qt3DSDMPropertyHandle inTarget) +{ + return inProperty == inTarget.GetHandleValue(); +} + +inline bool GetInstanceValue(Qt3DSDMInstanceHandle inInstanceHandle, + Qt3DSDMPropertyHandle inPropertyHandle, CSimpleDataCore &inDataCore, + SValue &outValue) +{ + const TDataModelInstancePtr theInstance = + CSimpleDataCore::GetInstanceNF(inInstanceHandle, inDataCore.m_Objects); + + TPropertyPairHash::const_iterator theInstanceProp = + theInstance->m_PropertyValues.find(inPropertyHandle.GetHandleValue()); + if (theInstanceProp != theInstance->m_PropertyValues.end()) { + outValue = theInstanceProp->second.second.GetValue(); + return true; + } + return false; +} + +inline void CopyInstanceProperty(Qt3DSDMPropertyHandle inSrcPropertyHandle, + Qt3DSDMInstanceHandle inSrcInstanceHandle, + Qt3DSDMInstanceHandle inInstanceHandle, CSimpleDataCore &inDataCore) +{ + // create the property definition that matches the source + const Qt3DSDMPropertyDefinition &theProperty = inDataCore.GetProperty(inSrcPropertyHandle); + Qt3DSDMPropertyHandle theNewProperty = + inDataCore.AddProperty(inInstanceHandle, theProperty.m_Name.wide_str(), theProperty.m_Type); + // copy the value if one exists on the src. + SValue theValue; + if (GetInstanceValue(inSrcInstanceHandle, inSrcPropertyHandle, inDataCore, theValue)) + inDataCore.SetInstancePropertyValue(inInstanceHandle, theNewProperty, theValue); +} + +// logic : if destination property is one gained through derivation in inSrcInstanceHandle, copy the +// value over. +inline void CopyAggregatedPropertyValues(Qt3DSDMPropertyHandle inDestPropertyHandle, + Qt3DSDMInstanceHandle inSrcInstanceHandle, + Qt3DSDMInstanceHandle inInstanceHandle, + const TPropertyHandleList &inSrcNonAggregateList, + CSimpleDataCore &inDataCore) +{ + if (find_if(inSrcNonAggregateList.begin(), inSrcNonAggregateList.end(), + bind(PropertyMatches, inDestPropertyHandle, std::placeholders::_1)) + == inSrcNonAggregateList.end() + && inDataCore.HasAggregateInstanceProperty(inSrcInstanceHandle, inDestPropertyHandle)) { + SValue theValue; + if (GetInstanceValue(inSrcInstanceHandle, inDestPropertyHandle, inDataCore, theValue)) + inDataCore.SetInstancePropertyValue(inInstanceHandle, inDestPropertyHandle, theValue); + } +} + +void CSimpleDataCore::CopyInstanceProperties(Qt3DSDMInstanceHandle inSrcInstance, + Qt3DSDMInstanceHandle inDestInstance) +{ + TPropertyHandleList theList; + GetInstanceProperties(inSrcInstance, theList); + do_all(theList, bind(CopyInstanceProperty, std::placeholders::_1, + inSrcInstance, inDestInstance, ref(*this))); + + TPropertyHandleList theDestList; + GetAggregateInstanceProperties(inDestInstance, theDestList); + do_all(theDestList, std::bind(CopyAggregatedPropertyValues, std::placeholders::_1, + inSrcInstance, inDestInstance, + theList, std::ref(*this))); +} + +void CSimpleDataCore::RemoveCachedValues(Qt3DSDMInstanceHandle inInstance) +{ + const TDataModelInstancePtr theInstance = CSimpleDataCore::GetInstanceNF(inInstance, m_Objects); + theInstance->RemoveCachedValues(); +} + +void GetAggregateProperties(const TDataModelInstancePtr inInstance, TIntList &inVisited, + TPropertyHandleList &outProperties) +{ + if (find(inVisited.begin(), inVisited.end(), inInstance->m_Handle) == inVisited.end()) { + inVisited.push_back(inInstance->m_Handle); + size_t theSize = outProperties.size(); + outProperties.resize(theSize + inInstance->m_Properties.size()); + transform(inInstance->m_Properties.begin(), inInstance->m_Properties.end(), + outProperties.begin() + theSize, identity<int>); + for (CDataModelInstance::TInstancePairList::const_iterator theParent = + inInstance->m_Parents.begin(); + theParent != inInstance->m_Parents.end(); ++theParent) + GetAggregateProperties(theParent->second, inVisited, outProperties); + } +} + +template <typename TPredicate> +inline std::tuple<bool, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle> +RecurseFindProperty(const TDataModelInstancePtr inInstance, TPredicate inPredicate) +{ + TIntList::const_iterator theFind = eastl::find_if(inInstance->m_Properties.begin(), + inInstance->m_Properties.end(), inPredicate); + if (theFind != inInstance->m_Properties.end()) + return make_tuple(true, inInstance->m_Handle, *theFind); + + for (CDataModelInstance::TInstancePairList::const_iterator theParent = + inInstance->m_Parents.begin(); + theParent != inInstance->m_Parents.end(); ++theParent) { + std::tuple<bool, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle> theValue = + RecurseFindProperty(theParent->second, inPredicate); + if (get<0>(theValue)) + return theValue; + } + return make_tuple(false, 0, 0); +} + +inline bool PropertyNameMatches(int inProperty, const THandleObjectMap &inObjects, + const TCharStr &inStr) +{ + const CDataModelPropertyDefinitionObject *theProp = + CSimpleDataCore::GetPropertyDefinitionNF(inProperty, inObjects); + return (theProp->m_Definition.m_Name == inStr); +} + +Qt3DSDMPropertyHandle +CSimpleDataCore::GetAggregateInstancePropertyByName(Qt3DSDMInstanceHandle inInstance, + const TCharStr &inStr) const +{ + const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects); + return get<2>( + RecurseFindProperty(theInstance, std::bind(PropertyNameMatches, + std::placeholders::_1, std::ref(m_Objects), + std::ref(inStr)))); +} + +// A simplified RecurseFindProperty function +bool RecurseFindPropertyMatches(const TDataModelInstancePtr inInstance, + Qt3DSDMPropertyHandle inProperty) +{ + TIntList::const_iterator theFind = + find(inInstance->m_Properties.begin(), inInstance->m_Properties.end(), + inProperty.GetHandleValue()); + if (theFind != inInstance->m_Properties.end()) + return true; + + for (CDataModelInstance::TInstancePairList::const_iterator theParent = + inInstance->m_Parents.begin(); + theParent != inInstance->m_Parents.end(); ++theParent) { + if (RecurseFindPropertyMatches(theParent->second, inProperty)) + return true; + } + return false; +} + +bool CSimpleDataCore::HasAggregateInstanceProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const +{ + const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects); + if (theInstance->m_PropertyValues.find(inProperty.GetHandleValue()) + != theInstance->m_PropertyValues.end()) + return true; + + return RecurseFindPropertyMatches(theInstance, inProperty); +} + +void CSimpleDataCore::GetAggregateInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const +{ + TIntList inVisited; + const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects); + GetAggregateProperties(theInstance, inVisited, outProperties); +} + +void CSimpleDataCore::CheckValue(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) const +{ + CheckPropertyExistence(GetInstanceNF(inInstance, m_Objects), inProperty, m_Objects); + const CDataModelPropertyDefinitionObject *theDefinition = + CSimpleDataCore::GetPropertyDefinitionNF(inProperty, m_Objects); + CheckValueType(theDefinition->m_Definition.m_Type, inValue); +} + +bool CSimpleDataCore::GetInstancePropertyValueHelper(const TDataModelInstancePtr inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + TPropertyPairHash::const_iterator theInstanceProp = + inInstance->m_PropertyValues.find(inProperty); + if (theInstanceProp != inInstance->m_PropertyValues.end()) { + outValue = theInstanceProp->second.second.GetValue(); + return true; + } else { + // Is the property valid? + const CDataModelPropertyDefinitionObject *theProp = + GetPropertyDefinitionNF(inProperty, m_Objects); + int thePropInstance = theProp->m_Definition.m_Instance; + if (thePropInstance != inInstance->m_Handle) { + for (CDataModelInstance::TInstancePairList::const_iterator theParent = + inInstance->m_Parents.begin(); + theParent != inInstance->m_Parents.end(); ++theParent) { + if (IsInstanceOrDerivedFromHelper(theParent->second, thePropInstance) + && GetInstancePropertyValueHelper(theParent->second, inProperty, outValue)) { + // Quietly propagate to this instance so next time we won't go through this + // large property lookup chain. + inInstance->m_PropertyValues.insert(std::make_pair( + inProperty, + TPropertyValuePair( + PropertyValueFlags(PropertyValueFlags::SetViaAutoPropagate), + SInternValue::ISwearThisHasAlreadyBeenInternalized(outValue)))); + return true; + } + } + } + } + return false; +} + +bool CSimpleDataCore::GetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + if (IsInstance(inHandle) == false || IsProperty(inProperty) == false) { + Q_ASSERT(0); + return false; + } + const TDataModelInstancePtr theInstance = GetInstanceNF(inHandle, m_Objects); + return GetInstancePropertyValueHelper(theInstance, inProperty, outValue); +} + +void CSimpleDataCore::SetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + if (IsInstance(inHandle) == false || IsProperty(inProperty) == false) { + Q_ASSERT(0); + return; + } + CheckValue(inHandle, inProperty, inValue); + UncheckedSetSpecificInstancePropertyValue(inHandle, inProperty, inValue, PropertyValueFlags()); +} + +void CSimpleDataCore::GetSpecificInstancePropertyValues(Qt3DSDMInstanceHandle inHandle, + TPropertyHandleValuePairList &outValues) +{ + if (IsInstance(inHandle) == false) + return; + + TDataModelInstancePtr theInstance = GetInstanceNF(inHandle, m_Objects); + for (TPropertyPairHash::const_iterator theIter = theInstance->m_PropertyValues.begin(), + theEnd = theInstance->m_PropertyValues.end(); + theIter != theEnd; ++theIter) { + const pair<int, TPropertyValuePair> &thePair(*theIter); + if (thePair.second.first.IsSetViaAutoPropagation() == false) { + Qt3DSDMPropertyHandle thePropertyHandle(thePair.first); + SValue theValue(thePair.second.second.GetValue()); + outValues.push_back(make_pair(thePair.first, theValue)); + } + } +} + +bool CSimpleDataCore::IsInstance(int inHandle) const +{ + return HandleObjectValid<CDataModelInstance>(inHandle, m_Objects); +} +bool CSimpleDataCore::IsProperty(int inHandle) const +{ + return HandleObjectValid<CDataModelPropertyDefinitionObject>(inHandle, m_Objects); +} + +Qt3DSDMInstanceHandle CSimpleDataCore::CreateInstanceWithHandle(int inHandle) +{ + if (g_DataModelDebugLogger) + g_DataModelDebugLogger("CSimpleDataCore::CreateInstance Enter"); + if (HandleValid(inHandle)) { + if (g_DataModelDebugLogger) { + g_DataModelDebugLogger("CSimpleDataCore::CreateInstance Handle Exists!!"); + char buf[32]; + sprintf(buf, "%d", inHandle); + g_DataModelDebugLogger(buf); + } + throw HandleExists(L""); + } + + THandleObjectPtr theHandleObjectPtr(new CDataModelInstance(inHandle)); + const pair<int, THandleObjectPtr> thePair(std::make_pair(inHandle, theHandleObjectPtr)); + m_Objects.insert(thePair); + + if (g_DataModelDebugLogger) + g_DataModelDebugLogger("CSimpleDataCore::CreateInstance Leave"); + + return inHandle; +} + +Qt3DSDMPropertyHandle CSimpleDataCore::AddPropertyWithHandle(int inHandle, + Qt3DSDMInstanceHandle inInstance, + TCharPtr inName, + DataModelDataType::Value inPropType) +{ + QT3DSDM_DEBUG_LOG("CSimpleDataCore::AddPropertyWithHandle Enter"); + QT3DSDM_DEBUG_LOG(m_StringTable->GetNarrowStr(inName)); + if (HandleValid(inHandle)) { + if (g_DataModelDebugLogger) { + g_DataModelDebugLogger("CSimpleDataCore::AddPropertyWithHandle Handle Exists!!"); + char buf[32]; + sprintf(buf, "%d", inHandle); + g_DataModelDebugLogger(buf); + } + + throw HandleExists(L""); + } + + TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects); + + Qt3DSDMPropertyDefinition theDefinition(inInstance, SafeStrPtr(inName), inPropType); + THandleObjectPtr theHandleObjectPtr( + new CDataModelPropertyDefinitionObject(inHandle, theDefinition)); + const pair<int, THandleObjectPtr> thePair(std::make_pair(inHandle, theHandleObjectPtr)); + m_Objects.insert(thePair); + theInstance->m_Properties.push_back(inHandle); + QT3DSDM_DEBUG_LOG("CSimpleDataCore::AddPropertyWithHandle Leave"); + return inHandle; +} + +bool CSimpleDataCore::GetSpecificInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects); + TPropertyPairHash::const_iterator theInstanceProp = + theInstance->m_PropertyValues.find(inProperty); + if (theInstanceProp != theInstance->m_PropertyValues.end()) { + outValue = theInstanceProp->second.second.GetValue(); + return true; + } + return false; +} + +void CSimpleDataCore::GetSpecificInstancePropertyValues(Qt3DSDMInstanceHandle inInstance, + TPropertyPairHash &outValues) const +{ + const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects); + outValues = theInstance->m_PropertyValues; +} + +void CSimpleDataCore::UncheckedSetSpecificInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue, + PropertyValueFlags inIsUserSet) +{ + TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects); + TPropertyValuePair theValuePair(inIsUserSet, SInternValue(inValue, GetStringTable())); + + std::pair<TPropertyPairHash::iterator, bool> theInsert = theInstance->m_PropertyValues.insert( + std::make_pair(inProperty.GetHandleValue(), theValuePair)); + if (theInsert.second == false) + theInsert.first->second = theValuePair; +} + +bool CSimpleDataCore::CheckParentPropertyExistenceWithFail(const TDataModelInstancePtr inInstance, + int inProperty, + const THandleObjectMap &inObjects) +{ + if (find(inInstance->m_Properties.begin(), inInstance->m_Properties.end(), inProperty) + != inInstance->m_Properties.end()) + return true; + for (CDataModelInstance::TInstancePairList::const_iterator theParent = + inInstance->m_Parents.begin(); + theParent != inInstance->m_Parents.end(); ++theParent) { + if (CheckParentPropertyExistenceWithFail(theParent->second, inProperty, inObjects)) + return true; + } + return false; +} + +// safety check to see if property exists +void CSimpleDataCore::CheckPropertyExistence(const TDataModelInstancePtr inInstance, int inProperty, + const THandleObjectMap &inObjects) +{ + if (!CheckParentPropertyExistenceWithFail(inInstance, inProperty, inObjects)) + throw PropertyNotFound(L""); +} + +bool CSimpleDataCore::IsInstanceOrDerivedFromHelper(const TDataModelInstancePtr inInstance, + Qt3DSDMInstanceHandle inParent) const +{ + if (inInstance->m_Handle == inParent) // Am I this object? + return true; + return inInstance->IsDerivedFrom(inParent); +} + +bool CSimpleDataCore::IsInstanceOrDerivedFrom(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) const +{ + if (IsInstance(inInstance) == false || IsInstance(inParent) == false) + return false; + if (inInstance == inParent) // Am I this object? + return true; + const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects); + return IsInstanceOrDerivedFromHelper(theInstance, inParent); +} +} diff --git a/src/dm/systems/cores/SimpleDataCore.h b/src/dm/systems/cores/SimpleDataCore.h new file mode 100644 index 0000000..2664dab --- /dev/null +++ b/src/dm/systems/cores/SimpleDataCore.h @@ -0,0 +1,373 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef DATACOREH +#define DATACOREH + +#include "Qt3DSDMDataTypes.h" +#include "Qt3DSDMSignals.h" +#include "HandleSystemBase.h" +#include "Qt3DSDMPropertyDefinition.h" +#include "Qt3DSDMDataCore.h" +#include "Qt3DSDMStringTable.h" +#include <unordered_set> +#include "Qt3DSDMValue.h" + +namespace qt3dsdm { + +struct PropertyValueFlags +{ + enum Enum { + // Property values that are set via event propagation should + // not be serialized to a file. The auto-propagation step + // is meant to make looking up property values quicker because + // the the derivation chain doesn't need to be followed to get + // the latest default value. + SetViaAutoPropagate = 1, + }; + + int m_Flags; + + PropertyValueFlags() + : m_Flags(0) + { + } + explicit PropertyValueFlags(int inFlags) + : m_Flags(inFlags) + { + } + + bool IsSetViaAutoPropagation() const { return (m_Flags & SetViaAutoPropagate) > 0; } +}; + +// Pair of property value flags and property value. The property value flags allow +// us to track metadata that is +typedef std::pair<PropertyValueFlags, SInternValue> TPropertyValuePair; +typedef std::unordered_map<int, TPropertyValuePair> TPropertyPairHash; +// Property pairs are referred to by property handle. +typedef std::pair<int, TPropertyValuePair> TPropertyPair; +typedef std::vector<TPropertyPair> TPropertyPairList; + +class CDataModelPropertyDefinitionObject : public CHandleObject +{ +public: + Qt3DSDMPropertyDefinition m_Definition; + + CDataModelPropertyDefinitionObject(int inHandle, const Qt3DSDMPropertyDefinition &inDefinition) + : CHandleObject(inHandle) + , m_Definition(inDefinition) + { + } + CDataModelPropertyDefinitionObject() {} + + static const EHandleObjectType s_Type = + CHandleObject::EHandleObjectTypeCDataModelPropertyDefinitionObject; + EHandleObjectType GetType() override { return s_Type; } +}; + +typedef std::unordered_map<int, SInternValue> TIntStringVariantList; + +class CDataModelInstance : public CHandleObject +{ +public: + typedef std::pair<int, std::shared_ptr<CDataModelInstance>> TInstancePair; + typedef std::unordered_map<int, std::shared_ptr<CDataModelInstance>> TInstancePairList; + typedef std::unordered_map<int, bool> TInstanceParentMap; + + TInstancePairList m_Parents; + mutable TInstanceParentMap m_CachedParents; + // Properties specific to this class + TIntList m_Properties; + TPropertyPairHash m_PropertyValues; + + CDataModelInstance() {} + CDataModelInstance(int inHandle) + : CHandleObject(inHandle) + { + } + + void ToPropertyPairList(TPropertyPairList &outList) const + { + for (TPropertyPairHash::const_iterator iter = m_PropertyValues.begin(), + end = m_PropertyValues.end(); + iter != end; ++iter) + outList.push_back(*iter); + } + + void FromPropertyPairList(const TPropertyPairList &inList) + { + m_PropertyValues.clear(); + for (TPropertyPairList::const_iterator iter = inList.begin(), end = inList.end(); + iter != end; ++iter) + m_PropertyValues.insert(*iter); + } + + void ClearParentCache() const { m_CachedParents.clear(); } + + bool IsDerivedFrom(Qt3DSDMInstanceHandle inParent) const + { + std::pair<TInstanceParentMap::iterator, bool> theQueryResult = + m_CachedParents.insert(std::make_pair(inParent.GetHandleValue(), false)); + // If the insert failed, returned what the hashtable already had in it + if (theQueryResult.second == false) + return theQueryResult.first->second; + + // Else find a valid answer + if (m_Parents.find(inParent.GetHandleValue()) != m_Parents.end()) { + theQueryResult.first->second = true; + } else { + for (TInstancePairList::const_iterator iter = m_Parents.begin(), end = m_Parents.end(); + iter != end; ++iter) { + if (iter->second->IsDerivedFrom(inParent)) { + theQueryResult.first->second = true; + break; + } + } + } + + // Note that we inserted false to begin with. This means that + // we can return the insert result here safely as if it wasn't + // supposed to be false, we would have set it above. + return theQueryResult.first->second; + } + + void RemoveCachedValues() + { + vector<int> theCachedProperties; + + for (TPropertyPairHash::iterator theProperty = m_PropertyValues.begin(), + end = m_PropertyValues.end(); + theProperty != end; ++theProperty) { + if (theProperty->second.first.IsSetViaAutoPropagation()) + theCachedProperties.push_back(theProperty->first); + } + + for (size_t idx = 0, end = theCachedProperties.size(); idx < end; ++idx) + m_PropertyValues.erase(theCachedProperties[idx]); + } + + // CHandleObject + static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeCDataModelInstance; + EHandleObjectType GetType() override { return s_Type; } +}; + +typedef std::shared_ptr<CDataModelInstance> TDataModelInstancePtr; + +class CSimpleDataCore : public CHandleBase, public IDataCore +{ + mutable TStringTablePtr m_StringTable; + +public: + CSimpleDataCore(TStringTablePtr strTable) + : m_StringTable(strTable) + { + } + CSimpleDataCore(const CSimpleDataCore &inOther) + : CHandleBase(inOther) + , m_StringTable(inOther.m_StringTable) + { + } + + CSimpleDataCore &operator=(const CSimpleDataCore &inOther) + { + CHandleBase::operator=(inOther); + return *this; + } + + IStringTable &GetStringTable() const override { return *m_StringTable.get(); } + TStringTablePtr GetStringTablePtr() const override { return m_StringTable; } + + // IHandleBase + bool HandleValid(int inHandle) const override + { + return m_Objects.find(inHandle) != m_Objects.end(); + } + + // IInstancePropertyCore + Qt3DSDMPropertyHandle GetAggregateInstancePropertyByName(Qt3DSDMInstanceHandle inInstance, + const TCharStr &inStr) const override; + void GetAggregateInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const override; + void GetSpecificInstancePropertyValues(Qt3DSDMInstanceHandle inHandle, + TPropertyHandleValuePairList &outValues) override; + bool HasAggregateInstanceProperty(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const override; + void CheckValue(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) const override; + bool GetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + void SetInstancePropertyValue(Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + + // IDataCore + //=============================================================== + Qt3DSDMInstanceHandle CreateInstance(Qt3DSDMInstanceHandle hdl = Qt3DSDMInstanceHandle()) override; + void DeleteInstance(Qt3DSDMInstanceHandle inHandle) override; + void GetInstances(TInstanceHandleList &outInstances) const override; + void GetInstancesDerivedFrom(TInstanceHandleList &outInstances, + Qt3DSDMInstanceHandle inParentHandle) const override; + + void DeriveInstance(Qt3DSDMInstanceHandle inInstance, Qt3DSDMInstanceHandle inParent) override; + void GetInstanceParents(Qt3DSDMInstanceHandle inHandle, + TInstanceHandleList &outParents) const override; + // Returns true if inParent == inInstance || inInstance is derived from inParent somehow. + // Recursive. + bool IsInstanceOrDerivedFrom(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMInstanceHandle inParent) const override; + + Qt3DSDMPropertyHandle AddProperty(Qt3DSDMInstanceHandle inClass, TCharPtr inName, + DataModelDataType::Value inPropType) override; + const Qt3DSDMPropertyDefinition &GetProperty(Qt3DSDMPropertyHandle inProperty) const override; + void GetInstanceProperties(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleList &outProperties) const override; + void RemoveProperty(Qt3DSDMPropertyHandle inProperty) override; + void CopyInstanceProperties(Qt3DSDMInstanceHandle inSrcInstance, + Qt3DSDMInstanceHandle inDestInstance) override; + void RemoveCachedValues(Qt3DSDMInstanceHandle inInstance) override; + + bool IsInstance(int inHandle) const override; + bool IsProperty(int inHandle) const override; + //=============================================================== + + bool GetSpecificInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const; + void GetSpecificInstancePropertyValues(Qt3DSDMInstanceHandle inInstance, + TPropertyPairHash &outValues) const; + + static CDataModelPropertyDefinitionObject *GetPropertyDefinitionNF(int inHandle, + THandleObjectMap &inObjects) + { + return const_cast<CDataModelPropertyDefinitionObject *>( + GetPropertyDefinitionNF(inHandle, static_cast<const THandleObjectMap &>(inObjects))); + } + + static const CDataModelPropertyDefinitionObject * + GetPropertyDefinitionNF(int inHandle, const THandleObjectMap &inObjects) + { + const CDataModelPropertyDefinitionObject *theClass = + GetHandleObject<CDataModelPropertyDefinitionObject>(inHandle, inObjects); + if (theClass) + return theClass; + throw PropertyNotFound(L""); + } + + static TDataModelInstancePtr GetInstance(int inHandle, const THandleObjectMap &inObjects) + { + THandleObjectMap::const_iterator theFind(inObjects.find(inHandle)); + // dynamic cast isn't allowed in runtime code as the runtime doesn't enable rtti. + if (theFind != inObjects.end()) + return std::static_pointer_cast<CDataModelInstance>(theFind->second); + return TDataModelInstancePtr(); + } + + static TDataModelInstancePtr GetInstanceNF(int inHandle, const THandleObjectMap &inObjects) + { + TDataModelInstancePtr retval = GetInstance(inHandle, inObjects); + if (retval) + return retval; + throw InstanceNotFound(L""); + } + + static inline bool InstancePairMatches(int inHandle, + const CDataModelInstance::TInstancePair &inInstancePair) + { + return inHandle == inInstancePair.first; + } + + // if inInstance doesn't exists in inObjects, it will push back NULL instead of throwing + // exception + static inline void UncheckAddInstancePair(CDataModelInstance::TInstancePairList &outInstances, + Qt3DSDMInstanceHandle inInstance, + THandleObjectMap &inObjects) + { + outInstances.insert( + std::make_pair(inInstance, CSimpleDataCore::GetInstance(inInstance, inObjects))); + } + + static inline bool InstancePropertyMatches(int inProp, const TPropertyPair &inPropPair) + { + return inProp == inPropPair.first; + } + + static bool CheckParentPropertyExistenceWithFail(const TDataModelInstancePtr inInstance, + int inProperty, + const THandleObjectMap &inObjects); + + static void CheckPropertyExistence(const TDataModelInstancePtr inInstance, int inProperty, + const THandleObjectMap &inObjects); + + static inline void FindRelatedItemsForDelete(int inInstance, TIntList &outProperties, + TIntList &outChildInstances, + const std::pair<int, THandleObjectPtr> &inPair) + { + + using namespace std; + if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeCDataModelInstance) { + TDataModelInstancePtr theInstance = + static_pointer_cast<CDataModelInstance>(inPair.second); + // No longer a parent class. + if (find_if(theInstance->m_Parents.begin(), theInstance->m_Parents.end(), + std::bind(InstancePairMatches, inInstance, std::placeholders::_1)) + != theInstance->m_Parents.end()) + outChildInstances.push_back(inPair.first); + } else if (inPair.second->GetType() + == CHandleObject::EHandleObjectTypeCDataModelPropertyDefinitionObject) { + const CDataModelPropertyDefinitionObject *theProperty = + static_cast<const CDataModelPropertyDefinitionObject *>(inPair.second.get()); + if (theProperty->m_Definition.m_Instance.GetHandleValue() == inInstance) + outProperties.push_back(inPair.first); + } + } + +protected: + bool IsInstanceOrDerivedFromHelper(const TDataModelInstancePtr inInstance, + Qt3DSDMInstanceHandle inParent) const; + void AddInstanceIfDerivedFrom(const std::pair<int, THandleObjectPtr> &inItem, + TInstanceHandleList &outInstances, + Qt3DSDMInstanceHandle inParentHandle) const; + + bool GetInstancePropertyValueHelper(const TDataModelInstancePtr inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const; + + // Create an instance *at* this specific handle position + // This is used for special cases of serialization + Qt3DSDMInstanceHandle CreateInstanceWithHandle(int inHandle); + Qt3DSDMPropertyHandle AddPropertyWithHandle(int inHandle, Qt3DSDMInstanceHandle inClass, + TCharPtr inName, DataModelDataType::Value inPropType); + + void UncheckedSetSpecificInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue, + PropertyValueFlags inIsUserSet); +}; + +typedef std::shared_ptr<CSimpleDataCore> TSimpleDataCorePtr; +} + +#endif diff --git a/src/dm/systems/cores/SimpleSlideCore.cpp b/src/dm/systems/cores/SimpleSlideCore.cpp new file mode 100644 index 0000000..87eadb9 --- /dev/null +++ b/src/dm/systems/cores/SimpleSlideCore.cpp @@ -0,0 +1,420 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "SimpleSlideCore.h" + +using namespace std; +#ifdef _WIN32 +#pragma warning(disable : 4503) +#endif + +namespace qt3dsdm { + +Qt3DSDMSlideHandle CSimpleSlideCore::CreateSlide(Qt3DSDMInstanceHandle inInstance) +{ + int nextId = GetNextId(); + return CreateSlideWithHandle(nextId, inInstance); +} + +Qt3DSDMInstanceHandle CSimpleSlideCore::GetSlideInstance(Qt3DSDMSlideHandle inSlide) const +{ + return GetSlideNF(inSlide, m_Objects)->m_Instance; +} + +inline bool SlideInstanceMatches(const THandleObjectPair &inPair, int inInstance) +{ + if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeSSlide + && static_cast<const SSlide *>(inPair.second.get())->m_Instance == inInstance) + return true; + return false; +} + +Qt3DSDMSlideHandle CSimpleSlideCore::GetSlideByInstance(Qt3DSDMInstanceHandle inInstance) const +{ + THandleObjectMap::const_iterator theSlide = + find_if(m_Objects.begin(), m_Objects.end(), + std::bind(SlideInstanceMatches, + std::placeholders::_1, inInstance.GetHandleValue())); + if (theSlide != m_Objects.end()) + return theSlide->first; + throw SlideNotFound(L""); +} + +void RecurseDeleteSlide(Qt3DSDMSlideHandle inSlide, THandleObjectMap &inObjects, + TInstanceHandleList &outInstances) +{ + SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, inObjects); + do_all(theSlide->m_Children, + std::bind(RecurseDeleteSlide, std::placeholders::_1, + std::ref(inObjects), std::ref(outInstances))); + outInstances.push_back(theSlide->m_Instance); + CHandleBase::EraseHandle(inSlide, inObjects); +} + +void CSimpleSlideCore::DeleteSlide(Qt3DSDMSlideHandle inSlide, TInstanceHandleList &outInstances) +{ + SSlide *theSlide = GetSlideNF(inSlide, m_Objects); + if (theSlide->m_Parent) { + SSlide *theParent = GetSlideNF(theSlide->m_Parent, m_Objects); + erase_if(theParent->m_Children, std::bind(equal_to<int>(), theSlide->m_Handle, + std::placeholders::_1)); + } + RecurseDeleteSlide(inSlide, m_Objects, outInstances); +} + +template <typename TDataType, typename TVectorType> +inline void MaybeAddObject(const THandleObjectPair &inPair, vector<TVectorType> &outVectorItems) +{ + if (inPair.second->GetType() == TDataType::s_Type) + outVectorItems.push_back(inPair.first); +} + +void CSimpleSlideCore::GetSlides(TSlideHandleList &outSlides) const +{ + do_all(m_Objects, + std::bind(MaybeAddObject<SSlide, Qt3DSDMSlideHandle>, + std::placeholders::_1, std::ref(outSlides))); +} + +float CSimpleSlideCore::GetSlideTime(Qt3DSDMSlideHandle inSlide) const +{ + return GetSlideNF(inSlide, m_Objects)->m_Time; +} + +void CSimpleSlideCore::SetSlideTime(Qt3DSDMSlideHandle inSlide, float inNewTime) +{ + GetSlideNF(inSlide, m_Objects)->m_Time = inNewTime; +} + +void CSimpleSlideCore::DeriveSlide(Qt3DSDMSlideHandle inSlide, Qt3DSDMSlideHandle inParent, + int inIndex) +{ + int oldParent = GetSlideNF(inSlide, m_Objects)->m_Parent; + if (oldParent) + erase_if(GetSlideNF(oldParent, m_Objects)->m_Children, + std::bind(equal_to<int>(), inSlide, std::placeholders::_1)); + if (inParent.Valid()) { + SSlide *theParent = GetSlideNF(inParent, m_Objects); + if (exists(theParent->m_Children, std::bind(equal_to<int>(), inSlide, + std::placeholders::_1))) + throw SlideDerivationError(L"Already derived"); + if (inIndex < 0 || inIndex >= (int)theParent->m_Children.size()) + inIndex = (int)theParent->m_Children.size(); + theParent->m_Children.insert(theParent->m_Children.begin() + inIndex, + inSlide.GetHandleValue()); + } + GetSlideNF(inSlide, m_Objects)->m_Parent = inParent; +} + +Qt3DSDMSlideHandle CSimpleSlideCore::GetParentSlide(Qt3DSDMSlideHandle inSlide) const +{ + return GetSlideNF(inSlide, m_Objects)->m_Parent; +} + +void CSimpleSlideCore::GetChildSlides(Qt3DSDMSlideHandle inSlide, + TSlideHandleList &outChildren) const +{ + transformv_all(GetSlideNF(inSlide, m_Objects)->m_Children, outChildren); +} + +int CSimpleSlideCore::GetChildIndex(Qt3DSDMSlideHandle inParent, Qt3DSDMSlideHandle inChild) const +{ + const SSlide *theSlide = GetSlideNF(inParent, m_Objects); + size_t dist = distance(theSlide->m_Children.begin(), + find_if<TIntList::const_iterator>( + theSlide->m_Children, std::bind(equal_to<int>(), inChild, + std::placeholders::_1))); + if (dist == theSlide->m_Children.size()) + throw SlideChildNotFoundError(L""); + return (int)dist; +} + +bool CSimpleSlideCore::GetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + const SSlide *theSlide = GetSlideNF(inSlide, m_Objects); + SInternValue *theValue = theSlide->GetInstancePropertyValue(inHandle, inProperty); + if (theValue) { + outValue = theValue->GetValue(); + return true; + } + if (theSlide->m_Parent) + return GetInstancePropertyValue(theSlide->m_Parent, inHandle, inProperty, outValue); + return false; +} + +std::pair<SSlide *, SInternValue *> CSimpleSlideCore::ResolveSetInstancePropertyValue( + Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, Qt3DSDMPropertyHandle inProperty) +{ + SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, m_Objects); + SInternValue *theValue = theSlide->GetInstancePropertyValue(inHandle, inProperty); + // If we have the value already *or* or parent is not a valid slide, then return now + if (theValue || theSlide->m_Parent == 0) + return std::make_pair(theSlide, theValue); + // Else give our parent a chance. + return ResolveSetInstancePropertyValue(theSlide->m_Parent, inHandle, inProperty); +} + +void CSimpleSlideCore::SetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + std::pair<SSlide *, SInternValue *> theTarget( + ResolveSetInstancePropertyValue(inSlide, inHandle, inProperty)); + SInternValue theValue(inValue, GetStringTable()); + if (theTarget.second) + *theTarget.second = theValue; + else + theTarget.first->SetInstancePropertyValue(inHandle, inProperty, theValue); +} + +void CSimpleSlideCore::ForceSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + CSimpleSlideCore::ForceSetPropertyValue(GetStringTable(), m_Objects, inSlide, inHandle, + inProperty, inValue); +} + +void CSimpleSlideCore::forceSetInstancePropertyValueOnAllSlides(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + for (auto &it : m_Objects) { + if (it.second->GetType() == SSlide::s_Type) { + Qt3DSDMSlideHandle slide(it.first); + ForceSetInstancePropertyValue(slide, inInstance, inProperty, inValue); + } + } +} + +bool CSimpleSlideCore::GetSpecificInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + const SSlide *theSlide = GetSlideNF(inSlide, m_Objects); + SInternValue *theValue = theSlide->GetInstancePropertyValue(inInstance, inProperty); + if (theValue) { + outValue = theValue->GetValue(); + return true; + } + return false; +} + +void CSimpleSlideCore::GetSpecificInstancePropertyValues(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + TPropertyHandleValuePairList &outValues) +{ + const SSlide *theSlide = GetSlideNF(inSlide, m_Objects); + theSlide->GetSpecificInstancePropertyValues(inInstance, outValues); +} + +void CSimpleSlideCore::GetSlidePropertyEntries(Qt3DSDMSlideHandle inSlide, + TSlideEntryList &outEntries) const +{ + const SSlide *theSlide = GetSlideNF(inSlide, m_Objects); + theSlide->ToSlideEntryList(outEntries); +} + +bool CSimpleSlideCore::ContainsProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) const +{ + const SSlide *theSlide = GetSlideNF(inSlide, m_Objects); + return theSlide->GetInstancePropertyValue(inHandle, inProperty) != NULL; +} + +Qt3DSDMSlideHandle CSimpleSlideCore::CreateSlideWithHandle(int inHandle, + Qt3DSDMInstanceHandle inInstance) +{ + if (HandleValid(inHandle)) + throw HandleExists(L""); + m_Objects.insert(make_pair(inHandle, (THandleObjectPtr) new SSlide(inHandle, inInstance))); + return inHandle; +} + +void CSimpleSlideCore::GetSlideProperties(Qt3DSDMSlideHandle inSlide, + TSlideEntryList &outProperties) const +{ + outProperties.clear(); + GetSlidePropertyEntries(inSlide, outProperties); +} + +bool CSimpleSlideCore::IsSlide(Qt3DSDMSlideHandle inSlide) const +{ + return m_Objects.find(inSlide) != m_Objects.end(); +} + +void CSimpleSlideCore::ForceSetPropertyValue(IStringTable &inStringTable, + THandleObjectMap &inObjects, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) +{ + CSimpleSlideCore::GetSlideNF(inSlide, inObjects) + ->SetInstancePropertyValue(inHandle, inProperty, SInternValue(inValue, inStringTable)); +} + +void CSimpleSlideCore::PushPropertyValueToChildren(Qt3DSDMSlideHandle inParent, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + ForceSetPropertyValue(GetStringTable(), m_Objects, inParent, inHandle, inProperty, inValue); + do_all(CSimpleSlideCore::GetSlideNF(inParent, m_Objects)->m_Children, + std::bind(ForceSetPropertyValue, std::ref(GetStringTable()), std::ref(m_Objects), + std::placeholders::_1, inHandle, inProperty, inValue)); +} + +inline void AddIntersectingEntry(TSlideEntryList &outEntries, Qt3DSDMInstanceHandle inst, + Qt3DSDMPropertyHandle prop, const SInternValue &inValue) +{ + outEntries.push_back(TSlideEntry(inst, prop, inValue.GetValue())); +} + +void CSimpleSlideCore::GetIntersectingProperties(Qt3DSDMSlideHandle inSlide1, + Qt3DSDMSlideHandle inSlide2, + TSlideEntryList &outEntries) const +{ + const SSlide *theSlide1 = GetSlideNF(inSlide1, m_Objects); + const SSlide *theSlide2 = GetSlideNF(inSlide2, m_Objects); + theSlide1->IntersectProperties( + *theSlide2, std::bind(AddIntersectingEntry, std::ref(outEntries), + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)); +} + +void CSimpleSlideCore::PushIntersectingProperties(Qt3DSDMSlideHandle inSlide1, + Qt3DSDMSlideHandle inSlide2, + Qt3DSDMSlideHandle inDestination) +{ + const SSlide *theSlide1 = GetSlideNF(inSlide1, m_Objects); + const SSlide *theSlide2 = GetSlideNF(inSlide2, m_Objects); + SSlide *theDest = GetSlideNF(inDestination, m_Objects); + theSlide1->IntersectProperties( + *theSlide2, std::bind(&SSlide::SetInstancePropertyValue, theDest, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3)); +} + +void CSimpleSlideCore::ClearPropertyValue(THandleObjectMap &inObjects, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) +{ + CSimpleSlideCore::GetSlideNF(inSlide, inObjects) + ->RemoveInstancePropertyValue(inInstance, inProperty); +} + +inline void DoForEachSlide(std::pair<int, THandleObjectPtr> inObject, + std::function<void(SSlide *)> inFunction) +{ + inFunction((SSlide *)inObject.second.get()); +} + +void CSimpleSlideCore::ForEachSlide(std::function<void(SSlide *)> inFunction) +{ + do_all(m_Objects, std::bind(DoForEachSlide, std::placeholders::_1, inFunction)); +} + +void LookupSlideAndDoSomething(Qt3DSDMSlideHandle inSlide, THandleObjectMap &inObjects, + std::function<void(SSlide *)> inFunction) +{ + inFunction(CSimpleSlideCore::GetSlideNF(inSlide, inObjects)); +} + +void CSimpleSlideCore::ForEachChild(Qt3DSDMSlideHandle inParent, + std::function<void(SSlide *)> inFunction) +{ + do_all(GetSlideNF(inParent, m_Objects)->m_Children, + std::bind(LookupSlideAndDoSomething, std::placeholders::_1, m_Objects, inFunction)); +} + +bool InstanceMatches(Qt3DSDMInstanceHandle inTarget, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle) +{ + return inTarget == inHandle; +} + +bool PropertyMatches(Qt3DSDMPropertyHandle inTarget, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle inProp) +{ + return inTarget == inProp; +} + +bool InstancePropertyMatchesVector(const TInstanceHandleList &inInstances, + const TPropertyHandleList &inProperties, + Qt3DSDMInstanceHandle slideInst, Qt3DSDMPropertyHandle slideProp) +{ + return std::find(inInstances.begin(), inInstances.end(), slideInst) != inInstances.end() + && std::find(inProperties.begin(), inProperties.end(), slideProp) != inProperties.end(); +} + +bool InstancePropertyMatches(const Qt3DSDMInstanceHandle inInstance, + const Qt3DSDMPropertyHandle inProperty, Qt3DSDMInstanceHandle slideInst, + Qt3DSDMPropertyHandle slideProp) +{ + return inInstance == slideInst && inProperty == slideProp; +} + +void CSimpleSlideCore::DeleteAllInstanceEntries(Qt3DSDMInstanceHandle inHandle) +{ + std::function<bool(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> predicate( + std::bind(InstanceMatches, inHandle, std::placeholders::_1, std::placeholders::_2)); + ForEachSlide(std::bind(&SSlide::ClearPropertiesIf, std::placeholders::_1, predicate)); +} + +void CSimpleSlideCore::DeleteAllPropertyEntries(Qt3DSDMPropertyHandle inHandle) +{ + std::function<bool(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> predicate( + std::bind(PropertyMatches, inHandle, std::placeholders::_1, std::placeholders::_2)); + ForEachSlide(std::bind(&SSlide::ClearPropertiesIf, std::placeholders::_1, predicate)); +} + +void CSimpleSlideCore::DeleteAllInstancePropertyEntries(const TInstanceHandleList &inInstances, + const TPropertyHandleList &inProperties) +{ + std::function<bool(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> predicate( + std::bind(InstancePropertyMatchesVector, inInstances, inProperties, + std::placeholders::_1, std::placeholders::_2)); + ForEachSlide(std::bind(&SSlide::ClearPropertiesIf, std::placeholders::_1, predicate)); +} + +void CSimpleSlideCore::ClearChildrenPropertyValues(Qt3DSDMSlideHandle inParent, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) +{ + std::function<bool(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> predicate( + std::bind(InstancePropertyMatches, inHandle, inProperty, + std::placeholders::_1, std::placeholders::_2)); + ForEachChild(inParent, std::bind(&SSlide::ClearPropertiesIf, std::placeholders::_1, predicate)); +} +} diff --git a/src/dm/systems/cores/SimpleSlideCore.h b/src/dm/systems/cores/SimpleSlideCore.h new file mode 100644 index 0000000..278ef77 --- /dev/null +++ b/src/dm/systems/cores/SimpleSlideCore.h @@ -0,0 +1,408 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef SLIDECOREH +#define SLIDECOREH +#include "HandleSystemBase.h" +#include "Qt3DSDMSlideCore.h" +#include "SimpleDataCore.h" +#include "Qt3DSDMStringTable.h" +#include <unordered_map> +#include <QtCore/qdebug.h> + +namespace std { + +template<> struct hash<std::pair<int,int> > +{ + typedef std::pair<int,int> argument_type; + typedef std::size_t result_type; + result_type operator()(std::pair<int,int> const& pa) const + { + result_type const h1 ( std::hash<int>{}(pa.first) ); + result_type const h2 ( std::hash<int>{}(pa.second) ); + return h1 ^ (h2 << 1); + } +}; + +} + +namespace qt3dsdm { + +// The first revision of this +typedef std::pair<int, int> TSlideInstancePropertyPair; +typedef std::unordered_map<TSlideInstancePropertyPair, SInternValue > TSlideEntryHash; + +using std::make_pair; + +// Abstract access to these objects a little bit because in the future we are going to +// reorganize the data such that getting a defined set of properties for a single instance is +// very fast. +struct SSlide : public CHandleObject +{ + SSlide() + : m_Instance(0) + , m_Parent(0) + { + } + SSlide(int inHandle, int inInstance) + : CHandleObject(inHandle) + , m_Instance(inInstance) + , m_Parent(0) + , m_Time(0) + { + } + int m_Instance; + int m_Parent; + TIntList m_Children; + TSlideEntryHash m_Properties; + float m_Time; + + // Returns true if it was inserted, false if the property value was set. + bool SetInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty, + const SInternValue &inValue) + { + TSlideInstancePropertyPair theKey(inInstance.GetHandleValue(), inProperty.GetHandleValue()); + std::pair<TSlideEntryHash::iterator, bool> insertResult = + m_Properties.insert(std::make_pair(theKey, inValue)); + + if (insertResult.second == false) + insertResult.first->second = inValue; + return insertResult.second; + } + // Returns true if the property was deleted + bool RemoveInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) + { + TSlideInstancePropertyPair theKey(inInstance.GetHandleValue(), inProperty.GetHandleValue()); + TSlideEntryHash::iterator find(m_Properties.find(theKey)); + if (find != m_Properties.end()) { + m_Properties.erase(find); + return true; + } + return false; + } + // Return a pointer to out property value. This allows quicker checks for isset and such + SInternValue *GetInstancePropertyValue(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty) const + { + TSlideInstancePropertyPair theKey(inInstance.GetHandleValue(), inProperty.GetHandleValue()); + TSlideEntryHash::const_iterator find(m_Properties.find(theKey)); + if (find != m_Properties.end()) + return const_cast<SInternValue *>(&find->second); + return NULL; + } + + void GetSpecificInstancePropertyValues(Qt3DSDMInstanceHandle inInstance, + TPropertyHandleValuePairList &outProperties) const + { + for (TSlideEntryHash::const_iterator theIter = m_Properties.begin(), + theEnd = m_Properties.end(); + theIter != theEnd; ++theIter) { + if (theIter->first.first == inInstance) + outProperties.push_back( + make_pair(theIter->first.second, theIter->second.GetValue())); + } + } + + bool HasProperty(std::function<bool(const TSlideEntry &)> inPredicate) const + { + for (TSlideEntryHash::const_iterator theIter = m_Properties.begin(), + theEnd = m_Properties.end(); + theIter != theEnd; ++theIter) { + if (inPredicate(TSlideEntry(theIter->first.first, theIter->first.second, + theIter->second.GetValue()))) + return true; + } + return false; + } + + void DeleteSlideEntries(TSlideEntryList &outList, + std::function<bool(const TSlideEntry &)> inPredicate) + { + for (TSlideEntryHash::const_iterator theIter = m_Properties.begin(), + theEnd = m_Properties.end(); + theIter != theEnd; ++theIter) { + if (inPredicate(TSlideEntry(theIter->first.first, theIter->first.second, + theIter->second.GetValue()))) { + outList.push_back(TSlideEntry(theIter->first.first, theIter->first.second, + theIter->second.GetValue())); + } + } + DeleteEntriesFromList(outList); + } + + void DeleteEntriesFromList(const TSlideEntryList &inList) + { + for (size_t idx = 0, end = inList.size(); idx < end; ++idx) + m_Properties.erase( + std::pair<int, int>(std::get<0>(inList[idx]), std::get<1>(inList[idx]))); + } + + void InsertSlideEntries(const TSlideEntryList &inList, IStringTable &inStringTable) + { + for (size_t idx = 0, end = inList.size(); idx < end; ++idx) { + TSlideInstancePropertyPair theKey(std::get<0>(inList[idx]), std::get<1>(inList[idx])); + + if (m_Properties.find(theKey) != m_Properties.end()) { + // The only known case when this condition happens is when DnD a sub-presentation to + // the scene as a texture rect then undoing. + qWarning() << __FUNCTION__ << ": Instance/Property Pair" << theKey + << "already exists, erasing it."; + m_Properties.erase(theKey); + } + + m_Properties.insert( + std::make_pair(theKey, SInternValue(std::get<2>(inList[idx]), inStringTable))); + } + } + + // Convert to the older, straight forward representation of the + // data in this slide. + void ToSlideEntryList(TSlideEntryList &outList) const + { + for (TSlideEntryHash::const_iterator theIter = m_Properties.begin(), + theEnd = m_Properties.end(); + theIter != theEnd; ++theIter) + outList.push_back(TSlideEntry(theIter->first.first, theIter->first.second, + theIter->second.GetValue())); + } + + void FromSlideEntryList(const TSlideEntryList &inList, IStringTable &inStringTable) + { + using namespace std; + m_Properties.clear(); + for (TSlideEntryList::const_iterator theIter = inList.begin(), theEnd = inList.end(); + theIter != theEnd; ++theIter) + SetInstancePropertyValue(get<0>(*theIter), get<1>(*theIter), + SInternValue(get<2>(*theIter), inStringTable)); + } + + // result is the instance, property, myvalue, othervalue + void IntersectProperties(const SSlide &inOther, + std::function<void(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + SInternValue, SInternValue)> + inResult) const + { + for (TSlideEntryHash::const_iterator theIter = m_Properties.begin(), + theEnd = m_Properties.end(); + theIter != theEnd; ++theIter) { + SInternValue *otherValue = + inOther.GetInstancePropertyValue(theIter->first.first, theIter->first.second); + if (otherValue) + inResult(theIter->first.first, theIter->first.second, theIter->second, *otherValue); + } + } + + // Call the predicate, if it returns true set the property for all properties. + // This allows a third party to manipulate the property values during the process. + void SetPropertyValuesIf( + IStringTable &inStringTable, + std::function<bool(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, SValue &)> inPredIntercept) + { + for (TSlideEntryHash::iterator theIter = m_Properties.begin(), theEnd = m_Properties.end(); + theIter != theEnd; ++theIter) { + SValue theValue(theIter->second.GetValue()); + if (inPredIntercept(theIter->first.first, theIter->first.second, theValue)) + theIter->second = SInternValue(theValue, inStringTable); + } + } + + void + ClearPropertiesIf(std::function<bool(Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle)> inPredicate) + { + bool foundOne; + do { + foundOne = false; + for (TSlideEntryHash::iterator theIter = m_Properties.begin(), + theEnd = m_Properties.end(); + theIter != theEnd; ++theIter) { + if (inPredicate(theIter->first.first, theIter->first.second)) { + foundOne = true; + m_Properties.erase(theIter->first); + break; + } + } + + } while (foundOne); + } + + static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeSSlide; + EHandleObjectType GetType() override { return s_Type; } +}; + +class CSimpleSlideCore : public CHandleBase, public ISlideCore +{ + TStringTablePtr m_StringTable; + +public: // use + CSimpleSlideCore(TStringTablePtr inStrTable) + : m_StringTable(inStrTable) + { + } + + TStringTablePtr GetStringTablePtr() const override { return m_StringTable; } + IStringTable &GetStringTable() const override { return *m_StringTable.get(); } + Qt3DSDMSlideHandle CreateSlide(Qt3DSDMInstanceHandle inInstance) override; + Qt3DSDMInstanceHandle GetSlideInstance(Qt3DSDMSlideHandle inSlide) const override; + Qt3DSDMSlideHandle GetSlideByInstance(Qt3DSDMInstanceHandle inInstance) const override; + void DeleteSlide(Qt3DSDMSlideHandle inSlide, TInstanceHandleList &outInstances) override; + void GetSlides(TSlideHandleList &outSlides) const override; + + float GetSlideTime(Qt3DSDMSlideHandle inSlide) const override; + void SetSlideTime(Qt3DSDMSlideHandle inSlide, float inNewTime) override; + + void DeriveSlide(Qt3DSDMSlideHandle inSlide, Qt3DSDMSlideHandle inParent, int inIndex = -1) override; + Qt3DSDMSlideHandle GetParentSlide(Qt3DSDMSlideHandle inSlide) const override; + void GetChildSlides(Qt3DSDMSlideHandle inSlide, TSlideHandleList &outChildren) const override; + int GetChildIndex(Qt3DSDMSlideHandle inParent, Qt3DSDMSlideHandle inChild) const override; + + bool GetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + void SetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + + // Return the slide this property should be set on, along with the previous value if any. + // Set the value on the slide. + std::pair<SSlide *, SInternValue *> + ResolveSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty); + void ForceSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + void forceSetInstancePropertyValueOnAllSlides(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) override; + + bool GetSpecificInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + + void GetSpecificInstancePropertyValues(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + TPropertyHandleValuePairList &outValues) override; + + void GetSlidePropertyEntries(Qt3DSDMSlideHandle inSlide, TSlideEntryList &outEntries) const override; + + void PushPropertyValueToChildren(Qt3DSDMSlideHandle inParent, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + + void GetIntersectingProperties(Qt3DSDMSlideHandle inSlide1, Qt3DSDMSlideHandle inSlide2, + TSlideEntryList &outEntries) const override; + void PushIntersectingProperties(Qt3DSDMSlideHandle inSlide1, Qt3DSDMSlideHandle inSlide2, + Qt3DSDMSlideHandle inDestination) override; + + void ClearChildrenPropertyValues(Qt3DSDMSlideHandle inParent, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) override; + + void DeleteAllInstanceEntries(Qt3DSDMInstanceHandle inHandle) override; + void DeleteAllPropertyEntries(Qt3DSDMPropertyHandle inHandle) override; + void DeleteAllInstancePropertyEntries(const TInstanceHandleList &inInstances, + const TPropertyHandleList &inProperties) override; + + bool ContainsProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) const override; + bool HandleValid(int inHandle) const override { return CHandleBase::HandleValid(inHandle); } + + Qt3DSDMSlideHandle CreateSlideWithHandle(int inHandle, Qt3DSDMInstanceHandle inInstance); + void GetSlideProperties(Qt3DSDMSlideHandle inSlide, TSlideEntryList &outProperties) const; + + bool IsSlide(Qt3DSDMSlideHandle inSlide) const override; + + // Possibly alter every slide in the database + void ForEachSlide(std::function<void(SSlide *)> inFunction); + void ForEachChild(Qt3DSDMSlideHandle inSlide, std::function<void(SSlide *)> inFunction); + + // Only implemented at the producer level, not at this lower level. + void CopyProperties(Qt3DSDMSlideHandle /*inSourceSlide*/, + Qt3DSDMInstanceHandle /*inSourceInstance*/, + Qt3DSDMSlideHandle /*inDestSlide*/, Qt3DSDMInstanceHandle /*inDestInstance*/) override + { + throw SlideNotFound(L""); + } + + static SSlide *GetSlideNF(int inHandle, THandleObjectMap &inObjects) + { + return const_cast<SSlide *>( + GetSlideNF(inHandle, static_cast<const THandleObjectMap &>(inObjects))); + } + + static const SSlide *GetSlideNF(int inHandle, const THandleObjectMap &inObjects) + { + const SSlide *theSlide = GetHandleObject<SSlide>(inHandle, inObjects); + if (theSlide) + return theSlide; + throw SlideNotFound(L""); + } + + static inline bool PropertyFound(int inInstance, int inProperty, const TSlideEntry &inEntry) + { + if (inInstance == std::get<0>(inEntry) && inProperty == std::get<1>(inEntry)) + return true; + return false; + } + + static void ForceSetPropertyValue(IStringTable &inStringTable, THandleObjectMap &inObjects, + Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue); + + static void ClearPropertyValue(THandleObjectMap &inObjects, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty); + + static inline bool SlideEntryInstanceMatches(const TSlideEntry &inEntry, + Qt3DSDMInstanceHandle inHandle) + { + using namespace std; + if (inHandle.GetHandleValue() == get<0>(inEntry)) + return true; + return false; + } + + static inline bool SlideEntryPropertyMatches(const TSlideEntry &inEntry, + Qt3DSDMPropertyHandle inProperty) + { + using namespace std; + return inProperty.GetHandleValue() == get<1>(inEntry); + } + + static inline bool SlideEntryInstancePropertyMatches(const TSlideEntry &inEntry, + const TInstanceHandleList &inInstances, + const TPropertyHandleList &inProperties) + { + using namespace std; + return exists(inInstances, std::bind(equal_to<int>(), get<0>(inEntry), + std::placeholders::_1)) + && exists(inProperties, std::bind(equal_to<int>(), get<1>(inEntry), + std::placeholders::_1)); + } +}; + +typedef std::shared_ptr<CSimpleSlideCore> TSimpleSlideCorePtr; +} + +#endif diff --git a/src/dm/systems/cores/SimpleSlideGraphCore.cpp b/src/dm/systems/cores/SimpleSlideGraphCore.cpp new file mode 100644 index 0000000..5f1de1e --- /dev/null +++ b/src/dm/systems/cores/SimpleSlideGraphCore.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "SimpleSlideGraphCore.h" + +using namespace std; + +namespace qt3dsdm { + +Qt3DSDMSlideGraphHandle CSimpleSlideGraphCore::CreateSlideGraph(Qt3DSDMSlideHandle inRoot) +{ + int nextId = GetNextId(); + return CreateSlideGraphWithHandle(nextId, inRoot); +} + +Qt3DSDMSlideHandle CSimpleSlideGraphCore::GetGraphRoot(Qt3DSDMSlideGraphHandle inGraph) const +{ + return GetSlideGraphNF(inGraph, m_Objects)->m_Root; +} + +inline bool RootSlideMatches(const THandleObjectPair &inPair, Qt3DSDMSlideHandle inSlide) +{ + const SSlideGraph *theGraph = static_cast<SSlideGraph *>(inPair.second.get()); + if (theGraph->m_Root == inSlide) + return true; + return false; +} + +Qt3DSDMSlideGraphHandle CSimpleSlideGraphCore::GetSlideGraph(Qt3DSDMSlideHandle inSlide) const +{ + THandleObjectMap::const_iterator theFind = find_if<THandleObjectMap::const_iterator>( + m_Objects, std::bind(RootSlideMatches, std::placeholders::_1, inSlide)); + if (theFind != m_Objects.end()) + return theFind->first; + return 0; +} + +inline Qt3DSDMSlideGraphHandle ToGraphHandle(const THandleObjectPair &inPair) +{ + return inPair.first; +} + +void CSimpleSlideGraphCore::GetSlideGraphs(TSlideGraphHandleList &outGraphs) const +{ + outGraphs.resize(m_Objects.size()); + transform(m_Objects.begin(), m_Objects.end(), outGraphs.begin(), ToGraphHandle); +} + +void CSimpleSlideGraphCore::DeleteSlideGraph(Qt3DSDMSlideGraphHandle inHandle) +{ + TSlideInstancePairList theAssociatedInstances; + GetAssociatedInstances(inHandle, theAssociatedInstances); + for (size_t idx = 0, end = theAssociatedInstances.size(); idx < end; ++idx) + DissociateInstance(theAssociatedInstances[idx].second); + EraseHandle(inHandle, m_Objects); +} + +void CSimpleSlideGraphCore::AssociateInstance(Qt3DSDMSlideGraphHandle inSlideGraph, + Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) +{ + pair<TInstanceToGraphMap::iterator, bool> theResult = + m_InstanceToGraph.insert(make_pair(inInstance, make_pair(inSlideGraph, inSlide))); + Q_ASSERT(theResult.second); + if (theResult.second == false) { + theResult.first->second.first = inSlideGraph; + theResult.first->second.second = inSlide; + } + pair<TGraphToInstanceMap::iterator, bool> theGraphResult = + m_GraphToInstances.insert(make_pair(inSlideGraph, TSlideInstancePairList())); + insert_unique(theGraphResult.first->second, make_pair(inSlide, inInstance)); +} + +void CSimpleSlideGraphCore::GetAssociatedInstances(Qt3DSDMSlideGraphHandle inSlideGraph, + TSlideInstancePairList &outAssociations) const +{ + TGraphToInstanceMap::const_iterator theFind = m_GraphToInstances.find(inSlideGraph); + if (theFind != m_GraphToInstances.end()) + outAssociations.insert(outAssociations.end(), theFind->second.begin(), + theFind->second.end()); +} + +TGraphSlidePair CSimpleSlideGraphCore::GetAssociatedGraph(Qt3DSDMInstanceHandle inInstance) const +{ + TInstanceToGraphMap::const_iterator theResult = m_InstanceToGraph.find(inInstance); + if (theResult != m_InstanceToGraph.end()) + return theResult->second; + return TGraphSlidePair(); +} + +struct SInstanceMatcher +{ + Qt3DSDMInstanceHandle m_Instance; + SInstanceMatcher(Qt3DSDMInstanceHandle inInst) + : m_Instance(inInst) + { + } + bool operator()(const pair<Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle> &inItem) const + { + return m_Instance == inItem.second; + } +}; + +void CSimpleSlideGraphCore::DissociateInstance(Qt3DSDMInstanceHandle inInstance) +{ + TGraphSlidePair theAssociatedGraph(GetAssociatedGraph(inInstance)); + + TGraphToInstanceMap::iterator theFind = m_GraphToInstances.find(theAssociatedGraph.first); + if (theFind != m_GraphToInstances.end()) { + erase_if(theFind->second, SInstanceMatcher(inInstance)); + if (theFind->second.size() == 0) + m_GraphToInstances.erase(theAssociatedGraph.first); + } + + m_InstanceToGraph.erase(inInstance); +} + +void CSimpleSlideGraphCore::SetGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph, + Qt3DSDMSlideHandle inSlide) +{ + GetSlideGraphNF(inGraph, m_Objects)->m_ActiveSlide = inSlide; +} + +Qt3DSDMSlideHandle CSimpleSlideGraphCore::GetGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph) const +{ + const SSlideGraph *theSlide = GetSlideGraphNF(inGraph, m_Objects); + if (theSlide->m_ActiveSlide) + return theSlide->m_ActiveSlide; + return theSlide->m_Root; +} + +bool CSimpleSlideGraphCore::HandleValid(int inHandle) const +{ + return CHandleBase::HandleValid(inHandle); +} + +Qt3DSDMSlideGraphHandle CSimpleSlideGraphCore::CreateSlideGraphWithHandle(int inHandle, + Qt3DSDMSlideHandle inRoot) +{ + m_Objects.insert(make_pair(inHandle, (THandleObjectPtr) new SSlideGraph(inHandle, inRoot))); + return inHandle; +} +} diff --git a/src/dm/systems/cores/SimpleSlideGraphCore.h b/src/dm/systems/cores/SimpleSlideGraphCore.h new file mode 100644 index 0000000..484d675 --- /dev/null +++ b/src/dm/systems/cores/SimpleSlideGraphCore.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef SLIDEGRAPHCOREH +#define SLIDEGRAPHCOREH +#include "Qt3DSDMStringTable.h" +#include "Qt3DSDMSlideGraphCore.h" +#include "HandleSystemBase.h" +#include "Qt3DSDMErrors.h" + +namespace qt3dsdm { +using namespace std; +struct SSlideGraph : public CHandleObject +{ + SSlideGraph() + : m_Root(0) + , m_ActiveSlide(0) + { + } + SSlideGraph(int inHandle, int inSlideRoot) + : CHandleObject(inHandle) + , m_Root(inSlideRoot) + , m_ActiveSlide(0) + { + } + Qt3DSDMSlideHandle m_Root; + Qt3DSDMSlideHandle m_ActiveSlide; + + static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeSSlideGraph; + EHandleObjectType GetType() override { return s_Type; } +}; + +class CSimpleSlideGraphCore : public CHandleBase, public ISlideGraphCore +{ + TStringTablePtr m_StringTable; + typedef std::unordered_map<Qt3DSDMInstanceHandle, + pair<Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle>, std::hash<int>> + TInstanceToGraphMap; + typedef std::unordered_map<Qt3DSDMSlideGraphHandle, TSlideInstancePairList, std::hash<int>> + TGraphToInstanceMap; + + TInstanceToGraphMap m_InstanceToGraph; + TGraphToInstanceMap m_GraphToInstances; + +public: + CSimpleSlideGraphCore(TStringTablePtr strTable = TStringTablePtr()) + : m_StringTable(strTable) + { + } + TStringTablePtr GetStringTablePtr() { return m_StringTable; } + /** + * A slide graph is used to associate a set of instances to a set of slides. + * This allows rapid lookup of properties, as an implementation of these. + * There are a few assumptions here. First is that a given slide can be a member + * of one and only one graph (i.e. it does not derive from another slide outside of the graph). + * Second is that an instance is a member of one and only one graph. + */ + Qt3DSDMSlideGraphHandle CreateSlideGraph(Qt3DSDMSlideHandle inRoot) override; + Qt3DSDMSlideHandle GetGraphRoot(Qt3DSDMSlideGraphHandle inGraph) const override; + Qt3DSDMSlideGraphHandle GetSlideGraph(Qt3DSDMSlideHandle inSlide) const override; + void GetSlideGraphs(TSlideGraphHandleList &outGraphs) const override; + void DeleteSlideGraph(Qt3DSDMSlideGraphHandle inHandle) override; + + /** + * Associate a given instance handle with a given graph. This will ensure that property + *lookups + * will travel through this graph before they hit the main data core. Instances may be + *associated + * with a sub-slide of a given graph, not just the root. An instance associated with the root + *is + * implicitly associated with any root-derived slides. + */ + void AssociateInstance(Qt3DSDMSlideGraphHandle inSlideGraph, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) override; + void GetAssociatedInstances(Qt3DSDMSlideGraphHandle inSlideGraph, + TSlideInstancePairList &outAssociations) const override; + TGraphSlidePair GetAssociatedGraph(Qt3DSDMInstanceHandle inInstance) const override; + void DissociateInstance(Qt3DSDMInstanceHandle inInstance) override; + + /** + * All graphs always have an active slide. This is assumed to be the root right off the bat. + */ + void SetGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide) override; + Qt3DSDMSlideHandle GetGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph) const override; + + bool HandleValid(int inHandle) const override; + + Qt3DSDMSlideGraphHandle CreateSlideGraphWithHandle(int inHandle, Qt3DSDMSlideHandle inRoot); + + static SSlideGraph *GetSlideGraphNF(int inHandle, THandleObjectMap &inObjects) + { + return const_cast<SSlideGraph *>( + GetSlideGraphNF(inHandle, static_cast<const THandleObjectMap &>(inObjects))); + } + + static const SSlideGraph *GetSlideGraphNF(int inHandle, const THandleObjectMap &inObjects) + { + const SSlideGraph *theSlide = GetHandleObject<SSlideGraph>(inHandle, inObjects); + if (theSlide) + return theSlide; + throw SlideGraphNotFound(L""); + } +}; + +typedef std::shared_ptr<CSimpleSlideGraphCore> TSimpleSlideGraphCorePtr; +} + +#endif diff --git a/src/dm/systems/cores/SlideCoreProducer.cpp b/src/dm/systems/cores/SlideCoreProducer.cpp new file mode 100644 index 0000000..86b0d1f --- /dev/null +++ b/src/dm/systems/cores/SlideCoreProducer.cpp @@ -0,0 +1,562 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#ifdef _WIN32 +#pragma warning(disable : 4503) // decorated name length exceeded +#endif +#include "SlideCoreProducer.h" +#include "HandleSystemTransactions.h" +#include "VectorTransactions.h" +#include "SignalsImpl.h" + +using namespace std; + +namespace qt3dsdm { + +Qt3DSDMSlideHandle CSlideCoreProducer::CreateSlide(Qt3DSDMInstanceHandle inInstance) +{ + Qt3DSDMSlideHandle retval = m_Data->CreateSlide(inInstance); + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + GetSignalSender()->SendSlideCreated(retval); + return retval; +} + +Qt3DSDMInstanceHandle CSlideCoreProducer::GetSlideInstance(Qt3DSDMSlideHandle inSlide) const +{ + return m_Data->GetSlideInstance(inSlide); +} + +Qt3DSDMSlideHandle CSlideCoreProducer::GetSlideByInstance(Qt3DSDMInstanceHandle inSlide) const +{ + return m_Data->GetSlideByInstance(inSlide); +} + +void SendPropertyRemoved(const TSlideEntry &inEntry, Qt3DSDMSlideHandle inSlide, + ISlideCoreSignalSender *inSender) +{ + inSender->SendPropertyValueRemoved(inSlide, get<0>(inEntry), get<1>(inEntry), get<2>(inEntry)); +} + +void RecurseCreateDeleteTransactions(TTransactionConsumerPtr inConsumer, Qt3DSDMSlideHandle inSlide, + THandleObjectMap &inObjects, ISlideCoreSignalSender *inSender) +{ + SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, inObjects); + inSender->SendBeforeSlideDeleted(theSlide->m_Handle); + do_all(theSlide->m_Children, std::bind(RecurseCreateDeleteTransactions, inConsumer, + std::placeholders::_1, + std::ref(inObjects), inSender)); + if (inConsumer) + CREATE_HANDLE_DELETE_TRANSACTION(inConsumer, inSlide, inObjects); + inSender->SendSlideDeleted(theSlide->m_Handle); +} + +void CSlideCoreProducer::DeleteSlide(Qt3DSDMSlideHandle inSlide, TInstanceHandleList &outInstances) +{ + // Ensure exists + SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, m_Data->m_Objects); + if (theSlide->m_Parent) { + SSlide *theParent = CSimpleSlideCore::GetSlideNF(theSlide->m_Parent, m_Data->m_Objects); + CreateVecEraseTransaction<int>(__FILE__, __LINE__, m_Consumer, inSlide, + theParent->m_Children); + } + RecurseCreateDeleteTransactions(m_Consumer, inSlide, m_Data->m_Objects, GetSignalSender()); + // Not any more... + m_Data->DeleteSlide(inSlide, outInstances); +} + +void CSlideCoreProducer::GetSlides(TSlideHandleList &outSlides) const +{ + m_Data->GetSlides(outSlides); +} + +float CSlideCoreProducer::GetSlideTime(Qt3DSDMSlideHandle inSlide) const +{ + return m_Data->GetSlideTime(inSlide); +} + +void CSlideCoreProducer::SetSlideTime(Qt3DSDMSlideHandle inSlide, float inNewTime) +{ + SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, m_Data->m_Objects); + float oldTime = theSlide->m_Time; + theSlide->m_Time = inNewTime; + if (m_Consumer) { + m_Consumer->OnTransaction(std::shared_ptr<ITransaction>(CREATE_GENERIC_TRANSACTION( + std::bind(&CSlideCoreProducer::SetSlideTime, this, inSlide, inNewTime), + std::bind(&CSlideCoreProducer::SetSlideTime, this, inSlide, oldTime)))); + } else + GetSignalSender()->SendSlideTimeChanged(inSlide); +} + +inline void SetSlideParent(THandleObjectMap &inObjects, int inSlide, int inParent) +{ + CSimpleSlideCore::GetSlideNF(inSlide, inObjects)->m_Parent = inParent; +} + +void CSlideCoreProducer::DeriveSlide(Qt3DSDMSlideHandle inSlide, Qt3DSDMSlideHandle inParent, + int inIndex) +{ + // Integrity checks to ensure operation will proceed + SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, m_Data->m_Objects); + SSlide *theNewParent = NULL; + if (inParent) + theNewParent = CSimpleSlideCore::GetSlideNF(inParent, m_Data->m_Objects); + SSlide *theOldParent = NULL; + if (theSlide->m_Parent) + theOldParent = CSimpleSlideCore::GetSlideNF(theSlide->m_Parent, m_Data->m_Objects); + + if (theSlide->m_Parent && m_Consumer) { + m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION( + std::bind(SetSlideParent, std::ref(m_Data->m_Objects), inSlide, inParent), + std::bind(SetSlideParent, std::ref(m_Data->m_Objects), inSlide, + theSlide->m_Parent)))); + if (theOldParent) + CreateVecEraseTransaction<int>(__FILE__, __LINE__, m_Consumer, inSlide, + theOldParent->m_Children); + GetSignalSender()->SendSlideDerived(inSlide, 0, inIndex); + } + m_Data->DeriveSlide(inSlide, inParent, inIndex); + if (theNewParent) + CreateVecInsertTransaction<int>(__FILE__, __LINE__, m_Consumer, inSlide, + theNewParent->m_Children); + GetSignalSender()->SendSlideDerived(inSlide, inParent, inIndex); +} + +Qt3DSDMSlideHandle CSlideCoreProducer::GetParentSlide(Qt3DSDMSlideHandle inSlide) const +{ + return m_Data->GetParentSlide(inSlide); +} + +void CSlideCoreProducer::GetChildSlides(Qt3DSDMSlideHandle inSlide, + TSlideHandleList &outChildren) const +{ + m_Data->GetChildSlides(inSlide, outChildren); +} + +int CSlideCoreProducer::GetChildIndex(Qt3DSDMSlideHandle inParent, Qt3DSDMSlideHandle inChild) const +{ + return m_Data->GetChildIndex(inParent, inChild); +} + +bool CSlideCoreProducer::GetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + return m_Data->GetInstancePropertyValue(inSlide, inHandle, inProperty, outValue); +} + +inline void EraseProperty(TSlideEntryList &inProperties, int inInstance, int inProperty) +{ + erase_if(inProperties, + std::bind(CSimpleSlideCore::PropertyFound, inInstance, inProperty, + std::placeholders::_1)); +} + +void CSlideCoreProducer::SetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + std::pair<SSlide *, SInternValue *> slideAndProp( + m_Data->ResolveSetInstancePropertyValue(inSlide, inHandle, inProperty)); + DoForceSetInstancePropertyValue(slideAndProp.first->m_Handle, inHandle, inProperty, inValue); +} + +struct HashMapDataValueInsertTransaction + : public HashMapInsertTransaction<TSlideInstancePropertyPair, SInternValue, + TSlideEntryHash::hasher> +{ + typedef HashMapInsertTransaction<TSlideInstancePropertyPair, SInternValue, + TSlideEntryHash::hasher> + TBase; + HashMapDataValueInsertTransaction( + const char *inFile, int inLine, TSlideEntryHash &map, + const std::pair<TSlideInstancePropertyPair, SInternValue> &val) + : TBase(inFile, inLine, map, val) + { + } + void Do() override + { + std::pair<int, int> theKey = m_Value.first; + SValue theTempValue = m_Value.second.GetValue(); + TDataStrPtr theStrPtr; + if (GetValueType(theTempValue) == DataModelDataType::String) { + theStrPtr = qt3dsdm::get<TDataStrPtr>(theTempValue); + } + (void)theStrPtr; + TBase::Add(); + } +}; + +inline void CSlideCoreProducer::DoForceSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, m_Data->m_Objects); + SInternValue theNewValue(inValue, m_Data->GetStringTable()); + SInternValue *theCurrentValue(theSlide->GetInstancePropertyValue(inHandle, inProperty)); + + std::pair<int, int> theKey(inHandle, inProperty); + SlideInstancePropertyKey mergeMapKey(inSlide, inHandle, inProperty); + TSlidePropertyMergeMap::iterator iter = m_PropertyMergeMap.find(mergeMapKey); + if (iter != m_PropertyMergeMap.end()) { + const SValue &theTempValue(theNewValue.GetValue()); + CSimpleSlideCore::ForceSetPropertyValue(m_Data->GetStringTable(), m_Data->m_Objects, + inSlide, inHandle, inProperty, theTempValue); + iter->second->Update(theNewValue); + if (GetValueType(theTempValue) == DataModelDataType::String) { + TDataStrPtr theStrPtr = qt3dsdm::get<TDataStrPtr>(theTempValue); + QT3DSDM_DEBUG_LOG(m_Data->GetStringTable().GetNarrowStr(theStrPtr->GetData())); + } + return; // don't signal + } else { + TSlidePropertyMergeMapEntry theEntry; + if (theCurrentValue) { + theEntry = + CreateHashMapSwapTransaction(__FILE__, __LINE__, m_Consumer, theKey, + *theCurrentValue, theNewValue, theSlide->m_Properties); + } else { + if (m_Consumer) { + std::shared_ptr<HashMapDataValueInsertTransaction> theTransaction = + std::make_shared<HashMapDataValueInsertTransaction>( + __FILE__, __LINE__, std::ref(theSlide->m_Properties), + std::make_pair(theKey, theNewValue)); + m_Consumer->OnTransaction(theTransaction); + theEntry = theTransaction; + } + } + if (theEntry) + m_PropertyMergeMap.insert(make_pair(mergeMapKey, theEntry)); + CSimpleSlideCore::ForceSetPropertyValue(m_Data->GetStringTable(), m_Data->m_Objects, + inSlide, inHandle, inProperty, + theNewValue.GetValue()); + GetSignalSender()->SendPropertyValueSet(inSlide, inHandle, inProperty, + theNewValue.GetValue()); + } +} + +void CSlideCoreProducer::ForceSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + if (m_Consumer) + DoForceSetInstancePropertyValue(inSlide, inHandle, inProperty, inValue); + else + m_Data->ForceSetInstancePropertyValue(inSlide, inHandle, inProperty, inValue); +} + +void CSlideCoreProducer::forceSetInstancePropertyValueOnAllSlides(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + m_Data->forceSetInstancePropertyValueOnAllSlides(inInstance, inProperty, inValue); +} + +bool CSlideCoreProducer::GetSpecificInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + return m_Data->GetSpecificInstancePropertyValue(inSlide, inInstance, inProperty, outValue); +} + +bool CSlideCoreProducer::ContainsProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) const +{ + return m_Data->ContainsProperty(inSlide, inHandle, inProperty); +} + +void CSlideCoreProducer::GetSlidePropertyEntries(Qt3DSDMSlideHandle inSlide, + TSlideEntryList &outEntries) const +{ + return m_Data->GetSlidePropertyEntries(inSlide, outEntries); +} + +void CSlideCoreProducer::PushPropertyValueToChildren(Qt3DSDMSlideHandle inParent, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + SSlide *theParent = CSimpleSlideCore::GetSlideNF(inParent, m_Data->m_Objects); + DoForceSetInstancePropertyValue(inParent, inHandle, inProperty, inValue); + do_all(theParent->m_Children, std::bind(&CSlideCoreProducer::DoForceSetInstancePropertyValue, + this, std::placeholders::_1, + inHandle, inProperty, inValue)); +} + +inline void ClearValueWithTransactions(TTransactionConsumerPtr inConsumer, + THandleObjectMap &inObjects, + ISlideCoreSignalSender *inSignalSender, int inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) +{ + SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, inObjects); + SInternValue *theCurrentValue(theSlide->GetInstancePropertyValue(inHandle, inProperty)); + if (theCurrentValue) { + SValue theValue(theCurrentValue->GetValue()); + std::pair<int, int> theKey(inHandle, inProperty); + CreateHashMapEraseTransaction(__FILE__, __LINE__, inConsumer, + std::make_pair(theKey, *theCurrentValue), + theSlide->m_Properties); + CSimpleSlideCore::ClearPropertyValue(inObjects, inSlide, inHandle, inProperty); + inSignalSender->SendPropertyValueRemoved(inSlide, inHandle, inProperty, theValue); + } +} + +void CSlideCoreProducer::ClearChildrenPropertyValues(Qt3DSDMSlideHandle inParent, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) +{ + SSlide *theParent = CSimpleSlideCore::GetSlideNF(inParent, m_Data->m_Objects); + do_all(theParent->m_Children, + std::bind(ClearValueWithTransactions, m_Consumer, std::ref(m_Data->m_Objects), + GetSignalSender(), std::placeholders::_1, inHandle, inProperty)); +} + +typedef tuple<int, TSlideEntryList, TSlideEntryList> TSlideSlideEntryTuple; +typedef std::vector<TSlideSlideEntryTuple> TSlideSlideEntryTupleList; + +inline void CreateVectorPreReplaceData(THandleObjectPair inPair, + TSlideSlideEntryTupleList &outSlideSlideEntries, + function<bool(const TSlideEntry &)> inPredicate) +{ + if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeSSlide) { + SSlide *theSlide = static_cast<SSlide *>(inPair.second.get()); + if (theSlide->HasProperty(inPredicate)) { + outSlideSlideEntries.push_back( + TSlideSlideEntryTuple(inPair.first, TSlideEntryList(), TSlideEntryList())); + theSlide->DeleteSlideEntries(get<1>(outSlideSlideEntries.back()), inPredicate); + } + } +} + +inline void RunInsert(tuple<int, TSlideEntryList, TSlideEntryList> &inTuple, + THandleObjectMap &inObjects, IStringTable &inStringTable) +{ + SSlide *theSlide = CSimpleSlideCore::GetSlideNF(get<0>(inTuple), inObjects); + theSlide->InsertSlideEntries(get<1>(inTuple), inStringTable); +} + +inline void RunFullInsert(std::shared_ptr<TSlideSlideEntryTupleList> inList, + THandleObjectMap &inObjects, IStringTable &inStringTable) +{ + for (TSlideSlideEntryTupleList::iterator theIter = inList->begin(); theIter != inList->end(); + ++theIter) + RunInsert(*theIter, inObjects, inStringTable); +} + +inline void RunFullErase(std::shared_ptr<TSlideSlideEntryTupleList> inList, + THandleObjectMap &inObjects) +{ + for (TSlideSlideEntryTupleList::iterator theIter = inList->begin(); theIter != inList->end(); + ++theIter) { + SSlide *theSlide = CSimpleSlideCore::GetSlideNF(get<0>(*theIter), inObjects); + theSlide->DeleteEntriesFromList(std::get<1>(*theIter)); + } +} + +void DeleteAllSlideEntriesWithUndo(TTransactionConsumerPtr inConsumer, IStringTable &inStringTable, + THandleObjectMap &inObjects, + function<bool(const TSlideEntry &)> inPredicate) +{ + std::shared_ptr<TSlideSlideEntryTupleList> theEntries(new TSlideSlideEntryTupleList); + do_all(inObjects, + std::bind(CreateVectorPreReplaceData, + std::placeholders::_1, std::ref(*theEntries), inPredicate)); + if (inConsumer) + CreateGenericTransactionWithConsumer( + __FILE__, __LINE__, inConsumer, + std::bind(RunFullErase, theEntries, std::ref(inObjects)), + std::bind(RunFullInsert, theEntries, std::ref(inObjects), + std::ref(inStringTable))); +} + +void CSlideCoreProducer::DeleteAllInstanceEntries(Qt3DSDMInstanceHandle inInstance) +{ + DeleteAllSlideEntriesWithUndo( + m_Consumer, GetStringTable(), m_Data->m_Objects, + std::bind(CSimpleSlideCore::SlideEntryInstanceMatches, std::placeholders::_1, inInstance)); +} +void CSlideCoreProducer::DeleteAllPropertyEntries(Qt3DSDMPropertyHandle inHandle) +{ + DeleteAllSlideEntriesWithUndo( + m_Consumer, GetStringTable(), m_Data->m_Objects, + std::bind(CSimpleSlideCore::SlideEntryPropertyMatches, std::placeholders::_1, inHandle)); +} + +void CSlideCoreProducer::DeleteAllInstancePropertyEntries(const TInstanceHandleList &inInstances, + const TPropertyHandleList &inProperties) +{ + DeleteAllSlideEntriesWithUndo(m_Consumer, GetStringTable(), m_Data->m_Objects, + std::bind(CSimpleSlideCore::SlideEntryInstancePropertyMatches, + std::placeholders::_1, std::cref(inInstances), + std::cref(inProperties))); +} + +void CSlideCoreProducer::GetIntersectingProperties(Qt3DSDMSlideHandle inSlide1, + Qt3DSDMSlideHandle inSlide2, + TSlideEntryList &outEntries) const +{ + return m_Data->GetIntersectingProperties(inSlide1, inSlide2, outEntries); +} + +bool InstancePropMatches(Qt3DSDMInstanceHandle instance, Qt3DSDMPropertyHandle prop, + const TSlideEntry &entry) +{ + return instance == get<0>(entry) && prop == get<1>(entry); +} + +bool SendPropertyAddedIfNotInList(Qt3DSDMInstanceHandle instance, Qt3DSDMPropertyHandle prop, + SValue & /*value*/, const TSlideEntryList &inList, + Qt3DSDMSlideHandle inSource, Qt3DSDMSlideHandle inSlide, + ISlideCoreSignalSender * /*inSignalSender*/) +{ + if (find_if<TSlideEntryList::const_iterator>( + inList, std::bind(InstancePropMatches, instance, prop, std::placeholders::_1)) + == inList.end()) { + return true; + } + return false; +} + +// destination gets the properties from slide 1 that have corresponding entries in slide 2 +void CSlideCoreProducer::PushIntersectingProperties(Qt3DSDMSlideHandle inSlide1, + Qt3DSDMSlideHandle inSlide2, + Qt3DSDMSlideHandle inDestination) +{ + SSlide *theDest = CSimpleSlideCore::GetSlideNF(inDestination, m_Data->m_Objects); + TSlideEntryList theProperties; + theDest->ToSlideEntryList(theProperties); + m_Data->PushIntersectingProperties(inSlide1, inSlide2, inDestination); + theDest->SetPropertyValuesIf(GetStringTable(), std::bind(SendPropertyAddedIfNotInList, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + theProperties, inSlide1, + inDestination, GetSignalSender())); + if (m_Consumer) { + TSlideEntryList theResult; + theDest->ToSlideEntryList(theResult); + m_Consumer->OnTransaction(TTransactionPtr( + CREATE_GENERIC_TRANSACTION(std::bind(&SSlide::FromSlideEntryList, theDest, theResult, + std::ref(GetStringTable())), + std::bind(&SSlide::FromSlideEntryList, theDest, + theProperties, std::ref(GetStringTable()))))); + } +} + +void CSlideCoreProducer::CopyProperties(Qt3DSDMSlideHandle inSourceSlide, + Qt3DSDMInstanceHandle inSourceInstance, + Qt3DSDMSlideHandle inDestSlide, + Qt3DSDMInstanceHandle inDestInstance) +{ + SSlide *sourceSlide = CSimpleSlideCore::GetSlideNF(inSourceSlide, m_Data->m_Objects); + + for (TSlideEntryHash::iterator theIter = sourceSlide->m_Properties.begin(), + theEnd = sourceSlide->m_Properties.end(); + theIter != theEnd; ++theIter) { + if (theIter->first.first == inSourceInstance) { + // Set it once so it appears in the slide + // Then call the main method that will send the events. + DoForceSetInstancePropertyValue(inDestSlide, inDestInstance, theIter->first.second, + theIter->second.GetValue()); + } + } +} + +bool CSlideCoreProducer::HandleValid(int inHandle) const +{ + return m_Data->HandleValid(inHandle); +} + +bool CSlideCoreProducer::IsSlide(Qt3DSDMSlideHandle inSlide) const +{ + return m_Data->IsSlide(inSlide); +} + +void CSlideCoreProducer::SetConsumer(TTransactionConsumerPtr inConsumer) +{ + m_Consumer = inConsumer; + m_PropertyMergeMap.clear(); +} + +TSignalConnectionPtr +CSlideCoreProducer::ConnectSlideCreated(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectSlideCreated(inCallback); +} +TSignalConnectionPtr CSlideCoreProducer::ConnectBeforeSlideDeleted( + const std::function<void(Qt3DSDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectBeforeSlideDeleted(inCallback); +} +TSignalConnectionPtr +CSlideCoreProducer::ConnectSlideDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectSlideDeleted(inCallback); +} +TSignalConnectionPtr CSlideCoreProducer::ConnectSlideDerived( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMSlideHandle, int)> &inCallback) +{ + return GetSignalProvider()->ConnectSlideDerived(inCallback); +} +TSignalConnectionPtr CSlideCoreProducer::ConnectInstancePropertyValueSet( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) +{ + return GetSignalProvider()->ConnectInstancePropertyValueSet(inCallback); +} +TSignalConnectionPtr CSlideCoreProducer::ConnectInstancePropertyValueRemoved( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) +{ + return GetSignalProvider()->ConnectInstancePropertyValueRemoved(inCallback); +} +TSignalConnectionPtr CSlideCoreProducer::ConnectSlideTimeChanged( + const std::function<void(Qt3DSDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectSlideTimeChanged(inCallback); +} + +void CSlideCoreProducer::InitSignaller() +{ + m_SlideCoreSignaller = CreateSlideCoreSignaller(); +} + +ISlideCoreSignalProvider *CSlideCoreProducer::GetSignalProvider() +{ + return dynamic_cast<ISlideCoreSignalProvider *>(m_SlideCoreSignaller.get()); +} +ISlideCoreSignalSender *CSlideCoreProducer::GetSignalSender() +{ + return dynamic_cast<ISlideCoreSignalSender *>(m_SlideCoreSignaller.get()); +} +} diff --git a/src/dm/systems/cores/SlideCoreProducer.h b/src/dm/systems/cores/SlideCoreProducer.h new file mode 100644 index 0000000..dec0297 --- /dev/null +++ b/src/dm/systems/cores/SlideCoreProducer.h @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef SLIDECOREPRODUCERH +#define SLIDECOREPRODUCERH +#include "Qt3DSDMTransactions.h" +#include "SimpleSlideCore.h" +#include "Qt3DSDMSignals.h" + +namespace qt3dsdm { +struct SlideInstancePropertyKey +{ + int m_Slide; + int m_Instance; + int m_Property; + SlideInstancePropertyKey(int slide, int inst, int prop) + : m_Slide(slide) + , m_Instance(inst) + , m_Property(prop) + { + } + SlideInstancePropertyKey() + : m_Slide(0) + , m_Instance(0) + , m_Property(0) + { + } + + bool operator==(const SlideInstancePropertyKey &inOther) const + { + return m_Slide == inOther.m_Slide && m_Instance == inOther.m_Instance + && m_Property == inOther.m_Property; + } +}; + +struct SlideInstancePropertyKeyHasher +{ + std::size_t operator()(const SlideInstancePropertyKey &inEntry) const + { + return std::hash<int>()(inEntry.m_Slide) ^ std::hash<int>()(inEntry.m_Instance) + ^ std::hash<int>()(inEntry.m_Property); + } +}; + +typedef std::shared_ptr<IMergeableTransaction<SInternValue>> TSlidePropertyMergeMapEntry; +typedef std::unordered_map<SlideInstancePropertyKey, TSlidePropertyMergeMapEntry, + SlideInstancePropertyKeyHasher> + TSlidePropertyMergeMap; + +class CSlideCoreProducer : public ISlideCore, + public ITransactionProducer, + public ISlideCoreSignalProvider +{ + Q_DISABLE_COPY(CSlideCoreProducer) + + TTransactionConsumerPtr m_Consumer; + TSimpleSlideCorePtr m_Data; + TSignalItemPtr m_SlideCoreSignaller; + TSlidePropertyMergeMap m_PropertyMergeMap; + +public: + CSlideCoreProducer(TStringTablePtr inStrTable) + : m_Data(new CSimpleSlideCore(inStrTable)) + { + InitSignaller(); + } + + IStringTable &GetStringTable() const override { return m_Data->GetStringTable(); } + TStringTablePtr GetStringTablePtr() const override { return m_Data->GetStringTablePtr(); } + + TSimpleSlideCorePtr GetTransactionlessSlideCore() { return m_Data; } + TSimpleSlideCorePtr GetTransactionlessSlideCore() const { return m_Data; } + + Qt3DSDMSlideHandle CreateSlide(Qt3DSDMInstanceHandle inInstance) override; + Qt3DSDMInstanceHandle GetSlideInstance(Qt3DSDMSlideHandle inSlide) const override; + Qt3DSDMSlideHandle GetSlideByInstance(Qt3DSDMInstanceHandle inSlide) const override; + void DeleteSlide(Qt3DSDMSlideHandle inSlide, TInstanceHandleList &outInstances) override; + void GetSlides(TSlideHandleList &outSlides) const override; + + float GetSlideTime(Qt3DSDMSlideHandle inSlide) const override; + void SetSlideTime(Qt3DSDMSlideHandle inSlide, float inNewTime) override; + + void DeriveSlide(Qt3DSDMSlideHandle inSlide, Qt3DSDMSlideHandle inParent, int inIndex = -1) override; + Qt3DSDMSlideHandle GetParentSlide(Qt3DSDMSlideHandle inSlide) const override; + void GetChildSlides(Qt3DSDMSlideHandle inSlide, TSlideHandleList &outChildren) const override; + int GetChildIndex(Qt3DSDMSlideHandle inParent, Qt3DSDMSlideHandle inChild) const override; + + bool GetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + void SetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + void ForceSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + void forceSetInstancePropertyValueOnAllSlides(Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) override; + bool GetSpecificInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + void GetSpecificInstancePropertyValues(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + TPropertyHandleValuePairList &outValues) override + { + return m_Data->GetSpecificInstancePropertyValues(inSlide, inInstance, outValues); + } + bool ContainsProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) const override; + void GetSlidePropertyEntries(Qt3DSDMSlideHandle inSlide, TSlideEntryList &outEntries) const override; + + void PushPropertyValueToChildren(Qt3DSDMSlideHandle inParent, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + void ClearChildrenPropertyValues(Qt3DSDMSlideHandle inParent, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) override; + void DeleteAllInstanceEntries(Qt3DSDMInstanceHandle inHandle) override; + void DeleteAllPropertyEntries(Qt3DSDMPropertyHandle inHandle) override; + void DeleteAllInstancePropertyEntries(const TInstanceHandleList &inInstances, + const TPropertyHandleList &inProperties) override; + + void GetIntersectingProperties(Qt3DSDMSlideHandle inSlide1, Qt3DSDMSlideHandle inSlide2, + TSlideEntryList &outEntries) const override; + void PushIntersectingProperties(Qt3DSDMSlideHandle inSlide1, Qt3DSDMSlideHandle inSlide2, + Qt3DSDMSlideHandle inDestination) override; + void CopyProperties(Qt3DSDMSlideHandle inSourceSlide, Qt3DSDMInstanceHandle inSourceInstance, + Qt3DSDMSlideHandle inDestSlide, Qt3DSDMInstanceHandle inDestInstance) override; + + bool IsSlide(Qt3DSDMSlideHandle inSlide) const override; + + bool HandleValid(int inHandle) const override; + + void SetConsumer(TTransactionConsumerPtr inConsumer) override; + + //=================================================================== + // Signals + //=================================================================== + + virtual TSignalConnectionPtr + ConnectSlideCreated(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectBeforeSlideDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectSlideDeleted(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override; + TSignalConnectionPtr ConnectSlideDerived( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMSlideHandle, int)> &inCallback) override; + TSignalConnectionPtr ConnectInstancePropertyValueSet( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) override; + TSignalConnectionPtr ConnectInstancePropertyValueRemoved( + const std::function<void(Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectSlideTimeChanged(const std::function<void(Qt3DSDMSlideHandle)> &inCallback) override; + +private: + inline void DoForceSetInstancePropertyValue(Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue); + void InitSignaller(); + ISlideCoreSignalProvider *GetSignalProvider(); + ISlideCoreSignalSender *GetSignalSender(); +}; +} + +#endif diff --git a/src/dm/systems/cores/SlideGraphCoreProducer.cpp b/src/dm/systems/cores/SlideGraphCoreProducer.cpp new file mode 100644 index 0000000..c514108 --- /dev/null +++ b/src/dm/systems/cores/SlideGraphCoreProducer.cpp @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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 "Qt3DSDMPrefix.h" +#include "SlideGraphCoreProducer.h" +#include "HandleSystemTransactions.h" +#include "VectorTransactions.h" +#include "SignalsImpl.h" +using namespace std; + +namespace qt3dsdm { + +Qt3DSDMSlideGraphHandle CSlideGraphCoreProducer::CreateSlideGraph(Qt3DSDMSlideHandle inRoot) +{ + Qt3DSDMSlideGraphHandle retval(m_Data->CreateSlideGraph(inRoot)); + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + GetSignalSender()->SendGraphCreated(retval, inRoot); + return retval; +} + +Qt3DSDMSlideHandle CSlideGraphCoreProducer::GetGraphRoot(Qt3DSDMSlideGraphHandle inGraph) const +{ + return m_Data->GetGraphRoot(inGraph); +} + +Qt3DSDMSlideGraphHandle CSlideGraphCoreProducer::GetSlideGraph(Qt3DSDMSlideHandle inSlide) const +{ + return m_Data->GetSlideGraph(inSlide); +} + +void CSlideGraphCoreProducer::GetSlideGraphs(TSlideGraphHandleList &outGraphs) const +{ + return m_Data->GetSlideGraphs(outGraphs); +} + +struct DissocateAllInstanceTrans : public ITransaction +{ + std::shared_ptr<CSimpleSlideGraphCore> m_Graph; + Qt3DSDMSlideGraphHandle m_Handle; + TSlideInstancePairList m_Instances; + DissocateAllInstanceTrans(const char *inFile, int inLine, + std::shared_ptr<CSimpleSlideGraphCore> inGraph, + Qt3DSDMSlideGraphHandle inHandle) + : ITransaction(inFile, inLine) + , m_Graph(inGraph) + , m_Handle(inHandle) + { + inGraph->GetAssociatedInstances(m_Handle, m_Instances); + } + void Do() override + { + for (size_t idx = 0, end = m_Instances.size(); idx < end; ++idx) + m_Graph->DissociateInstance(m_Instances[idx].second); + } + void Undo() override + { + for (size_t idx = 0, end = m_Instances.size(); idx < end; ++idx) + m_Graph->AssociateInstance(m_Handle, m_Instances[idx].first, m_Instances[idx].second); + } +}; + +void CSlideGraphCoreProducer::DeleteSlideGraph(Qt3DSDMSlideGraphHandle inHandle) +{ + SSlideGraph *theGraph = CSimpleSlideGraphCore::GetSlideGraphNF(inHandle, m_Data->m_Objects); + Qt3DSDMSlideHandle theRootSlide(theGraph->m_Root); + if (m_Consumer) + m_Consumer->OnTransaction( + make_shared<DissocateAllInstanceTrans>(__FILE__, __LINE__, m_Data, inHandle)); + CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inHandle, m_Data->m_Objects); + m_Data->DeleteSlideGraph(inHandle); + GetSignalSender()->SendGraphDeleted(inHandle, theRootSlide); +} + +struct SInstanceAssociateTrans : public ITransaction +{ + std::shared_ptr<CSimpleSlideGraphCore> m_Graph; + Qt3DSDMSlideGraphHandle m_GraphHandle; + Qt3DSDMSlideHandle m_Slide; + Qt3DSDMInstanceHandle m_Instance; + bool m_InsertOnDo; + SInstanceAssociateTrans(const char *inFile, int inLine, + std::shared_ptr<CSimpleSlideGraphCore> inGraph, + Qt3DSDMSlideGraphHandle inGraphHandle, Qt3DSDMSlideHandle inSlideHandle, + Qt3DSDMInstanceHandle inInstance, bool inInsertOnDo) + : ITransaction(inFile, inLine) + , m_Graph(inGraph) + , m_GraphHandle(inGraphHandle) + , m_Slide(inSlideHandle) + , m_Instance(inInstance) + , m_InsertOnDo(inInsertOnDo) + { + } + void Insert() { m_Graph->AssociateInstance(m_GraphHandle, m_Slide, m_Instance); } + void Remove() { m_Graph->DissociateInstance(m_Instance); } + + void Do() override + { + if (m_InsertOnDo) + Insert(); + else + Remove(); + } + void Undo() override + { + if (m_InsertOnDo) + Remove(); + else + Insert(); + } +}; + +void CSlideGraphCoreProducer::AssociateInstance(Qt3DSDMSlideGraphHandle inSlideGraph, + Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) +{ + m_Data->AssociateInstance(inSlideGraph, inSlide, inInstance); + if (m_Consumer) + m_Consumer->OnTransaction(make_shared<SInstanceAssociateTrans>( + __FILE__, __LINE__, m_Data, inSlideGraph, inSlide, inInstance, true)); + + GetSignalSender()->SendInstanceAssociated(inSlideGraph, inSlide, inInstance); +} +void CSlideGraphCoreProducer::GetAssociatedInstances(Qt3DSDMSlideGraphHandle inSlideGraph, + TSlideInstancePairList &outAssociations) const +{ + m_Data->GetAssociatedInstances(inSlideGraph, outAssociations); +} + +TGraphSlidePair CSlideGraphCoreProducer::GetAssociatedGraph(Qt3DSDMInstanceHandle inInstance) const +{ + return m_Data->GetAssociatedGraph(inInstance); +} + +void CSlideGraphCoreProducer::DissociateInstance(Qt3DSDMInstanceHandle inInstance) +{ + TGraphSlidePair theAssociatedGraph(m_Data->GetAssociatedGraph(inInstance)); + + if (theAssociatedGraph.first.Valid()) { + m_Data->DissociateInstance(inInstance); + if (m_Consumer) + m_Consumer->OnTransaction(make_shared<SInstanceAssociateTrans>( + __FILE__, __LINE__, m_Data, theAssociatedGraph.first, theAssociatedGraph.second, + inInstance, false)); + GetSignalSender()->SendInstanceDissociated(theAssociatedGraph.first, + theAssociatedGraph.second, inInstance); + } +} + +void CSlideGraphCoreProducer::SetGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph, + Qt3DSDMSlideHandle inSlide) +{ + if (m_Consumer) { + Qt3DSDMSlideHandle current = m_Data->GetGraphActiveSlide(inGraph); + TTransactionPtr theTransaction(CREATE_GENERIC_TRANSACTION( + bind(&CSimpleSlideGraphCore::SetGraphActiveSlide, m_Data, inGraph, inSlide), + bind(&CSimpleSlideGraphCore::SetGraphActiveSlide, m_Data, inGraph, current))); + m_Consumer->OnTransaction(theTransaction); + } + m_Data->SetGraphActiveSlide(inGraph, inSlide); + GetSignalSender()->SendGraphActiveSlide(inGraph, inSlide); +} + +Qt3DSDMSlideHandle CSlideGraphCoreProducer::GetGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph) const +{ + return m_Data->GetGraphActiveSlide(inGraph); +} + +bool CSlideGraphCoreProducer::HandleValid(int inHandle) const +{ + return m_Data->HandleValid(inHandle); +} + +void CSlideGraphCoreProducer::SetConsumer(TTransactionConsumerPtr inConsumer) +{ + m_Consumer = inConsumer; +} + +TSignalConnectionPtr CSlideGraphCoreProducer::ConnectGraphCreated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectGraphCreated(inCallback); +} +TSignalConnectionPtr CSlideGraphCoreProducer::ConnectGraphDeleted( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectGraphDeleted(inCallback); +} +TSignalConnectionPtr CSlideGraphCoreProducer::ConnectInstanceAssociated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) +{ + return GetSignalProvider()->ConnectInstanceAssociated(inCallback); +} +TSignalConnectionPtr CSlideGraphCoreProducer::ConnectInstanceDissociated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) +{ + return GetSignalProvider()->ConnectInstanceDissociated(inCallback); +} +TSignalConnectionPtr CSlideGraphCoreProducer::ConnectGraphActiveSlide( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectGraphActiveSlide(inCallback); +} + +void CSlideGraphCoreProducer::InitSignaller() +{ + m_Signaller = CreateSlideGraphCoreSignaller(); +} + +ISlideGraphCoreSignalProvider *CSlideGraphCoreProducer::GetSignalProvider() +{ + return dynamic_cast<ISlideGraphCoreSignalProvider *>(m_Signaller.get()); +} + +ISlideGraphCoreSignalSender *CSlideGraphCoreProducer::GetSignalSender() +{ + return dynamic_cast<ISlideGraphCoreSignalSender *>(m_Signaller.get()); +} +} diff --git a/src/dm/systems/cores/SlideGraphCoreProducer.h b/src/dm/systems/cores/SlideGraphCoreProducer.h new file mode 100644 index 0000000..5b34cdb --- /dev/null +++ b/src/dm/systems/cores/SlideGraphCoreProducer.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef SLIDEGRAPHCOREPRODUCERH +#define SLIDEGRAPHCOREPRODUCERH +#include "SimpleSlideGraphCore.h" +#include "Qt3DSDMTransactions.h" +#include "Qt3DSDMSignals.h" + +namespace qt3dsdm { +class CSlideGraphCoreProducer : public ISlideGraphCore, + public ITransactionProducer, + public ISlideGraphCoreSignalProvider +{ + Q_DISABLE_COPY(CSlideGraphCoreProducer) + + TSimpleSlideGraphCorePtr m_Data; + TTransactionConsumerPtr m_Consumer; + TSignalItemPtr m_Signaller; + +public: + CSlideGraphCoreProducer(TStringTablePtr strTable = TStringTablePtr()) + : m_Data(new CSimpleSlideGraphCore(strTable)) + { + InitSignaller(); + } + TSimpleSlideGraphCorePtr GetTransactionlessSlideGraphCore() { return m_Data; } + TSimpleSlideGraphCorePtr GetTransactionlessSlideGraphCore() const { return m_Data; } + + Qt3DSDMSlideGraphHandle CreateSlideGraph(Qt3DSDMSlideHandle inRoot) override; + Qt3DSDMSlideHandle GetGraphRoot(Qt3DSDMSlideGraphHandle inGraph) const override; + Qt3DSDMSlideGraphHandle GetSlideGraph(Qt3DSDMSlideHandle inSlide) const override; + void GetSlideGraphs(TSlideGraphHandleList &outGraphs) const override; + void DeleteSlideGraph(Qt3DSDMSlideGraphHandle inHandle) override; + + void AssociateInstance(Qt3DSDMSlideGraphHandle inSlideGraph, Qt3DSDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) override; + void GetAssociatedInstances(Qt3DSDMSlideGraphHandle inSlideGraph, + TSlideInstancePairList &outAssociations) const override; + TGraphSlidePair GetAssociatedGraph(Qt3DSDMInstanceHandle inInstance) const override; + void DissociateInstance(Qt3DSDMInstanceHandle inInstance) override; + + void SetGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph, Qt3DSDMSlideHandle inSlide) override; + Qt3DSDMSlideHandle GetGraphActiveSlide(Qt3DSDMSlideGraphHandle inGraph) const override; + + bool HandleValid(int inHandle) const override; + void SetConsumer(TTransactionConsumerPtr inConsumer) override; + + //=================================================================== + // Signals + //=================================================================== + TSignalConnectionPtr ConnectGraphCreated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) override; + TSignalConnectionPtr ConnectGraphDeleted( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) override; + TSignalConnectionPtr ConnectInstanceAssociated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) override; + TSignalConnectionPtr ConnectInstanceDissociated( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) override; + TSignalConnectionPtr ConnectGraphActiveSlide( + const std::function<void(Qt3DSDMSlideGraphHandle, Qt3DSDMSlideHandle)> &inCallback) override; + +private: + void InitSignaller(); + ISlideGraphCoreSignalProvider *GetSignalProvider(); + ISlideGraphCoreSignalSender *GetSignalSender(); +}; +} + +#endif |