Support multiple window rendering
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / constraint-base.cpp
1 /*
2  * Copyright (c) 2019 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/constraint-base.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/object/handle.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/internal/event/common/event-thread-services.h>
25 #include <dali/internal/event/common/property-helper.h>
26 #include <dali/internal/event/common/stage-impl.h>
27 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
28 #include <dali/internal/update/common/animatable-property.h>
29 #include <dali/internal/update/common/property-owner-messages.h>
30
31 using Dali::Internal::SceneGraph::AnimatableProperty;
32
33 namespace Dali
34 {
35
36 namespace Internal
37 {
38
39 namespace
40 {
41 /**
42  * Helper to add only unique entries to the propertyOwner container
43  * @param propertyOwners to add the entries to
44  * @param object to add
45  */
46 inline void AddUnique( SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object )
47 {
48   const SceneGraph::PropertyOwnerIter iter = std::find( propertyOwners.Begin(), propertyOwners.End(), object );
49   if( iter == propertyOwners.End() )
50   {
51     // each owner should only be added once
52     propertyOwners.PushBack( object );
53   }
54 }
55 } // unnamed namespace
56
57 ConstraintBase::ConstraintBase( Object& object, Property::Index targetPropertyIndex, SourceContainer& sources )
58 : mEventThreadServices( EventThreadServices::Get() ),
59   mTargetObject( &object ),
60   mSceneGraphConstraint( NULL ),
61   mSources( sources ),
62   mObservedObjects(),
63   mTargetPropertyIndex( targetPropertyIndex ),
64   mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
65   mTag( 0 ),
66   mApplied( false ),
67   mSourceDestroyed( false )
68 {
69   ObserveObject( object );
70 }
71
72 ConstraintBase* ConstraintBase::Clone( Object& object )
73 {
74   DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
75
76   // create the type specific object
77   ConstraintBase* clone = DoClone( object );
78   clone->SetRemoveAction( mRemoveAction );
79   clone->SetTag( mTag );
80   return clone;
81 }
82
83 ConstraintBase::~ConstraintBase()
84 {
85   StopObservation();
86
87   RemoveInternal();
88 }
89
90 void ConstraintBase::AddSource( Source source )
91 {
92   mSources.push_back( source );
93
94   // Observe the object providing this property
95   if ( OBJECT_PROPERTY == source.sourceType )
96   {
97     if ( source.object != NULL )
98     {
99       ObserveObject( *source.object );
100     }
101     else
102     {
103       DALI_LOG_ERROR( "Constraint source object not found\n" );
104     }
105   }
106 }
107
108 void ConstraintBase::Apply()
109 {
110   if ( mTargetObject && !mApplied && !mSourceDestroyed )
111   {
112     mApplied = true;
113     ConnectConstraint();
114
115     mTargetObject->ApplyConstraint( *this );
116   }
117 }
118
119 void ConstraintBase::Remove()
120 {
121   RemoveInternal();
122
123   if( mTargetObject )
124   {
125     mTargetObject->RemoveConstraint( *this );
126   }
127 }
128
129 void ConstraintBase::RemoveInternal()
130 {
131   if ( mApplied )
132   {
133     mApplied = false;
134
135     // Guard against constraint sending messages during core destruction
136     if( Stage::IsInstalled() )
137     {
138       if( mTargetObject && mSceneGraphConstraint )
139       {
140         const SceneGraph::PropertyOwner& propertyOwner =  mTargetObject->GetSceneObject();
141         // Remove from scene-graph
142         RemoveConstraintMessage( GetEventThreadServices(), propertyOwner, *(mSceneGraphConstraint) );
143         // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
144         mSceneGraphConstraint = NULL;
145       }
146     }
147   }
148 }
149
150 Object* ConstraintBase::GetParent()
151 {
152   return mTargetObject;
153 }
154
155 Dali::Handle ConstraintBase::GetTargetObject()
156 {
157   return Dali::Handle( mTargetObject );
158 }
159
160 Property::Index ConstraintBase::GetTargetProperty()
161 {
162   return mTargetPropertyIndex;
163 }
164
165 void ConstraintBase::SetRemoveAction( ConstraintBase::RemoveAction action )
166 {
167   mRemoveAction = action;
168 }
169
170 ConstraintBase::RemoveAction ConstraintBase::GetRemoveAction() const
171 {
172   return mRemoveAction;
173 }
174
175 void ConstraintBase::SetTag( uint32_t tag )
176 {
177   mTag = tag;
178 }
179
180 uint32_t ConstraintBase::GetTag() const
181 {
182   return mTag;
183 }
184
185 void ConstraintBase::SceneObjectAdded( Object& object )
186 {
187   if ( mApplied &&
188        ( NULL == mSceneGraphConstraint ) &&
189        mTargetObject )
190   {
191     ConnectConstraint();
192   }
193 }
194
195 void ConstraintBase::SceneObjectRemoved( Object& object )
196 {
197   if ( mSceneGraphConstraint )
198   {
199     // An input property owning source has been deleted, need to tell the scene-graph-constraint owner to remove it
200     if ( &object != mTargetObject )
201     {
202       if( mTargetObject )
203       {
204         const SceneGraph::PropertyOwner& propertyOwner = mTargetObject->GetSceneObject();
205         // Remove from scene-graph
206         RemoveConstraintMessage( GetEventThreadServices(), propertyOwner, *(mSceneGraphConstraint) );
207       }
208     }
209
210     // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
211     mSceneGraphConstraint = NULL;
212   }
213 }
214
215 void ConstraintBase::ObjectDestroyed( Object& object )
216 {
217   // Remove object pointer from observation set
218   ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
219   DALI_ASSERT_DEBUG( mObservedObjects.End() != iter );
220   mObservedObjects.Erase( iter );
221
222   // Constraint is not useful anymore as an input-source has been destroyed
223   mSourceDestroyed = true;
224
225   // Stop observing the remaining objects
226   StopObservation();
227
228   // Clear our sources as well
229   mSources.clear();
230
231   // Discard all object & scene-graph pointers
232   mSceneGraphConstraint = NULL;
233   mTargetObject = NULL;
234 }
235
236 void ConstraintBase::ObserveObject( Object& object )
237 {
238   ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
239   if ( mObservedObjects.End() == iter )
240   {
241     object.AddObserver( *this );
242     mObservedObjects.PushBack( &object );
243   }
244 }
245
246 void ConstraintBase::StopObservation()
247 {
248   const ObjectIter end = mObservedObjects.End();
249   for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
250   {
251     (*iter)->RemoveObserver( *this );
252   }
253
254   mObservedObjects.Clear();
255 }
256
257 PropertyInputImpl* ConstraintBase::AddInputProperty( Source& source, SceneGraph::PropertyOwnerContainer& propertyOwners, int32_t& componentIndex )
258 {
259   PropertyInputImpl* inputProperty = nullptr;
260
261   if ( OBJECT_PROPERTY == source.sourceType )
262   {
263     DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
264
265     SceneGraph::PropertyOwner& owner = const_cast< SceneGraph::PropertyOwner& >( source.object->GetSceneObject() );
266
267     AddUnique( propertyOwners, &owner );
268     inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
269     componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
270
271     // The scene-object property should exist, when the property owner exists
272     DALI_ASSERT_ALWAYS( inputProperty && "Constraint source property does not exist" );
273   }
274   else if ( LOCAL_PROPERTY == source.sourceType )
275   {
276     DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
277
278     inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
279     componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
280
281     // The target scene-object should provide this property
282     DALI_ASSERT_ALWAYS( inputProperty && "Constraint source property does not exist" );
283   }
284   else
285   {
286     DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
287
288     Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
289
290     // This will not exist, if the target object is off-stage
291     if ( objectParent )
292     {
293       DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
294
295       SceneGraph::PropertyOwner& owner = const_cast< SceneGraph::PropertyOwner& >( objectParent->GetSceneObject() );
296
297       AddUnique( propertyOwners, &owner );
298       inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
299       componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
300
301       // The scene-object property should exist, when the property owner exists
302       DALI_ASSERT_ALWAYS( inputProperty && "Constraint source property does not exist" );
303     }
304   }
305   return inputProperty;
306 }
307
308
309 } // namespace Internal
310
311 } // namespace Dali