Merge "DALi Version 1.9.35" into devel/master
[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() = default;
45
46   KeyFrameChannelId GetId() const
47   {
48     return mChannelId;
49   }
50
51   virtual bool IsActive(float progress) = 0;
52
53 protected:
54   KeyFrameChannelId       mChannelId;
55 };
56
57
58 template <typename V>
59 class KeyFrameChannel : public KeyFrameChannelBase
60 {
61 public:
62   using ProgressValues = std::vector<ProgressValue<V> >;
63
64   KeyFrameChannel(KeyFrameChannelId channel_id, ProgressValues& values )
65   : KeyFrameChannelBase(channel_id),
66     mValues(values)
67   {
68   }
69
70   ~KeyFrameChannel() override = default;
71
72   bool IsActive (float progress) override;
73
74   V GetValue(float progress, Dali::Animation::Interpolation interpolation) const;
75
76   bool FindInterval(typename ProgressValues::iterator& start,
77                     typename ProgressValues::iterator& end,
78                     float progress) const;
79
80   ProgressValues& mValues;
81 };
82
83 template <class V>
84 bool KeyFrameChannel<V>::IsActive (float progress)
85 {
86   bool active = false;
87   if(!mValues.empty())
88   {
89     ProgressValue<V>& first = mValues.front();
90
91     if( progress >= first.GetProgress() )
92     {
93       active = true;
94     }
95   }
96   return active;
97 }
98
99 /**
100  * Use a linear search to find the interval containing progress
101  */
102 template <class V>
103 bool KeyFrameChannel<V>::FindInterval(
104   typename ProgressValues::iterator& start,
105   typename ProgressValues::iterator& end,
106   float progress) const
107 {
108   bool found = false;
109   typename std::vector<ProgressValue<V> >::iterator iter = mValues.begin();
110   typename std::vector<ProgressValue<V> >::iterator prevIter = iter;
111
112   while(iter != mValues.end() && iter->GetProgress() <= progress)
113   {
114     prevIter = iter;
115     ++iter;
116   }
117
118   if(iter == mValues.end())
119   {
120     --prevIter;
121     --iter;
122   }
123
124   if(prevIter->GetProgress() <= progress
125      &&
126      iter->GetProgress() > progress)
127   {
128     found = true;
129     start = prevIter;
130     end   = iter;
131   }
132
133   return found;
134 }
135
136 template <class V>
137 V KeyFrameChannel<V>::GetValue (float progress, Dali::Animation::Interpolation interpolation) const
138 {
139   ProgressValue<V>&  firstPV =  mValues.front();
140
141   typename std::vector<ProgressValue<V> >::iterator start;
142   typename std::vector<ProgressValue<V> >::iterator end;
143
144   V interpolatedV = firstPV.GetValue();
145   if(progress >= mValues.back().GetProgress() )
146   {
147     interpolatedV = mValues.back().GetValue(); // This should probably be last value...
148   }
149   else if(FindInterval(start, end, progress))
150   {
151     float frameProgress = (progress - start->GetProgress()) / (end->GetProgress() - start->GetProgress());
152
153     if( interpolation == Dali::Animation::LINEAR )
154     {
155       Interpolate(interpolatedV, start->GetValue(), end->GetValue(), frameProgress);
156     }
157     else
158     {
159       //Calculate prev and next values
160       V prev;
161       if( start != mValues.begin() )
162       {
163         prev = (start-1)->GetValue();
164       }
165       else
166       {
167         //Project next value through start point
168         prev = start->GetValue() + (start->GetValue()-(start+1)->GetValue());
169       }
170
171       V next;
172       if( end != mValues.end()-1)
173       {
174         next = (end+1)->GetValue();
175       }
176       else
177       {
178         //Project prev value through end point
179         next = end->GetValue() + (end->GetValue()-(end-1)->GetValue());
180       }
181
182       CubicInterpolate(interpolatedV, prev, start->GetValue(), end->GetValue(), next, frameProgress);
183     }
184   }
185
186   return interpolatedV;
187 }
188
189 using KeyFrameChannelNumber     = KeyFrameChannel<float>;
190 using KeyFrameChannelVector2    = KeyFrameChannel<Vector2>;
191 using KeyFrameChannelVector3    = KeyFrameChannel<Vector3>;
192 using KeyFrameChannelVector4    = KeyFrameChannel<Vector4>;
193 using KeyFrameChannelQuaternion = KeyFrameChannel<Quaternion>;
194 using KeyFrameChannelAngleAxis  = KeyFrameChannel<AngleAxis>;
195
196 } // Internal
197 } // namespace Dali
198
199 #endif // DALI_INTERNAL_KEY_FRAME_CHANNEL_H