Revert "License conversion from Flora to Apache 2.0"
[platform/core/uifw/dali-core.git] / dali / internal / update / animation / scene-graph-animation.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 // CLASS HEADER
18 #include <dali/internal/update/animation/scene-graph-animation.h>
19
20 // EXTERNAL INCLUDES
21 #include <cmath> // fmod
22
23 // INTERNAL INCLUDES
24 #include <dali/internal/render/common/performance-monitor.h>
25
26 using namespace std;
27
28 namespace Dali
29 {
30
31 namespace Internal
32 {
33
34 namespace SceneGraph
35 {
36
37 float DefaultAlphaFunc(float progress)
38 {
39   return progress; // linear
40 }
41
42 Animation::Animation(float durationSeconds, bool isLooping, Dali::Animation::EndAction endAction, Dali::Animation::EndAction destroyAction)
43 : mDurationSeconds(durationSeconds),
44   mLooping(isLooping),
45   mEndAction(endAction),
46   mDestroyAction(destroyAction),
47   mState(Stopped),
48   mElapsedSeconds(0.0f),
49   mPlayCount(0)
50 {
51 }
52
53 Animation::~Animation()
54 {
55 }
56
57 void Animation::SetDuration(float durationSeconds)
58 {
59   DALI_ASSERT_DEBUG(durationSeconds > 0.0f);
60
61   mDurationSeconds = durationSeconds;
62 }
63
64 void Animation::SetLooping(bool looping)
65 {
66   mLooping = looping;
67 }
68
69 void Animation::SetEndAction(Dali::Animation::EndAction action)
70 {
71   mEndAction = action;
72 }
73
74 void Animation::SetDestroyAction(Dali::Animation::EndAction action)
75 {
76   mDestroyAction = action;
77 }
78
79 void Animation::Play()
80 {
81   mState = Playing;
82 }
83
84 void Animation::Pause()
85 {
86   if (mState == Playing)
87   {
88     mState = Paused;
89   }
90 }
91
92 bool Animation::Stop(BufferIndex bufferIndex)
93 {
94   bool animationFinished(false);
95
96   if (mState == Playing || mState == Paused)
97   {
98     animationFinished = true; // The actor-thread should be notified of this
99
100     if( mEndAction != Dali::Animation::Discard )
101     {
102       if( mEndAction == Dali::Animation::BakeFinal )
103       {
104         mElapsedSeconds = mDurationSeconds + Math::MACHINE_EPSILON_1; // Force animation to reach it's end
105       }
106       UpdateAnimators(bufferIndex, true/*bake the final result*/);
107     }
108
109     // The animation has now been played to completion
110     ++mPlayCount;
111   }
112
113   mElapsedSeconds = 0.0f;
114   mState = Stopped;
115
116   return animationFinished;
117 }
118
119 void Animation::OnDestroy(BufferIndex bufferIndex)
120 {
121   if (mState == Playing || mState == Paused)
122   {
123     if (mDestroyAction != Dali::Animation::Discard)
124     {
125       UpdateAnimators(bufferIndex, true/*bake the final result*/);
126     }
127   }
128
129   mState = Destroyed;
130 }
131
132 void Animation::AddAnimator( AnimatorBase* animator, PropertyOwner* propertyOwner )
133 {
134   animator->Attach( propertyOwner );
135
136   mAnimators.PushBack( animator );
137 }
138
139 bool Animation::Update(BufferIndex bufferIndex, float elapsedSeconds)
140 {
141   if (mState == Stopped || mState == Destroyed)
142   {
143     // Short circuit when animation isn't running
144     return false;
145   }
146
147   // The animation must still be applied when Paused/Stopping
148   if (mState == Playing)
149   {
150     mElapsedSeconds += elapsedSeconds;
151   }
152
153   if (mLooping)
154   {
155     if (mElapsedSeconds > mDurationSeconds)
156     {
157       mElapsedSeconds = fmod(mElapsedSeconds, mDurationSeconds);
158     }
159   }
160
161   const bool animationFinished(mState == Playing && mElapsedSeconds > mDurationSeconds);
162
163   UpdateAnimators(bufferIndex, animationFinished && (mEndAction != Dali::Animation::Discard));
164
165   if (animationFinished)
166   {
167     // The animation has now been played to completion
168     ++mPlayCount;
169
170     mElapsedSeconds = 0.0f;
171     mState = Stopped;
172   }
173
174   return animationFinished;
175 }
176
177 void Animation::UpdateAnimators(BufferIndex bufferIndex, bool bake)
178 {
179   for ( AnimatorIter iter = mAnimators.Begin(); iter != mAnimators.End(); )
180   {
181     // If an animator is not successfully applied, then it has been orphaned
182     bool applied(true);
183
184     AnimatorBase *animator = *iter;
185     const float initialDelay(animator->GetInitialDelay());
186
187     if (mElapsedSeconds >= initialDelay)
188     {
189       // Calculate a progress specific to each individual animator
190       float progress(1.0f);
191       const float animatorDuration = animator->GetDuration();
192       if (animatorDuration > 0.0f) // animators can be "immediate"
193       {
194         progress = min(1.0f, (mElapsedSeconds - initialDelay) / animatorDuration);
195       }
196
197       applied = animator->Update(bufferIndex, progress, bake);
198     }
199
200     // Animators are automatically removed, when orphaned from animatable scene objects.
201     if (!applied)
202     {
203       iter = mAnimators.Erase(iter);
204     }
205     else
206     {
207       ++iter;
208
209       INCREASE_COUNTER(PerformanceMonitor::ANIMATORS_APPLIED);
210     }
211   }
212 }
213
214 } // namespace SceneGraph
215
216 } // namespace Internal
217
218 } // namespace Dali