Merge remote-tracking branch 'origin/tizen' into new_text
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / key-frame-channel.h
1 #ifndef __DALI_INTERNAL_KEY_FRAME_CHANNEL_H__
2 #define __DALI_INTERNAL_KEY_FRAME_CHANNEL_H__
3
4 /*
5  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/event/animation/progress-value.h>
23 #include <dali/public-api/animation/animation.h>
24 #include <dali/public-api/common/vector-wrapper.h>
25
26 namespace Dali
27 {
28 namespace Internal
29 {
30
31 class KeyFrameChannelBase
32 {
33 public:
34   enum KeyFrameChannelId
35   {
36     Translate, Rotate, Scale,
37   };
38
39   KeyFrameChannelBase(KeyFrameChannelId channel_id)
40   : mChannelId(channel_id)
41   {
42   }
43
44   virtual ~KeyFrameChannelBase()
45   {
46   }
47
48   KeyFrameChannelId GetId() const
49   {
50     return mChannelId;
51   }
52
53   virtual bool IsActive(float progress) = 0;
54
55 protected:
56   KeyFrameChannelId       mChannelId;
57 };
58
59
60 template <typename V>
61 class KeyFrameChannel : public KeyFrameChannelBase
62 {
63 public:
64   typedef std::vector<ProgressValue<V> > ProgressValues;
65
66   KeyFrameChannel(KeyFrameChannelId channel_id, ProgressValues& values )
67   : KeyFrameChannelBase(channel_id),
68     mValues(values)
69   {
70   }
71
72
73   virtual ~KeyFrameChannel()
74   {
75   }
76
77   bool IsActive (float progress);
78
79   V GetValue(float progress, Dali::Animation::Interpolation interpolation) const;
80
81   bool FindInterval(typename ProgressValues::iterator& start,
82                     typename ProgressValues::iterator& end,
83                     float progress) const;
84
85   ProgressValues& mValues;
86 };
87
88 template <class V>
89 bool KeyFrameChannel<V>::IsActive (float progress)
90 {
91   bool active = false;
92   if(!mValues.empty())
93   {
94     ProgressValue<V>& first = mValues.front();
95
96     if( progress >= first.GetProgress() )
97     {
98       active = true;
99     }
100   }
101   return active;
102 }
103
104 /**
105  * Use a linear search to find the interval containing progress
106  * TODO: Use binary search instead
107  */
108 template <class V>
109 bool KeyFrameChannel<V>::FindInterval(
110   typename ProgressValues::iterator& start,
111   typename ProgressValues::iterator& end,
112   float progress) const
113 {
114   bool found = false;
115   typename std::vector<ProgressValue<V> >::iterator iter = mValues.begin();
116   typename std::vector<ProgressValue<V> >::iterator prevIter = iter;
117
118   while(iter != mValues.end() && iter->GetProgress() <= progress)
119   {
120     prevIter = iter;
121     ++iter;
122   }
123
124   if(iter == mValues.end())
125   {
126     --prevIter;
127     --iter;
128   }
129
130   if(prevIter->GetProgress() <= progress
131      &&
132      iter->GetProgress() > progress)
133   {
134     found = true;
135     start = prevIter;
136     end   = iter;
137   }
138
139   return found;
140 }
141
142 template <class V>
143 V KeyFrameChannel<V>::GetValue (float progress, Dali::Animation::Interpolation interpolation) const
144 {
145   ProgressValue<V>&  firstPV =  mValues.front();
146
147   typename std::vector<ProgressValue<V> >::iterator start;
148   typename std::vector<ProgressValue<V> >::iterator end;
149
150   V interpolatedV = firstPV.GetValue();
151   if(progress >= mValues.back().GetProgress() )
152   {
153     interpolatedV = mValues.back().GetValue(); // This should probably be last value...
154   }
155   else if(FindInterval(start, end, progress))
156   {
157     float frameProgress = (progress - start->GetProgress()) / (end->GetProgress() - start->GetProgress());
158
159     if( interpolation == Dali::Animation::Linear )
160     {
161       Interpolate(interpolatedV, start->GetValue(), end->GetValue(), frameProgress);
162     }
163     else
164     {
165       //Calculate prev and next values
166       V prev;
167       if( start != mValues.begin() )
168       {
169         prev = (start-1)->GetValue();
170       }
171       else
172       {
173         //Project next value through start point
174         prev = start->GetValue() + (start->GetValue()-(start+1)->GetValue());
175       }
176
177       V next;
178       if( end != mValues.end()-1)
179       {
180         next = (end+1)->GetValue();
181       }
182       else
183       {
184         //Project prev value through end point
185         next = end->GetValue() + (end->GetValue()-(end-1)->GetValue());
186       }
187
188       CubicInterpolate(interpolatedV, prev, start->GetValue(), end->GetValue(), next, frameProgress);
189     }
190   }
191
192   return interpolatedV;
193 }
194
195 typedef KeyFrameChannel<float>      KeyFrameChannelNumber;
196 typedef KeyFrameChannel<Vector2>    KeyFrameChannelVector2;
197 typedef KeyFrameChannel<Vector3>    KeyFrameChannelVector3;
198 typedef KeyFrameChannel<Vector4>    KeyFrameChannelVector4;
199 typedef KeyFrameChannel<Quaternion> KeyFrameChannelQuaternion;
200 typedef KeyFrameChannel<AngleAxis>  KeyFrameChannelAngleAxis;
201
202
203 } // Internal
204 } // namespace Dali
205
206 #endif // __DALI_INTERNAL_KEY_FRAME_CHANNEL_H__