summaryrefslogtreecommitdiffstats
path: root/src/Runtime/Source/runtime/Qt3DSTimePolicy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/Source/runtime/Qt3DSTimePolicy.cpp')
-rw-r--r--src/Runtime/Source/runtime/Qt3DSTimePolicy.cpp407
1 files changed, 407 insertions, 0 deletions
diff --git a/src/Runtime/Source/runtime/Qt3DSTimePolicy.cpp b/src/Runtime/Source/runtime/Qt3DSTimePolicy.cpp
new file mode 100644
index 00000000..e1efb8e0
--- /dev/null
+++ b/src/Runtime/Source/runtime/Qt3DSTimePolicy.cpp
@@ -0,0 +1,407 @@
+/****************************************************************************
+**
+** 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 "Qt3DSTimePolicy.h"
+#include "foundation/Qt3DSUnionCast.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "Qt3DSComponentManager.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const TTimeUnit CTimePolicy::FOREVER = 0;
+
+SAlignedTimeUnit::SAlignedTimeUnit(const TTimeUnit &inUnit)
+{
+ StaticAssert<sizeof(SAlignedTimeUnit) == sizeof(TTimeUnit)>::valid_expression();
+ qt3ds::intrinsics::memCopy(this, &inUnit, sizeof(TTimeUnit));
+}
+
+SAlignedTimeUnit::operator TTimeUnit() const
+{
+ TTimeUnit retval;
+ qt3ds::intrinsics::memCopy(&retval, this, sizeof(TTimeUnit));
+ return retval;
+}
+
+void SAlignedTimeUnit::operator-=(const TTimeUnit &inTime)
+{
+ TTimeUnit theThis(*this);
+ theThis -= inTime;
+ *this = SAlignedTimeUnit(theThis);
+}
+
+void SAlignedTimeUnit::operator%=(const TTimeUnit &inTime)
+{
+ TTimeUnit theThis(*this);
+ theThis %= inTime;
+ *this = SAlignedTimeUnit(theThis);
+}
+
+//==============================================================================
+/**
+ * Initialization
+ */
+
+void CTimePolicy::Initialize(const TTimeUnit inLoopingDuration, TimePolicyModes::Enum inMode)
+{
+ m_LocalTime = 0;
+ m_LoopingDuration = (unsigned long)inLoopingDuration;
+ m_TimePolicyMode = inMode;
+ m_Offset = 0;
+ m_Paused = false;
+ m_OffsetInvalid = 1;
+ m_Backward = 0;
+ m_Rate = 1.0f;
+}
+
+void CTimePolicy::Initialize(const TTimeUnit inLoopingDuration /*= FOREVER*/,
+ UINT32 inRepetitions /*= 1*/, BOOL inPingPong /*= false*/)
+{
+ // UINT8 m_Repetitions : 2; ///< Number of traversal ( 0 = forever, 1 = stop at end, 2 =
+ // ping )
+ TimePolicyModes::Enum theMode = TimePolicyModes::StopAtEnd;
+ if (inRepetitions == 1)
+ theMode = TimePolicyModes::StopAtEnd;
+ else if (inRepetitions == 0) {
+ if (inPingPong)
+ theMode = TimePolicyModes::PingPong;
+ else
+ theMode = TimePolicyModes::Looping;
+ } else
+ theMode = TimePolicyModes::Ping;
+
+ Initialize(inLoopingDuration, theMode);
+}
+
+//==============================================================================
+/**
+ * Return the last computed time. This is subjected to playmodes.
+ * @return local time
+ */
+TTimeUnit CTimePolicy::InternalGetTime() const
+{
+ if (m_LocalTime < m_LoopingDuration)
+ return m_LocalTime;
+ else {
+ if (m_LoopingDuration == 0)
+ return m_LocalTime;
+
+ switch (m_TimePolicyMode) {
+ case TimePolicyModes::StopAtEnd:
+ return m_LoopingDuration;
+ case TimePolicyModes::Looping:
+ return m_LocalTime % m_LoopingDuration;
+ case TimePolicyModes::Ping: {
+ unsigned long interval = m_LocalTime / m_LoopingDuration;
+ unsigned long leftover = m_LocalTime % m_LoopingDuration;
+ if (interval == 1)
+ return m_LoopingDuration - leftover;
+ return 0;
+ }
+ case TimePolicyModes::PingPong: {
+ unsigned long interval = m_LocalTime / m_LoopingDuration;
+ unsigned long leftover = m_LocalTime % m_LoopingDuration;
+ if (interval % 2)
+ return m_LoopingDuration - leftover;
+ return leftover;
+ }
+ default:
+ QT3DS_ASSERT(false);
+ return 0;
+ break;
+ }
+ }
+}
+
+TTimeUnit CTimePolicy::GetTime() const
+{
+ TTimeUnit retval = InternalGetTime();
+ // Apply direction and rate.
+ bool isPlayingBack = m_Backward;
+ if (m_Rate < 0)
+ isPlayingBack = !isPlayingBack;
+
+ if (isPlayingBack)
+ retval = m_LoopingDuration - retval;
+ return retval;
+}
+
+static unsigned long clampTime(long inTime, unsigned long inDuration)
+{
+ if (inTime < 0)
+ return 0;
+ if (inTime > (long)inDuration)
+ return inDuration;
+ return (unsigned long)inTime;
+}
+
+//==============================================================================
+/**
+ * Trigger the policy to return inTime next GetTime is called.
+ * This is tricky math and the m_Offset field is being used both normally to
+ * simply change the time and here to calibrate itself next time ComputeTime
+ * is called.
+ * @param inTime time to be returned next ComputeTime
+ */
+void CTimePolicy::SetTime(TTimeUnit inTime)
+{
+
+ bool isPlayingBack = m_Backward;
+ if (m_Rate < 0)
+ isPlayingBack = !isPlayingBack;
+
+ if (isPlayingBack)
+ inTime = m_LoopingDuration - inTime;
+
+ m_OffsetInvalid = 1;
+
+ // Setup m_LocalTime such that it reflects intime.
+ if (m_LoopingDuration == 0) {
+ m_LocalTime = (unsigned long)inTime;
+ return;
+ }
+
+ switch (m_TimePolicyMode) {
+ case TimePolicyModes::StopAtEnd:
+ m_LocalTime = clampTime((long)inTime, m_LoopingDuration);
+ break;
+ case TimePolicyModes::Looping: {
+ long input = (long)inTime;
+ while (input < 0)
+ input += (long)m_LoopingDuration;
+ m_LocalTime = ((unsigned long)input) % m_LoopingDuration;
+ } break;
+ case TimePolicyModes::Ping: {
+ long input = (long)inTime;
+ if (input < 0)
+ input = 0;
+
+ long totalInterval = (long)(m_LoopingDuration * 2);
+ if (input > totalInterval)
+ m_LocalTime = (unsigned long)totalInterval;
+ else
+ m_LocalTime = (unsigned long)input;
+ } break;
+ case TimePolicyModes::PingPong: {
+ long totalInterval = (long)(m_LoopingDuration * 2);
+ long input = (long)inTime;
+ while (input < 0)
+ input += totalInterval;
+ m_LocalTime = (unsigned long)(input % totalInterval);
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ }
+}
+
+//==============================================================================
+/**
+ * Retrieves the looping duration.
+ * @see CTimePolicy::SetLoopingDuration( )
+ * @return TTimeUnit looping duration
+ */
+TTimeUnit CTimePolicy::GetLoopingDuration() const
+{
+ return m_LoopingDuration;
+}
+
+//==============================================================================
+/**
+ * Set the looping duration.
+ * Looping duration is defined as the time it takes before stopping, pinging or
+ * looping.
+ * @param inTime looping duration
+ */
+void CTimePolicy::SetLoopingDuration(const TTimeUnit inTime)
+{
+ m_LoopingDuration = (unsigned long)inTime;
+}
+
+//==============================================================================
+/**
+ * Return the paused state.
+ * @return BOOL pause state
+ */
+BOOL CTimePolicy::GetPaused() const
+{
+ return m_Paused;
+}
+
+BOOL CTimePolicy::GetPlayBackDirection() const
+{
+ bool reversePlaybackDirection = m_Backward;
+ if (m_Rate < 0)
+ reversePlaybackDirection = !reversePlaybackDirection;
+
+ bool retval = m_LocalTime < m_LoopingDuration;
+
+ if (reversePlaybackDirection)
+ retval = !retval;
+ return retval;
+}
+
+//==============================================================================
+/**
+ * Sets the paused state
+ * @param inPaused pause state
+ */
+void CTimePolicy::SetPaused(const BOOL inPaused)
+{
+ m_Paused = static_cast<UINT8>(inPaused);
+}
+
+BOOL CTimePolicy::UpdateTime(const TTimeUnit inTime)
+{
+ if (fabs(m_Rate) > .001f)
+ m_LocalTime =
+ static_cast<unsigned long>(((unsigned long)(inTime + m_Offset)) * fabs(m_Rate));
+ // else we are effectively stopped and we can't update the time.
+
+ if (m_LoopingDuration == 0)
+ return FALSE;
+
+ unsigned long maxUsefulDuration = m_LoopingDuration * 2;
+ BOOL retval = 0;
+ switch (m_TimePolicyMode) {
+ case TimePolicyModes::StopAtEnd:
+ if (m_LocalTime > m_LoopingDuration) {
+ retval = 1;
+ m_LocalTime = m_LoopingDuration;
+ }
+ break;
+ case TimePolicyModes::Looping:
+ m_LocalTime = m_LocalTime % m_LoopingDuration;
+ break;
+ case TimePolicyModes::Ping:
+ if (m_LocalTime > maxUsefulDuration) {
+ retval = 1;
+ m_LocalTime = maxUsefulDuration;
+ }
+ break;
+ case TimePolicyModes::PingPong:
+ m_LocalTime = m_LocalTime % maxUsefulDuration;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ return retval;
+}
+//==============================================================================
+/**
+ * Compute the local time based off the current global time and the settings
+ * such as duration, repetitions and ping-pong.
+ * @param inTime global time being fed
+ * @return BOOL true if policy has reached it's end time
+ */
+BOOL CTimePolicy::ComputeTime(const TTimeUnit inTime)
+{
+ // Return the last computed time if paused
+ if (m_Paused || m_OffsetInvalid) {
+ // m_LocalTime = inTime + m_Offset;
+ if (fabs(m_Rate) > .001)
+ m_Offset = (TTimeUnit)(m_LocalTime / fabs(m_Rate)) - inTime;
+ else // rate is zero, this should not happen.
+ m_Offset = (TTimeUnit)(m_LocalTime)-inTime;
+ m_OffsetInvalid = 0;
+ return false;
+ }
+ return UpdateTime(inTime);
+}
+
+eastl::pair<BOOL, TTimeUnit>
+SComponentTimePolicyOverride::ComputeLocalTime(CTimePolicy &inTimePolicy, TTimeUnit inGlobalTime)
+{
+ TTimeUnit retval = 0;
+ BOOL finished = FALSE;
+ if (inTimePolicy.m_Paused || inTimePolicy.m_OffsetInvalid) {
+ finished = inTimePolicy.ComputeTime(inGlobalTime);
+ } else {
+ Q3DStudio_ASSERT(m_EndTime <= inTimePolicy.GetLoopingDuration());
+ unsigned long newLocalTime = (unsigned long)(inGlobalTime + inTimePolicy.m_Offset);
+
+ float diff = static_cast<float>(newLocalTime - inTimePolicy.GetTime());
+ diff *= m_TimeMultiplier;
+ float updatedLocalTime = static_cast<float>(inTimePolicy.m_LocalTime) + diff;
+
+ if (updatedLocalTime < 0.0f)
+ updatedLocalTime = 0.0f;
+
+ inTimePolicy.m_LocalTime = static_cast<unsigned long>(updatedLocalTime);
+
+ bool runningBackwards = m_TimeMultiplier < 0;
+
+ if (runningBackwards) {
+ if (inTimePolicy.m_LocalTime <= m_EndTime) {
+ finished = TRUE;
+ inTimePolicy.m_LocalTime = (unsigned long)m_EndTime;
+ }
+ } else // running forwards
+ {
+ if (inTimePolicy.m_LocalTime >= m_EndTime) {
+ finished = TRUE;
+ inTimePolicy.m_LocalTime = (unsigned long)m_EndTime;
+ }
+ }
+ inTimePolicy.m_Offset = inTimePolicy.m_LocalTime - inGlobalTime;
+ }
+ retval = inTimePolicy.GetTime();
+ return eastl::make_pair(finished, retval);
+}
+
+void SComponentTimePolicyOverride::SetTime(CTimePolicy &inTimePolicy, TTimeUnit inLocalTime)
+{
+ if (inLocalTime < 0)
+ inLocalTime = 0;
+ if (m_TimeMultiplier < 0) {
+ if (inLocalTime <= m_EndTime) {
+ inLocalTime = m_EndTime;
+ }
+ } else // running forwards
+ {
+ if (inLocalTime >= m_EndTime) {
+ inLocalTime = m_EndTime;
+ }
+ }
+ inTimePolicy.SetTime(inLocalTime);
+}
+
+} // namespace Q3DStudio