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