2 * Copyright (c) 2021 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/internal/event/common/event-thread-services.h>
23 #include <dali/internal/event/common/property-helper.h>
24 #include <dali/internal/event/common/stage-impl.h>
25 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
26 #include <dali/internal/update/common/animatable-property.h>
27 #include <dali/internal/update/common/property-owner-messages.h>
28 #include <dali/public-api/object/handle.h>
29 #include <dali/public-api/object/type-registry.h>
31 using Dali::Internal::SceneGraph::AnimatableProperty;
40 * Helper to add only unique entries to the propertyOwner container
41 * @param propertyOwners to add the entries to
42 * @param object to add
44 inline void AddUnique(SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object)
46 const SceneGraph::PropertyOwnerIter iter = std::find(propertyOwners.Begin(), propertyOwners.End(), object);
47 if(iter == propertyOwners.End())
49 // each owner should only be added once
50 propertyOwners.PushBack(object);
53 } // unnamed namespace
55 ConstraintBase::ConstraintBase(Object& object, Property::Index targetPropertyIndex, SourceContainer& sources)
56 : mEventThreadServices(EventThreadServices::Get()),
57 mTargetObject(&object),
58 mSceneGraphConstraint(nullptr),
61 mTargetPropertyIndex(targetPropertyIndex),
62 mRemoveAction(Dali::Constraint::DEFAULT_REMOVE_ACTION),
65 mSourceDestroyed(false)
67 ObserveObject(object);
70 ConstraintBase* ConstraintBase::Clone(Object& object)
72 DALI_ASSERT_ALWAYS(!mSourceDestroyed && "An input source object has been destroyed");
74 // create the type specific object
75 ConstraintBase* clone = DoClone(object);
76 clone->SetRemoveAction(mRemoveAction);
81 ConstraintBase::~ConstraintBase()
88 void ConstraintBase::AddSource(Source source)
90 mSources.push_back(source);
92 // Observe the object providing this property
93 if(OBJECT_PROPERTY == source.sourceType)
95 if(source.object != nullptr)
97 ObserveObject(*source.object);
101 DALI_LOG_ERROR("Constraint source object not found\n");
106 void ConstraintBase::Apply()
108 if(mTargetObject && !mApplied && !mSourceDestroyed)
113 mTargetObject->ApplyConstraint(*this);
117 void ConstraintBase::Remove()
123 mTargetObject->RemoveConstraint(*this);
127 void ConstraintBase::RemoveInternal()
133 // Guard against constraint sending messages during core destruction
134 if(Stage::IsInstalled())
136 if(mTargetObject && mSceneGraphConstraint)
138 const SceneGraph::PropertyOwner& propertyOwner = mTargetObject->GetSceneObject();
139 // Remove from scene-graph
140 RemoveConstraintMessage(GetEventThreadServices(), propertyOwner, *(mSceneGraphConstraint));
141 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
142 mSceneGraphConstraint = nullptr;
148 Object* ConstraintBase::GetParent()
150 return mTargetObject;
153 Dali::Handle ConstraintBase::GetTargetObject()
155 return Dali::Handle(mTargetObject);
158 Property::Index ConstraintBase::GetTargetProperty()
160 return mTargetPropertyIndex;
163 void ConstraintBase::SetRemoveAction(ConstraintBase::RemoveAction action)
165 mRemoveAction = action;
168 ConstraintBase::RemoveAction ConstraintBase::GetRemoveAction() const
170 return mRemoveAction;
173 void ConstraintBase::SetTag(uint32_t tag)
178 uint32_t ConstraintBase::GetTag() const
183 void ConstraintBase::SceneObjectAdded(Object& object)
186 (nullptr == mSceneGraphConstraint) &&
193 void ConstraintBase::SceneObjectRemoved(Object& object)
195 if(mSceneGraphConstraint)
197 // An input property owning source has been deleted, need to tell the scene-graph-constraint owner to remove it
198 if(&object != mTargetObject)
202 const SceneGraph::PropertyOwner& propertyOwner = mTargetObject->GetSceneObject();
203 // Remove from scene-graph
204 RemoveConstraintMessage(GetEventThreadServices(), propertyOwner, *(mSceneGraphConstraint));
208 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
209 mSceneGraphConstraint = nullptr;
213 void ConstraintBase::ObjectDestroyed(Object& object)
215 // Remove object pointer from observation set
216 ObjectIter iter = std::find(mObservedObjects.Begin(), mObservedObjects.End(), &object);
217 DALI_ASSERT_DEBUG(mObservedObjects.End() != iter);
218 mObservedObjects.Erase(iter);
220 // Constraint is not useful anymore as an input-source has been destroyed
221 mSourceDestroyed = true;
223 // Stop observing the remaining objects
226 // Clear our sources as well
229 // Discard all object & scene-graph pointers
230 mSceneGraphConstraint = nullptr;
231 mTargetObject = nullptr;
234 void ConstraintBase::ObserveObject(Object& object)
236 ObjectIter iter = std::find(mObservedObjects.Begin(), mObservedObjects.End(), &object);
237 if(mObservedObjects.End() == iter)
239 object.AddObserver(*this);
240 mObservedObjects.PushBack(&object);
244 void ConstraintBase::StopObservation()
246 const ObjectIter end = mObservedObjects.End();
247 for(ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter)
249 (*iter)->RemoveObserver(*this);
252 mObservedObjects.Clear();
255 PropertyInputImpl* ConstraintBase::AddInputProperty(Source& source, SceneGraph::PropertyOwnerContainer& propertyOwners, int32_t& componentIndex)
257 PropertyInputImpl* inputProperty = nullptr;
259 if(OBJECT_PROPERTY == source.sourceType)
261 DALI_ASSERT_ALWAYS(source.object->IsPropertyAConstraintInput(source.propertyIndex));
263 SceneGraph::PropertyOwner& owner = const_cast<SceneGraph::PropertyOwner&>(source.object->GetSceneObject());
265 AddUnique(propertyOwners, &owner);
266 inputProperty = const_cast<PropertyInputImpl*>(source.object->GetSceneObjectInputProperty(source.propertyIndex));
267 componentIndex = source.object->GetPropertyComponentIndex(source.propertyIndex);
269 // The scene-object property should exist, when the property owner exists
270 DALI_ASSERT_ALWAYS(inputProperty && "Constraint source property does not exist");
272 else if(LOCAL_PROPERTY == source.sourceType)
274 DALI_ASSERT_ALWAYS(mTargetObject->IsPropertyAConstraintInput(source.propertyIndex));
276 inputProperty = const_cast<PropertyInputImpl*>(mTargetObject->GetSceneObjectInputProperty(source.propertyIndex));
277 componentIndex = mTargetObject->GetPropertyComponentIndex(source.propertyIndex);
279 // The target scene-object should provide this property
280 DALI_ASSERT_ALWAYS(inputProperty && "Constraint source property does not exist");
284 DALI_ASSERT_ALWAYS(PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid");
286 Object* objectParent = dynamic_cast<Actor&>(*mTargetObject).GetParent();
288 // This will not exist, if the target object is off-stage
291 DALI_ASSERT_ALWAYS(objectParent->IsPropertyAConstraintInput(source.propertyIndex));
293 SceneGraph::PropertyOwner& owner = const_cast<SceneGraph::PropertyOwner&>(objectParent->GetSceneObject());
295 AddUnique(propertyOwners, &owner);
296 inputProperty = const_cast<PropertyInputImpl*>(objectParent->GetSceneObjectInputProperty(source.propertyIndex));
297 componentIndex = objectParent->GetPropertyComponentIndex(source.propertyIndex);
299 // The scene-object property should exist, when the property owner exists
300 DALI_ASSERT_ALWAYS(inputProperty && "Constraint source property does not exist");
303 return inputProperty;
306 } // namespace Internal