2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/animation/constraint-base.h>
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>
31 using Dali::Internal::SceneGraph::AnimatableProperty;
42 * Helper to add only unique entries to the propertyOwner container
43 * @param propertyOwners to add the entries to
44 * @param object to add
46 inline void AddUnique( SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object )
48 const SceneGraph::PropertyOwnerIter iter = std::find( propertyOwners.Begin(), propertyOwners.End(), object );
49 if( iter == propertyOwners.End() )
51 // each owner should only be added once
52 propertyOwners.PushBack( object );
55 } // unnamed namespace
57 ConstraintBase::ConstraintBase( Object& object, Property::Index targetPropertyIndex, SourceContainer& sources )
58 : mEventThreadServices( EventThreadServices::Get() ),
59 mTargetObject( &object ),
60 mSceneGraphConstraint( NULL ),
63 mTargetPropertyIndex( targetPropertyIndex ),
64 mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
67 mSourceDestroyed( false )
69 ObserveObject( object );
72 ConstraintBase* ConstraintBase::Clone( Object& object )
74 DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
76 // create the type specific object
77 ConstraintBase* clone = DoClone( object );
78 clone->SetRemoveAction( mRemoveAction );
79 clone->SetTag( mTag );
83 ConstraintBase::~ConstraintBase()
90 void ConstraintBase::AddSource( Source source )
92 mSources.push_back( source );
94 // Observe the object providing this property
95 if ( OBJECT_PROPERTY == source.sourceType )
97 if ( source.object != NULL )
99 ObserveObject( *source.object );
103 DALI_LOG_ERROR( "Constraint source object not found\n" );
108 void ConstraintBase::Apply()
110 if ( mTargetObject && !mApplied && !mSourceDestroyed )
115 mTargetObject->ApplyConstraint( *this );
119 void ConstraintBase::Remove()
125 mTargetObject->RemoveConstraint( *this );
129 void ConstraintBase::RemoveInternal()
135 // Guard against constraint sending messages during core destruction
136 if( Stage::IsInstalled() )
138 if( mTargetObject && mSceneGraphConstraint )
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;
150 Object* ConstraintBase::GetParent()
152 return mTargetObject;
155 Dali::Handle ConstraintBase::GetTargetObject()
157 return Dali::Handle( mTargetObject );
160 Property::Index ConstraintBase::GetTargetProperty()
162 return mTargetPropertyIndex;
165 void ConstraintBase::SetRemoveAction( ConstraintBase::RemoveAction action )
167 mRemoveAction = action;
170 ConstraintBase::RemoveAction ConstraintBase::GetRemoveAction() const
172 return mRemoveAction;
175 void ConstraintBase::SetTag( uint32_t tag )
180 uint32_t ConstraintBase::GetTag() const
185 void ConstraintBase::SceneObjectAdded( Object& object )
188 ( NULL == mSceneGraphConstraint ) &&
195 void ConstraintBase::SceneObjectRemoved( Object& object )
197 if ( mSceneGraphConstraint )
199 // An input property owning source has been deleted, need to tell the scene-graph-constraint owner to remove it
200 if ( &object != mTargetObject )
204 const SceneGraph::PropertyOwner& propertyOwner = mTargetObject->GetSceneObject();
205 // Remove from scene-graph
206 RemoveConstraintMessage( GetEventThreadServices(), propertyOwner, *(mSceneGraphConstraint) );
210 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
211 mSceneGraphConstraint = NULL;
215 void ConstraintBase::ObjectDestroyed( Object& object )
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 );
222 // Constraint is not useful anymore as an input-source has been destroyed
223 mSourceDestroyed = true;
225 // Stop observing the remaining objects
228 // Clear our sources as well
231 // Discard all object & scene-graph pointers
232 mSceneGraphConstraint = NULL;
233 mTargetObject = NULL;
236 void ConstraintBase::ObserveObject( Object& object )
238 ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
239 if ( mObservedObjects.End() == iter )
241 object.AddObserver( *this );
242 mObservedObjects.PushBack( &object );
246 void ConstraintBase::StopObservation()
248 const ObjectIter end = mObservedObjects.End();
249 for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
251 (*iter)->RemoveObserver( *this );
254 mObservedObjects.Clear();
257 PropertyInputImpl* ConstraintBase::AddInputProperty( Source& source, SceneGraph::PropertyOwnerContainer& propertyOwners, int32_t& componentIndex )
259 PropertyInputImpl* inputProperty = nullptr;
261 if ( OBJECT_PROPERTY == source.sourceType )
263 DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
265 SceneGraph::PropertyOwner& owner = const_cast< SceneGraph::PropertyOwner& >( source.object->GetSceneObject() );
267 AddUnique( propertyOwners, &owner );
268 inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
269 componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
271 // The scene-object property should exist, when the property owner exists
272 DALI_ASSERT_ALWAYS( inputProperty && "Constraint source property does not exist" );
274 else if ( LOCAL_PROPERTY == source.sourceType )
276 DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
278 inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
279 componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
281 // The target scene-object should provide this property
282 DALI_ASSERT_ALWAYS( inputProperty && "Constraint source property does not exist" );
286 DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
288 Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
290 // This will not exist, if the target object is off-stage
293 DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
295 SceneGraph::PropertyOwner& owner = const_cast< SceneGraph::PropertyOwner& >( objectParent->GetSceneObject() );
297 AddUnique( propertyOwners, &owner );
298 inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
299 componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
301 // The scene-object property should exist, when the property owner exists
302 DALI_ASSERT_ALWAYS( inputProperty && "Constraint source property does not exist" );
305 return inputProperty;
309 } // namespace Internal