diff options
author | Määttä Antti <antti.maatta@qt.io> | 2017-10-19 11:10:15 +0300 |
---|---|---|
committer | Antti Määttä <antti.maatta@qt.io> | 2017-10-24 13:23:48 +0000 |
commit | 51e7b6187f3816336e4c9a4a0ab87f788ff1c092 (patch) | |
tree | 1affc607519b945b6fb434a9a29dc84a9ab073ec /src/Authoring/QT3DSDM/Systems/Cores | |
parent | aa75bf1a20a101a5a5080cc99075a345f2a61caf (diff) |
Rename UICDM and UICIMP to QT3DS
Task-number: QT3DS-18
Change-Id: I3800cd72b449b033b0b42cf2dd9e9eccc4eb7f8f
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Diffstat (limited to 'src/Authoring/QT3DSDM/Systems/Cores')
20 files changed, 6061 insertions, 0 deletions
diff --git a/src/Authoring/QT3DSDM/Systems/Cores/ActionCoreProducer.cpp b/src/Authoring/QT3DSDM/Systems/Cores/ActionCoreProducer.cpp new file mode 100644 index 00000000..89bcd183 --- /dev/null +++ b/src/Authoring/QT3DSDM/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 { + +CUICDMActionHandle CActionCoreProducer::CreateAction(Qt3DSDMInstanceHandle inInstance, + CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner, + SLong4 inTriggerTargetObjects) +{ + CUICDMActionHandle retval = + m_Data->CreateAction(inInstance, inSlide, inOwner, inTriggerTargetObjects); + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + return retval; +} + +void CActionCoreProducer::DeleteAction(CUICDMActionHandle 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(CUICDMActionHandle inAction) const +{ + return m_Data->GetActionInfo(inAction); +} + +void CActionCoreProducer::GetActions(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const +{ + return m_Data->GetActions(inSlide, inOwner, outActions); +} + +void CActionCoreProducer::GetActions(CUICDMSlideHandle 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(CUICDMActionHandle inAction) const +{ + return m_Data->GetActionInstance(inAction); +} + +CUICDMActionHandle +CActionCoreProducer::GetActionByInstance(Qt3DSDMInstanceHandle inActionInstance) const +{ + return m_Data->GetActionByInstance(inActionInstance); +} + +void CActionCoreProducer::SetTriggerObject(CUICDMActionHandle 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(CUICDMActionHandle 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(CUICDMActionHandle 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(CUICDMActionHandle 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); +} + +CUICDMHandlerArgHandle CActionCoreProducer::AddHandlerArgument(CUICDMActionHandle inAction, + const TCharStr &inName, + HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) +{ + CUICDMHandlerArgHandle retval = + m_Data->AddHandlerArgument(inAction, inName, inArgType, inValueType); + SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects); + CreateVecInsertTransaction<CUICDMHandlerArgHandle>(__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(CUICDMHandlerArgHandle 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<CUICDMHandlerArgHandle>(), inHandlerArgument, + std::placeholders::_1))) { + CreateVecEraseTransaction<CUICDMHandlerArgHandle>(__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(CUICDMHandlerArgHandle inHandlerArgument) const +{ + return m_Data->GetHandlerArgumentInfo(inHandlerArgument); +} + +void CActionCoreProducer::GetHandlerArguments(CUICDMActionHandle inAction, + THandlerArgHandleList &outHandlerArguments) const +{ + return m_Data->GetHandlerArguments(inAction, outHandlerArguments); +} + +void CActionCoreProducer::GetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument, + SValue &outValue) const +{ + return m_Data->GetHandlerArgumentValue(inHandlerArgument, outValue); +} + +void CActionCoreProducer::SetHandlerArgumentValue(CUICDMHandlerArgHandle 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(CUICDMActionHandle, SObjectRefType &)> &inCallback) +{ + return GetSignalProvider()->ConnectTriggerObjectSet(inCallback); +} +TSignalConnectionPtr CActionCoreProducer::ConnectTargetObjectSet( + const std::function<void(CUICDMActionHandle, SObjectRefType &)> &inCallback) +{ + return GetSignalProvider()->ConnectTargetObjectSet(inCallback); +} +TSignalConnectionPtr CActionCoreProducer::ConnectEventSet( + const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback) +{ + return GetSignalProvider()->ConnectEventSet(inCallback); +} +TSignalConnectionPtr CActionCoreProducer::ConnectHandlerSet( + const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback) +{ + return GetSignalProvider()->ConnectHandlerSet(inCallback); +} + +TSignalConnectionPtr CActionCoreProducer::ConnectHandlerArgumentAdded( + const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) +{ + return GetSignalProvider()->ConnectHandlerArgumentAdded(inCallback); +} +TSignalConnectionPtr CActionCoreProducer::ConnectHandlerArgumentRemoved( + const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) +{ + return GetSignalProvider()->ConnectHandlerArgumentRemoved(inCallback); +} +TSignalConnectionPtr CActionCoreProducer::ConnectHandlerArgumentValueSet( + const std::function<void(CUICDMHandlerArgHandle, 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/Authoring/QT3DSDM/Systems/Cores/ActionCoreProducer.h b/src/Authoring/QT3DSDM/Systems/Cores/ActionCoreProducer.h new file mode 100644 index 00000000..5aec831b --- /dev/null +++ b/src/Authoring/QT3DSDM/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 + CUICDMActionHandle CreateAction(Qt3DSDMInstanceHandle inInstance, CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner, SLong4 inTriggerTargetObjects) override; + void DeleteAction(CUICDMActionHandle inAction, Qt3DSDMInstanceHandle &outInstance) override; + const SActionInfo &GetActionInfo(CUICDMActionHandle inAction) const override; + void GetActions(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const override; + void GetActions(CUICDMSlideHandle inSlide, TActionHandleList &outActions) const override; + void GetActions(Qt3DSDMInstanceHandle inOwner, TActionHandleList &outActions) const override; + void GetActions(TActionHandleList &outActions) const override; + Qt3DSDMInstanceHandle GetActionInstance(CUICDMActionHandle inAction) const override; + CUICDMActionHandle GetActionByInstance(Qt3DSDMInstanceHandle inActionInstance) const override; + + // Action Properties + void SetTriggerObject(CUICDMActionHandle inAction, const SObjectRefType &inTriggerObject) override; + void SetTargetObject(CUICDMActionHandle inAction, const SObjectRefType &inTargetObject) override; + void SetEvent(CUICDMActionHandle inAction, const wstring &inEventHandle) override; + void SetHandler(CUICDMActionHandle inAction, const wstring &inHandlerHandle) override; + + // Action Argument + CUICDMHandlerArgHandle AddHandlerArgument(CUICDMActionHandle inAction, const TCharStr &inName, + HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) override; + void RemoveHandlerArgument(CUICDMHandlerArgHandle inHandlerArgument) override; + const SHandlerArgumentInfo & + GetHandlerArgumentInfo(CUICDMHandlerArgHandle inHandlerArgument) const override; + void GetHandlerArguments(CUICDMActionHandle inAction, + THandlerArgHandleList &outHandlerArguments) const override; + + // Action Argument Properties + void GetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument, SValue &outValue) const override; + void SetHandlerArgumentValue(CUICDMHandlerArgHandle 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(CUICDMActionHandle, SObjectRefType &)> &inCallback) override; + TSignalConnectionPtr ConnectTargetObjectSet( + const std::function<void(CUICDMActionHandle, SObjectRefType &)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectEventSet(const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectHandlerSet(const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback) override; + + TSignalConnectionPtr ConnectHandlerArgumentAdded( + const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) override; + TSignalConnectionPtr ConnectHandlerArgumentRemoved( + const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &, + HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) override; + TSignalConnectionPtr ConnectHandlerArgumentValueSet( + const std::function<void(CUICDMHandlerArgHandle, const SValue &)> &inCallback) override; + +private: + void InitSignaller(); + IActionCoreSignalProvider *GetSignalProvider(); + IActionCoreSignalSender *GetSignalSender(); +}; +} + +#endif diff --git a/src/Authoring/QT3DSDM/Systems/Cores/AnimationCoreProducer.cpp b/src/Authoring/QT3DSDM/Systems/Cores/AnimationCoreProducer.cpp new file mode 100644 index 00000000..10c934b6 --- /dev/null +++ b/src/Authoring/QT3DSDM/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; + CUICDMAnimationHandle m_Animation; + TTransactionConsumerPtr m_Consumer; + bool m_ArtistEdited; + SArtistEditedUndoRedoScope(TSimpleAnimationCorePtr inAnimCore, CUICDMAnimationHandle 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, CUICDMAnimationHandle 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(); + } +}; + +CUICDMAnimationHandle +CAnimationCoreProducer::CreateAnimation(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType, bool inFirstKeyframeDynamic) +{ + CUICDMAnimationHandle 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(CUICDMAnimationHandle 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); +} + +CUICDMAnimationHandle CAnimationCoreProducer::GetAnimation(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + size_t inIndex) const +{ + return m_Data->GetAnimation(inSlide, inInstance, inProperty, inIndex); +} + +SAnimationInfo CAnimationCoreProducer::GetAnimationInfo(CUICDMAnimationHandle inAnimation) const +{ + return m_Data->GetAnimationInfo(inAnimation); +} + +void CAnimationCoreProducer::GetAnimations(TAnimationHandleList &outAnimations) const +{ + return m_Data->GetAnimations(outAnimations); +} + +void CAnimationCoreProducer::GetAnimations(TAnimationInfoList &outAnimations, + CUICDMSlideHandle inMaster, + CUICDMSlideHandle inSlide) const +{ + return m_Data->GetAnimations(outAnimations, inMaster, inSlide); +} + +void CAnimationCoreProducer::SetFirstKeyframeDynamic(CUICDMAnimationHandle 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(CUICDMAnimationHandle inAnimation, THandleObjectMap &inObjects) +{ + SAnimationTrack *theAnimation = CSimpleAnimationCore::GetAnimationNF(inAnimation, inObjects); + theAnimation->m_KeyframesDirty = true; +} + +inline void CreateDirtyKeyframesTransaction(TTransactionConsumerPtr inConsumer, + CUICDMAnimationHandle 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))))); + } +} + +CUICDMKeyframeHandle CAnimationCoreProducer::InsertKeyframe(CUICDMAnimationHandle inAnimation, + const TKeyframe &inKeyframe) +{ + SArtistEditedUndoRedoScope __editedScope(m_Data, inAnimation, m_Consumer); + CUICDMKeyframeHandle retval = m_Data->InsertKeyframe(inAnimation, inKeyframe); + SAnimationTrack *theAnimation = + CSimpleAnimationCore::GetAnimationNF(inAnimation, m_Data->m_Objects); + CreateVecInsertTransaction<CUICDMKeyframeHandle>(__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(CUICDMKeyframeHandle 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<CUICDMKeyframeHandle>(__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(CUICDMAnimationHandle 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<CUICDMKeyframeHandle>>( + __FILE__, __LINE__, std::ref(theAnimation->m_Keyframes))); + theAnimation->m_Keyframes.clear(); +} + +CUICDMAnimationHandle +CAnimationCoreProducer::GetAnimationForKeyframe(CUICDMKeyframeHandle inKeyframe) const +{ + return m_Data->GetAnimationForKeyframe(inKeyframe); +} + +struct KeyframeDataTransaction : public ITransaction, public IMergeableTransaction<TKeyframe> +{ + TSimpleAnimationCorePtr m_AnimationCore; + CUICDMKeyframeHandle m_Keyframe; + TKeyframe m_OldData; + TKeyframe m_NewData; + + KeyframeDataTransaction(const char *inFile, int inLine, TSimpleAnimationCorePtr animCore, + CUICDMKeyframeHandle 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(CUICDMKeyframeHandle 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(CUICDMKeyframeHandle inKeyframe) const +{ + return m_Data->GetKeyframeData(inKeyframe); +} + +void CAnimationCoreProducer::GetKeyframes(CUICDMAnimationHandle inAnimation, + TKeyframeHandleList &outKeyframes) const +{ + return m_Data->GetKeyframes(inAnimation, outKeyframes); +} + +size_t CAnimationCoreProducer::GetKeyframeCount(CUICDMAnimationHandle inAnimation) const +{ + return m_Data->GetKeyframeCount(inAnimation); +} + +void CAnimationCoreProducer::OffsetAnimations(CUICDMSlideHandle 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) { + CUICDMKeyframeHandle 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(CUICDMAnimationHandle inAnimation, bool inEdited) +{ + SArtistEditedUndoRedoScope __editedScope(m_Data, inAnimation, m_Consumer); + m_Data->SetIsArtistEdited(inAnimation, inEdited); +} + +bool CAnimationCoreProducer::IsArtistEdited(CUICDMAnimationHandle inAnimation) const +{ + return m_Data->IsArtistEdited(inAnimation); +} +// Animation Evaluation. +float CAnimationCoreProducer::EvaluateAnimation(CUICDMAnimationHandle inAnimation, + float inSeconds) const +{ + return m_Data->EvaluateAnimation(inAnimation, inSeconds); +} + +bool CAnimationCoreProducer::KeyframeValid(CUICDMKeyframeHandle inKeyframe) const +{ + return m_Data->KeyframeValid(inKeyframe); +} + +bool CAnimationCoreProducer::AnimationValid(CUICDMAnimationHandle inAnimation) const +{ + return m_Data->AnimationValid(inAnimation); +} + +void CAnimationCoreProducer::CopyAnimations(CUICDMSlideHandle inSourceSlide, + Qt3DSDMInstanceHandle inSourceInstance, + CUICDMSlideHandle 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]); + CUICDMAnimationHandle 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(CUICDMAnimationHandle, CUICDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) +{ + return GetSignalProvider()->ConnectAnimationCreated(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectBeforeAnimationDeleted( + const std::function<void(CUICDMAnimationHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectBeforeAnimationDeleted(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectAnimationDeleted( + const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) +{ + return GetSignalProvider()->ConnectAnimationDeleted(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectKeyframeInserted( + const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)> + &inCallback) +{ + return GetSignalProvider()->ConnectKeyframeInserted(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectBeforeKeyframeErased( + const std::function<void(CUICDMKeyframeHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectBeforeKeyframeErased(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectKeyframeErased( + const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)> + &inCallback) +{ + return GetSignalProvider()->ConnectKeyframeErased(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectBeforeAllKeyframesErased( + const std::function<void(CUICDMAnimationHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectBeforeAllKeyframesErased(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectKeyframeUpdated( + const std::function<void(CUICDMKeyframeHandle, const TKeyframe &)> &inCallback) +{ + return GetSignalProvider()->ConnectKeyframeUpdated(inCallback); +} +TSignalConnectionPtr CAnimationCoreProducer::ConnectFirstKeyframeDynamicSet( + const std::function<void(CUICDMAnimationHandle, 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/Authoring/QT3DSDM/Systems/Cores/AnimationCoreProducer.h b/src/Authoring/QT3DSDM/Systems/Cores/AnimationCoreProducer.h new file mode 100644 index 00000000..b8e4d23a --- /dev/null +++ b/src/Authoring/QT3DSDM/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 + + CUICDMAnimationHandle CreateAnimation(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType, + bool inFirstKeyframeDynamic) override; + void DeleteAnimation(CUICDMAnimationHandle inAnimation) override; + CUICDMAnimationHandle GetAnimation(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex) const override; + SAnimationInfo GetAnimationInfo(CUICDMAnimationHandle inAnimation) const override; + void GetAnimations(TAnimationHandleList &outAnimations) const override; + void GetAnimations(TAnimationInfoList &outAnimations, CUICDMSlideHandle inMaster, + CUICDMSlideHandle inSlide) const override; + void GetSpecificInstanceAnimations(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + TAnimationHandleList &outAnimations) override + { + m_Data->GetSpecificInstanceAnimations(inSlide, inInstance, outAnimations); + } + + void SetFirstKeyframeDynamic(CUICDMAnimationHandle inAnimation, bool inValue) override; + + CUICDMKeyframeHandle InsertKeyframe(CUICDMAnimationHandle inAnimation, + const TKeyframe &inKeyframe) override; + void EraseKeyframe(CUICDMKeyframeHandle) override; + void DeleteAllKeyframes(CUICDMAnimationHandle inAnimation) override; + CUICDMAnimationHandle GetAnimationForKeyframe(CUICDMKeyframeHandle inKeyframe) const override; + TKeyframe GetKeyframeData(CUICDMKeyframeHandle inKeyframe) const override; + void SetKeyframeData(CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) override; + void GetKeyframes(CUICDMAnimationHandle inAnimation, TKeyframeHandleList &outKeyframes) const override; + size_t GetKeyframeCount(CUICDMAnimationHandle inAnimation) const override; + bool IsFirstKeyframe(CUICDMKeyframeHandle inKeyframe) const override + { + return m_Data->IsFirstKeyframe(inKeyframe); + } + void OffsetAnimations(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + long inMillisecondOffset) override; + + void SetIsArtistEdited(CUICDMAnimationHandle inAnimation, bool inEdited = true) override; + bool IsArtistEdited(CUICDMAnimationHandle inAnimation) const override; + + // Animation Evaluation. + float EvaluateAnimation(CUICDMAnimationHandle inAnimation, float inSeconds) const override; + + bool KeyframeValid(CUICDMKeyframeHandle inKeyframe) const override; + bool AnimationValid(CUICDMAnimationHandle inAnimation) const override; + + void CopyAnimations(CUICDMSlideHandle inSourceSlide, Qt3DSDMInstanceHandle inSourceInstance, + CUICDMSlideHandle inDestSlide, Qt3DSDMInstanceHandle inDestInstance) override; + + // ITransactionProducer implementation + void SetConsumer(TTransactionConsumerPtr inConsumer) override; + + TSignalConnectionPtr ConnectAnimationCreated( + const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectBeforeAnimationDeleted(const std::function<void(CUICDMAnimationHandle)> &inCallback) override; + TSignalConnectionPtr ConnectAnimationDeleted( + const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, Qt3DSDMInstanceHandle, + Qt3DSDMPropertyHandle, size_t, EAnimationType)> &inCallback) override; + TSignalConnectionPtr ConnectKeyframeInserted( + const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)> + &inCallback) override; + virtual TSignalConnectionPtr + ConnectBeforeKeyframeErased(const std::function<void(CUICDMKeyframeHandle)> &inCallback) override; + TSignalConnectionPtr ConnectKeyframeErased( + const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)> + &inCallback) override; + virtual TSignalConnectionPtr + ConnectBeforeAllKeyframesErased(const std::function<void(CUICDMAnimationHandle)> &inCallback) override; + TSignalConnectionPtr ConnectKeyframeUpdated( + const std::function<void(CUICDMKeyframeHandle, const TKeyframe &)> &inCallback) override; + TSignalConnectionPtr ConnectFirstKeyframeDynamicSet( + const std::function<void(CUICDMAnimationHandle, bool)> &inCallback) override; + +private: + void InitSignaller(); + IAnimationCoreSignalProvider *GetSignalProvider(); + IAnimationCoreSignalSender *GetSignalSender(); +}; +} + +#endif diff --git a/src/Authoring/QT3DSDM/Systems/Cores/DataCoreProducer.cpp b/src/Authoring/QT3DSDM/Systems/Cores/DataCoreProducer.cpp new file mode 100644 index 00000000..51194105 --- /dev/null +++ b/src/Authoring/QT3DSDM/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, SUICDMPropertyDefinition> +TransformProperty(Qt3DSDMPropertyHandle inProperty, CSimpleDataCore &inData) +{ + return make_tuple(inProperty, inData.GetProperty(inProperty)); +} + +inline void SignalPropertyRemoved(Qt3DSDMInstanceHandle inInstance, + tuple<Qt3DSDMPropertyHandle, SUICDMPropertyDefinition> 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, SUICDMPropertyDefinition>> theDefinitionList; + theDefinitionList.resize(theProperties.size()); + + function<tuple<Qt3DSDMPropertyHandle, SUICDMPropertyDefinition>(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 SUICDMPropertyDefinition & +CDataCoreProducer::GetProperty(Qt3DSDMPropertyHandle inProperty) const +{ + return m_Data->GetProperty(inProperty); +} + +void CDataCoreProducer::RemoveProperty(Qt3DSDMPropertyHandle inProperty) +{ + SUICDMPropertyDefinition 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/Authoring/QT3DSDM/Systems/Cores/DataCoreProducer.h b/src/Authoring/QT3DSDM/Systems/Cores/DataCoreProducer.h new file mode 100644 index 00000000..0b4e697a --- /dev/null +++ b/src/Authoring/QT3DSDM/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 SUICDMPropertyDefinition &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/Authoring/QT3DSDM/Systems/Cores/SimpleActionCore.cpp b/src/Authoring/QT3DSDM/Systems/Cores/SimpleActionCore.cpp new file mode 100644 index 00000000..4f4e0a46 --- /dev/null +++ b/src/Authoring/QT3DSDM/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 { + +CUICDMActionHandle CSimpleActionCore::CreateAction(Qt3DSDMInstanceHandle inInstance, + CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner, + SLong4 inTriggerTargetObjects) +{ + int nextId = GetNextId(); + CUICDMActionHandle retval = CreateActionWithHandle(nextId, inInstance, inSlide, inOwner); + SetTriggerObject(retval, inTriggerTargetObjects); + SetTargetObject(retval, inTriggerTargetObjects); + return retval; +} + +void CSimpleActionCore::DeleteAction(CUICDMActionHandle 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(CUICDMActionHandle inAction) const +{ + const SAction *theAction = GetActionNF(inAction, m_Objects); + return theAction->m_ActionInfo; +} + +inline void AddIfActionMatches(const THandleObjectPair &inPair, CUICDMSlideHandle 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(CUICDMSlideHandle 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(CUICDMSlideHandle 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, CUICDMActionHandle>, + std::placeholders::_1, std::ref(outActions))); +} + +// Return the instance that was allocated for this action. +Qt3DSDMInstanceHandle CSimpleActionCore::GetActionInstance(CUICDMActionHandle 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. +CUICDMActionHandle +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(CUICDMActionHandle inAction, + const SObjectRefType &inTriggerObject) +{ + SAction *theAction = GetActionNF(inAction, m_Objects); + theAction->m_ActionInfo.m_TriggerObject = inTriggerObject; +} + +void CSimpleActionCore::SetTargetObject(CUICDMActionHandle inAction, + const SObjectRefType &inTargetObject) +{ + SAction *theAction = GetActionNF(inAction, m_Objects); + theAction->m_ActionInfo.m_TargetObject = inTargetObject; +} + +void CSimpleActionCore::SetEvent(CUICDMActionHandle inAction, const wstring &inEventHandle) +{ + SAction *theAction = GetActionNF(inAction, m_Objects); + theAction->m_ActionInfo.m_Event = inEventHandle; +} + +void CSimpleActionCore::SetHandler(CUICDMActionHandle inAction, const wstring &inHandlerHandle) +{ + SAction *theAction = GetActionNF(inAction, m_Objects); + theAction->m_ActionInfo.m_Handler = inHandlerHandle; +} + +// Action Argument +CUICDMHandlerArgHandle CSimpleActionCore::AddHandlerArgument(CUICDMActionHandle inAction, + const TCharStr &inName, + HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) +{ + int nextId = GetNextId(); + return AddHandlerArgumentWithHandle(nextId, inAction, inName, inArgType, inValueType); +} + +void CSimpleActionCore::RemoveHandlerArgument(CUICDMHandlerArgHandle 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(CUICDMHandlerArgHandle 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(CUICDMActionHandle inAction, + THandlerArgHandleList &outHandlerArguments) const +{ + const SAction *theAction = GetActionNF(inAction, m_Objects); + outHandlerArguments = theAction->m_ActionInfo.m_HandlerArgs; +} + +// Action Argument Properties +void CSimpleActionCore::GetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument, + SValue &outValue) const +{ + const SHandlerArgument *theHandlerArgument = GetHandlerArgumentNF(inHandlerArgument, m_Objects); + outValue = theHandlerArgument->m_HandlerArgInfo.m_Value; +} + +void CSimpleActionCore::SetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument, + const SValue &inValue) +{ + SHandlerArgument *theHandlerArgument = GetHandlerArgumentNF(inHandlerArgument, m_Objects); + theHandlerArgument->m_HandlerArgInfo.m_Value = inValue; +} + +// Helper functions +CUICDMActionHandle CSimpleActionCore::CreateActionWithHandle(int inHandle, + Qt3DSDMInstanceHandle inInstance, + CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner) +{ + if (HandleValid(inHandle)) + throw HandleExists(L""); + m_Objects.insert(make_pair( + inHandle, (THandleObjectPtr) new SAction(inHandle, inInstance, inSlide, inOwner))); + return inHandle; +} + +CUICDMHandlerArgHandle +CSimpleActionCore::AddHandlerArgumentWithHandle(int inHandle, CUICDMActionHandle 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/Authoring/QT3DSDM/Systems/Cores/SimpleActionCore.h b/src/Authoring/QT3DSDM/Systems/Cores/SimpleActionCore.h new file mode 100644 index 00000000..0700d5c9 --- /dev/null +++ b/src/Authoring/QT3DSDM/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, CUICDMSlideHandle 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, CUICDMActionHandle 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 + CUICDMActionHandle CreateAction(Qt3DSDMInstanceHandle inInstance, CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner, SLong4 inTriggerTargetObjects) override; + void DeleteAction(CUICDMActionHandle inAction, Qt3DSDMInstanceHandle &outInstance) override; + const SActionInfo &GetActionInfo(CUICDMActionHandle inAction) const override; + void GetActions(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner, + TActionHandleList &outActions) const override; + void GetActions(CUICDMSlideHandle 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(CUICDMActionHandle inAction) const override; + // Reverse lookup into the action system so you can match actions to instances. + CUICDMActionHandle GetActionByInstance(Qt3DSDMInstanceHandle inActionInstance) const override; + + // Action Properties + void SetTriggerObject(CUICDMActionHandle inAction, const SObjectRefType &inTriggerObject) override; + void SetTargetObject(CUICDMActionHandle inAction, const SObjectRefType &inTargetObject) override; + void SetEvent(CUICDMActionHandle inAction, const wstring &inEvent) override; + void SetHandler(CUICDMActionHandle inAction, const wstring &inHandler) override; + + // Action Argument + CUICDMHandlerArgHandle AddHandlerArgument(CUICDMActionHandle inAction, const TCharStr &inName, + HandlerArgumentType::Value inArgType, + DataModelDataType::Value inValueType) override; + void RemoveHandlerArgument(CUICDMHandlerArgHandle inHandlerArgument) override; + const SHandlerArgumentInfo & + GetHandlerArgumentInfo(CUICDMHandlerArgHandle inHandlerArgument) const override; + void GetHandlerArguments(CUICDMActionHandle inAction, + THandlerArgHandleList &outHandlerArguments) const override; + + // Action Argument Properties + void GetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument, SValue &outValue) const override; + void SetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument, const SValue &inValue) override; + + // CHandleBase + bool HandleValid(int inHandle) const override { return CHandleBase::HandleValid(inHandle); } + + // Helper functions + CUICDMActionHandle CreateActionWithHandle(int inHandle, Qt3DSDMInstanceHandle inInstance, + CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inOwner); + CUICDMHandlerArgHandle AddHandlerArgumentWithHandle(int inHandle, CUICDMActionHandle 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/Authoring/QT3DSDM/Systems/Cores/SimpleAnimationCore.cpp b/src/Authoring/QT3DSDM/Systems/Cores/SimpleAnimationCore.cpp new file mode 100644 index 00000000..dd761cbc --- /dev/null +++ b/src/Authoring/QT3DSDM/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" + +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" +#include <boost/unordered_map.hpp> +#include <boost/iterator/transform_iterator.hpp> +using namespace std; +using namespace boost; + +namespace qt3dsdm { + +CUICDMAnimationHandle +CSimpleAnimationCore::CreateAnimation(CUICDMSlideHandle 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(); + CUICDMAnimationHandle retval = CreateAnimationWithHandle( + nextId, inSlide, inInstance, inProperty, inIndex, inAnimationType, inFirstKeyframeDynamic); + AddAnimationToLookupCache(retval); + return retval; +} + +void CSimpleAnimationCore::DeleteAnimation(CUICDMAnimationHandle 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)); + } + } +} + +CUICDMAnimationHandle CSimpleAnimationCore::GetAnimation(CUICDMSlideHandle 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(CUICDMAnimationHandle 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, + CUICDMSlideHandle inMaster, + CUICDMSlideHandle 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, CUICDMSlideHandle 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(CUICDMSlideHandle 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(CUICDMAnimationHandle 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 +CUICDMKeyframeHandle CSimpleAnimationCore::InsertKeyframe(CUICDMAnimationHandle 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(CUICDMKeyframeHandle 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(CUICDMAnimationHandle 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); +} + +CUICDMAnimationHandle +CSimpleAnimationCore::GetAnimationForKeyframe(CUICDMKeyframeHandle inKeyframe) const +{ + const SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects); + return theKeyframe->m_Animation; +} + +TKeyframe CSimpleAnimationCore::GetKeyframeData(CUICDMKeyframeHandle inKeyframe) const +{ + const SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects); + return theKeyframe->m_Keyframe; +} + +void CSimpleAnimationCore::SetKeyframeData(CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) +{ + DoSetKeyframeData(inKeyframe, inData); + SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects); + SetIsArtistEdited(theKeyframe->m_Animation); +} + +void CSimpleAnimationCore::DoSetKeyframeData(CUICDMKeyframeHandle 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(CUICDMAnimationHandle inAnimation, + TKeyframeHandleList &outKeyframes) const +{ + const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + CheckKeyframesSorted(theItem, m_Objects); + outKeyframes = theItem->m_Keyframes; +} + +size_t CSimpleAnimationCore::GetKeyframeCount(CUICDMAnimationHandle inAnimation) const +{ + const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects); + return theItem->m_Keyframes.size(); +} + +bool CSimpleAnimationCore::IsFirstKeyframe(CUICDMKeyframeHandle inKeyframe) const +{ + CUICDMAnimationHandle 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(CUICDMSlideHandle /*inSlide*/, + Qt3DSDMInstanceHandle /*inInstance*/, long /*inOffset*/) +{ + throw std::runtime_error("unimplemented"); +} + +void CSimpleAnimationCore::SetIsArtistEdited(CUICDMAnimationHandle 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(CUICDMAnimationHandle 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(CUICDMAnimationHandle 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))); + typedef transform_iterator<function<TKeyframe(int)>, TKeyframeHandleList::const_iterator> + TTransformIterator; + TTransformIterator theBound = + lower_bound(make_transform_iterator(theItem->m_Keyframes.begin(), theIntToKeyframe), + make_transform_iterator(theItem->m_Keyframes.end(), theIntToKeyframe), + theSearchKey, KeyframeValueTimeLessThan); + if (theBound.base() == theItem->m_Keyframes.end()) + return KeyframeValue(theItem->m_Keyframes.back(), m_Objects); + if (theBound.base() == theItem->m_Keyframes.begin()) + return KeyframeValue(*theItem->m_Keyframes.begin(), m_Objects); + TTransformIterator theStartIter = theBound; + --theStartIter; + + // Both iterators must be valid at this point... + TKeyframe theStart = *theStartIter; + TKeyframe theFinish = *theBound; + switch (theItem->m_AnimationType) { + default: + throw AnimationEvaluationError(L""); + case EAnimationTypeLinear: { + SLinearKeyframe k1 = get<SLinearKeyframe>(theStart); + SLinearKeyframe k2 = get<SLinearKeyframe>(theFinish); + return EvaluateLinearKeyframe(k1, k2, inSeconds); + } + case EAnimationTypeBezier: { + SBezierKeyframe k1 = get<SBezierKeyframe>(theStart); + SBezierKeyframe k2 = get<SBezierKeyframe>(theFinish); + return DoBezierEvaluation(inSeconds, k1, k2); + } + case EAnimationTypeEaseInOut: { + SEaseInEaseOutKeyframe k1 = get<SEaseInEaseOutKeyframe>(theStart); + SEaseInEaseOutKeyframe k2 = get<SEaseInEaseOutKeyframe>(theFinish); + return DoBezierEvaluation( + inSeconds, CreateBezierKeyframeFromEaseInEaseOutKeyframe(NULL, k1, &k2.m_KeyframeValue), + CreateBezierKeyframeFromEaseInEaseOutKeyframe(&k1.m_KeyframeValue, k2, NULL)); + } + } +} + +bool CSimpleAnimationCore::KeyframeValid(CUICDMKeyframeHandle inKeyframe) const +{ + return HandleObjectValid<SKeyframe>(inKeyframe, m_Objects); +} + +bool CSimpleAnimationCore::AnimationValid(CUICDMAnimationHandle inAnimation) const +{ + return HandleObjectValid<SAnimationTrack>(inAnimation, m_Objects); +} + +CUICDMAnimationHandle CSimpleAnimationCore::CreateAnimationWithHandle( + int inHandle, CUICDMSlideHandle 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(CUICDMAnimationHandle 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(CUICDMAnimationHandle 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 +{ + CUICDMSlideHandle 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); + CUICDMSlideHandle 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(CUICDMAnimationHandle inAnimation, CUICDMKeyframeHandle inKeyframe, + const IAnimationCore &inSourceAnimationCore, IAnimationCore &inDestAnimationCore) +{ + TKeyframe theData = inSourceAnimationCore.GetKeyframeData(inKeyframe); + inDestAnimationCore.InsertKeyframe(inAnimation, theData); +} + +void CopyKeyframes(const IAnimationCore &inSourceAnimationCore, IAnimationCore &inDestAnimationCore, + CUICDMAnimationHandle inDestAnimation, const TKeyframeHandleList &inKeyframes) +{ + do_all(inKeyframes, + std::bind(CopyKeyframe, inDestAnimation, std::placeholders::_1, + std::cref(inSourceAnimationCore), std::ref(inDestAnimationCore))); +} + +CUICDMAnimationHandle CopyAnimation(TAnimationCorePtr inAnimationCore, + CUICDMAnimationHandle inAnimation, CUICDMSlideHandle inNewSlide, + Qt3DSDMInstanceHandle inNewInstance, + Qt3DSDMPropertyHandle inNewProperty, size_t inNewIndex) +{ + TKeyframeHandleList theKeyframes; + inAnimationCore->GetKeyframes(inAnimation, theKeyframes); + SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation)); + CUICDMAnimationHandle theAnimation = + inAnimationCore->CreateAnimation(inNewSlide, inNewInstance, inNewProperty, inNewIndex, + theInfo.m_AnimationType, theInfo.m_DynamicFirstKeyframe); + CopyKeyframes(*inAnimationCore, *inAnimationCore, theAnimation, theKeyframes); + return theAnimation; +} + +SBezierKeyframe GetBezierKeyframeData(CUICDMKeyframeHandle inKeyframe, + const IAnimationCore &inAnimationCore) +{ + return get<SBezierKeyframe>(inAnimationCore.GetKeyframeData(inKeyframe)); +} + +SEaseInEaseOutKeyframe GetEaseInEaseOutKeyframeData(CUICDMKeyframeHandle 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(CUICDMAnimationHandle 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(CUICDMKeyframeHandle)> TConvertFunc; + TConvertFunc theDataConverter( + std::bind(GetEaseInEaseOutKeyframeData, std::placeholders::_1, + std::cref(inAnimationCore))); + typedef boost::transform_iterator<TConvertFunc, TKeyframeHandleList::iterator> + TTransformIterator; + TTransformIterator thePreviousKeyframe( + make_transform_iterator(theKeyframes.begin(), theDataConverter)); + TTransformIterator theCurrentKeyframe(make_transform_iterator( + SafeIncrementIterator(thePreviousKeyframe.base(), theEndKeyframe), theDataConverter)); + TTransformIterator theNextKeyframe(make_transform_iterator( + SafeIncrementIterator(theCurrentKeyframe.base(), theEndKeyframe), theDataConverter)); + + TBezierKeyframeList::iterator theResult(outKeyframes.begin()); + + if (thePreviousKeyframe.base() != theEndKeyframe) { + float *theNextValuePtr = NULL; + float theNextValue; + if (theCurrentKeyframe.base() != theEndKeyframe) { + theNextValue = theCurrentKeyframe->m_KeyframeValue; + theNextValuePtr = &theNextValue; + } + *theResult = CreateBezierKeyframeFromEaseInEaseOutKeyframe(NULL, *thePreviousKeyframe, + theNextValuePtr); + theResult = theResult + 1; + } + for (; theCurrentKeyframe.base() != theEndKeyframe; + ++thePreviousKeyframe, + theCurrentKeyframe = make_transform_iterator( + SafeIncrementIterator(theCurrentKeyframe.base(), theEndKeyframe), + theDataConverter), + theNextKeyframe = make_transform_iterator( + SafeIncrementIterator(theNextKeyframe.base(), theEndKeyframe), theDataConverter), + ++theResult) { + float theLastValue(thePreviousKeyframe->m_KeyframeValue); + float *theNextValuePtr = NULL; + float theNextValue; + if (theNextKeyframe.base() != theEndKeyframe) { + theNextValue = theNextKeyframe->m_KeyframeValue; + theNextValuePtr = &theNextValue; + } + *theResult = CreateBezierKeyframeFromEaseInEaseOutKeyframe( + &theLastValue, *theCurrentKeyframe, theNextValuePtr); + } + } break; + } +} +} diff --git a/src/Authoring/QT3DSDM/Systems/Cores/SimpleAnimationCore.h b/src/Authoring/QT3DSDM/Systems/Cores/SimpleAnimationCore.h new file mode 100644 index 00000000..62d7e6c8 --- /dev/null +++ b/src/Authoring/QT3DSDM/Systems/Cores/SimpleAnimationCore.h @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** 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 <boost/unordered_map.hpp> + +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, CUICDMSlideHandle 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 boost::unordered_multimap<std::pair<int, int>, std::shared_ptr<SAnimationTrack>> + 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; } + + CUICDMAnimationHandle CreateAnimation(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex, + EAnimationType inAnimationType, + bool inFirstKeyframeDynamic) override; + void DeleteAnimation(CUICDMAnimationHandle inAnimation) override; + CUICDMAnimationHandle GetAnimation(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, size_t inIndex) const override; + SAnimationInfo GetAnimationInfo(CUICDMAnimationHandle inAnimation) const override; + void GetAnimations(TAnimationHandleList &outAnimations) const override; + void GetAnimations(TAnimationInfoList &outAnimations, CUICDMSlideHandle inMaster, + CUICDMSlideHandle inSlide) const override; + void GetSpecificInstanceAnimations(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + TAnimationHandleList &outAnimations) override; + + void SetFirstKeyframeDynamic(CUICDMAnimationHandle inAnimation, bool inValue) override; + + // keyframe manipulation + CUICDMKeyframeHandle InsertKeyframe(CUICDMAnimationHandle inAnimation, + const TKeyframe &inKeyframe) override; + void EraseKeyframe(CUICDMKeyframeHandle inKeyframe) override; + void DeleteAllKeyframes(CUICDMAnimationHandle inAnimation) override; + CUICDMAnimationHandle GetAnimationForKeyframe(CUICDMKeyframeHandle inKeyframe) const override; + TKeyframe GetKeyframeData(CUICDMKeyframeHandle inKeyframe) const override; + void SetKeyframeData(CUICDMKeyframeHandle 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(CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData); + void GetKeyframes(CUICDMAnimationHandle inAnimation, TKeyframeHandleList &outKeyframes) const override; + size_t GetKeyframeCount(CUICDMAnimationHandle inAnimation) const override; + bool IsFirstKeyframe(CUICDMKeyframeHandle inKeyframe) const override; + // Only implemented in the producer for now. + void OffsetAnimations(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance, + long inOffset) override; + + void SetIsArtistEdited(CUICDMAnimationHandle inAnimation, bool inEdited = true) override; + bool IsArtistEdited(CUICDMAnimationHandle inAnimation) const override; + + // Animation Evaluation. + float EvaluateAnimation(CUICDMAnimationHandle inAnimation, float inSeconds) const override; + + bool KeyframeValid(CUICDMKeyframeHandle inKeyframe) const override; + bool AnimationValid(CUICDMAnimationHandle inAnimation) const override; + + // Only implemented at the producer level, not at the simple core level. + void CopyAnimations(CUICDMSlideHandle /*inSourceSlide*/, + Qt3DSDMInstanceHandle /*inSourceInstance*/, + CUICDMSlideHandle /*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(CUICDMAnimationHandle inAnimation) const; + void RemoveAnimationFromLookupCache(CUICDMAnimationHandle inAnimation) const; + void AddAnimationToLookupCache(std::shared_ptr<SAnimationTrack> inAnimation) const; + void RemoveAnimationFromLookupCache(std::shared_ptr<SAnimationTrack> inAnimation) const; + + void EnsureAnimationCache() const; + + CUICDMAnimationHandle CreateAnimationWithHandle(int inHandle, CUICDMSlideHandle 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/Authoring/QT3DSDM/Systems/Cores/SimpleDataCore.cpp b/src/Authoring/QT3DSDM/Systems/Cores/SimpleDataCore.cpp new file mode 100644 index 00000000..b401d83c --- /dev/null +++ b/src/Authoring/QT3DSDM/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 { +TUICDMDebugLogFunction g_UICDMDebugLogger = 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_UICDMDebugLogger) + g_UICDMDebugLogger("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_UICDMDebugLogger) + g_UICDMDebugLogger("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) +{ + UICDM_LOG_FUNCTION("CSimpleDataCore::AddProperty"); + UICDM_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()) { + UICDM_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 SUICDMPropertyDefinition &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 SUICDMPropertyDefinition &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_UICDMDebugLogger) + g_UICDMDebugLogger("CSimpleDataCore::CreateInstance Enter"); + if (HandleValid(inHandle)) { + if (g_UICDMDebugLogger) { + g_UICDMDebugLogger("CSimpleDataCore::CreateInstance Handle Exists!!"); + char buf[32]; + sprintf(buf, "%d", inHandle); + g_UICDMDebugLogger(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_UICDMDebugLogger) + g_UICDMDebugLogger("CSimpleDataCore::CreateInstance Leave"); + + return inHandle; +} + +Qt3DSDMPropertyHandle CSimpleDataCore::AddPropertyWithHandle(int inHandle, + Qt3DSDMInstanceHandle inInstance, + TCharPtr inName, + DataModelDataType::Value inPropType) +{ + UICDM_DEBUG_LOG("CSimpleDataCore::AddPropertyWithHandle Enter"); + UICDM_DEBUG_LOG(m_StringTable->GetNarrowStr(inName)); + if (HandleValid(inHandle)) { + if (g_UICDMDebugLogger) { + g_UICDMDebugLogger("CSimpleDataCore::AddPropertyWithHandle Handle Exists!!"); + char buf[32]; + sprintf(buf, "%d", inHandle); + g_UICDMDebugLogger(buf); + } + + throw HandleExists(L""); + } + + TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects); + + SUICDMPropertyDefinition 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); + UICDM_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/Authoring/QT3DSDM/Systems/Cores/SimpleDataCore.h b/src/Authoring/QT3DSDM/Systems/Cores/SimpleDataCore.h new file mode 100644 index 00000000..2f216d1a --- /dev/null +++ b/src/Authoring/QT3DSDM/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: + SUICDMPropertyDefinition m_Definition; + + CDataModelPropertyDefinitionObject(int inHandle, const SUICDMPropertyDefinition &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 SUICDMPropertyDefinition &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/Authoring/QT3DSDM/Systems/Cores/SimpleSlideCore.cpp b/src/Authoring/QT3DSDM/Systems/Cores/SimpleSlideCore.cpp new file mode 100644 index 00000000..cc364db7 --- /dev/null +++ b/src/Authoring/QT3DSDM/Systems/Cores/SimpleSlideCore.cpp @@ -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$ +** +****************************************************************************/ +#include "Qt3DSDMPrefix.h" +#include "SimpleSlideCore.h" + +using namespace std; +#ifdef _WIN32 +#pragma warning(disable : 4503) +#endif + +namespace qt3dsdm { + +CUICDMSlideHandle CSimpleSlideCore::CreateSlide(Qt3DSDMInstanceHandle inInstance) +{ + int nextId = GetNextId(); + return CreateSlideWithHandle(nextId, inInstance); +} + +Qt3DSDMInstanceHandle CSimpleSlideCore::GetSlideInstance(CUICDMSlideHandle 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; +} + +CUICDMSlideHandle 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(CUICDMSlideHandle 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(CUICDMSlideHandle 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, CUICDMSlideHandle>, + std::placeholders::_1, std::ref(outSlides))); +} + +float CSimpleSlideCore::GetSlideTime(CUICDMSlideHandle inSlide) const +{ + return GetSlideNF(inSlide, m_Objects)->m_Time; +} + +void CSimpleSlideCore::SetSlideTime(CUICDMSlideHandle inSlide, float inNewTime) +{ + GetSlideNF(inSlide, m_Objects)->m_Time = inNewTime; +} + +void CSimpleSlideCore::DeriveSlide(CUICDMSlideHandle inSlide, CUICDMSlideHandle 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; +} + +CUICDMSlideHandle CSimpleSlideCore::GetParentSlide(CUICDMSlideHandle inSlide) const +{ + return GetSlideNF(inSlide, m_Objects)->m_Parent; +} + +void CSimpleSlideCore::GetChildSlides(CUICDMSlideHandle inSlide, + TSlideHandleList &outChildren) const +{ + transformv_all(GetSlideNF(inSlide, m_Objects)->m_Children, outChildren); +} + +int CSimpleSlideCore::GetChildIndex(CUICDMSlideHandle inParent, CUICDMSlideHandle 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(CUICDMSlideHandle 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( + CUICDMSlideHandle 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(CUICDMSlideHandle 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(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + CSimpleSlideCore::ForceSetPropertyValue(GetStringTable(), m_Objects, inSlide, inHandle, + inProperty, inValue); +} + +bool CSimpleSlideCore::GetSpecificInstancePropertyValue(CUICDMSlideHandle 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(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + TPropertyHandleValuePairList &outValues) +{ + const SSlide *theSlide = GetSlideNF(inSlide, m_Objects); + theSlide->GetSpecificInstancePropertyValues(inInstance, outValues); +} + +void CSimpleSlideCore::GetSlidePropertyEntries(CUICDMSlideHandle inSlide, + TSlideEntryList &outEntries) const +{ + const SSlide *theSlide = GetSlideNF(inSlide, m_Objects); + theSlide->ToSlideEntryList(outEntries); +} + +bool CSimpleSlideCore::ContainsProperty(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) const +{ + const SSlide *theSlide = GetSlideNF(inSlide, m_Objects); + return theSlide->GetInstancePropertyValue(inHandle, inProperty) != NULL; +} + +CUICDMSlideHandle 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(CUICDMSlideHandle inSlide, + TSlideEntryList &outProperties) const +{ + outProperties.clear(); + GetSlidePropertyEntries(inSlide, outProperties); +} + +bool CSimpleSlideCore::IsSlide(CUICDMSlideHandle inSlide) const +{ + return m_Objects.find(inSlide) != m_Objects.end(); +} + +void CSimpleSlideCore::ForceSetPropertyValue(IStringTable &inStringTable, + THandleObjectMap &inObjects, CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) +{ + CSimpleSlideCore::GetSlideNF(inSlide, inObjects) + ->SetInstancePropertyValue(inHandle, inProperty, SInternValue(inValue, inStringTable)); +} + +void CSimpleSlideCore::PushPropertyValueToChildren(CUICDMSlideHandle 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(CUICDMSlideHandle inSlide1, + CUICDMSlideHandle 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(CUICDMSlideHandle inSlide1, + CUICDMSlideHandle inSlide2, + CUICDMSlideHandle 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, CUICDMSlideHandle 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(CUICDMSlideHandle inSlide, THandleObjectMap &inObjects, + std::function<void(SSlide *)> inFunction) +{ + inFunction(CSimpleSlideCore::GetSlideNF(inSlide, inObjects)); +} + +void CSimpleSlideCore::ForEachChild(CUICDMSlideHandle 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(CUICDMSlideHandle 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/Authoring/QT3DSDM/Systems/Cores/SimpleSlideCore.h b/src/Authoring/QT3DSDM/Systems/Cores/SimpleSlideCore.h new file mode 100644 index 00000000..1188f5a0 --- /dev/null +++ b/src/Authoring/QT3DSDM/Systems/Cores/SimpleSlideCore.h @@ -0,0 +1,395 @@ +/**************************************************************************** +** +** 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> + +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])); + Q_ASSERT(m_Properties.find(theKey) == m_Properties.end()); + 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(); } + CUICDMSlideHandle CreateSlide(Qt3DSDMInstanceHandle inInstance) override; + Qt3DSDMInstanceHandle GetSlideInstance(CUICDMSlideHandle inSlide) const override; + CUICDMSlideHandle GetSlideByInstance(Qt3DSDMInstanceHandle inInstance) const override; + void DeleteSlide(CUICDMSlideHandle inSlide, TInstanceHandleList &outInstances) override; + void GetSlides(TSlideHandleList &outSlides) const override; + + float GetSlideTime(CUICDMSlideHandle inSlide) const override; + void SetSlideTime(CUICDMSlideHandle inSlide, float inNewTime) override; + + void DeriveSlide(CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent, int inIndex = -1) override; + CUICDMSlideHandle GetParentSlide(CUICDMSlideHandle inSlide) const override; + void GetChildSlides(CUICDMSlideHandle inSlide, TSlideHandleList &outChildren) const override; + int GetChildIndex(CUICDMSlideHandle inParent, CUICDMSlideHandle inChild) const override; + + bool GetInstancePropertyValue(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + void SetInstancePropertyValue(CUICDMSlideHandle 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(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty); + void ForceSetInstancePropertyValue(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + + bool GetSpecificInstancePropertyValue(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + + void GetSpecificInstancePropertyValues(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + TPropertyHandleValuePairList &outValues) override; + + void GetSlidePropertyEntries(CUICDMSlideHandle inSlide, TSlideEntryList &outEntries) const override; + + void PushPropertyValueToChildren(CUICDMSlideHandle inParent, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + + void GetIntersectingProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2, + TSlideEntryList &outEntries) const override; + void PushIntersectingProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2, + CUICDMSlideHandle inDestination) override; + + void ClearChildrenPropertyValues(CUICDMSlideHandle 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(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) const override; + bool HandleValid(int inHandle) const override { return CHandleBase::HandleValid(inHandle); } + + CUICDMSlideHandle CreateSlideWithHandle(int inHandle, Qt3DSDMInstanceHandle inInstance); + void GetSlideProperties(CUICDMSlideHandle inSlide, TSlideEntryList &outProperties) const; + + bool IsSlide(CUICDMSlideHandle inSlide) const override; + + // Possibly alter every slide in the database + void ForEachSlide(std::function<void(SSlide *)> inFunction); + void ForEachChild(CUICDMSlideHandle inSlide, std::function<void(SSlide *)> inFunction); + + // Only implemented at the producer level, not at this lower level. + void CopyProperties(CUICDMSlideHandle /*inSourceSlide*/, + Qt3DSDMInstanceHandle /*inSourceInstance*/, + CUICDMSlideHandle /*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, + CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue); + + static void ClearPropertyValue(THandleObjectMap &inObjects, CUICDMSlideHandle 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/Authoring/QT3DSDM/Systems/Cores/SimpleSlideGraphCore.cpp b/src/Authoring/QT3DSDM/Systems/Cores/SimpleSlideGraphCore.cpp new file mode 100644 index 00000000..ce7159a5 --- /dev/null +++ b/src/Authoring/QT3DSDM/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 { + +CUICDMSlideGraphHandle CSimpleSlideGraphCore::CreateSlideGraph(CUICDMSlideHandle inRoot) +{ + int nextId = GetNextId(); + return CreateSlideGraphWithHandle(nextId, inRoot); +} + +CUICDMSlideHandle CSimpleSlideGraphCore::GetGraphRoot(CUICDMSlideGraphHandle inGraph) const +{ + return GetSlideGraphNF(inGraph, m_Objects)->m_Root; +} + +inline bool RootSlideMatches(const THandleObjectPair &inPair, CUICDMSlideHandle inSlide) +{ + const SSlideGraph *theGraph = static_cast<SSlideGraph *>(inPair.second.get()); + if (theGraph->m_Root == inSlide) + return true; + return false; +} + +CUICDMSlideGraphHandle CSimpleSlideGraphCore::GetSlideGraph(CUICDMSlideHandle 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 CUICDMSlideGraphHandle 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(CUICDMSlideGraphHandle 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(CUICDMSlideGraphHandle inSlideGraph, + CUICDMSlideHandle 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(CUICDMSlideGraphHandle 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<CUICDMSlideHandle, 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(CUICDMSlideGraphHandle inGraph, + CUICDMSlideHandle inSlide) +{ + GetSlideGraphNF(inGraph, m_Objects)->m_ActiveSlide = inSlide; +} + +CUICDMSlideHandle CSimpleSlideGraphCore::GetGraphActiveSlide(CUICDMSlideGraphHandle 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); +} + +CUICDMSlideGraphHandle CSimpleSlideGraphCore::CreateSlideGraphWithHandle(int inHandle, + CUICDMSlideHandle inRoot) +{ + m_Objects.insert(make_pair(inHandle, (THandleObjectPtr) new SSlideGraph(inHandle, inRoot))); + return inHandle; +} +} diff --git a/src/Authoring/QT3DSDM/Systems/Cores/SimpleSlideGraphCore.h b/src/Authoring/QT3DSDM/Systems/Cores/SimpleSlideGraphCore.h new file mode 100644 index 00000000..b4e82c76 --- /dev/null +++ b/src/Authoring/QT3DSDM/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) + { + } + CUICDMSlideHandle m_Root; + CUICDMSlideHandle 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<CUICDMSlideGraphHandle, CUICDMSlideHandle>, std::hash<int>> + TInstanceToGraphMap; + typedef std::unordered_map<CUICDMSlideGraphHandle, 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. + */ + CUICDMSlideGraphHandle CreateSlideGraph(CUICDMSlideHandle inRoot) override; + CUICDMSlideHandle GetGraphRoot(CUICDMSlideGraphHandle inGraph) const override; + CUICDMSlideGraphHandle GetSlideGraph(CUICDMSlideHandle inSlide) const override; + void GetSlideGraphs(TSlideGraphHandleList &outGraphs) const override; + void DeleteSlideGraph(CUICDMSlideGraphHandle 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(CUICDMSlideGraphHandle inSlideGraph, CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) override; + void GetAssociatedInstances(CUICDMSlideGraphHandle 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(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide) override; + CUICDMSlideHandle GetGraphActiveSlide(CUICDMSlideGraphHandle inGraph) const override; + + bool HandleValid(int inHandle) const override; + + CUICDMSlideGraphHandle CreateSlideGraphWithHandle(int inHandle, CUICDMSlideHandle 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/Authoring/QT3DSDM/Systems/Cores/SlideCoreProducer.cpp b/src/Authoring/QT3DSDM/Systems/Cores/SlideCoreProducer.cpp new file mode 100644 index 00000000..b23ba012 --- /dev/null +++ b/src/Authoring/QT3DSDM/Systems/Cores/SlideCoreProducer.cpp @@ -0,0 +1,555 @@ +/**************************************************************************** +** +** 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 { + +CUICDMSlideHandle CSlideCoreProducer::CreateSlide(Qt3DSDMInstanceHandle inInstance) +{ + CUICDMSlideHandle retval = m_Data->CreateSlide(inInstance); + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + GetSignalSender()->SendSlideCreated(retval); + return retval; +} + +Qt3DSDMInstanceHandle CSlideCoreProducer::GetSlideInstance(CUICDMSlideHandle inSlide) const +{ + return m_Data->GetSlideInstance(inSlide); +} + +CUICDMSlideHandle CSlideCoreProducer::GetSlideByInstance(Qt3DSDMInstanceHandle inSlide) const +{ + return m_Data->GetSlideByInstance(inSlide); +} + +void SendPropertyRemoved(const TSlideEntry &inEntry, CUICDMSlideHandle inSlide, + ISlideCoreSignalSender *inSender) +{ + inSender->SendPropertyValueRemoved(inSlide, get<0>(inEntry), get<1>(inEntry), get<2>(inEntry)); +} + +void RecurseCreateDeleteTransactions(TTransactionConsumerPtr inConsumer, CUICDMSlideHandle 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(CUICDMSlideHandle 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(CUICDMSlideHandle inSlide) const +{ + return m_Data->GetSlideTime(inSlide); +} + +void CSlideCoreProducer::SetSlideTime(CUICDMSlideHandle 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(CUICDMSlideHandle inSlide, CUICDMSlideHandle 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); +} + +CUICDMSlideHandle CSlideCoreProducer::GetParentSlide(CUICDMSlideHandle inSlide) const +{ + return m_Data->GetParentSlide(inSlide); +} + +void CSlideCoreProducer::GetChildSlides(CUICDMSlideHandle inSlide, + TSlideHandleList &outChildren) const +{ + m_Data->GetChildSlides(inSlide, outChildren); +} + +int CSlideCoreProducer::GetChildIndex(CUICDMSlideHandle inParent, CUICDMSlideHandle inChild) const +{ + return m_Data->GetChildIndex(inParent, inChild); +} + +bool CSlideCoreProducer::GetInstancePropertyValue(CUICDMSlideHandle 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(CUICDMSlideHandle 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(CUICDMSlideHandle 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); + UICDM_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(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue) +{ + if (m_Consumer) + DoForceSetInstancePropertyValue(inSlide, inHandle, inProperty, inValue); + else + m_Data->ForceSetInstancePropertyValue(inSlide, inHandle, inProperty, inValue); +} + +bool CSlideCoreProducer::GetSpecificInstancePropertyValue(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, + SValue &outValue) const +{ + return m_Data->GetSpecificInstancePropertyValue(inSlide, inInstance, inProperty, outValue); +} + +bool CSlideCoreProducer::ContainsProperty(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) const +{ + return m_Data->ContainsProperty(inSlide, inHandle, inProperty); +} + +void CSlideCoreProducer::GetSlidePropertyEntries(CUICDMSlideHandle inSlide, + TSlideEntryList &outEntries) const +{ + return m_Data->GetSlidePropertyEntries(inSlide, outEntries); +} + +void CSlideCoreProducer::PushPropertyValueToChildren(CUICDMSlideHandle 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(CUICDMSlideHandle 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(CUICDMSlideHandle inSlide1, + CUICDMSlideHandle 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, + CUICDMSlideHandle inSource, CUICDMSlideHandle 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(CUICDMSlideHandle inSlide1, + CUICDMSlideHandle inSlide2, + CUICDMSlideHandle 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(CUICDMSlideHandle inSourceSlide, + Qt3DSDMInstanceHandle inSourceInstance, + CUICDMSlideHandle 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(CUICDMSlideHandle 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(CUICDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectSlideCreated(inCallback); +} +TSignalConnectionPtr CSlideCoreProducer::ConnectBeforeSlideDeleted( + const std::function<void(CUICDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectBeforeSlideDeleted(inCallback); +} +TSignalConnectionPtr +CSlideCoreProducer::ConnectSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectSlideDeleted(inCallback); +} +TSignalConnectionPtr CSlideCoreProducer::ConnectSlideDerived( + const std::function<void(CUICDMSlideHandle, CUICDMSlideHandle, int)> &inCallback) +{ + return GetSignalProvider()->ConnectSlideDerived(inCallback); +} +TSignalConnectionPtr CSlideCoreProducer::ConnectInstancePropertyValueSet( + const std::function<void(CUICDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) +{ + return GetSignalProvider()->ConnectInstancePropertyValueSet(inCallback); +} +TSignalConnectionPtr CSlideCoreProducer::ConnectInstancePropertyValueRemoved( + const std::function<void(CUICDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) +{ + return GetSignalProvider()->ConnectInstancePropertyValueRemoved(inCallback); +} +TSignalConnectionPtr CSlideCoreProducer::ConnectSlideTimeChanged( + const std::function<void(CUICDMSlideHandle)> &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/Authoring/QT3DSDM/Systems/Cores/SlideCoreProducer.h b/src/Authoring/QT3DSDM/Systems/Cores/SlideCoreProducer.h new file mode 100644 index 00000000..848ed2a1 --- /dev/null +++ b/src/Authoring/QT3DSDM/Systems/Cores/SlideCoreProducer.h @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** 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; } + + CUICDMSlideHandle CreateSlide(Qt3DSDMInstanceHandle inInstance) override; + Qt3DSDMInstanceHandle GetSlideInstance(CUICDMSlideHandle inSlide) const override; + CUICDMSlideHandle GetSlideByInstance(Qt3DSDMInstanceHandle inSlide) const override; + void DeleteSlide(CUICDMSlideHandle inSlide, TInstanceHandleList &outInstances) override; + void GetSlides(TSlideHandleList &outSlides) const override; + + float GetSlideTime(CUICDMSlideHandle inSlide) const override; + void SetSlideTime(CUICDMSlideHandle inSlide, float inNewTime) override; + + void DeriveSlide(CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent, int inIndex = -1) override; + CUICDMSlideHandle GetParentSlide(CUICDMSlideHandle inSlide) const override; + void GetChildSlides(CUICDMSlideHandle inSlide, TSlideHandleList &outChildren) const override; + int GetChildIndex(CUICDMSlideHandle inParent, CUICDMSlideHandle inChild) const override; + + bool GetInstancePropertyValue(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + void SetInstancePropertyValue(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + void ForceSetInstancePropertyValue(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + bool GetSpecificInstancePropertyValue(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + Qt3DSDMPropertyHandle inProperty, SValue &outValue) const override; + void GetSpecificInstancePropertyValues(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance, + TPropertyHandleValuePairList &outValues) override + { + return m_Data->GetSpecificInstancePropertyValues(inSlide, inInstance, outValues); + } + bool ContainsProperty(CUICDMSlideHandle inSlide, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty) const override; + void GetSlidePropertyEntries(CUICDMSlideHandle inSlide, TSlideEntryList &outEntries) const override; + + void PushPropertyValueToChildren(CUICDMSlideHandle inParent, Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, const SValue &inValue) override; + void ClearChildrenPropertyValues(CUICDMSlideHandle 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(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2, + TSlideEntryList &outEntries) const override; + void PushIntersectingProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2, + CUICDMSlideHandle inDestination) override; + void CopyProperties(CUICDMSlideHandle inSourceSlide, Qt3DSDMInstanceHandle inSourceInstance, + CUICDMSlideHandle inDestSlide, Qt3DSDMInstanceHandle inDestInstance) override; + + bool IsSlide(CUICDMSlideHandle inSlide) const override; + + bool HandleValid(int inHandle) const override; + + void SetConsumer(TTransactionConsumerPtr inConsumer) override; + + //=================================================================== + // Signals + //=================================================================== + + virtual TSignalConnectionPtr + ConnectSlideCreated(const std::function<void(CUICDMSlideHandle)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectBeforeSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) override; + TSignalConnectionPtr ConnectSlideDerived( + const std::function<void(CUICDMSlideHandle, CUICDMSlideHandle, int)> &inCallback) override; + TSignalConnectionPtr ConnectInstancePropertyValueSet( + const std::function<void(CUICDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) override; + TSignalConnectionPtr ConnectInstancePropertyValueRemoved( + const std::function<void(CUICDMSlideHandle, Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle, + const SValue &)> &inCallback) override; + virtual TSignalConnectionPtr + ConnectSlideTimeChanged(const std::function<void(CUICDMSlideHandle)> &inCallback) override; + +private: + inline void DoForceSetInstancePropertyValue(CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inHandle, + Qt3DSDMPropertyHandle inProperty, + const SValue &inValue); + void InitSignaller(); + ISlideCoreSignalProvider *GetSignalProvider(); + ISlideCoreSignalSender *GetSignalSender(); +}; +} + +#endif diff --git a/src/Authoring/QT3DSDM/Systems/Cores/SlideGraphCoreProducer.cpp b/src/Authoring/QT3DSDM/Systems/Cores/SlideGraphCoreProducer.cpp new file mode 100644 index 00000000..52ea12b5 --- /dev/null +++ b/src/Authoring/QT3DSDM/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 { + +CUICDMSlideGraphHandle CSlideGraphCoreProducer::CreateSlideGraph(CUICDMSlideHandle inRoot) +{ + CUICDMSlideGraphHandle retval(m_Data->CreateSlideGraph(inRoot)); + CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects); + GetSignalSender()->SendGraphCreated(retval, inRoot); + return retval; +} + +CUICDMSlideHandle CSlideGraphCoreProducer::GetGraphRoot(CUICDMSlideGraphHandle inGraph) const +{ + return m_Data->GetGraphRoot(inGraph); +} + +CUICDMSlideGraphHandle CSlideGraphCoreProducer::GetSlideGraph(CUICDMSlideHandle 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; + CUICDMSlideGraphHandle m_Handle; + TSlideInstancePairList m_Instances; + DissocateAllInstanceTrans(const char *inFile, int inLine, + std::shared_ptr<CSimpleSlideGraphCore> inGraph, + CUICDMSlideGraphHandle 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(CUICDMSlideGraphHandle inHandle) +{ + SSlideGraph *theGraph = CSimpleSlideGraphCore::GetSlideGraphNF(inHandle, m_Data->m_Objects); + CUICDMSlideHandle 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; + CUICDMSlideGraphHandle m_GraphHandle; + CUICDMSlideHandle m_Slide; + Qt3DSDMInstanceHandle m_Instance; + bool m_InsertOnDo; + SInstanceAssociateTrans(const char *inFile, int inLine, + std::shared_ptr<CSimpleSlideGraphCore> inGraph, + CUICDMSlideGraphHandle inGraphHandle, CUICDMSlideHandle 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(CUICDMSlideGraphHandle inSlideGraph, + CUICDMSlideHandle 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(CUICDMSlideGraphHandle 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(CUICDMSlideGraphHandle inGraph, + CUICDMSlideHandle inSlide) +{ + if (m_Consumer) { + CUICDMSlideHandle 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); +} + +CUICDMSlideHandle CSlideGraphCoreProducer::GetGraphActiveSlide(CUICDMSlideGraphHandle 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(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectGraphCreated(inCallback); +} +TSignalConnectionPtr CSlideGraphCoreProducer::ConnectGraphDeleted( + const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) +{ + return GetSignalProvider()->ConnectGraphDeleted(inCallback); +} +TSignalConnectionPtr CSlideGraphCoreProducer::ConnectInstanceAssociated( + const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) +{ + return GetSignalProvider()->ConnectInstanceAssociated(inCallback); +} +TSignalConnectionPtr CSlideGraphCoreProducer::ConnectInstanceDissociated( + const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) +{ + return GetSignalProvider()->ConnectInstanceDissociated(inCallback); +} +TSignalConnectionPtr CSlideGraphCoreProducer::ConnectGraphActiveSlide( + const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &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/Authoring/QT3DSDM/Systems/Cores/SlideGraphCoreProducer.h b/src/Authoring/QT3DSDM/Systems/Cores/SlideGraphCoreProducer.h new file mode 100644 index 00000000..2cc50436 --- /dev/null +++ b/src/Authoring/QT3DSDM/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; } + + CUICDMSlideGraphHandle CreateSlideGraph(CUICDMSlideHandle inRoot) override; + CUICDMSlideHandle GetGraphRoot(CUICDMSlideGraphHandle inGraph) const override; + CUICDMSlideGraphHandle GetSlideGraph(CUICDMSlideHandle inSlide) const override; + void GetSlideGraphs(TSlideGraphHandleList &outGraphs) const override; + void DeleteSlideGraph(CUICDMSlideGraphHandle inHandle) override; + + void AssociateInstance(CUICDMSlideGraphHandle inSlideGraph, CUICDMSlideHandle inSlide, + Qt3DSDMInstanceHandle inInstance) override; + void GetAssociatedInstances(CUICDMSlideGraphHandle inSlideGraph, + TSlideInstancePairList &outAssociations) const override; + TGraphSlidePair GetAssociatedGraph(Qt3DSDMInstanceHandle inInstance) const override; + void DissociateInstance(Qt3DSDMInstanceHandle inInstance) override; + + void SetGraphActiveSlide(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide) override; + CUICDMSlideHandle GetGraphActiveSlide(CUICDMSlideGraphHandle inGraph) const override; + + bool HandleValid(int inHandle) const override; + void SetConsumer(TTransactionConsumerPtr inConsumer) override; + + //=================================================================== + // Signals + //=================================================================== + TSignalConnectionPtr ConnectGraphCreated( + const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) override; + TSignalConnectionPtr ConnectGraphDeleted( + const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) override; + TSignalConnectionPtr ConnectInstanceAssociated( + const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) override; + TSignalConnectionPtr ConnectInstanceDissociated( + const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, Qt3DSDMInstanceHandle)> + &inCallback) override; + TSignalConnectionPtr ConnectGraphActiveSlide( + const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) override; + +private: + void InitSignaller(); + ISlideGraphCoreSignalProvider *GetSignalProvider(); + ISlideGraphCoreSignalSender *GetSignalSender(); +}; +} + +#endif |