241eb06779569436d9e60246e042b06e31ef8539
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / transition / transition-base-impl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/transition/transition-base-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23
24 // EXTERNAL INCLUDES
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/integration-api/debug.h>
27 #include <dali/public-api/animation/key-frames.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/object/type-registry.h>
30
31 namespace Dali
32 {
33 namespace Toolkit
34 {
35 namespace Internal
36 {
37 namespace
38 {
39 const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION(Dali::AlphaFunction::DEFAULT);
40
41 Property::Map GetOriginalProperties(Dali::Toolkit::Control control)
42 {
43   Property::Map propertyMap;
44   propertyMap.Insert(Dali::Actor::Property::ANCHOR_POINT, control[Dali::Actor::Property::ANCHOR_POINT]);
45   propertyMap.Insert(Dali::Actor::Property::PARENT_ORIGIN, control[Dali::Actor::Property::PARENT_ORIGIN]);
46   propertyMap.Insert(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT, control[Dali::Actor::Property::POSITION_USES_ANCHOR_POINT]);
47   propertyMap.Insert(Dali::Actor::Property::INHERIT_POSITION, control[Dali::Actor::Property::INHERIT_POSITION]);
48   propertyMap.Insert(Dali::Actor::Property::INHERIT_ORIENTATION, control[Dali::Actor::Property::INHERIT_ORIENTATION]);
49   propertyMap.Insert(Dali::Actor::Property::INHERIT_SCALE, control[Dali::Actor::Property::INHERIT_SCALE]);
50   propertyMap.Insert(Dali::Actor::Property::COLOR_MODE, control[Dali::Actor::Property::COLOR_MODE]);
51   propertyMap.Insert(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, control[Dali::Actor::Property::HEIGHT_RESIZE_POLICY]);
52   propertyMap.Insert(Dali::Actor::Property::WIDTH_RESIZE_POLICY, control[Dali::Actor::Property::WIDTH_RESIZE_POLICY]);
53   propertyMap.Insert(Dali::Actor::Property::POSITION, control[Dali::Actor::Property::POSITION]);
54   propertyMap.Insert(Dali::Actor::Property::ORIENTATION, control[Dali::Actor::Property::ORIENTATION]);
55   propertyMap.Insert(Dali::Actor::Property::SCALE, control[Dali::Actor::Property::SCALE]);
56   propertyMap.Insert(Dali::Actor::Property::COLOR, control[Dali::Actor::Property::COLOR]);
57
58   return propertyMap;
59 }
60
61 /**
62  * @brief Computes and center position by using transform properties.
63  * @param[in] anchorPoint anchorPoint of an actor.
64  * @param[in] positionUsesAnchorPoint positionUsesAnchorPoint of an actor.
65  * @param[in] size size of an actor.
66  * @param[in] scale scale of an actor.
67  * @param[in] orientation orientation of an actor.
68  */
69 Vector3 CalculateCenterPosition(
70   const Vector3&    anchorPoint,
71   const bool        positionUsesAnchorPoint,
72   const Vector3&    size,
73   const Vector3&    scale,
74   const Quaternion& orientation)
75 {
76   Vector3       centerPosition;
77   const Vector3 half(0.5f, 0.5f, 0.5f);
78   const Vector3 topLeft(0.0f, 0.0f, 0.5f);
79   // Calculate the center-point by applying the scale and rotation on the anchor point.
80   centerPosition = (half - anchorPoint) * size * scale;
81   centerPosition *= orientation;
82
83   // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
84   if(!positionUsesAnchorPoint)
85   {
86     centerPosition -= (topLeft - anchorPoint) * size;
87   }
88   return centerPosition;
89 }
90
91 } // anonymous namespace
92
93 TransitionBasePtr TransitionBase::New()
94 {
95   TransitionBasePtr transition = new TransitionBase();
96
97   // Second-phase construction
98   transition->Initialize();
99
100   return transition;
101 }
102
103 TransitionBase::TransitionBase()
104 : mAlphaFunction(DEFAULT_ALPHA_FUNCTION),
105   mTimePeriod(TimePeriod(0.0f)),
106   mTransitionWithChild(false),
107   mMoveTargetChildren(false),
108   mIsAppearingTransition(true)
109 {
110 }
111
112 void TransitionBase::Initialize()
113 {
114   RegisterObject();
115 }
116
117 void TransitionBase::SetTimePeriod(const Dali::TimePeriod& timePeriod)
118 {
119   if(timePeriod.durationSeconds < 0.0f)
120   {
121     DALI_LOG_WARNING("Duration should be greater than 0.0f.\n");
122   }
123   else
124   {
125     mTimePeriod.durationSeconds = timePeriod.durationSeconds;
126   }
127
128   if(timePeriod.delaySeconds < 0.0f)
129   {
130     DALI_LOG_WARNING("Delay should be greater than 0.0f.\n");
131     return;
132   }
133   else
134   {
135     mTimePeriod.delaySeconds = timePeriod.delaySeconds;
136   }
137 }
138
139 Dali::TimePeriod TransitionBase::GetTimePeriod() const
140 {
141   return mTimePeriod;
142 }
143
144 void TransitionBase::TransitionWithChild(bool transitionWithChild)
145 {
146   mTransitionWithChild = transitionWithChild;
147 }
148
149 void TransitionBase::PreProcess(Dali::Animation animation)
150 {
151   mAnimation           = animation;
152   // Retrieve original property map of mTarget to backup and to reset after transition is finished.
153   mOriginalPropertyMap = GetOriginalProperties(mTarget);
154   mMoveTargetChildren  = false;
155   if(!mTransitionWithChild && mTarget.GetChildCount() > 0)
156   {
157     mMoveTargetChildren = true;
158     CopyTarget();
159   }
160   GetImplementation(mTarget).SetTransparent(false);
161 }
162
163 void TransitionBase::Play()
164 {
165   if(!mTarget[Dali::Actor::Property::CONNECTED_TO_SCENE])
166   {
167     DALI_LOG_ERROR("The target is not added on the window\n");
168     return;
169   }
170
171   OnPlay();
172
173   SetAnimation();
174 }
175
176 void TransitionBase::SetAnimation()
177 {
178   if(!mAnimation)
179   {
180     DALI_LOG_ERROR("animation is not initialized\n");
181     return;
182   }
183
184   for(uint32_t i = 0; i < mStartPropertyMap.Count(); ++i)
185   {
186     Property::Value* initialValuePointer = mInitialPropertyMap.Find(mStartPropertyMap.GetKeyAt(i).indexKey);
187     Property::Value* finishValue = mFinishPropertyMap.Find(mStartPropertyMap.GetKeyAt(i).indexKey);
188     if(finishValue)
189     {
190       Property::Value initialValue = mStartPropertyMap.GetValue(i);
191       if(initialValuePointer)
192       {
193         initialValue = *initialValuePointer;
194       }
195       AnimateBetween(mTarget, mStartPropertyMap.GetKeyAt(i).indexKey, initialValue, mStartPropertyMap.GetValue(i), *finishValue);
196     }
197   }
198 }
199
200 void TransitionBase::AnimateBetween(Dali::Toolkit::Control target, Property::Index index, Property::Value initialValue, Property::Value sourceValue, Property::Value destinationValue)
201 {
202   if(mAnimation)
203   {
204     if(mTimePeriod.delaySeconds>0.0f)
205     {
206       Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
207       initialKeyframes.Add(0.0f, initialValue);
208       initialKeyframes.Add(1.0f, initialValue);
209       mAnimation.AnimateBetween(Property(target, index), initialKeyframes, TimePeriod(mTimePeriod.delaySeconds));
210     }
211     Dali::KeyFrames keyframes = Dali::KeyFrames::New();
212     keyframes.Add(0.0f, sourceValue);
213     keyframes.Add(1.0f, destinationValue);
214     mAnimation.AnimateBetween(Property(target, index), keyframes, mAlphaFunction, mTimePeriod);
215   }
216 }
217
218 void TransitionBase::CopyTarget()
219 {
220   mCopiedActor = Dali::Actor::New();
221   mTarget.GetParent().Add(mCopiedActor);
222   mCopiedActor[Dali::DevelActor::Property::SIBLING_ORDER] = static_cast<int32_t>(mTarget[Dali::DevelActor::Property::SIBLING_ORDER]) + 1;
223   for(uint32_t i = 0; i < mTarget.GetChildCount(); ++i)
224   {
225     Dali::Actor child = mTarget.GetChildAt(i);
226     Dali::DevelActor::SwitchParent(child, mCopiedActor);
227   }
228
229   // Copy Size property to mCopiedActor because Size is not included mOriginalPropertyMap.
230   mCopiedActor[Dali::Actor::Property::SIZE] = mTarget.GetProperty<Vector3>(Dali::Actor::Property::SIZE);
231   mCopiedActor.SetProperties(mOriginalPropertyMap);
232 }
233
234 void TransitionBase::TransitionFinished()
235 {
236   OnFinished();
237
238   mTarget.SetProperties(mOriginalPropertyMap);
239   if(mMoveTargetChildren)
240   {
241     for(uint32_t i = 0; i < mCopiedActor.GetChildCount(); ++i)
242     {
243       Dali::Actor child = mCopiedActor.GetChildAt(i);
244       Dali::DevelActor::SwitchParent(child, mTarget);
245     }
246     mCopiedActor.Unparent();
247     mCopiedActor.Reset();
248   }
249   mAnimation.Reset();
250 }
251
252 Matrix TransitionBase::GetWorldTransform(Dali::Actor actor)
253 {
254   enum InheritanceMode
255   {
256     DONT_INHERIT_TRANSFORM = 0,
257     INHERIT_POSITION       = 1,
258     INHERIT_SCALE          = 2,
259     INHERIT_ORIENTATION    = 4,
260     INHERIT_ALL            = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION,
261   };
262
263   std::vector<Dali::Actor>     descentList;
264   std::vector<InheritanceMode> inheritanceModeList;
265   Dali::Actor                  currentActor = actor;
266   int                          inheritance  = 0;
267   do
268   {
269     inheritance = (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_ORIENTATION)) << 2) +
270                   (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_SCALE)) << 1) +
271                   static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_POSITION));
272     inheritanceModeList.push_back(static_cast<InheritanceMode>(inheritance));
273     descentList.push_back(currentActor);
274     currentActor = currentActor.GetParent();
275   } while(inheritance != DONT_INHERIT_TRANSFORM && currentActor);
276
277   Matrix  worldMatrix;
278   Vector3 localPosition;
279   for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i)
280   {
281     Vector3    anchorPoint             = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::ANCHOR_POINT);
282     Vector3    parentOrigin            = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::PARENT_ORIGIN);
283     bool       positionUsesAnchorPoint = descentList[i].GetProperty<bool>(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT);
284     Vector3    size                    = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
285     Vector3    actorPosition           = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::POSITION);
286     Quaternion localOrientation        = descentList[i].GetProperty<Quaternion>(Dali::Actor::Property::ORIENTATION);
287     Vector3    localScale              = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SCALE);
288
289     Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
290     if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent())
291     {
292       Matrix  localMatrix;
293       Vector3 parentSize = descentList[i + 1].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
294       if(inheritanceModeList[i] == INHERIT_ALL)
295       {
296         localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
297         localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
298
299         //Update the world matrix
300         Matrix tempMatrix;
301         Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
302         worldMatrix = tempMatrix;
303       }
304       else
305       {
306         Vector3    parentPosition, parentScale;
307         Quaternion parentOrientation;
308         worldMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
309
310         if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
311         {
312           //Don't inherit scale
313           localScale /= parentScale;
314         }
315
316         if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
317         {
318           //Don't inherit orientation
319           parentOrientation.Invert();
320           localOrientation = parentOrientation * localOrientation;
321         }
322
323         if((inheritanceModeList[i] & INHERIT_POSITION) == 0)
324         {
325           localMatrix.SetTransformComponents(localScale, localOrientation, Vector3::ZERO);
326           Matrix tempMatrix;
327           Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
328           worldMatrix = tempMatrix;
329           worldMatrix.SetTranslation(actorPosition + centerPosition);
330         }
331         else
332         {
333           localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
334           localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
335           Matrix tempMatrix;
336           Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
337           worldMatrix = tempMatrix;
338         }
339       }
340     }
341     else
342     {
343       localPosition = actorPosition + centerPosition;
344       worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
345     }
346   }
347
348   return worldMatrix;
349 }
350
351 Vector4 TransitionBase::GetWorldColor(Dali::Actor actor)
352 {
353   std::vector<Dali::Actor>     descentList;
354   std::vector<Dali::ColorMode> inheritanceModeList;
355   Dali::Actor                  currentActor = actor;
356   Dali::ColorMode              inheritance  = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA;
357   do
358   {
359     inheritance = currentActor.GetProperty<Dali::ColorMode>(Dali::Actor::Property::COLOR_MODE);
360     inheritanceModeList.push_back(inheritance);
361     descentList.push_back(currentActor);
362     currentActor = currentActor.GetParent();
363   } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor);
364
365   Vector4 worldColor;
366   for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i)
367   {
368     if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1)
369     {
370       worldColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
371     }
372     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA)
373     {
374       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
375       worldColor       = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a);
376     }
377     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR)
378     {
379       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
380       worldColor *= ownColor;
381     }
382   }
383
384   return worldColor;
385 }
386
387 } // namespace Internal
388
389 } // namespace Toolkit
390
391 } // namespace Dali