[dali_1.2.52] Merge branch 'devel/master'
[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) 2017 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   typedef Dali::Constraint::RemoveAction RemoveAction;
56
57   /**
58    * Constructor
59    * @param ownerContainer the properties to constraint
60    * @oparam removeAction perform when removed
61    */
62   ConstraintBase( PropertyOwnerContainer& ownerContainer, RemoveAction removeAction );
63
64   /**
65    * Virtual destructor.
66    */
67   virtual ~ConstraintBase();
68
69   /**
70    * Initialize the constraint.
71    * This should by called by a scene-object, when the constraint is connected.
72    */
73   void OnConnect()
74   {
75     StartObservation();
76
77     mDisconnected = false;
78   }
79
80   /**
81    * @copydoc Dali::Constraint::SetRemoveAction()
82    */
83   void SetRemoveAction( RemoveAction action )
84   {
85     mRemoveAction = action;
86   }
87
88   /**
89    * @copydoc Dali::Constraint::GetRemoveAction()
90    */
91   RemoveAction GetRemoveAction() const
92   {
93     return mRemoveAction;
94   }
95
96   /**
97    * Constrain the associated scene object.
98    * @param[in] updateBufferIndex The current update buffer index.
99    */
100   virtual void Apply( BufferIndex updateBufferIndex ) = 0;
101
102   /**
103    * Helper for internal test cases; only available for debug builds.
104    * @return The current number of Constraint instances in existence.
105    */
106   static unsigned int GetCurrentInstanceCount();
107
108   /**
109    * Helper for internal test cases; only available for debug builds.
110    * @return The total number of Constraint instances created during the Dali core lifetime.
111    */
112   static unsigned int GetTotalInstanceCount();
113
114 private:
115
116   /**
117    * Helper to start observing property owners
118    */
119   void StartObservation()
120   {
121     const PropertyOwnerIter end =  mObservedOwners.End();
122     for( PropertyOwnerIter iter = mObservedOwners.Begin(); end != iter; ++iter )
123     {
124       (*iter)->AddObserver( *this );
125     }
126   }
127
128   /**
129    * Helper to stop observing property owners
130    */
131   void StopObservation()
132   {
133     const PropertyOwnerIter end =  mObservedOwners.End();
134     for( PropertyOwnerIter iter = mObservedOwners.Begin(); end != iter; ++iter )
135     {
136       (*iter)->RemoveObserver( *this );
137     }
138
139     mObservedOwners.Clear();
140   }
141
142   /**
143    * @copydoc PropertyOwner::Observer::PropertyOwnerConnected()
144    */
145   virtual void PropertyOwnerConnected( PropertyOwner& owner )
146   {
147   }
148
149   /**
150    * @copydoc PropertyOwner::Observer::PropertyOwnerDisconnected()
151    */
152   virtual void PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
153   {
154     if ( !mDisconnected )
155     {
156       // Stop observing property owners
157       StopObservation();
158
159       // Notification for derived class
160       OnDisconnect();
161
162       mDisconnected = true;
163     }
164   }
165
166   /**
167    * @copydoc PropertyOwner::Observer::PropertyOwnerDestroyed()
168    */
169   virtual void PropertyOwnerDestroyed( PropertyOwner& owner )
170   {
171     if ( !mDisconnected )
172     {
173       // Discard pointer to destroyed property owner. Otherwise StopObservation() would crash when trying to remove
174       //the constraint from the destroyed PropertyOwner's observers list
175       PropertyOwnerIter iter = std::find( mObservedOwners.Begin(), mObservedOwners.End(), &owner );
176       if( mObservedOwners.End() != iter )
177       {
178         mObservedOwners.Erase( iter );
179       }
180
181       // Stop observing the rest of property owners
182       StopObservation();
183
184       // Notification for derived class
185       OnDisconnect();
186
187       mDisconnected = true;
188
189     }
190   }
191
192   /**
193    * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
194    */
195   virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
196
197   /**
198    * Notify the derived class to disconnect from property owners
199    */
200   virtual void OnDisconnect() = 0;
201
202 protected:
203
204   RemoveAction mRemoveAction;
205
206   bool mFirstApply   : 1;
207   bool mDisconnected : 1;
208
209 private:
210
211   PropertyOwnerContainer mObservedOwners; ///< A set of pointers to each observed object. Not owned.
212
213 #ifdef DEBUG_ENABLED
214   static unsigned int mCurrentInstanceCount;  ///< The current number of Constraint instances in existence.
215   static unsigned int mTotalInstanceCount;    ///< The total number of Constraint instances created during the Dali core lifetime.
216 #endif
217 };
218
219 // Messages for ConstraintBase
220
221 inline void  SetRemoveActionMessage( EventThreadServices& eventThreadServices, const ConstraintBase& constraint, Dali::Constraint::RemoveAction removeAction )
222 {
223   typedef MessageValue1< ConstraintBase, Dali::Constraint::RemoveAction > LocalType;
224
225   // Reserve some memory inside the message queue
226   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
227
228   // Construct message in the message queue memory; note that delete should not be called on the return value
229   new (slot) LocalType( &constraint, &ConstraintBase::SetRemoveAction, removeAction );
230 }
231
232 } // namespace SceneGraph
233
234 } // namespace Internal
235
236 } // namespace Dali
237
238 #endif // __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_BASE_H__