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 Dali::Property::Type mType{Property::NONE}; // Type of the specialization
87 std::unique_ptr<KeyFrameSpec> mKeyFrames; // Pointer to the specialized key frame object
91 * This is the base class for the individual template specializations, allowing a ptr to be
92 * stored in the handle object above.
97 virtual ~KeyFrameSpec() = default;
99 virtual std::size_t GetNumberOfKeyFrames() const = 0;
102 * Get the key frame value as a Property::Value.
103 * @param[in] index The index of the key frame to fetch
104 * @param[out] value The value of the given key frame
106 virtual void GetKeyFrameAsValue(std::size_t index, Property::Value& value) = 0;
110 * The base template class for each key frame specialization.
113 class KeyFrameBaseSpec : public KeyFrameSpec
115 KeyFrameChannel<V> mChannel; // The key frame channel
119 * Add a key frame to the channel. Key frames should be added
120 * in time order (this method does not sort the vector by time)
121 * @param[in] t - progress
122 * @param[in] v - value
123 * @param[in] alpha - Alpha function for blending to the next keyframe
125 void AddKeyFrame(float t, V v, AlphaFunction alpha)
127 mChannel.mValues.push_back({t, v});
131 * Get the number of key frames
132 * @return Channel size
134 std::size_t GetNumberOfKeyFrames() const override
136 return mChannel.mValues.size();
141 * @param[in] index The index of the key frame to fetch
142 * @param[out] time The progress of the given key frame
143 * @param[out] value The value of the given key frame
145 void GetKeyFrame(unsigned int index, float& time, V& value) const
147 DALI_ASSERT_ALWAYS(index < mChannel.mValues.size() && "KeyFrame index is out of bounds");
148 const auto& element = mChannel.mValues[index];
149 time = element.mProgress;
150 value = element.mValue;
154 * @copydoc KeyFrameSpec::GetKeyFrameAsValue()
156 void GetKeyFrameAsValue(std::size_t index, Property::Value& value) override
158 value = mChannel.mValues[index].mValue;
162 * Return whether the progress is valid for the range of keyframes. (The first
163 * keyframe doesn't have to start at 0, and the last doesn't have to end at 1.0)
164 * @param[in] progress The progress to test
165 * @return True if the progress is valid for this object
167 bool IsActive(float progress) const
169 return mChannel.IsActive(progress);
173 * Return an interpolated value for the given progress.
174 * @param[in] progress The progress to test
175 * @return The interpolated value
177 V GetValue(float progress, Dali::Animation::Interpolation interpolation) const
179 return mChannel.GetValue(progress, interpolation);
183 using KeyFrameNumber = KeyFrameBaseSpec<float>;
184 using KeyFrameBoolean = KeyFrameBaseSpec<bool>;
185 using KeyFrameInteger = KeyFrameBaseSpec<int>;
186 using KeyFrameVector2 = KeyFrameBaseSpec<Vector2>;
187 using KeyFrameVector3 = KeyFrameBaseSpec<Vector3>;
188 using KeyFrameVector4 = KeyFrameBaseSpec<Vector4>;
189 using KeyFrameQuaternion = KeyFrameBaseSpec<Quaternion>;
191 template<typename DeriveClass>
192 auto GetSpecialization(const Internal::KeyFrames& keyFrames)
194 return static_cast<DeriveClass>(keyFrames.GetKeyFramesBase());
197 } // namespace Internal
199 // Get impl of handle
200 inline Internal::KeyFrames& GetImplementation(Dali::KeyFrames& keyFrames)
202 DALI_ASSERT_ALWAYS(keyFrames && "KeyFrames handle is empty");
203 Dali::RefObject& object = keyFrames.GetBaseObject();
204 return static_cast<Internal::KeyFrames&>(object);
207 inline const Internal::KeyFrames& GetImplementation(const Dali::KeyFrames& keyFrames)
209 DALI_ASSERT_ALWAYS(keyFrames && "KeyFrames handle is empty");
210 const Dali::RefObject& object = keyFrames.GetBaseObject();
211 return static_cast<const Internal::KeyFrames&>(object);
216 #endif // DALI_INTERNAL_KEY_FRAMES_H