diff options
author | rachytski <siarhei.rachytski@gmail.com> | 2012-10-05 18:44:42 +0400 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 01:44:41 +0300 |
commit | 13b42462f946cd0912b25c91264975d8285a667b (patch) | |
tree | f9fec8ee8c596634f9002d69364ed5ea6d260ad7 /anim | |
parent | 63b732f8f92aaeb98a525bfdf2f8d7eef0331938 (diff) |
bug fixes for release.
Diffstat (limited to 'anim')
-rw-r--r-- | anim/angle_interpolation.cpp | 10 | ||||
-rw-r--r-- | anim/anyrect_interpolation.cpp | 69 | ||||
-rw-r--r-- | anim/anyrect_interpolation.hpp | 1 | ||||
-rw-r--r-- | anim/controller.cpp | 33 | ||||
-rw-r--r-- | anim/controller.hpp | 3 | ||||
-rw-r--r-- | anim/task.cpp | 51 | ||||
-rw-r--r-- | anim/task.hpp | 19 |
7 files changed, 145 insertions, 41 deletions
diff --git a/anim/angle_interpolation.cpp b/anim/angle_interpolation.cpp index 0d8ba70dfa..acb588cae6 100644 --- a/anim/angle_interpolation.cpp +++ b/anim/angle_interpolation.cpp @@ -1,6 +1,8 @@ #include "angle_interpolation.hpp" +#include "controller.hpp" #include "../geometry/angles.hpp" +#include "../base/logging.hpp" namespace anim { @@ -22,20 +24,21 @@ namespace anim void AngleInterpolation::OnStart(double ts) { m_startTime = ts; + m_outAngle = m_startAngle; Task::OnStart(ts); } void AngleInterpolation::OnStep(double ts) { + if (!IsRunning()) + return; + if (ts - m_startTime >= m_interval) { End(); return; } - if (!IsRunning()) - return; - double elapsedSec = ts - m_startTime; m_curAngle = m_outAngle = m_startAngle + m_dist * elapsedSec / m_interval; @@ -56,6 +59,7 @@ namespace anim void AngleInterpolation::SetEndAngle(double val) { + m_startTime = GetController()->GetCurrentTime(); m_startAngle = m_curAngle; m_dist = ang::GetShortestDistance(m_startAngle, val); m_endAngle = m_startAngle + m_dist; diff --git a/anim/anyrect_interpolation.cpp b/anim/anyrect_interpolation.cpp index 74ca20eace..51565f1561 100644 --- a/anim/anyrect_interpolation.cpp +++ b/anim/anyrect_interpolation.cpp @@ -1,13 +1,15 @@ #include "anyrect_interpolation.hpp" +#include "../base/logging.hpp" + namespace anim { AnyRectInterpolation::AnyRectInterpolation(m2::AnyRectD const & startRect, m2::AnyRectD const & endRect, double rotationSpeed, m2::AnyRectD & outRect) - : m_interval(rotationSpeed * fabs(ang::GetShortestDistance(startRect.Angle().val(), - endRect.Angle().val())) / (2 * math::pi)), + : m_interval(max(0.5, rotationSpeed * fabs(ang::GetShortestDistance(startRect.Angle().val(), + endRect.Angle().val())) / (2 * math::pi))), m_angleInt(startRect.Angle().val(), endRect.Angle().val(), rotationSpeed, @@ -35,9 +37,16 @@ namespace anim m_startTime = ts; m_angleInt.OnStart(ts); + m_angleInt.Start(); + m_segmentInt.OnStart(ts); + m_segmentInt.Start(); + m_sizeXInt.OnStart(ts); + m_sizeXInt.Start(); + m_sizeYInt.OnStart(ts); + m_sizeYInt.Start(); m_outRect = m_startRect; @@ -46,34 +55,68 @@ namespace anim void AnyRectInterpolation::OnStep(double ts) { + if (!IsRunning()) + return; + if (ts - m_startTime >= m_interval) { End(); return; } - if (!IsRunning()) - return; + if (m_angleInt.IsRunning()) + m_angleInt.OnStep(ts); + + if (m_segmentInt.IsRunning()) + m_segmentInt.OnStep(ts); + + if (m_sizeXInt.IsRunning()) + m_sizeXInt.OnStep(ts); - m_angleInt.OnStep(ts); - m_segmentInt.OnStep(ts); - m_sizeXInt.OnStep(ts); - m_sizeYInt.OnStep(ts); + if (m_sizeYInt.IsRunning()) + m_sizeYInt.OnStep(ts); - m_outRect = m2::AnyRectD(m_curCenter, m_curAngle, m2::RectD(-m_curSizeX / 2, -m_curSizeY / 2, m_curSizeX / 2, m_curSizeY / 2)); + m_outRect = m2::AnyRectD(m_curCenter, + m_curAngle, + m2::RectD(-m_curSizeX / 2, -m_curSizeY / 2, + m_curSizeX / 2, m_curSizeY / 2)); anim::Task::OnStep(ts); } void AnyRectInterpolation::OnEnd(double ts) { - m_angleInt.OnEnd(ts); - m_segmentInt.OnEnd(ts); - m_sizeXInt.OnEnd(ts); - m_sizeYInt.OnEnd(ts); + if (m_angleInt.IsRunning()) + m_angleInt.OnEnd(ts); + + if (m_segmentInt.IsRunning()) + m_segmentInt.OnEnd(ts); + + if (m_sizeXInt.IsRunning()) + m_sizeXInt.OnEnd(ts); + + if (m_sizeYInt.IsRunning()) + m_sizeYInt.OnEnd(ts); m_outRect = m_endRect; anim::Task::OnEnd(ts); } + + void AnyRectInterpolation::OnCancel(double ts) + { + if (m_angleInt.IsRunning()) + m_angleInt.Cancel(); + + if (m_segmentInt.IsRunning()) + m_segmentInt.Cancel(); + + if (m_sizeXInt.IsRunning()) + m_sizeXInt.Cancel(); + + if (m_sizeYInt.IsRunning()) + m_sizeYInt.Cancel(); + + anim::Task::OnCancel(ts); + } } diff --git a/anim/anyrect_interpolation.hpp b/anim/anyrect_interpolation.hpp index 13df48c8db..9ba9272b0a 100644 --- a/anim/anyrect_interpolation.hpp +++ b/anim/anyrect_interpolation.hpp @@ -41,5 +41,6 @@ namespace anim void OnStart(double ts); void OnStep(double ts); void OnEnd(double ts); + void OnCancel(double ts); }; } diff --git a/anim/controller.cpp b/anim/controller.cpp index 3f217cf48c..2482a21370 100644 --- a/anim/controller.cpp +++ b/anim/controller.cpp @@ -20,6 +20,7 @@ namespace anim void Controller::AddTask(shared_ptr<Task> const & task) { + task->SetController(this); m_tasks.PushBack(task); m_IdleFrames = m_IdleThreshold; } @@ -30,6 +31,11 @@ namespace anim swap(from, to); } + void Controller::MergeTasks(TTasks & from, TTasks & to) + { + copy(from.begin(), from.end(), back_inserter(to)); + } + bool Controller::HasTasks() { return !m_tasks.Empty(); @@ -55,7 +61,7 @@ namespace anim { m_tasks.ProcessList(bind(&Controller::CopyAndClearTasks, _1, ref(m_tasksList))); - double ts = my::Timer::LocalTime(); + double ts = GetCurrentTime(); TTasks l; @@ -66,30 +72,43 @@ namespace anim m_IdleFrames = m_IdleThreshold; shared_ptr<Task> const & task = *it; - if (task->State() == Task::EStarted) + + task->Lock(); + + if (task->IsReady()) + { + task->Start(); task->OnStart(ts); - if (task->State() == Task::EInProgress) + } + if (task->IsRunning()) task->OnStep(ts); - if (task->State() == Task::EInProgress) + if (task->IsRunning()) l.push_back(task); else { - if (task->State() == Task::ECancelled) + if (task->IsCancelled()) task->OnCancel(ts); - if (task->State() == Task::EEnded) + if (task->IsEnded()) task->OnEnd(ts); } + + task->Unlock(); } if (!hasTasks && m_IdleFrames > 0) m_IdleFrames -= 1; - m_tasks.ProcessList(bind(&Controller::CopyAndClearTasks, ref(l), _1)); + m_tasks.ProcessList(bind(&Controller::MergeTasks, ref(l), _1)); } bool Controller::IsPreWarmed() const { return m_IdleFrames > 0; } + + double Controller::GetCurrentTime() const + { + return my::Timer::LocalTime(); + } } diff --git a/anim/controller.hpp b/anim/controller.hpp index ff8a66e863..398f191a4d 100644 --- a/anim/controller.hpp +++ b/anim/controller.hpp @@ -26,6 +26,7 @@ namespace anim int m_IdleFrames; static void CopyAndClearTasks(list<shared_ptr<Task> > & from, list<shared_ptr<Task> > & to); + static void MergeTasks(list<shared_ptr<Task> > & from, list<shared_ptr<Task> > & to); public: // Constructor @@ -53,5 +54,7 @@ namespace anim // interrupting rendering process, which might had happened in these // "frames-in-the-middle". bool IsPreWarmed() const; + // Getting current simulation time + double GetCurrentTime() const; }; } diff --git a/anim/task.cpp b/anim/task.cpp index b012ce2fc7..92a5c4b04e 100644 --- a/anim/task.cpp +++ b/anim/task.cpp @@ -1,9 +1,13 @@ #include "task.hpp" +#include "../std/bind.hpp" + +#include "../base/assert.hpp" + namespace anim { Task::Task() - : m_State(EStarted) + : m_State(EReady) {} Task::~Task() @@ -26,46 +30,50 @@ namespace anim void Task::SetState(EState State) { - Lock(); m_State = State; - Unlock(); } - void Task::PerformCallback(EState state) + void Task::PerformCallbacks(EState state) { - TCallback const & cb = m_Callbacks[state]; - if (cb) - cb(); + list<TCallback> const & cb = m_Callbacks[state]; + for_each(cb.begin(), cb.end(), bind(&TCallback::operator(), _1)); } void Task::OnStart(double ts) { - PerformCallback(EStarted); - SetState(EInProgress); + PerformCallbacks(EReady); } void Task::OnStep(double ts) { - PerformCallback(EInProgress); + PerformCallbacks(EInProgress); } void Task::OnCancel(double ts) { - PerformCallback(ECancelled); + PerformCallbacks(ECancelled); } void Task::OnEnd(double ts) { - PerformCallback(EEnded); + PerformCallbacks(EEnded); + } + + void Task::Start() + { + ASSERT(IsReady(), ()); + SetState(EInProgress); } void Task::Cancel() { + ASSERT(IsRunning() || IsReady(), ()); SetState(ECancelled); } void Task::End() { + ASSERT(IsRunning() || IsReady(), ()); SetState(EEnded); } @@ -84,8 +92,23 @@ namespace anim return State() == EInProgress; } - void Task::SetCallback(EState state, TCallback const & cb) + bool Task::IsReady() const + { + return State() == EReady; + } + + void Task::AddCallback(EState state, TCallback const & cb) + { + m_Callbacks[state].push_back(cb); + } + + void Task::SetController(Controller * controller) + { + m_controller = controller; + } + + Controller * Task::GetController() const { - m_Callbacks[state] = cb; + return m_controller; } } diff --git a/anim/task.hpp b/anim/task.hpp index d55c61d129..8cea0054dd 100644 --- a/anim/task.hpp +++ b/anim/task.hpp @@ -1,12 +1,15 @@ #pragma once #include "../std/map.hpp" +#include "../std/list.hpp" #include "../std/function.hpp" #include "../base/mutex.hpp" namespace anim { + class Controller; + // Interface for single animation task class Task { @@ -16,7 +19,7 @@ namespace anim enum EState { - EStarted, + EReady, EInProgress, ECancelled, EEnded @@ -26,21 +29,27 @@ namespace anim EState m_State; - map<EState, TCallback> m_Callbacks; + map<EState, list<TCallback> > m_Callbacks; - void PerformCallback(EState state); + void PerformCallbacks(EState state); threads::Mutex m_mutex; + Controller * m_controller; + protected: void SetState(EState state); + friend class Controller; + void SetController(Controller * controller); public: Task(); virtual ~Task(); + Controller * GetController() const; + EState State() const; virtual void OnStart(double ts); @@ -48,16 +57,18 @@ namespace anim virtual void OnEnd(double ts); virtual void OnCancel(double ts); + void Start(); void Cancel(); void End(); bool IsCancelled() const; bool IsEnded() const; bool IsRunning() const; + bool IsReady() const; void Lock(); void Unlock(); - void SetCallback(EState state, TCallback const & cb); + void AddCallback(EState state, TCallback const & cb); }; } |