1 #ifndef DALI_INTERNAL_KEY_FRAMES_H
2 #define DALI_INTERNAL_KEY_FRAMES_H
5 * Copyright (c) 2023 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 * @copydoc Dali::DevelKeyFrames::SetKeyFrameValue()
98 void SetKeyFrameValue(std::size_t index, const Property::Value& value);
101 Dali::Property::Type mType{Property::NONE}; // Type of the specialization
102 std::unique_ptr<KeyFrameSpec> mKeyFrames; // Pointer to the specialized key frame object
106 * This is the base class for the individual template specializations, allowing a ptr to be
107 * stored in the handle object above.
112 virtual ~KeyFrameSpec() = default;
114 virtual std::size_t GetNumberOfKeyFrames() const = 0;
117 * Get the key frame value as a Property::Value.
118 * @param[in] index The index of the key frame to fetch
119 * @param[out] time The progress of the given key frame
120 * @param[out] value The value of the given key frame
122 virtual void GetKeyFrameAsValue(std::size_t index, float& time, Property::Value& value) const = 0;
125 * Set the key frame value as a Property::Value.
126 * @param[in] index The index of the key frame to set
127 * @param[in] value The value of the given key frame
129 virtual void SetKeyFrameValue(std::size_t index, const Property::Value& value) = 0;
133 * The base template class for each key frame specialization.
136 class KeyFrameBaseSpec : public KeyFrameSpec
138 KeyFrameChannel<V> mChannel; // The key frame channel
142 * Add a key frame to the channel. Key frames should be added
143 * in time order (this method does not sort the vector by time)
144 * @param[in] t - progress
145 * @param[in] v - value
146 * @param[in] alpha - Alpha function for blending to the next keyframe
148 void AddKeyFrame(float t, V v, AlphaFunction alpha)
150 mChannel.mValues.push_back({t, v});
154 * Get the number of key frames
155 * @return Channel size
157 std::size_t GetNumberOfKeyFrames() const override
159 return mChannel.mValues.size();
164 * @param[in] index The index of the key frame to fetch
165 * @param[out] time The progress of the given key frame
166 * @param[out] value The value of the given key frame
168 void GetKeyFrame(unsigned int index, float& time, V& value) const
170 DALI_ASSERT_ALWAYS(index < mChannel.mValues.size() && "KeyFrame index is out of bounds");
171 const auto& element = mChannel.mValues[index];
172 time = element.mProgress;
173 value = element.mValue;
177 * @copydoc KeyFrameSpec::GetKeyFrameAsValue()
179 void GetKeyFrameAsValue(std::size_t index, float& time, Property::Value& value) const override
181 const auto& element = mChannel.mValues[index];
182 time = element.mProgress;
183 value = element.mValue;
187 * @copydoc KeyFrameSpec::SetKeyFrameValue()
189 void SetKeyFrameValue(std::size_t index, const Property::Value& value) override
191 auto& element = mChannel.mValues[index];
192 element.mValue = value.Get<V>();
196 * Return whether the progress is valid for the range of keyframes. (The first
197 * keyframe doesn't have to start at 0, and the last doesn't have to end at 1.0)
198 * @param[in] progress The progress to test
199 * @return True if the progress is valid for this object
201 bool IsActive(float progress) const
203 return mChannel.IsActive(progress);
207 * Return an interpolated value for the given progress.
208 * @param[in] progress The progress to test
209 * @return The interpolated value
211 V GetValue(float progress, Dali::Animation::Interpolation interpolation) const
213 return mChannel.GetValue(progress, interpolation);
217 using KeyFrameNumber = KeyFrameBaseSpec<float>;
218 using KeyFrameBoolean = KeyFrameBaseSpec<bool>;
219 using KeyFrameInteger = KeyFrameBaseSpec<int>;
220 using KeyFrameVector2 = KeyFrameBaseSpec<Vector2>;
221 using KeyFrameVector3 = KeyFrameBaseSpec<Vector3>;
222 using KeyFrameVector4 = KeyFrameBaseSpec<Vector4>;
223 using KeyFrameQuaternion = KeyFrameBaseSpec<Quaternion>;
225 template<typename DeriveClass>
226 auto GetSpecialization(const Internal::KeyFrames& keyFrames)
228 return static_cast<DeriveClass>(keyFrames.GetKeyFramesBase());
231 } // namespace Internal
233 // Get impl of handle
234 inline Internal::KeyFrames& GetImplementation(Dali::KeyFrames& keyFrames)
236 DALI_ASSERT_ALWAYS(keyFrames && "KeyFrames handle is empty");
237 Dali::RefObject& object = keyFrames.GetBaseObject();
238 return static_cast<Internal::KeyFrames&>(object);
241 inline const Internal::KeyFrames& GetImplementation(const Dali::KeyFrames& keyFrames)
243 DALI_ASSERT_ALWAYS(keyFrames && "KeyFrames handle is empty");
244 const Dali::RefObject& object = keyFrames.GetBaseObject();
245 return static_cast<const Internal::KeyFrames&>(object);
250 #endif // DALI_INTERNAL_KEY_FRAMES_H