Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / animation-playlist.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
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
18 // CLASS HEADER
19 #include <dali/internal/event/animation/animation-playlist.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/internal/event/animation/animation-impl.h>
24 #include <dali/public-api/common/vector-wrapper.h>
25
26 namespace Dali
27 {
28 namespace Internal
29 {
30 AnimationPlaylist* AnimationPlaylist::New()
31 {
32   return new AnimationPlaylist();
33 }
34
35 AnimationPlaylist::AnimationPlaylist() = default;
36
37 AnimationPlaylist::~AnimationPlaylist() = default;
38
39 void AnimationPlaylist::AnimationCreated(Animation& animation)
40 {
41   mAnimations.PushBack(&animation);
42 }
43
44 void AnimationPlaylist::AnimationDestroyed(Animation& animation)
45 {
46   Dali::Vector<Animation*>::Iterator iter = std::find(mAnimations.Begin(), mAnimations.End(), &animation);
47   DALI_ASSERT_ALWAYS(iter != mAnimations.End() && "Animation not found");
48
49   mAnimations.Remove(iter);
50 }
51
52 void AnimationPlaylist::OnPlay(Animation& animation)
53 {
54   mPlaylist.push_back(Dali::Animation(&animation));
55 }
56
57 void AnimationPlaylist::OnClear(Animation& animation)
58 {
59   std::vector<Dali::Animation>::iterator iter = std::find(mPlaylist.begin(), mPlaylist.end(), Dali::Animation(&animation));
60   std::vector<Dali::Animation>::iterator last = mPlaylist.end();
61   if(iter != last)
62   {
63     --last;                  // move to real last
64     std::swap(*iter, *last); // swap
65     mPlaylist.resize(mPlaylist.size() - 1u);
66   }
67 }
68
69 void AnimationPlaylist::NotifyCompleted()
70 {
71   std::vector<Dali::Animation> finishedAnimations;
72
73   // Since animations can be unreferenced during the signal emissions, iterators into animationPointers may be invalidated.
74   // First copy and reference the finished animations, then emit signals
75   for(Dali::Vector<Animation*>::Iterator iter = mAnimations.Begin(); iter != mAnimations.End(); ++iter)
76   {
77     Animation* animation = *iter;
78
79     if(animation->HasFinished())
80     {
81       finishedAnimations.push_back(Dali::Animation(animation));
82
83       // The animation may be present in mPlaylist - remove if necessary
84       // Note that the animation "Finish" signal is emitted after Stop() has been called
85       std::vector<Dali::Animation>::iterator iter = std::find(mPlaylist.begin(), mPlaylist.end(), Dali::Animation(animation));
86       DALI_ASSERT_DEBUG(iter != mPlaylist.end());
87       mPlaylist.erase(iter);
88     }
89   }
90
91   // Now it's safe to emit the signals
92   for(std::vector<Dali::Animation>::iterator iter = finishedAnimations.begin(); iter != finishedAnimations.end(); ++iter)
93   {
94     Dali::Animation& handle = *iter;
95
96     GetImplementation(handle).EmitSignalFinish();
97   }
98 }
99
100 void AnimationPlaylist::NotifyProgressReached(const SceneGraph::Animation* sceneGraphAnimation)
101 {
102   std::vector<Dali::Animation> notifyProgressAnimations; // Will own animations until all emits have been done
103
104   for(Dali::Vector<Animation*>::Iterator iter = mAnimations.Begin(); iter != mAnimations.End(); ++iter)
105   {
106     Animation* animation = *iter;
107
108     if((animation->GetSceneObject()) == sceneGraphAnimation)
109     {
110       // Store handles to animations that need signals emitted in the case of an animation being cleared in-between emits
111       notifyProgressAnimations.push_back(Dali::Animation(animation));
112     }
113   }
114
115   for(std::vector<Dali::Animation>::iterator iter = notifyProgressAnimations.begin(); iter != notifyProgressAnimations.end(); ++iter)
116   {
117     Dali::Animation& handle = *iter;
118
119     GetImplementation(handle).EmitSignalProgressReached();
120   }
121 }
122
123 uint32_t AnimationPlaylist::GetAnimationCount()
124 {
125   return mAnimations.Size();
126 }
127
128 Dali::Animation AnimationPlaylist::GetAnimationAt(uint32_t index)
129 {
130   if(index >= mAnimations.Size())
131   {
132     DALI_LOG_ERROR("Animation index is out of bounds.\n");
133     return Dali::Animation();
134   }
135   return Dali::Animation(mAnimations[index]);
136 }
137
138 } // namespace Internal
139
140 } // namespace Dali