Merge remote-tracking branch 'origin/tizen' into new_text
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / path-constraint-impl.cpp
1 /*
2  * Copyright (c) 2015 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-constraint-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/event/common/property-helper.h>
23 #include <dali/public-api/animation/constraint.h>
24
25 namespace Dali
26 {
27
28 namespace Internal
29 {
30
31 namespace
32 {
33
34 // Properties
35
36 //              Name         Type   writable animatable constraint-input  enum for index-checking
37 DALI_PROPERTY_TABLE_BEGIN
38 DALI_PROPERTY( "range",     VECTOR2,   true,    false,        false,        Dali::PathConstraint::Property::RANGE )
39 DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
40
41
42 } //Unnamed namespace
43
44 PathConstraint* PathConstraint::New( Path& path, const Vector2& range)
45 {
46   return new PathConstraint( path, range);
47 }
48
49 PathConstraint::PathConstraint( Path& path, const Vector2& range)
50 : Object(),
51   mPath( Path::Clone(path)),
52   mRange(range)
53 {
54 }
55
56 PathConstraint::~PathConstraint()
57 {
58   //Remove constraints created by this PathConstraint
59   size_t tag = reinterpret_cast<size_t>( this );
60   const ObjectIter end = mObservedObjects.End();
61   for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
62   {
63     //Remove PathConstraint from the observers list of the object
64     (*iter)->RemoveObserver( *this );
65
66     //Remove constraints created by this PathConstraint in the object
67     (*iter)->RemoveConstraints( tag );
68   }
69 }
70
71 void PathConstraint::ObjectDestroyed(Object& object)
72 {
73   //Remove object from the list of observed
74   const ObjectIter end = mObservedObjects.End();
75   for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
76   {
77     if( *iter == &object )
78     {
79       mObservedObjects.Erase(iter);
80       return;
81     }
82   }
83 }
84
85 unsigned int PathConstraint::GetDefaultPropertyCount() const
86 {
87   return DEFAULT_PROPERTY_COUNT;
88 }
89
90 void PathConstraint::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
91 {
92   indices.reserve( DEFAULT_PROPERTY_COUNT );
93
94   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
95   {
96     indices.push_back( i );
97   }
98 }
99
100 const char* PathConstraint::GetDefaultPropertyName(Property::Index index) const
101 {
102   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
103   {
104     return DEFAULT_PROPERTY_DETAILS[index].name;
105   }
106
107   // index out of range
108   return NULL;
109 }
110
111 Property::Index PathConstraint::GetDefaultPropertyIndex(const std::string& name) const
112 {
113   Property::Index index = Property::INVALID_INDEX;
114
115   // Look for name in default properties
116   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
117   {
118     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
119     if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
120     {
121       index = i;
122       break;
123     }
124   }
125   return index;
126 }
127
128 Property::Type PathConstraint::GetDefaultPropertyType(Property::Index index) const
129 {
130   if( index < DEFAULT_PROPERTY_COUNT )
131   {
132     return DEFAULT_PROPERTY_DETAILS[index].type;
133   }
134
135   // index out of range
136   return Property::NONE;
137 }
138
139 Property::Value PathConstraint::GetDefaultProperty( Property::Index index ) const
140 {
141   if( index == Dali::PathConstraint::Property::RANGE )
142   {
143     return Property::Value( mRange );
144   }
145
146   return Property::Value();
147 }
148
149 void PathConstraint::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
150 {
151   if( index == Dali::PathConstraint::Property::RANGE )
152   {
153     propertyValue.Get(mRange);
154   }
155 }
156
157 bool PathConstraint::IsDefaultPropertyWritable(Property::Index index) const
158 {
159   if( index < DEFAULT_PROPERTY_COUNT )
160   {
161     return DEFAULT_PROPERTY_DETAILS[index].writable;
162   }
163
164   return false;
165 }
166
167 bool PathConstraint::IsDefaultPropertyAnimatable(Property::Index index) const
168 {
169   if( index < DEFAULT_PROPERTY_COUNT )
170   {
171     return DEFAULT_PROPERTY_DETAILS[index].animatable;
172   }
173
174   return false;
175 }
176
177 bool PathConstraint::IsDefaultPropertyAConstraintInput( Property::Index index ) const
178 {
179   if( index < DEFAULT_PROPERTY_COUNT )
180   {
181     return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
182   }
183
184   return false;
185 }
186
187 void PathConstraint::Apply( Property source, Property target, const Vector3& forward)
188 {
189
190   Dali::Property::Type propertyType = target.object.GetPropertyType( target.propertyIndex);
191
192
193   if( propertyType == Dali::Property::VECTOR3)
194   {
195     //If property is Vector3, contraint its value to the position of the path
196
197     Dali::Constraint constraint = Dali::Constraint::New<Vector3>( target.propertyIndex,
198                                                                   Source(source.object, source.propertyIndex ),
199                                                                   PathConstraintFunctor( mPath, mRange ) );
200
201     constraint.SetTag( reinterpret_cast<size_t>( this ) );
202     constraint.SetRemoveAction( Dali::Constraint::Discard );
203     target.object.ApplyConstraint(constraint);
204   }
205   else if( propertyType == Dali::Property::ROTATION )
206   {
207     //If property is Rotation, constraint its value to align the forward vector to the tangent of the path
208     Dali::Constraint constraint = Dali::Constraint::New<Quaternion>( target.propertyIndex,
209                                                                      Source(source.object, source.propertyIndex ),
210                                                                      PathConstraintFunctor( mPath, mRange,forward) );
211
212     constraint.SetTag( reinterpret_cast<size_t>( this ) );
213     constraint.SetRemoveAction( Dali::Constraint::Discard );
214     target.object.ApplyConstraint(constraint);
215   }
216
217   //Add the object to the list of observed objects if it is not there already
218   Object& object = dynamic_cast<Object&>( GetImplementation(target.object) );
219   const ObjectIter end = mObservedObjects.End();
220   ObjectIter iter = mObservedObjects.Begin();
221   for(; iter != end; ++iter )
222   {
223     if( *iter == &object )
224     {
225       break;
226     }
227   }
228
229   if( iter == end )
230   {
231     //Start observing the object
232     object.AddObserver( *this );
233
234     //Add object in the observed objects vector
235     mObservedObjects.PushBack( &object );
236   }
237 }
238
239 void PathConstraint::Remove( Dali::Handle& target )
240 {
241   Object& object = dynamic_cast<Object&>( GetImplementation(target) );
242   const ObjectIter end = mObservedObjects.End();
243   for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
244   {
245     if( *iter == &object )
246     {
247       //Stop observing the object
248       (*iter)->RemoveObserver( *this );
249
250       //Remove constraints created by PathConstraint in the object
251       size_t tag = reinterpret_cast<size_t>( this );
252       target.RemoveConstraints( tag );
253
254       //Remove object from the vector of observed objects
255       mObservedObjects.Erase(iter);
256     }
257   }
258 }
259
260 } // Internal
261 } // Dali