Use modern construct 'using' instead of typedef.
[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) 2019 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   using ProgressValues = std::vector<ProgressValue<V> >;
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  */
107 template <class V>
108 bool KeyFrameChannel<V>::FindInterval(
109   typename ProgressValues::iterator& start,
110   typename ProgressValues::iterator& end,
111   float progress) const
112 {
113   bool found = false;
114   typename std::vector<ProgressValue<V> >::iterator iter = mValues.begin();
115   typename std::vector<ProgressValue<V> >::iterator prevIter = iter;
116
117   while(iter != mValues.end() && iter->GetProgress() <= progress)
118   {
119     prevIter = iter;
120     ++iter;
121   }
122
123   if(iter == mValues.end())
124   {
125     --prevIter;
126     --iter;
127   }
128
129   if(prevIter->GetProgress() <= progress
130      &&
131      iter->GetProgress() > progress)
132   {
133     found = true;
134     start = prevIter;
135     end   = iter;
136   }
137
138   return found;
139 }
140
141 template <class V>
142 V KeyFrameChannel<V>::GetValue (float progress, Dali::Animation::Interpolation interpolation) const
143 {
144   ProgressValue<V>&  firstPV =  mValues.front();
145
146   typename std::vector<ProgressValue<V> >::iterator start;
147   typename std::vector<ProgressValue<V> >::iterator end;
148
149   V interpolatedV = firstPV.GetValue();
150   if(progress >= mValues.back().GetProgress() )
151   {
152     interpolatedV = mValues.back().GetValue(); // This should probably be last value...
153   }
154   else if(FindInterval(start, end, progress))
155   {
156     float frameProgress = (progress - start->GetProgress()) / (end->GetProgress() - start->GetProgress());
157
158     if( interpolation == Dali::Animation::LINEAR )
159     {
160       Interpolate(interpolatedV, start->GetValue(), end->GetValue(), frameProgress);
161     }
162     else
163     {
164       //Calculate prev and next values
165       V prev;
166       if( start != mValues.begin() )
167       {
168         prev = (start-1)->GetValue();
169       }
170       else
171       {
172         //Project next value through start point
173         prev = start->GetValue() + (start->GetValue()-(start+1)->GetValue());
174       }
175
176       V next;
177       if( end != mValues.end()-1)
178       {
179         next = (end+1)->GetValue();
180       }
181       else
182       {
183         //Project prev value through end point
184         next = end->GetValue() + (end->GetValue()-(end-1)->GetValue());
185       }
186
187       CubicInterpolate(interpolatedV, prev, start->GetValue(), end->GetValue(), next, frameProgress);
188     }
189   }
190
191   return interpolatedV;
192 }
193
194 using KeyFrameChannelNumber     = KeyFrameChannel<float>;
195 using KeyFrameChannelVector2    = KeyFrameChannel<Vector2>;
196 using KeyFrameChannelVector3    = KeyFrameChannel<Vector3>;
197 using KeyFrameChannelVector4    = KeyFrameChannel<Vector4>;
198 using KeyFrameChannelQuaternion = KeyFrameChannel<Quaternion>;
199 using KeyFrameChannelAngleAxis  = KeyFrameChannel<AngleAxis>;
200
201 } // Internal
202 } // namespace Dali
203
204 #endif // DALI_INTERNAL_KEY_FRAME_CHANNEL_H