Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / path-constrainer-impl.h
1 #ifndef DALI_INTERNAL_PATH_CONSTRAINER_H
2 #define DALI_INTERNAL_PATH_CONSTRAINER_H
3
4 /*
5  * Copyright (c) 2021 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/devel-api/animation/path-constrainer.h>
23 #include <dali/internal/event/animation/constrainer.h>
24 #include <dali/internal/event/animation/path-impl.h>
25 #include <dali/public-api/math/math-utils.h>
26
27 namespace Dali
28 {
29 namespace Internal
30 {
31 typedef IntrusivePtr<PathConstrainer> PathConstrainerPtr;
32
33 /**
34  * @brief Constraint functor to constraint properties to paths.
35  *
36  * Vector3 properties will be constrained to the position of the path and
37  * Rotation properties will be constrained to follow the tangent of the path
38  * given a forward vector in object's local space.
39  */
40 struct PathConstraintFunctor
41 {
42   /**
43    * @brief Constructor.
44    *
45    * @param[in] path The path used in the constraint
46    * @param[in] range The range of values in the input property which will be mapped to [0,1]
47    * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
48    */
49   PathConstraintFunctor(PathPtr path, const Vector2& range, const Vector2& wrap)
50   : mPath(path),
51     mRange(range),
52     mWrap(wrap)
53   {
54   }
55
56   /**
57    * @brief Constructor.
58    *
59    * @param[in] path The path used in the constraint
60    * @param[in] range The range of values in the input property which will be mapped to 0..1
61    * @param[in] forward Vector in object space which will be aligned with the tangent of the path
62    * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
63    */
64   PathConstraintFunctor(PathPtr path, const Vector2& range, const Vector3& forward, const Vector2& wrap)
65   : mPath(path),
66     mForward(forward),
67     mRange(range),
68     mWrap(wrap)
69   {
70   }
71
72   /**
73    * @brief Functor operator for Vector3 properties
74    *
75    * @param[in,out] position Current value of the property
76    * @param[in]     inputs Contains the input property used as the parameter for the path
77    *
78    * @return The position of the path at the given parameter.
79    */
80   void operator()(Vector3&                      position,
81                   const PropertyInputContainer& inputs)
82   {
83     float inputWrapped = inputs[0]->GetFloat();
84     if(inputWrapped < mWrap.x || inputWrapped > mWrap.y)
85     {
86       inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y);
87     }
88
89     float t = (inputWrapped - mRange.x) / (mRange.y - mRange.x);
90
91     Vector3 tangent;
92     mPath->Sample(t, position, tangent);
93   }
94
95   /**
96    * @brief Functor operator for Quaternion properties
97    *
98    * @param[in,out] current Current value of the property
99    * @param[in]     inputs Contains the input property used as the parameter for the path
100    *
101    * @return The rotation which will align the forward vector and the tangent of the path at the given parameter.
102    */
103   void operator()(Quaternion&                   current,
104                   const PropertyInputContainer& inputs)
105   {
106     float inputWrapped = inputs[0]->GetFloat();
107     if(inputWrapped < mWrap.x || inputWrapped > mWrap.y)
108     {
109       inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y);
110     }
111
112     float t = (inputWrapped - mRange.x) / (mRange.y - mRange.x);
113
114     Vector3 position, tangent;
115     mPath->Sample(t, position, tangent);
116     current = Quaternion(mForward, tangent);
117   }
118
119   PathPtr mPath;    ///< The path used
120   Vector3 mForward; ///< Vector in object space which will be aligned with the tangent of the path
121   Vector2 mRange;   ///< The range of values in the input property which will be mapped to 0..1
122   Vector2 mWrap;    ///< Wrapping domain. Input property will be wrapped in this domain before being mapped to [0,1]
123 };
124
125 /**
126  * @brief A PathConstrainer used to constraint properties to a path
127  */
128 class PathConstrainer : public Constrainer
129 {
130 public:
131   /**
132    * Create a new PathConstrainer
133    * @return A smart-pointer to the newly allocated PathConstrainer.
134    */
135   static PathConstrainer* New();
136
137 protected:
138   /**
139    * virtual destructor
140    */
141   ~PathConstrainer() override;
142
143 private:
144   /**
145    * @copydoc Dali::Internal::Object::SetDefaultProperty()
146    */
147   void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue) override;
148
149   /**
150    * @copydoc Dali::Internal::Object::GetDefaultProperty()
151    */
152   Property::Value GetDefaultProperty(Property::Index index) const override;
153
154   /**
155   * @copydoc Dali::Internal::Object::GetDefaultPropertyCurrentValue()
156   */
157   Property::Value GetDefaultPropertyCurrentValue(Property::Index index) const override;
158
159 public:
160   /**
161    * @copydoc Dali::PathConstrainer::Apply
162    */
163   void Apply(Property target, Property source, const Vector2& range, const Vector2& wrap) override;
164
165 private:
166   //Constructor
167   PathConstrainer();
168
169   // Undefined
170   PathConstrainer(const PathConstrainer&);
171
172   // Undefined
173   PathConstrainer& operator=(const PathConstrainer& rhs);
174
175   PathPtr mPath;    ///< The path used in the constraints
176   Vector3 mForward; ///< Vector in object space which will be aligned with the tangent of the path
177 };
178
179 } // namespace Internal
180
181 // Get impl of handle
182 inline Internal::PathConstrainer& GetImplementation(Dali::PathConstrainer& pathConstrainer)
183 {
184   DALI_ASSERT_ALWAYS(pathConstrainer && "PathConstrainer handle is empty");
185   Dali::RefObject& object = pathConstrainer.GetBaseObject();
186   return static_cast<Internal::PathConstrainer&>(object);
187 }
188
189 inline const Internal::PathConstrainer& GetImplementation(const Dali::PathConstrainer& pathConstrainer)
190 {
191   DALI_ASSERT_ALWAYS(pathConstrainer && "PathConstrainer handle is empty");
192   const Dali::RefObject& object = pathConstrainer.GetBaseObject();
193   return static_cast<const Internal::PathConstrainer&>(object);
194 }
195
196 } // namespace Dali
197
198 #endif // DALI_INTERNAL_PATH_CONSTRAINER_H