DALi Version 2.2.14
[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) 2021 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   }
64
65   /**
66    * Reset the property to it's base value if the property owner is still alive and on stage
67    * @param[in] updateBufferIndex the current buffer index
68    */
69   void ResetToBaseValue(BufferIndex updateBufferIndex)
70   {
71     if(mPropertyOwner != nullptr && mActive)
72     {
73       // If property-owner has disconnected, start aging.
74       // We need to reset the property for two frames after disconnection to ensure both
75       // property values are set appropriately.
76       if(mDisconnected)
77       {
78         --mActive;
79       }
80
81       mBaseProperty->ResetToBaseValue(updateBufferIndex);
82     }
83   };
84
85   /**
86    * Called when mPropertyOwner is connected to the scene graph.
87    *
88    * Note, this resetter object may be created after the property owner has been connected
89    * to the stage, so we track disconnection and re-connection instead of connection
90    *
91    * @param[in] owner The property owner
92    */
93   void PropertyOwnerConnected(PropertyOwner& owner) override
94   {
95     mDisconnected = false;
96     mActive       = ACTIVE;
97   }
98
99   /**
100    * Called when mPropertyOwner is disconnected from the scene graph.
101    * @param[in] bufferIndex the current buffer index
102    * @param[in] owner The property owner
103    */
104   void PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
105   {
106     mDisconnected = true;
107   }
108
109   /**
110    * Called shortly before the propertyOwner is destroyed
111    * @param[in] owner The property owner
112    */
113   void PropertyOwnerDestroyed(PropertyOwner& owner) override
114   {
115     mDisconnected  = true;
116     mPropertyOwner = nullptr;
117
118     // Don't need to wait another frame as the property is being destroyed
119     mActive  = STOPPED;
120     mRunning = STOPPED;
121   }
122
123   /**
124    * Determine if the resetter has finished.
125    *
126    * If an animation or constraint stops, then we need to reset the
127    * property in the next frame as well to ensure both property values
128    * are set appropriately.
129    *
130    * @return true if the resetter has finished.
131    */
132   virtual bool IsFinished()
133   {
134     bool finished = mRunning <= STOPPED;
135     if(mRunning == AGING)
136     {
137       mRunning = STOPPED;
138     }
139     return finished;
140   }
141
142 protected:
143   enum
144   {
145     STOPPED = 0,
146     AGING   = 1,
147     ACTIVE  = 2,
148   };
149
150   /**
151    * Constructor
152    *
153    * @param[in] propertyOwner The property owner storing the base property
154    * @param[in] baseProperty The base property
155    */
156   PropertyResetterBase(PropertyOwner* propertyOwner,
157                        PropertyBase*  baseProperty)
158   : mPropertyOwner(propertyOwner),
159     mBaseProperty(baseProperty),
160     mRunning(ACTIVE),
161     mActive(ACTIVE),
162     mDisconnected(false)
163   {
164   }
165
166   PropertyOwner* mPropertyOwner; ///< The property owner
167   PropertyBase*  mBaseProperty;  ///< The base property being animated or constrained
168   int8_t         mRunning;       ///< Used to determine if we should finish or not, 2 if running, 1 if aging, 0 if stopped
169   int8_t         mActive;        ///< 2 if active, 1 if aging, 0 if stopped
170   bool           mDisconnected;  ///< True if the property owner has been disconnected
171 };
172
173 /**
174  * Specialization of Resetter based on templated modifier type (either Constraint or Animator)
175  */
176 template<typename ModifierType>
177 class Resetter : public PropertyResetterBase, public ModifierType::LifecycleObserver
178 {
179 public:
180   /**
181    * New method.
182    * @param[in] propertyOwner  The owner of the property
183    * @param[in] baseProperty   The property being animated
184    * @param[in] modifier       The scene-graph animator/constraint of the property
185    * @return the new property resetter
186    */
187   static PropertyResetterBase* New(const PropertyOwner& propertyOwner,
188                                    const PropertyBase&  baseProperty,
189                                    const ModifierType&  modifier)
190   {
191     return new Resetter<ModifierType>(const_cast<PropertyOwner*>(&propertyOwner),
192                                       const_cast<PropertyBase*>(&baseProperty),
193                                       const_cast<ModifierType*>(&modifier));
194   }
195
196   /**
197    * Virtual destructor.
198    */
199   ~Resetter() override
200   {
201     // Disconnect from modifier object. Although this resetter should match the lifecycle of the modifier object,
202     // there are situations where it is deleted first (e.g. if the property owner is destroyed)
203     if(mModifier)
204     {
205       mModifier->RemoveLifecycleObserver(*this);
206     }
207   }
208
209 private:
210   /**
211    * Constructor
212    * @param[in] propertyOwner The owner of the property
213    * @param[in] baseProperty  The property being animated
214    * @param[in] modifier      The scene-graph animator/constraint of the property
215    */
216   Resetter(PropertyOwner* propertyOwner,
217            PropertyBase*  baseProperty,
218            ModifierType*  modifier)
219   : PropertyResetterBase(propertyOwner, baseProperty),
220     mModifier(modifier)
221   {
222     // Track the lifecycle of the modifying object
223     mModifier->AddLifecycleObserver(*this);
224   }
225
226   /**
227    * The Animator or Constraint is destroyed
228    */
229   void ObjectDestroyed() override
230   {
231     // When the modifier is destroyed, reduce the running value to ensure we stay alive for
232     // another frame to reset the other buffer.
233     --mRunning;
234     mModifier = nullptr;
235   }
236
237   ModifierType* mModifier;
238 };
239
240 using AnimatorResetter   = Resetter<SceneGraph::AnimatorBase>;
241 using ConstraintResetter = Resetter<SceneGraph::ConstraintBase>;
242
243 } // namespace SceneGraph
244
245 } // namespace Internal
246
247 } // namespace Dali
248
249 #endif //DALI_INTERNAL_SCENEGRAPH_PROPERTY_RESETTER_H