877a9388a4ba0f1c35eda22138b5af693094c97a
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / path-constrainer-impl.cpp
1 /*
2  * Copyright (c) 2018 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/public-api/animation/constraint.h>
26 #include <dali/public-api/object/property-array.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/internal/event/common/property-helper.h>
29
30 namespace Dali
31 {
32
33 namespace Internal
34 {
35
36 namespace
37 {
38
39 // Properties
40 //              Name             Type   writable animatable constraint-input  enum for index-checking
41 DALI_PROPERTY_TABLE_BEGIN
42 DALI_PROPERTY( "forward",       VECTOR3,   true,    false,       false,        Dali::PathConstrainer::Property::FORWARD )
43 DALI_PROPERTY( "points",         ARRAY,    true,    false,       false,        Dali::PathConstrainer::Property::POINTS )
44 DALI_PROPERTY( "controlPoints",  ARRAY,    true,    false,       false,        Dali::PathConstrainer::Property::CONTROL_POINTS )
45 DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX, PathConstrainerDefaultProperties )
46
47 BaseHandle Create()
48 {
49   return Dali::PathConstrainer::New();
50 }
51
52 TypeRegistration mType( typeid( Dali::PathConstrainer ), typeid( Dali::Handle ), Create, PathConstrainerDefaultProperties );
53
54 } //Unnamed namespace
55
56 PathConstrainer* PathConstrainer::New()
57 {
58   return new PathConstrainer();
59 }
60
61 PathConstrainer::PathConstrainer()
62 : Constrainer(),
63   mPath( Path::New() )
64 {
65 }
66
67 PathConstrainer::~PathConstrainer()
68 {
69 }
70
71 Property::Value PathConstrainer::GetDefaultProperty( Property::Index index ) const
72 {
73   if( index == Dali::PathConstrainer::Property::FORWARD )
74   {
75     return Property::Value( mForward );
76   }
77   else
78   {
79     if( index == Dali::PathConstrainer::Property::POINTS )
80     {
81       Property::Value value( Property::ARRAY );
82       Property::Array* array = value.GetArray();
83       const Dali::Vector<Vector3>& point = mPath->GetPoints();
84       Property::Array::SizeType pointCount = static_cast<Property::Array::SizeType>( point.Size() );
85
86       if( array )
87       {
88         array->Reserve( pointCount );
89         for( Property::Array::SizeType i = 0; i < pointCount; ++i )
90         {
91           array->PushBack( point[i] );
92         }
93       }
94       return value;
95     }
96     else if( index == Dali::PathConstrainer::Property::CONTROL_POINTS )
97     {
98       Property::Value value( Property::ARRAY );
99       Property::Array* array = value.GetArray();
100       const Dali::Vector<Vector3>& point = mPath->GetControlPoints();
101       Property::Array::SizeType pointCount = static_cast<Property::Array::SizeType>( point.Size() );
102
103       if( array )
104       {
105         array->Reserve( pointCount );
106         for( Property::Array::SizeType i = 0; i < pointCount; ++i )
107         {
108           array->PushBack( point[i] );
109         }
110       }
111       return value;
112     }
113   }
114
115   return Property::Value();
116 }
117
118 Property::Value PathConstrainer::GetDefaultPropertyCurrentValue( Property::Index index ) const
119 {
120   return GetDefaultProperty( index ); // Event-side only properties
121 }
122
123 void PathConstrainer::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
124 {
125   if( index == Dali::PathConstrainer::Property::FORWARD )
126   {
127     propertyValue.Get(mForward);
128   }
129   else if( index == Dali::PathConstrainer::Property::POINTS  )
130   {
131     const Property::Array* array = propertyValue.GetArray();
132     mPath->ClearPoints();
133     if( array )
134     {
135       for( Property::Array::SizeType i = 0, count = array->Count(); i < count; ++i )
136       {
137         Vector3 point;
138         array->GetElementAt( i ).Get( point );
139         mPath->AddPoint( point );
140       }
141     }
142   }
143   else if( index == Dali::PathConstrainer::Property::CONTROL_POINTS )
144   {
145     const Property::Array* array = propertyValue.GetArray();
146     mPath->ClearControlPoints();
147     if( array )
148     {
149       for( Property::Array::SizeType i = 0, count = array->Count(); i < count; ++i )
150       {
151         Vector3 point;
152         array->GetElementAt( i ).Get( point );
153         mPath->AddControlPoint( point );
154       }
155     }
156   }
157 }
158
159 void PathConstrainer::Apply( Property target, Property source, const Vector2& range, const Vector2& wrap)
160 {
161   Dali::Property::Type propertyType = target.object.GetPropertyType( target.propertyIndex);
162   if( propertyType == Dali::Property::VECTOR3)
163   {
164     // If property type is Vector3, constrain its value to the position of the path
165     Dali::Constraint constraint = Dali::Constraint::New<Vector3>( target.object, target.propertyIndex, PathConstraintFunctor( mPath, range, wrap ) );
166     constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) );
167
168     constraint.SetTag( static_cast<uint32_t>( reinterpret_cast<uintptr_t>( this ) ) ); // taking 32bits of this as tag
169     constraint.SetRemoveAction( Dali::Constraint::Discard );
170     constraint.Apply();
171   }
172   else if( propertyType == Dali::Property::ROTATION )
173   {
174     // If property type is Rotation, constrain its value to align the forward vector to the tangent of the path
175     Dali::Constraint constraint = Dali::Constraint::New<Quaternion>( target.object, target.propertyIndex, PathConstraintFunctor( mPath, range, mForward, wrap) );
176     constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) );
177
178     constraint.SetTag( static_cast<uint32_t>( reinterpret_cast<uintptr_t>( this ) ) ); // taking 32bits of this as tag
179     constraint.SetRemoveAction( Dali::Constraint::Discard );
180     constraint.Apply();
181   }
182
183   //Start observing the object
184   Observe( target.object );
185 }
186
187 } // Internal
188
189 } // Dali