1 #ifndef DALI_INTERNAL_KEY_FRAMES_H
2 #define DALI_INTERNAL_KEY_FRAMES_H
5 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <dali/public-api/common/vector-wrapper.h>
23 #include <dali/public-api/animation/key-frames.h>
24 #include <dali/public-api/object/base-object.h>
25 #include <dali/public-api/animation/alpha-function.h>
26 #include <dali/internal/event/animation/progress-value.h>
27 #include <dali/internal/event/animation/key-frame-channel.h>
35 using KeyFramesPtr = IntrusivePtr<KeyFrames>;
38 * KeyFrames class is responsible for creating and building a specialized KeyFrame class
39 * from the Property::Value type used in Add.
41 class KeyFrames : public BaseObject
44 static KeyFrames* New();
47 * Instantiate an empty KeyFrames object
52 ~KeyFrames() override;
56 * Don't allow copy constructor
58 KeyFrames(const KeyFrames& rhs);
61 * Don't allow copy operator
63 KeyFrames& operator=(const KeyFrames& rhs);
66 * Create a specialization from the given type, and store it to the mSpec
69 void CreateKeyFramesSpec(Property::Type type);
73 * Get the type of this key frame.
74 * An empty key frame will return Property::NONE, wheras an initialised
75 * key frame object will return the type of it's first element.
76 * @return the Property::Type of the key frame values
78 Property::Type GetType() const;
81 * Add a key frame. The first key frame to be added denotes the type
82 * of all subsequent key frames. If a value with a different type is
83 * added, it will throw a run time assert.
84 * @param[in] time The time (between 0 and 1)
85 * @param[in] value The value of the keyframe at the given time
86 * @param[in] alpha An alpha function to blend between this key frame and the
89 void Add(float time, Property::Value value, AlphaFunction alpha);
92 * Return the key frames without specialization. The GetSpecialization methods
93 * below will convert to the specialized objects.
95 KeyFrameSpec* GetKeyFramesBase() const;
98 * Return the value of the last key frame.
100 Dali::Property::Value GetLastKeyFrameValue() const;
103 Dali::Property::Type mType; // Type of the specialization
104 IntrusivePtr<KeyFrameSpec> mKeyFrames; // Pointer to the specialized key frame object
109 * This is the base class for the individual template specializations, allowing a ptr to be
110 * stored in the handle object above. It inherits from RefObject to allow smart pointers
111 * to be used for the specializations. Note that the derived template class below
112 * allows for a copy constructor so that the specialization object can be cloned before
113 * being passed to the scene-graph for animation.
115 class KeyFrameSpec : public RefObject
118 KeyFrameSpec() = default;
120 virtual std::size_t GetNumberOfKeyFrames() const = 0;
123 * Get the key frame value as a Property::Value.
124 * @param[in] index The index of the key frame to fetch
125 * @param[out] value The value of the given key frame
127 virtual void GetKeyFrameAsValue( std::size_t index, Property::Value& value ) = 0;
132 * A reference counted object may only be deleted by calling Unreference()
134 ~KeyFrameSpec() override = default;
139 * The base template class for each key frame specialization. It stores a vector of
140 * ProgressValue pairs in mPVs, and uses the existing interface for KeyFrameChannel
141 * to point at this vector.
144 class KeyFrameBaseSpec : public KeyFrameSpec
147 using PV = ProgressValue<V>;
148 using PVContainer = std::vector<PV>;
150 PVContainer mPVs; // The ProgressValue pairs
151 KeyFrameChannel<V>* mKeyFrames; // The key frame interpolator
154 static KeyFrameBaseSpec<V>* New()
156 return new KeyFrameBaseSpec<V>();
159 static KeyFrameBaseSpec<V>* Clone(const KeyFrameBaseSpec<V>& keyFrames)
161 return new KeyFrameBaseSpec<V>(keyFrames);
167 KeyFrameBaseSpec<V>()
169 mKeyFrames = new KeyFrameChannel<V>(KeyFrameChannelBase::Translate, mPVs);
175 * Allow cloning of this object
177 KeyFrameBaseSpec<V>(const KeyFrameBaseSpec<V>& keyFrames)
178 : mPVs(keyFrames.mPVs)
180 mKeyFrames = new KeyFrameChannel<V>(KeyFrameChannelBase::Translate, mPVs);
183 KeyFrameBaseSpec<V>& operator=( const KeyFrameBaseSpec<V>& keyFrames )
185 if( this != &keyFrames )
188 mPVs = keyFrames.mPVs;
190 mKeyFrames = new KeyFrameChannel<V>(KeyFrameChannelBase::Translate, mPVs);
196 * Destructor. Ensure progress value pairs are cleared down
198 ~KeyFrameBaseSpec<V>() override
206 * Add a key frame to the progress value vector. Key frames should be added
207 * in time order (this method does not sort the vector by time)
208 * @param[in] t - progress
209 * @param[in] v - value
210 * @param[in] alpha - Alpha function for blending to the next keyframe
212 void AddKeyFrame(float t, V v, AlphaFunction alpha)
214 mPVs.push_back(PV(t, v));
218 * Get the number of key frames
219 * @return The size of the progress value vector
221 std::size_t GetNumberOfKeyFrames() const override
228 * @param[in] index The index of the key frame to fetch
229 * @param[out] time The progress of the given key frame
230 * @param[out] value The value of the given key frame
232 virtual void GetKeyFrame(unsigned int index, float& time, V& value) const
234 DALI_ASSERT_ALWAYS( index < mPVs.size() && "KeyFrame index is out of bounds" );
235 time = mPVs[index].mProgress;
236 value = mPVs[index].mValue;
240 * @copydoc KeyFrameSpec::GetKeyFrameAsValue()
242 void GetKeyFrameAsValue( std::size_t index, Property::Value& value ) override
244 value = mPVs[index].mValue;
248 * Return whether the progress is valid for the range of keyframes. (The first
249 * keyframe doesn't have to start at 0, and the last doesn't have to end at 1.0)
250 * @param[in] progress The progress to test
251 * @return True if the progress is valid for this object
253 bool IsActive(float progress) const
255 return mKeyFrames->IsActive(progress);
259 * Return an interpolated value for the given progress.
260 * @param[in] progress The progress to test
261 * @return The interpolated value
263 V GetValue(float progress, Dali::Animation::Interpolation interpolation) const
265 return mKeyFrames->GetValue(progress, interpolation);
269 using KeyFrameNumber = KeyFrameBaseSpec<float>;
270 using KeyFrameBoolean = KeyFrameBaseSpec<bool>;
271 using KeyFrameInteger = KeyFrameBaseSpec<int>;
272 using KeyFrameVector2 = KeyFrameBaseSpec<Vector2>;
273 using KeyFrameVector3 = KeyFrameBaseSpec<Vector3>;
274 using KeyFrameVector4 = KeyFrameBaseSpec<Vector4>;
275 using KeyFrameQuaternion = KeyFrameBaseSpec<Quaternion>;
277 using KeyFrameBooleanPtr = IntrusivePtr<KeyFrameBoolean>;
278 using KeyFrameNumberPtr = IntrusivePtr<KeyFrameNumber>;
279 using KeyFrameIntegerPtr = IntrusivePtr<KeyFrameInteger>;
280 using KeyFrameVector2Ptr = IntrusivePtr<KeyFrameVector2>;
281 using KeyFrameVector3Ptr = IntrusivePtr<KeyFrameVector3>;
282 using KeyFrameVector4Ptr = IntrusivePtr<KeyFrameVector4>;
283 using KeyFrameQuaternionPtr = IntrusivePtr<KeyFrameQuaternion>;
285 inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameBoolean*& keyFrameSpec)
287 keyFrameSpec = static_cast<Internal::KeyFrameBoolean*>(keyFrames.GetKeyFramesBase());
290 inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameBoolean*& keyFrameSpec)
292 keyFrameSpec = static_cast<const Internal::KeyFrameBoolean*>(keyFrames.GetKeyFramesBase());
295 inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameNumber*& keyFrameSpec)
297 keyFrameSpec = static_cast<Internal::KeyFrameNumber*>(keyFrames.GetKeyFramesBase());
300 inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameNumber*& keyFrameSpec)
302 keyFrameSpec = static_cast<const Internal::KeyFrameNumber*>(keyFrames.GetKeyFramesBase());
305 inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameInteger*& keyFrameSpec)
307 keyFrameSpec = static_cast<Internal::KeyFrameInteger*>(keyFrames.GetKeyFramesBase());
310 inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameInteger*& keyFrameSpec)
312 keyFrameSpec = static_cast<const Internal::KeyFrameInteger*>(keyFrames.GetKeyFramesBase());
315 inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameVector2*& keyFrameSpec)
317 keyFrameSpec = static_cast<Internal::KeyFrameVector2*>(keyFrames.GetKeyFramesBase());
320 inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameVector2*& keyFrameSpec)
322 keyFrameSpec = static_cast<const Internal::KeyFrameVector2*>(keyFrames.GetKeyFramesBase());
325 inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameVector3*& keyFrameSpec)
327 keyFrameSpec = static_cast<Internal::KeyFrameVector3*>(keyFrames.GetKeyFramesBase());
330 inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameVector3*& keyFrameSpec)
332 keyFrameSpec = static_cast<const Internal::KeyFrameVector3*>(keyFrames.GetKeyFramesBase());
335 inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameVector4*& keyFrameSpec)
337 keyFrameSpec = static_cast<Internal::KeyFrameVector4*>(keyFrames.GetKeyFramesBase());
340 inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameVector4*& keyFrameSpec)
342 keyFrameSpec = static_cast<const Internal::KeyFrameVector4*>(keyFrames.GetKeyFramesBase());
345 inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameQuaternion*& keyFrameSpec)
347 keyFrameSpec = static_cast<Internal::KeyFrameQuaternion*>(keyFrames.GetKeyFramesBase());
350 inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameQuaternion*& keyFrameSpec)
352 keyFrameSpec = static_cast<const Internal::KeyFrameQuaternion*>(keyFrames.GetKeyFramesBase());
358 // Get impl of handle
359 inline Internal::KeyFrames& GetImplementation(Dali::KeyFrames& keyFrames)
361 DALI_ASSERT_ALWAYS( keyFrames && "KeyFrames handle is empty" );
362 Dali::RefObject& object = keyFrames.GetBaseObject();
363 return static_cast<Internal::KeyFrames&>(object);
366 inline const Internal::KeyFrames& GetImplementation(const Dali::KeyFrames& keyFrames)
368 DALI_ASSERT_ALWAYS( keyFrames && "KeyFrames handle is empty" );
369 const Dali::RefObject& object = keyFrames.GetBaseObject();
370 return static_cast<const Internal::KeyFrames&>(object);
376 #endif // DALI_INTERNAL_KEY_FRAMES_H