[dali_2.3.27] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / path-constrainer-impl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/animation/path-constrainer-impl.h>
20
21 //EXTRENAL INCLUDES
22 #include <cstring> // for strcmp
23
24 // INTERNAL INCLUDES
25 #include <dali/internal/event/common/property-helper.h>
26 #include <dali/public-api/animation/constraint.h>
27 #include <dali/public-api/object/property-array.h>
28 #include <dali/public-api/object/type-registry.h>
29
30 namespace Dali
31 {
32 namespace Internal
33 {
34 namespace
35 {
36 // Properties
37 //              Name             Type   writable animatable constraint-input  enum for index-checking
38 DALI_PROPERTY_TABLE_BEGIN
39 DALI_PROPERTY("forward", VECTOR3, true, false, false, Dali::PathConstrainer::Property::FORWARD)
40 DALI_PROPERTY("points", ARRAY, true, false, false, Dali::PathConstrainer::Property::POINTS)
41 DALI_PROPERTY("controlPoints", ARRAY, true, false, false, Dali::PathConstrainer::Property::CONTROL_POINTS)
42 DALI_PROPERTY_TABLE_END(DEFAULT_OBJECT_PROPERTY_START_INDEX, PathConstrainerDefaultProperties)
43
44 BaseHandle Create()
45 {
46   return Dali::PathConstrainer::New();
47 }
48
49 TypeRegistration mType(typeid(Dali::PathConstrainer), typeid(Dali::Handle), Create, PathConstrainerDefaultProperties);
50
51 } //Unnamed namespace
52
53 PathConstrainer* PathConstrainer::New()
54 {
55   return new PathConstrainer();
56 }
57
58 PathConstrainer::PathConstrainer()
59 : Constrainer(),
60   mPath(Path::New())
61 {
62 }
63
64 PathConstrainer::~PathConstrainer() = default;
65
66 Property::Value PathConstrainer::GetDefaultProperty(Property::Index index) const
67 {
68   if(index == Dali::PathConstrainer::Property::FORWARD)
69   {
70     return Property::Value(mForward);
71   }
72   else
73   {
74     if(index == Dali::PathConstrainer::Property::POINTS)
75     {
76       Property::Value              value(Property::ARRAY);
77       Property::Array*             array      = value.GetArray();
78       const Dali::Vector<Vector3>& point      = mPath->GetPoints();
79       Property::Array::SizeType    pointCount = static_cast<Property::Array::SizeType>(point.Size());
80
81       if(array)
82       {
83         array->Reserve(pointCount);
84         for(Property::Array::SizeType i = 0; i < pointCount; ++i)
85         {
86           array->PushBack(point[i]);
87         }
88       }
89       return value;
90     }
91     else if(index == Dali::PathConstrainer::Property::CONTROL_POINTS)
92     {
93       Property::Value              value(Property::ARRAY);
94       Property::Array*             array      = value.GetArray();
95       const Dali::Vector<Vector3>& point      = mPath->GetControlPoints();
96       Property::Array::SizeType    pointCount = static_cast<Property::Array::SizeType>(point.Size());
97
98       if(array)
99       {
100         array->Reserve(pointCount);
101         for(Property::Array::SizeType i = 0; i < pointCount; ++i)
102         {
103           array->PushBack(point[i]);
104         }
105       }
106       return value;
107     }
108   }
109
110   return Property::Value();
111 }
112
113 Property::Value PathConstrainer::GetDefaultPropertyCurrentValue(Property::Index index) const
114 {
115   return GetDefaultProperty(index); // Event-side only properties
116 }
117
118 void PathConstrainer::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
119 {
120   if(index == Dali::PathConstrainer::Property::FORWARD)
121   {
122     propertyValue.Get(mForward);
123   }
124   else if(index == Dali::PathConstrainer::Property::POINTS)
125   {
126     const Property::Array* array = propertyValue.GetArray();
127     mPath->ClearPoints();
128     if(array)
129     {
130       for(Property::Array::SizeType i = 0, count = array->Count(); i < count; ++i)
131       {
132         Vector3 point;
133         array->GetElementAt(i).Get(point);
134         mPath->AddPoint(point);
135       }
136     }
137   }
138   else if(index == Dali::PathConstrainer::Property::CONTROL_POINTS)
139   {
140     const Property::Array* array = propertyValue.GetArray();
141     mPath->ClearControlPoints();
142     if(array)
143     {
144       for(Property::Array::SizeType i = 0, count = array->Count(); i < count; ++i)
145       {
146         Vector3 point;
147         array->GetElementAt(i).Get(point);
148         mPath->AddControlPoint(point);
149       }
150     }
151   }
152 }
153
154 void PathConstrainer::Apply(Property target, Property source, const Vector2& range, const Vector2& wrap)
155 {
156   Dali::Property::Type propertyType = target.object.GetPropertyType(target.propertyIndex);
157   if(propertyType == Dali::Property::VECTOR3)
158   {
159     // If property type is Vector3, constrain its value to the position of the path
160     Dali::Constraint constraint = Dali::Constraint::New<Vector3>(target.object, target.propertyIndex, PathConstraintFunctor(mPath, range, wrap));
161     constraint.AddSource(Dali::Source(source.object, source.propertyIndex));
162
163     constraint.SetTag(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this))); // taking 32bits of this as tag
164     constraint.SetRemoveAction(Dali::Constraint::DISCARD);
165     constraint.Apply();
166   }
167   else if(propertyType == Dali::Property::ROTATION)
168   {
169     // If property type is Rotation, constrain its value to align the forward vector to the tangent of the path
170     Dali::Constraint constraint = Dali::Constraint::New<Quaternion>(target.object, target.propertyIndex, PathConstraintFunctor(mPath, range, mForward, wrap));
171     constraint.AddSource(Dali::Source(source.object, source.propertyIndex));
172
173     constraint.SetTag(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this))); // taking 32bits of this as tag
174     constraint.SetRemoveAction(Dali::Constraint::DISCARD);
175     constraint.Apply();
176   }
177
178   //Start observing the object
179   Observe(target.object);
180 }
181
182 } // namespace Internal
183
184 } // namespace Dali