diff options
Diffstat (limited to 'src/Runtime/Source/runtime/Qt3DSComponentManager.cpp')
-rw-r--r-- | src/Runtime/Source/runtime/Qt3DSComponentManager.cpp | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/src/Runtime/Source/runtime/Qt3DSComponentManager.cpp b/src/Runtime/Source/runtime/Qt3DSComponentManager.cpp new file mode 100644 index 00000000..2cfb2311 --- /dev/null +++ b/src/Runtime/Source/runtime/Qt3DSComponentManager.cpp @@ -0,0 +1,480 @@ +/**************************************************************************** +** +** 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$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "RuntimePrefix.h" + +//============================================================================== +// Includes +//============================================================================== +#include "Qt3DSComponentManager.h" +#include "Qt3DSIPresentation.h" +#include "Qt3DSSlideSystem.h" +#include "Qt3DSCommandEventTypes.h" +#include "Qt3DSPresentationFrameData.h" +#include "Qt3DSApplication.h" +#include "Qt3DSActivationManager.h" +#include "Qt3DSPresentation.h" + +using qt3ds::runtime::SSlideKey; +//============================================================================== +// Namespace +//============================================================================== +namespace Q3DStudio { + +//============================================================================== +/** + * Constructor + * @param inPresentation reference to its presentation + */ +CComponentManager::CComponentManager(IPresentation &inPresentation) + : m_Presentation(static_cast<CPresentation &>(inPresentation)) +{ +} + +//============================================================================== +/** + * Enforces the contract that slide switching requires a reset to the master + * slide (slide 0) before switching to the desired slide index. + * Also updates the TComponent's current slide number. + * @param inComponent TComponent to set slide on + * @param inSlideIndex relative index of the slide to switch to + * @param inSlideExit true if exiting the slide, false otherwise + */ +void CComponentManager::GotoSlideIndex(TElement *inComponent, + const SComponentGotoSlideData &inGotoData, + BOOL inSlideExit /*= true*/) +{ + TComponent *theComponent = GetComponent(inComponent); + + if (theComponent == NULL) { + return; + } + + if (inGotoData.m_Slide < 1 || inGotoData.m_Slide >= theComponent->GetSlideCount()) { + qCCritical(qt3ds::INVALID_PARAMETER) + << "GotoSlide: Index out of range: Index " << inGotoData.m_Slide + << " SlideCount: "<< theComponent->GetSlideCount(); + return; + } + + if (theComponent->GetActive() == false) { + m_ComponentInitialSlideMap[inComponent] = inGotoData; + return; + } + + SComponentGotoSlideData theGotoSlideData(inGotoData); + + TComponentGotoSlideDataMap::iterator iter = m_ComponentInitialSlideMap.find(inComponent); + if (iter != m_ComponentInitialSlideMap.end()) { + theGotoSlideData = iter->second; + m_ComponentInitialSlideMap.erase(iter); + } + + const UINT8 theCurrentSlideIndex = theComponent->GetCurrentSlide(); + + QString elementPath = QString::fromUtf8(inComponent->m_Path.c_str()); + + if (inSlideExit) { + SEventCommand theEvent = { inComponent, EVENT_ONSLIDEEXIT }; + theEvent.m_IsEvent = true; + m_Presentation.ProcessEvent(theEvent); + + // Signal previous slide change + m_Presentation.signalProxy()->SigSlideExited(elementPath, theCurrentSlideIndex, + GetCurrentSlideName(inComponent)); + + // m_Presentation.FireEvent(EVENT_ONSLIDEEXIT, inComponent); + // m_Presentation.FlushEventCommandQueue(); + } + + // Update dynamic keys to use current values before slide switching, with the exception of + // master slides because playback only starts from non-master slides. + if (theCurrentSlideIndex > 0) { + m_Presentation.GetSlideSystem().InitializeDynamicKeys( + SSlideKey(*theComponent, (qt3ds::QT3DSU8)theGotoSlideData.m_Slide), + m_Presentation.GetAnimationSystem()); + // deactivate actions and animation tracks on the current slide. + m_Presentation.GetSlideSystem().RollbackSlide( + SSlideKey(*inComponent, (qt3ds::QT3DSU8)theCurrentSlideIndex), + m_Presentation.GetAnimationSystem(), m_Presentation.GetLogicSystem()); + } else { + m_Presentation.GetSlideSystem().ExecuteSlide(SSlideKey(*inComponent, 0), + m_Presentation.GetAnimationSystem(), + m_Presentation.GetLogicSystem()); + } + // Execute new slide. + m_Presentation.GetSlideSystem().ExecuteSlide( + SSlideKey(*inComponent, (qt3ds::QT3DSU8)theGotoSlideData.m_Slide), + m_Presentation.GetAnimationSystem(), m_Presentation.GetLogicSystem()); + CTimePolicy &thePolicy(theComponent->GetTimePolicy()); + TTimeUnit theLoopingDuration = thePolicy.GetLoopingDuration(); + if (theGotoSlideData.m_Mode.hasValue()) { + inComponent->SetPlayThrough(false); + switch (*theGotoSlideData.m_Mode) { + case TimePolicyModes::Looping: + thePolicy.Initialize(theLoopingDuration, 0, false); + break; + case TimePolicyModes::PingPong: + thePolicy.Initialize(theLoopingDuration, 0, true); + break; + case TimePolicyModes::StopAtEnd: + thePolicy.Initialize(theLoopingDuration, 1, false); + break; + case TimePolicyModes::Ping: + thePolicy.Initialize(theLoopingDuration, 1, true); + break; + default: + QT3DS_ASSERT(false); + break; + } + } + + // Update the current index which also updates the back index + theComponent->SetCurrentSlide(static_cast<UINT8>(theGotoSlideData.m_Slide)); + m_PlaythroughOverrideMap.erase(inComponent); + if (theGotoSlideData.m_PlaythroughTo.hasValue()) { + m_PlaythroughOverrideMap.insert( + eastl::make_pair(inComponent, *theGotoSlideData.m_PlaythroughTo)); + theComponent->SetPlayThrough(true); + } + + // Reset time for component to 0 + + if (theGotoSlideData.m_Paused.hasValue()) + thePolicy.SetPaused(*theGotoSlideData.m_Paused); + + thePolicy.SetRate(theGotoSlideData.m_Rate); + thePolicy.SetReverse(theGotoSlideData.m_Reverse); + + if (theGotoSlideData.m_StartTime.hasValue()) + thePolicy.SetTime(*theGotoSlideData.m_StartTime); + + inComponent->SetDirty(); + m_Presentation.FireEvent(EVENT_ONSLIDEENTER, inComponent); + qt3ds::runtime::IActivityZone *theZone = m_Presentation.GetActivityZone(); + if (theZone) + theZone->OnSlideChange(*inComponent); + + // Signal current slide change + m_Presentation.signalProxy()->SigSlideEntered(elementPath, GetCurrentSlide(inComponent), + GetCurrentSlideName(inComponent)); +} + +//============================================================================== +/** + * Sets a component to a specified slide using the slide name hash. + * Performs a switch to Slide 0 (master) first, before switching to the + * required slide. + * @param inComponent reference to the TComponent + * @param inSlideHashName hash of the slide to switch to + */ +void CComponentManager::GotoSlideName(TElement *inComponent, const TStringHash inSlideHashName) +{ + TComponent *theComponent = GetComponent(inComponent); + UINT8 theSlideIndex = m_Presentation.GetSlideSystem().FindSlide(*theComponent, inSlideHashName); + + if (theSlideIndex < 1 || theSlideIndex >= theComponent->GetSlideCount()) { + const char *slideName = m_Presentation.GetApplication().ReverseHash(inSlideHashName); + if (slideName && *slideName) + qCCritical(qt3ds::INVALID_PARAMETER) << "GotoSlide: Name not found: " << slideName; + else + qCCritical(qt3ds::INVALID_PARAMETER) << "GotoSlide: Name not found: " << inSlideHashName; + + } else + GotoSlideIndex(inComponent, theSlideIndex); +} + +//============================================================================== +/** + * Return the index of the current slide of the component. + * @param inComponent reference to the TComponent + * @return the index of current slide + */ +UINT8 CComponentManager::GetCurrentSlide(TElement *inComponent) +{ + return GetComponent(inComponent)->GetCurrentSlide(); +} + +//============================================================================== +/** + * Return the number of slides on a component. + * @param inComponent reference to the TComponent + * @return the number of slides + */ +UINT8 CComponentManager::GetSlideCount(TElement *inComponent) +{ + return GetComponent(inComponent)->GetSlideCount(); +} + +//============================================================================== +/** + * Performs a switch to the slide following the current slide (current slide + 1). + * @param inComponent reference to the TComponent + * @param inIncrement slide increment offset + */ +void CComponentManager::GoToNextSlide(TElement *inComponent, const INT32 inIncrement) +{ + TComponent *theComponent = GetComponent(inComponent); + INT32 theNewIndex = Q3DStudio_clamp<INT32>(inIncrement + theComponent->GetCurrentSlide(), 1L, + theComponent->GetSlideCount() - 1); + + // Trigger goto to slide only if the next slide is not the current + if (theComponent->GetActive()) { + if (theNewIndex != theComponent->GetCurrentSlide()) + GotoSlideIndex(inComponent, theNewIndex); + } else { + qCCritical(qt3ds::INVALID_PARAMETER) + << "Runtime: Attempt to goto slide on an inactive component!"; + } +} + +//============================================================================== +/** + * Performs a switch to the slide following the current slide (current slide - 1). + * @param inComponent reference to the TComponent + * @param inDecrement slide decrement offset + */ +void CComponentManager::GoToPreviousSlide(TElement *inComponent, const INT32 inDecrement) +{ + TComponent *theComponent = GetComponent(inComponent); + INT32 theNewIndex = Q3DStudio_clamp<INT32>(theComponent->GetCurrentSlide() - inDecrement, 1L, + theComponent->GetSlideCount() - 1); + + // Trigger goto to slide only if the next slide is not the current + if (theNewIndex != theComponent->GetCurrentSlide()) + GotoSlideIndex(inComponent, theNewIndex); +} + +//============================================================================== +/** + * Playthrough to the next slide that is specified. + * @param inComponent reference to the TComponent + */ +void CComponentManager::PlaythroughToSlide(TElement *inComponent) +{ + TComponent *theComponent = GetComponent(inComponent); + TComponentIntMap::iterator iter = m_PlaythroughOverrideMap.find(inComponent); + INT32 thePlaythroughTo = 0; + if (iter != m_PlaythroughOverrideMap.end()) { + thePlaythroughTo = iter->second; + m_PlaythroughOverrideMap.erase(iter); + } else { + thePlaythroughTo = m_Presentation.GetSlideSystem().GetPlaythroughToSlideIndex( + SSlideKey(*theComponent, (qt3ds::QT3DSU8)theComponent->GetCurrentSlide())); + if (thePlaythroughTo == -1) { + qCCritical(qt3ds::INVALID_OPERATION) << "Missing slide to play through to"; + inComponent->SetPlayThrough( + false); // clear this flag, so that this is equivalent to a "Stop At End" + } + } + + if (thePlaythroughTo == -2) { + GoToPreviousSlide(inComponent, 1); + } else if (thePlaythroughTo == -1) { + GoToNextSlide(inComponent, 1); + } else { + GotoSlideIndex(inComponent, thePlaythroughTo); + } +} + +//============================================================================== +/** + * Performs a switch to the previous slide. + * @param inComponent reference to the TComponent + */ +void CComponentManager::GoToBackSlide(TElement *inComponent) +{ + TComponent *theComponent = GetComponent(inComponent); + GotoSlideIndex(theComponent, theComponent->GetPreviousSlide()); +} + +//============================================================================== +/** + * Set the component's local time using the supplied time. + * @param inComponent reference to the TComponent + * @param inTime supplied time + */ +void CComponentManager::GoToTime(TElement *inComponent, const TTimeUnit inTime) +{ + if (inComponent == NULL) + return; + if (inComponent->GetActive() == false) { + qCCritical(qt3ds::INVALID_OPERATION) + << "Runtime: Attempt to goto time on inactive component!"; + return; + } + m_Presentation.GetActivityZone()->GoToTime(*inComponent, inTime); + inComponent->SetDirty(); +} + +//============================================================================== +/** + * Get the component's playback state + * @param inComponent reference to the TComponent + * @return true if it's paused, false if it's playing + */ +BOOL CComponentManager::GetPause(TElement *inComponent) +{ + CTimePolicy &theTimePolicy = GetComponent(inComponent)->GetTimePolicy(); + return theTimePolicy.GetPaused(); +} + +//============================================================================== +/** + * Get the component's ping pong direction + * @param inComponent reference to the TComponent + * @return true if it's pingponging forward, false if it's pingponging backwards + */ +BOOL CComponentManager::GetPlayBackDirection(TElement *inComponent) +{ + return GetComponent(inComponent)->GetPlayBackDirection(); +} + +//============================================================================== +/** + * Update time policy of the component during each slide execution + * @param inComponent reference to the TComponent + * @param inLoopDuration loop duration of component at that slide + * @param inRepetitions number of repetitions + * @param inPingPong if true the component will move with respect to reverse time + *sequence + * @param inPlayThrough if true the component will continue to execute next slide + */ +void CComponentManager::SetTimePolicy(TElement *inComponent, const TTimeUnit inLoopDuration, + const UINT32 inRepetitions, const BOOL inPingPong, + const BOOL inPlayThrough) +{ + CTimePolicy &theTimePolicy = GetComponent(inComponent)->GetTimePolicy(); + theTimePolicy.Initialize(inLoopDuration, inRepetitions, inPingPong); + inComponent->SetPlayThrough(inPlayThrough); +} + +//============================================================================== +/** + * Set the component's playback to either play or pause + * @param inComponent reference to the TComponent + * @param inPause true = pause, false = play + */ +void CComponentManager::SetPause(TElement *inComponent, const BOOL inPause) +{ + CTimePolicy &theTimePolicy = GetComponent(inComponent)->GetTimePolicy(); + BOOL wasPaused = theTimePolicy.GetPaused(); + theTimePolicy.SetPaused(inPause); + if (wasPaused != inPause) + inComponent->SetDirty(); +} + +//============================================================================== +/** + * Promote from TElement* to TComponent. + * @param inElement TElement pointer to be recast as TComponent + * @return pointer to the component + */ +TComponent *CComponentManager::GetComponent(TElement *inElement) +{ + Q3DStudio_ASSERT(inElement->IsComponent()); + return static_cast<TComponent *>(inElement); +} + +//============================================================================== +/** + * Gets the string name of the current slide. + * @param inComponent the component to query for it's current slide name + * @return the char buffer storing the name + */ +const CHAR *CComponentManager::GetCurrentSlideName(TElement *inComponent) +{ + TComponent *theComponent = GetComponent(inComponent); + return m_Presentation.GetSlideSystem().GetSlideName( + SSlideKey(*theComponent, (qt3ds::QT3DSU8)theComponent->GetCurrentSlide())); +} + +void CComponentManager::OnElementDeactivated(TElement *) +{ +} + +void CComponentManager::SetComponentTimeOverride(TElement *inElement, TTimeUnit inEndTime, + FLOAT inInterpolation, + IComponentTimeOverrideFinishedCallback *inCallback) +{ + if (inElement->IsComponent()) { + qCCritical(qt3ds::INVALID_OPERATION) + << "ComponentManager: SetComponentTimeOverride called on object that " + << "wasn't an element"; + if (inCallback) + inCallback->Release(); + Q3DStudio_ASSERT(false); + return; + } + // sanitize end time. + CTimePolicy &theTimePolicy = GetComponent(inElement)->GetTimePolicy(); + if (inEndTime < 0) + inEndTime = 0; + if (inEndTime > theTimePolicy.GetLoopingDuration()) + inEndTime = theTimePolicy.GetLoopingDuration(); + m_Presentation.GetActivityZone()->GetOrCreateItemComponentOverride(*inElement, inInterpolation, + inEndTime, inCallback); + + // Force the time policy object to respect its own time. If we played through till the end and + // sat there for a while + // we need the actual time will travel further and further from the time policy's local time. + // If we then play backward we + // will jump until the offset is synchronized with the actual time. + theTimePolicy.SetTime(theTimePolicy.GetTime()); + inElement->SetDirty(); +} + +void CComponentManager::SetupComponentGotoSlideCommand(TElement *inElement, + const SComponentGotoSlideData &inSlide) +{ + m_ComponentGotoSlideMap[inElement] = inSlide; +} + +bool CComponentManager::HasComponentGotoSlideCommand(TElement *inElement) +{ + return m_ComponentGotoSlideMap.find(inElement) != m_ComponentGotoSlideMap.end(); +} + +SComponentGotoSlideData CComponentManager::GetComponentGotoSlideCommand(TElement *inElement) +{ + TComponentGotoSlideDataMap::iterator iter = m_ComponentGotoSlideMap.find(inElement); + if (iter != m_ComponentGotoSlideMap.end()) + return iter->second; + return -1; +} + +void CComponentManager::ReleaseComponentGotoSlideCommand(TElement *inElement) +{ + TComponentGotoSlideDataMap::iterator iter = m_ComponentGotoSlideMap.find(inElement); + if (iter != m_ComponentGotoSlideMap.end()) + m_ComponentGotoSlideMap.erase(iter); +} + +} // namespace Q3DStudio |