1 #ifndef DALI_INTERNAL_KEY_FRAMES_H
2 #define DALI_INTERNAL_KEY_FRAMES_H
5 * Copyright (c) 2021 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.
25 #include <dali/internal/event/animation/key-frame-channel.h>
26 #include <dali/public-api/animation/alpha-function.h>
27 #include <dali/public-api/animation/key-frames.h>
28 #include <dali/public-api/common/vector-wrapper.h>
29 #include <dali/public-api/object/base-object.h>
39 * KeyFrames class is responsible for creating and building a specialized KeyFrame class
40 * from the Property::Value type used in Add.
42 class KeyFrames : public BaseObject
45 static KeyFrames* New();
49 * Create a specialization from the given type, and store it to the mSpec
52 void CreateKeyFramesSpec(Property::Type type);
56 * Get the type of this key frame.
57 * An empty key frame will return Property::NONE, wheras an initialised
58 * key frame object will return the type of it's first element.
59 * @return the Property::Type of the key frame values
61 Property::Type GetType() const;
64 * Add a key frame. The first key frame to be added denotes the type
65 * of all subsequent key frames. If a value with a different type is
66 * added, it will throw a run time assert.
67 * @param[in] time The time (between 0 and 1)
68 * @param[in] value The value of the keyframe at the given time
69 * @param[in] alpha An alpha function to blend between this key frame and the
72 void Add(float time, const Property::Value& value, AlphaFunction alpha);
75 * Return the key frames without specialization. The GetSpecialization methods
76 * below will convert to the specialized objects.
78 KeyFrameSpec* GetKeyFramesBase() const;
81 * Return the value of the last key frame.
83 Dali::Property::Value GetLastKeyFrameValue() const;
86 * @copydoc Dali::DevelKeyFrames::GetKeyFrameCount()
88 std::size_t GetKeyFrameCount() const;
91 * @copydoc Dali::DevelKeyFrames::GetKeyFrame()
93 void GetKeyFrame(std::size_t index, float& time, Property::Value& value) const;
96 Dali::Property::Type mType{Property::NONE}; // Type of the specialization
97 std::unique_ptr<KeyFrameSpec> mKeyFrames; // Pointer to the specialized key frame object
101 * This is the base class for the individual template specializations, allowing a ptr to be
102 * stored in the handle object above.
107 virtual ~KeyFrameSpec() = default;
109 virtual std::size_t GetNumberOfKeyFrames() const = 0;
112 * Get the key frame value as a Property::Value.
113 * @param[in] index The index of the key frame to fetch
114 * @param[out] time The progress of the given key frame
115 * @param[out] value The value of the given key frame
117 virtual void GetKeyFrameAsValue(std::size_t index, float& time, Property::Value& value) const = 0;
121 * The base template class for each key frame specialization.
124 class KeyFrameBaseSpec : public KeyFrameSpec
126 KeyFrameChannel<V> mChannel; // The key frame channel
130 * Add a key frame to the channel. Key frames should be added
131 * in time order (this method does not sort the vector by time)
132 * @param[in] t - progress
133 * @param[in] v - value
134 * @param[in] alpha - Alpha function for blending to the next keyframe
136 void AddKeyFrame(float t, V v, AlphaFunction alpha)
138 mChannel.mValues.push_back({t, v});
142 * Get the number of key frames
143 * @return Channel size
145 std::size_t GetNumberOfKeyFrames() const override
147 return mChannel.mValues.size();
152 * @param[in] index The index of the key frame to fetch
153 * @param[out] time The progress of the given key frame
154 * @param[out] value The value of the given key frame
156 void GetKeyFrame(unsigned int index, float& time, V& value) const
158 DALI_ASSERT_ALWAYS(index < mChannel.mValues.size() && "KeyFrame index is out of bounds");
159 const auto& element = mChannel.mValues[index];
160 time = element.mProgress;
161 value = element.mValue;
165 * @copydoc KeyFrameSpec::GetKeyFrameAsValue()
167 void GetKeyFrameAsValue(std::size_t index, float& time, Property::Value& value) const override
169 const auto& element = mChannel.mValues[index];
170 time = element.mProgress;
171 value = element.mValue;
175 * Return whether the progress is valid for the range of keyframes. (The first
176 * keyframe doesn't have to start at 0, and the last doesn't have to end at 1.0)
177 * @param[in] progress The progress to test
178 * @return True if the progress is valid for this object
180 bool IsActive(float progress) const
182 return mChannel.IsActive(progress);
186 * Return an interpolated value for the given progress.
187 * @param[in] progress The progress to test
188 * @return The interpolated value
190 V GetValue(float progress, Dali::Animation::Interpolation interpolation) const
192 return mChannel.GetValue(progress, interpolation);
196 using KeyFrameNumber = KeyFrameBaseSpec<float>;
197 using KeyFrameBoolean = KeyFrameBaseSpec<bool>;
198 using KeyFrameInteger = KeyFrameBaseSpec<int>;
199 using KeyFrameVector2 = KeyFrameBaseSpec<Vector2>;
200 using KeyFrameVector3 = KeyFrameBaseSpec<Vector3>;
201 using KeyFrameVector4 = KeyFrameBaseSpec<Vector4>;
202 using KeyFrameQuaternion = KeyFrameBaseSpec<Quaternion>;
204 template<typename DeriveClass>
205 auto GetSpecialization(const Internal::KeyFrames& keyFrames)
207 return static_cast<DeriveClass>(keyFrames.GetKeyFramesBase());
210 } // namespace Internal
212 // Get impl of handle
213 inline Internal::KeyFrames& GetImplementation(Dali::KeyFrames& keyFrames)
215 DALI_ASSERT_ALWAYS(keyFrames && "KeyFrames handle is empty");
216 Dali::RefObject& object = keyFrames.GetBaseObject();
217 return static_cast<Internal::KeyFrames&>(object);
220 inline const Internal::KeyFrames& GetImplementation(const Dali::KeyFrames& keyFrames)
222 DALI_ASSERT_ALWAYS(keyFrames && "KeyFrames handle is empty");
223 const Dali::RefObject& object = keyFrames.GetBaseObject();
224 return static_cast<const Internal::KeyFrames&>(object);
229 #endif // DALI_INTERNAL_KEY_FRAMES_H