Merge "Add BuildPickingRay to devel api" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / update / common / property-resetter.h
1 #ifndef DALI_INTERNAL_SCENEGRAPH_PROPERTY_RESETTER_H
2 #define DALI_INTERNAL_SCENEGRAPH_PROPERTY_RESETTER_H
3
4 /*
5  * Copyright (c) 2023 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 // EXTERNAL INCLDUES
21 #include <cstdint> // int8_t
22
23 #include <dali/internal/update/animation/property-accessor.h>
24 #include <dali/internal/update/animation/property-component-accessor.h>
25 #include <dali/internal/update/animation/scene-graph-animator.h>
26 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
27 #include <dali/internal/update/common/property-owner.h>
28
29 namespace Dali
30 {
31 namespace Internal
32 {
33 namespace SceneGraph
34 {
35 /**
36  * Class to reset the watched property to it's base value. Used by UpdateManager to
37  * reset animating and constrained properties. The derived classes AnimatorResetter and
38  * ConstraintResetter are designed to match the lifecycle of the SceneGraph::Animator
39  * and SceneGraph::Constraint respectively.
40  */
41 class PropertyResetterBase : public PropertyOwner::Observer
42 {
43 public:
44   /**
45    * Virtual Destructor
46    */
47   ~PropertyResetterBase() override
48   {
49     if(mPropertyOwner != nullptr)
50     {
51       mPropertyOwner->RemoveObserver(*this);
52     }
53   }
54
55   /**
56    * Initialize.
57    *
58    * Watches the property owner to track if it's disconnected or not.
59    */
60   void Initialize()
61   {
62     mPropertyOwner->AddObserver(*this);
63     mPropertyOwner->SetUpdated(true);
64   }
65
66   /**
67    * Reset the property to it's base value if the property owner is still alive and on stage
68    * @param[in] updateBufferIndex the current buffer index
69    */
70   virtual void ResetToBaseValue(BufferIndex updateBufferIndex)
71   {
72     if(mPropertyOwner != nullptr && mActive)
73     {
74       // If property-owner has disconnected, start aging.
75       // We need to reset the property for two frames after disconnection to ensure both
76       // property values are set appropriately.
77       if(mDisconnected)
78       {
79         --mActive;
80       }
81
82       mBaseProperty->ResetToBaseValue(updateBufferIndex);
83     }
84   };
85
86   /**
87    * Called when mPropertyOwner is connected to the scene graph.
88    *
89    * Note, this resetter object may be created after the property owner has been connected
90    * to the stage, so we track disconnection and re-connection instead of connection
91    *
92    * @param[in] owner The property owner
93    */
94   void PropertyOwnerConnected(PropertyOwner& owner) override
95   {
96     mDisconnected = false;
97     mActive       = ACTIVE;
98   }
99
100   /**
101    * Called when mPropertyOwner is disconnected from the scene graph.
102    * @param[in] bufferIndex the current buffer index
103    * @param[in] owner The property owner
104    */
105   void PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
106   {
107     mDisconnected = true;
108   }
109
110   /**
111    * Called shortly before the propertyOwner is destroyed
112    * @param[in] owner The property owner
113    */
114   void PropertyOwnerDestroyed(PropertyOwner& owner) override
115   {
116     mDisconnected  = true;
117     mPropertyOwner = nullptr;
118
119     // Don't need to wait another frame as the property is being destroyed
120     mActive  = STOPPED;
121     mRunning = STOPPED;
122   }
123
124   /**
125    * Determine if the resetter has finished.
126    *
127    * If an animation or constraint stops, then we need to reset the
128    * property in the next frame as well to ensure both property values
129    * are set appropriately.
130    *
131    * @return true if the resetter has finished.
132    */
133   virtual bool IsFinished()
134   {
135     return mRunning <= STOPPED;
136   }
137
138   enum
139   {
140     STOPPED = 0,
141     AGING   = 1,
142     ACTIVE  = 2,
143   };
144
145 protected:
146   /**
147    * Constructor
148    *
149    * @param[in] propertyOwner The property owner storing the base property
150    * @param[in] baseProperty The base property
151    */
152   PropertyResetterBase(PropertyOwner* propertyOwner,
153                        PropertyBase*  baseProperty)
154   : mPropertyOwner(propertyOwner),
155     mBaseProperty(baseProperty),
156     mRunning(ACTIVE),
157     mActive(ACTIVE),
158     mDisconnected(false)
159   {
160   }
161
162   PropertyOwner* mPropertyOwner; ///< The property owner
163   PropertyBase*  mBaseProperty;  ///< The base property being animated or constrained
164   int8_t         mRunning;       ///< Used to determine if we should finish or not, 2 if running, 1 if aging, 0 if stopped
165   int8_t         mActive;        ///< 2 if active, 1 if aging, 0 if stopped
166   bool           mDisconnected;  ///< True if the property owner has been disconnected
167 };
168
169 class BakerResetter : public PropertyResetterBase
170 {
171 public:
172   enum class Lifetime
173   {
174     BAKE,
175     SET
176   };
177
178   /**
179    * New method.
180    * @param[in] propertyOwner  The owner of the property
181    * @param[in] baseProperty   The property being animated
182    * @param[in] lifetime       How long this resetter stays alive (1 or 2 frames)
183    * @return the new property resetter
184    */
185   static PropertyResetterBase* New(const PropertyOwner& propertyOwner,
186                                    const PropertyBase&  baseProperty,
187                                    Lifetime             lifetime)
188   {
189     return new BakerResetter(const_cast<PropertyOwner*>(&propertyOwner),
190                              const_cast<PropertyBase*>(&baseProperty),
191                              lifetime);
192   }
193
194   /**
195    * Constructor
196    * @param[in] propertyOwner The owner of the property
197    * @param[in] baseProperty  The property being animated
198    * @param[in] lifetime      How many frames this stays alive for
199    */
200   BakerResetter(PropertyOwner* propertyOwner,
201                 PropertyBase*  baseProperty,
202                 Lifetime       lifetime)
203   : PropertyResetterBase(propertyOwner, baseProperty)
204   {
205     mRunning = lifetime == Lifetime::BAKE ? AGING : ACTIVE;
206   }
207
208   /**
209    * Virtual destructor.
210    */
211   ~BakerResetter() override = default;
212
213   /**
214    * @param updateBufferIndex
215    */
216   void ResetToBaseValue(BufferIndex updateBufferIndex) override
217   {
218     if(mPropertyOwner && mRunning > 0)
219     {
220       mRunning--;
221       mBaseProperty->ResetToBaseValue(updateBufferIndex);
222
223       if(mRunning > 0)
224       {
225         mPropertyOwner->SetUpdated(true);
226       }
227     }
228   }
229 };
230
231 /**
232  * Specialization of Resetter based on templated modifier type (either Constraint or Animator)
233  */
234 template<typename ModifierType>
235 class Resetter : public PropertyResetterBase, public ModifierType::LifecycleObserver
236 {
237 public:
238   /**
239    * New method.
240    * @param[in] propertyOwner  The owner of the property
241    * @param[in] baseProperty   The property being animated
242    * @param[in] modifier       The scene-graph animator/constraint of the property
243    * @return the new property resetter
244    */
245   static PropertyResetterBase* New(const PropertyOwner& propertyOwner,
246                                    const PropertyBase&  baseProperty,
247                                    const ModifierType&  modifier)
248   {
249     return new Resetter<ModifierType>(const_cast<PropertyOwner*>(&propertyOwner),
250                                       const_cast<PropertyBase*>(&baseProperty),
251                                       const_cast<ModifierType*>(&modifier));
252   }
253
254   /**
255    * Virtual destructor.
256    */
257   ~Resetter() override
258   {
259     // Disconnect from modifier object. Although this resetter should match the lifecycle of the modifier object,
260     // there are situations where it is deleted first (e.g. if the property owner is destroyed)
261     if(mModifier)
262     {
263       mModifier->RemoveLifecycleObserver(*this);
264     }
265   }
266
267 private:
268   /**
269    * Constructor
270    * @param[in] propertyOwner The owner of the property
271    * @param[in] baseProperty  The property being animated
272    * @param[in] modifier      The scene-graph animator/constraint of the property
273    */
274   Resetter(PropertyOwner* propertyOwner,
275            PropertyBase*  baseProperty,
276            ModifierType*  modifier)
277   : PropertyResetterBase(propertyOwner, baseProperty),
278     mModifier(modifier)
279   {
280     // Track the lifecycle of the modifying object
281     mModifier->AddLifecycleObserver(*this);
282   }
283
284   /**
285    * The Animator or Constraint is destroyed
286    */
287   void ObjectDestroyed() override
288   {
289     // When the modifier is destroyed, reduce the running value to ensure we stay alive for
290     // another frame to reset the other buffer.
291     --mRunning;
292     mModifier = nullptr;
293   }
294
295   ModifierType* mModifier;
296 };
297
298 using AnimatorResetter   = Resetter<SceneGraph::AnimatorBase>;
299 using ConstraintResetter = Resetter<SceneGraph::ConstraintBase>;
300
301 } // namespace SceneGraph
302
303 } // namespace Internal
304
305 } // namespace Dali
306
307 #endif //DALI_INTERNAL_SCENEGRAPH_PROPERTY_RESETTER_H