5911fbf008fcfdcc56ca0c7ee0a2869c928df7d6
[platform/core/uifw/dali-core.git] / dali / internal / update / animation / scene-graph-constraint-base.h
1 #ifndef DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_BASE_H
2 #define DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_BASE_H
3
4 /*
5  * Copyright (c) 2019 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/animation/constraint.h>
23 #include <dali/public-api/common/dali-common.h>
24 #include <dali/internal/common/message.h>
25 #include <dali/internal/event/common/event-thread-services.h>
26 #include <dali/internal/update/common/animatable-property.h>
27 #include <dali/internal/update/common/property-owner.h>
28 #include <dali/internal/update/common/scene-graph-buffers.h>
29 #include <dali/internal/update/animation/scene-graph-constraint-declarations.h>
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 // value types used by messages
38 template <> struct ParameterType< Dali::Constraint::RemoveAction >
39 : public BasicType< Dali::Constraint::RemoveAction > {};
40
41 namespace SceneGraph
42 {
43
44 typedef Dali::Vector<PropertyOwner*>     PropertyOwnerContainer;
45 typedef PropertyOwnerContainer::Iterator PropertyOwnerIter;
46
47 /**
48  * An abstract base class for Constraints.
49  * This can be used to constrain a property of a scene-object, after animations have been applied.
50  */
51 class ConstraintBase : public PropertyOwner::Observer
52 {
53 public:
54   /**
55    * Observer to determine when the constraint is no longer present
56    */
57   class LifecycleObserver
58   {
59   public:
60     /**
61      * Called shortly before the constraint is destroyed.
62      */
63     virtual void ObjectDestroyed() = 0;
64
65   protected:
66     /**
67      * Virtual destructor, no deletion through this interface
68      */
69     virtual ~LifecycleObserver() = default;
70   };
71
72 public:
73
74   typedef Dali::Constraint::RemoveAction RemoveAction;
75
76   /**
77    * Constructor
78    * @param ownerContainer the properties to constraint
79    * @oparam removeAction perform when removed
80    */
81   ConstraintBase( PropertyOwnerContainer& ownerContainer, RemoveAction removeAction );
82
83   /**
84    * Virtual destructor.
85    */
86   virtual ~ConstraintBase();
87
88   /**
89    * Property resetter observes the lifecycle of this object
90    */
91   void AddLifecycleObserver( LifecycleObserver& observer )
92   {
93     mLifecycleObserver = &observer;
94   }
95
96   /**
97    * Property resetter observers the lifecycle of this object
98    */
99   void RemoveLifecycleObserver( LifecycleObserver& observer )
100   {
101     mLifecycleObserver = nullptr;
102   }
103
104   /**
105    * Initialize the constraint.
106    * This should by called by a scene-object, when the constraint is connected.
107    */
108   void OnConnect()
109   {
110     StartObservation();
111
112     mDisconnected = false;
113   }
114
115   /**
116    * @copydoc Dali::Constraint::SetRemoveAction()
117    */
118   void SetRemoveAction( RemoveAction action )
119   {
120     mRemoveAction = action;
121   }
122
123   /**
124    * @copydoc Dali::Constraint::GetRemoveAction()
125    */
126   RemoveAction GetRemoveAction() const
127   {
128     return mRemoveAction;
129   }
130
131   /**
132    * Constrain the associated scene object.
133    * @param[in] updateBufferIndex The current update buffer index.
134    */
135   virtual void Apply( BufferIndex updateBufferIndex ) = 0;
136
137   /**
138    * Helper for internal test cases; only available for debug builds.
139    * @return The current number of Constraint instances in existence.
140    */
141   static uint32_t GetCurrentInstanceCount();
142
143   /**
144    * Helper for internal test cases; only available for debug builds.
145    * @return The total number of Constraint instances created during the Dali core lifetime.
146    */
147   static uint32_t GetTotalInstanceCount();
148
149 private:
150
151   /**
152    * Helper to start observing property owners
153    */
154   void StartObservation()
155   {
156     const PropertyOwnerIter end =  mObservedOwners.End();
157     for( PropertyOwnerIter iter = mObservedOwners.Begin(); end != iter; ++iter )
158     {
159       (*iter)->AddObserver( *this );
160     }
161   }
162
163   /**
164    * Helper to stop observing property owners
165    */
166   void StopObservation()
167   {
168     const PropertyOwnerIter end =  mObservedOwners.End();
169     for( PropertyOwnerIter iter = mObservedOwners.Begin(); end != iter; ++iter )
170     {
171       (*iter)->RemoveObserver( *this );
172     }
173
174     mObservedOwners.Clear();
175   }
176
177   /**
178    * @copydoc PropertyOwner::Observer::PropertyOwnerConnected()
179    */
180   virtual void PropertyOwnerConnected( PropertyOwner& owner )
181   {
182   }
183
184   /**
185    * @copydoc PropertyOwner::Observer::PropertyOwnerDisconnected()
186    */
187   virtual void PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
188   {
189     if ( !mDisconnected )
190     {
191       // Stop observing property owners
192       StopObservation();
193
194       // Notification for derived class
195       OnDisconnect();
196
197       mDisconnected = true;
198     }
199   }
200
201   /**
202    * @copydoc PropertyOwner::Observer::PropertyOwnerDestroyed()
203    */
204   virtual void PropertyOwnerDestroyed( PropertyOwner& owner )
205   {
206     if ( !mDisconnected )
207     {
208       // Discard pointer to destroyed property owner. Otherwise StopObservation() would crash when trying to remove
209       //the constraint from the destroyed PropertyOwner's observers list
210       PropertyOwnerIter iter = std::find( mObservedOwners.Begin(), mObservedOwners.End(), &owner );
211       if( mObservedOwners.End() != iter )
212       {
213         mObservedOwners.Erase( iter );
214       }
215
216       // Stop observing the rest of property owners
217       StopObservation();
218
219       // Notification for derived class
220       OnDisconnect();
221
222       mDisconnected = true;
223
224     }
225   }
226
227   /**
228    * Notify the derived class to disconnect from property owners
229    */
230   virtual void OnDisconnect() = 0;
231
232 protected:
233
234   RemoveAction mRemoveAction;
235
236   bool mFirstApply   : 1;
237   bool mDisconnected : 1;
238
239 private:
240
241   PropertyOwnerContainer mObservedOwners; ///< A set of pointers to each observed object. Not owned.
242   LifecycleObserver* mLifecycleObserver; ///< Resetter observers this object
243
244 #ifdef DEBUG_ENABLED
245   static uint32_t mCurrentInstanceCount;  ///< The current number of Constraint instances in existence.
246   static uint32_t mTotalInstanceCount;    ///< The total number of Constraint instances created during the Dali core lifetime.
247 #endif
248 };
249
250 // Messages for ConstraintBase
251
252 inline void  SetRemoveActionMessage( EventThreadServices& eventThreadServices, const ConstraintBase& constraint, Dali::Constraint::RemoveAction removeAction )
253 {
254   typedef MessageValue1< ConstraintBase, Dali::Constraint::RemoveAction > LocalType;
255
256   // Reserve some memory inside the message queue
257   uint32_t* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
258
259   // Construct message in the message queue memory; note that delete should not be called on the return value
260   new (slot) LocalType( &constraint, &ConstraintBase::SetRemoveAction, removeAction );
261 }
262
263 } // namespace SceneGraph
264
265 } // namespace Internal
266
267 } // namespace Dali
268
269 #endif // DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_BASE_H