CanvasView: Do ApplyNativeFragmentShader for NativeImage buffer
[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 static constexpr float OPACITY_TRANSPARENT = 0.0f;
40
41 const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION(Dali::AlphaFunction::DEFAULT);
42
43 const Property::Map PROPERTY_MAP_INDEPENDENT_CONTROL{
44   {Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER},
45   {Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER},
46   {Dali::Actor::Property::POSITION_USES_ANCHOR_POINT, true},
47   {Dali::Actor::Property::INHERIT_POSITION, false},
48   {Dali::Actor::Property::INHERIT_ORIENTATION, false},
49   {Dali::Actor::Property::INHERIT_SCALE, false},
50   {Dali::Actor::Property::COLOR_MODE, Dali::ColorMode::USE_OWN_COLOR},
51 };
52
53 Property::Map GetOriginalProperties(Dali::Toolkit::Control control)
54 {
55   Property::Map propertyMap;
56   propertyMap.Insert(Dali::Actor::Property::ANCHOR_POINT, control[Dali::Actor::Property::ANCHOR_POINT]);
57   propertyMap.Insert(Dali::Actor::Property::PARENT_ORIGIN, control[Dali::Actor::Property::PARENT_ORIGIN]);
58   propertyMap.Insert(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT, control[Dali::Actor::Property::POSITION_USES_ANCHOR_POINT]);
59   propertyMap.Insert(Dali::Actor::Property::INHERIT_POSITION, control[Dali::Actor::Property::INHERIT_POSITION]);
60   propertyMap.Insert(Dali::Actor::Property::INHERIT_ORIENTATION, control[Dali::Actor::Property::INHERIT_ORIENTATION]);
61   propertyMap.Insert(Dali::Actor::Property::INHERIT_SCALE, control[Dali::Actor::Property::INHERIT_SCALE]);
62   propertyMap.Insert(Dali::Actor::Property::COLOR_MODE, control[Dali::Actor::Property::COLOR_MODE]);
63   propertyMap.Insert(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, control[Dali::Actor::Property::HEIGHT_RESIZE_POLICY]);
64   propertyMap.Insert(Dali::Actor::Property::WIDTH_RESIZE_POLICY, control[Dali::Actor::Property::WIDTH_RESIZE_POLICY]);
65   propertyMap.Insert(Dali::Actor::Property::POSITION, control[Dali::Actor::Property::POSITION]);
66   propertyMap.Insert(Dali::Actor::Property::ORIENTATION, control[Dali::Actor::Property::ORIENTATION]);
67   propertyMap.Insert(Dali::Actor::Property::SCALE, control[Dali::Actor::Property::SCALE]);
68   propertyMap.Insert(Dali::Actor::Property::COLOR, control[Dali::Actor::Property::COLOR]);
69
70   return propertyMap;
71 }
72
73 /**
74  * @brief Computes and center position by using transform properties.
75  * @param[in] anchorPoint anchorPoint of an actor.
76  * @param[in] positionUsesAnchorPoint positionUsesAnchorPoint of an actor.
77  * @param[in] size size of an actor.
78  * @param[in] scale scale of an actor.
79  * @param[in] orientation orientation of an actor.
80  */
81 Vector3 CalculateCenterPosition(
82   const Vector3&    anchorPoint,
83   const bool        positionUsesAnchorPoint,
84   const Vector3&    size,
85   const Vector3&    scale,
86   const Quaternion& orientation)
87 {
88   Vector3       centerPosition;
89   const Vector3 half(0.5f, 0.5f, 0.5f);
90   const Vector3 topLeft(0.0f, 0.0f, 0.5f);
91   // Calculate the center-point by applying the scale and rotation on the anchor point.
92   centerPosition = (half - anchorPoint) * size * scale;
93   centerPosition *= orientation;
94
95   // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
96   if(!positionUsesAnchorPoint)
97   {
98     centerPosition -= (topLeft - anchorPoint) * size;
99   }
100   return centerPosition;
101 }
102
103 } // anonymous namespace
104
105 TransitionBasePtr TransitionBase::New()
106 {
107   TransitionBasePtr transition = new TransitionBase();
108
109   // Second-phase construction
110   transition->Initialize();
111
112   return transition;
113 }
114
115 TransitionBase::TransitionBase()
116 : mAlphaFunction(DEFAULT_ALPHA_FUNCTION),
117   mTimePeriod(TimePeriod(0.0f)),
118   mTransitionWithChild(false),
119   mMoveTargetChildren(false),
120   mIsAppearingTransition(true),
121   mIsPairTransition(false)
122 {
123 }
124
125 void TransitionBase::Initialize()
126 {
127   RegisterObject();
128 }
129
130 void TransitionBase::SetTimePeriod(const Dali::TimePeriod& timePeriod)
131 {
132   if(timePeriod.durationSeconds < 0.0f)
133   {
134     DALI_LOG_WARNING("Duration should be greater than 0.0f.\n");
135   }
136   else
137   {
138     mTimePeriod.durationSeconds = timePeriod.durationSeconds;
139   }
140
141   if(timePeriod.delaySeconds < 0.0f)
142   {
143     DALI_LOG_WARNING("Delay should be greater than 0.0f.\n");
144     return;
145   }
146   else
147   {
148     mTimePeriod.delaySeconds = timePeriod.delaySeconds;
149   }
150 }
151
152 Dali::TimePeriod TransitionBase::GetTimePeriod() const
153 {
154   return mTimePeriod;
155 }
156
157 void TransitionBase::TransitionWithChild(bool transitionWithChild)
158 {
159   mTransitionWithChild = transitionWithChild;
160 }
161
162 void TransitionBase::PreProcess(Dali::Animation animation)
163 {
164   mAnimation           = animation;
165   // Retrieve original property map of mTarget to backup and to reset after transition is finished.
166   mOriginalPropertyMap = GetOriginalProperties(mTarget);
167   mMoveTargetChildren  = false;
168   if(!mTransitionWithChild && mTarget.GetChildCount() > 0)
169   {
170     mMoveTargetChildren = true;
171     CopyTarget();
172   }
173   GetImplementation(mTarget).SetTransparent(false);
174 }
175
176 void TransitionBase::Play()
177 {
178   if(!mTarget[Dali::Actor::Property::CONNECTED_TO_SCENE])
179   {
180     DALI_LOG_ERROR("The target is not added on the window\n");
181     return;
182   }
183
184   // Set world transform and color to the target control to make it independent of the parent control and its transition.
185   // The properties will be returned at the TransitionFinished() method.
186   Matrix     targetWorldTransform = GetWorldTransform(mTarget);
187   Vector3    targetPosition, targetScale;
188   Quaternion targetOrientation;
189   targetWorldTransform.GetTransformComponents(targetPosition, targetOrientation, targetScale);
190   Vector4 targetColor = GetWorldColor(mTarget);
191
192   mTarget.SetProperties(PROPERTY_MAP_INDEPENDENT_CONTROL);
193   mTarget[Dali::Actor::Property::POSITION]    = targetPosition;
194   mTarget[Dali::Actor::Property::SCALE]       = targetScale;
195   mTarget[Dali::Actor::Property::ORIENTATION] = targetOrientation;
196   mTarget[Dali::Actor::Property::COLOR]       = targetColor;
197
198   OnPlay();
199
200   SetAnimation();
201 }
202
203 void TransitionBase::SetAnimation()
204 {
205   if(!mAnimation)
206   {
207     DALI_LOG_ERROR("animation is not initialized\n");
208     return;
209   }
210
211   // If this transition is not a transition from a Control to another Control
212   // and a transition effect to appear with delay,
213   // the mTarget should not be shown until delay seconds.
214   if(!IsPairTransition() && mIsAppearingTransition && mAnimation && mTimePeriod.delaySeconds > Dali::Math::MACHINE_EPSILON_10)
215   {
216     Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
217     initialKeyframes.Add(0.0f, OPACITY_TRANSPARENT);
218     initialKeyframes.Add(1.0f, OPACITY_TRANSPARENT);
219     mAnimation.AnimateBetween(Property(mTarget, Dali::Actor::Property::OPACITY), initialKeyframes, TimePeriod(mTimePeriod.delaySeconds));
220   }
221
222   for(uint32_t i = 0; i < mStartPropertyMap.Count(); ++i)
223   {
224     Property::Value* finishValue = mFinishPropertyMap.Find(mStartPropertyMap.GetKeyAt(i).indexKey);
225     if(finishValue)
226     {
227       AnimateBetween(mTarget, mStartPropertyMap.GetKeyAt(i).indexKey, mStartPropertyMap.GetValue(i), *finishValue);
228     }
229   }
230 }
231
232 void TransitionBase::AnimateBetween(Dali::Toolkit::Control target, Property::Index index, Property::Value sourceValue, Property::Value destinationValue)
233 {
234   if(mAnimation)
235   {
236     // To make each property keep start value during delay time.
237     // When this transition is not Pair transition, it is not required.
238     // (For appearing transition, the mTarget control will not be shown during delay time,
239     //  For disapplearing transition, the property of mTarget control keeps current value during delay time)
240     if(IsPairTransition() && mTimePeriod.delaySeconds > Dali::Math::MACHINE_EPSILON_10)
241     {
242       Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
243       initialKeyframes.Add(0.0f, sourceValue);
244       initialKeyframes.Add(1.0f, sourceValue);
245       mAnimation.AnimateBetween(Property(target, index), initialKeyframes, TimePeriod(mTimePeriod.delaySeconds));
246     }
247     Dali::KeyFrames keyframes = Dali::KeyFrames::New();
248     keyframes.Add(0.0f, sourceValue);
249     keyframes.Add(1.0f, destinationValue);
250     mAnimation.AnimateBetween(Property(target, index), keyframes, mAlphaFunction, mTimePeriod);
251   }
252 }
253
254 void TransitionBase::CopyTarget()
255 {
256   mCopiedActor = Dali::Actor::New();
257   mTarget.GetParent().Add(mCopiedActor);
258
259   mCopiedActor[Dali::DevelActor::Property::SIBLING_ORDER] = static_cast<int32_t>(mTarget[Dali::DevelActor::Property::SIBLING_ORDER]) + 1;
260   while(mTarget.GetChildCount() > 0)
261   {
262     Dali::Actor child = mTarget.GetChildAt(0);
263     Dali::DevelActor::SwitchParent(child, mCopiedActor);
264   }
265
266   // Copy Size property to mCopiedActor because Size is not included mOriginalPropertyMap.
267   mCopiedActor[Dali::Actor::Property::SIZE] = mTarget.GetProperty<Vector3>(Dali::Actor::Property::SIZE);
268   mCopiedActor.SetProperties(mOriginalPropertyMap);
269 }
270
271 void TransitionBase::TransitionFinished()
272 {
273   OnFinished();
274
275   mTarget.SetProperties(mOriginalPropertyMap);
276   if(mMoveTargetChildren)
277   {
278     while(mCopiedActor.GetChildCount() > 0)
279     {
280       Dali::Actor child = mCopiedActor.GetChildAt(0);
281       Dali::DevelActor::SwitchParent(child, mTarget);
282     }
283     mCopiedActor.Unparent();
284     mCopiedActor.Reset();
285   }
286   mAnimation.Reset();
287 }
288
289 Matrix TransitionBase::GetWorldTransform(Dali::Actor actor)
290 {
291   enum InheritanceMode
292   {
293     DONT_INHERIT_TRANSFORM = 0,
294     INHERIT_POSITION       = 1,
295     INHERIT_SCALE          = 2,
296     INHERIT_ORIENTATION    = 4,
297     INHERIT_ALL            = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION,
298   };
299
300   std::vector<Dali::Actor>     descentList;
301   std::vector<InheritanceMode> inheritanceModeList;
302   Dali::Actor                  currentActor = actor;
303   int                          inheritance  = 0;
304   do
305   {
306     inheritance = (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_ORIENTATION)) << 2) +
307                   (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_SCALE)) << 1) +
308                   static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_POSITION));
309     inheritanceModeList.push_back(static_cast<InheritanceMode>(inheritance));
310     descentList.push_back(currentActor);
311     currentActor = currentActor.GetParent();
312   } while(inheritance != DONT_INHERIT_TRANSFORM && currentActor);
313
314   Matrix  worldMatrix;
315   Vector3 localPosition;
316   for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i)
317   {
318     Vector3    anchorPoint             = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::ANCHOR_POINT);
319     Vector3    parentOrigin            = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::PARENT_ORIGIN);
320     bool       positionUsesAnchorPoint = descentList[i].GetProperty<bool>(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT);
321     Vector3    size                    = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
322     Vector3    actorPosition           = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::POSITION);
323     Quaternion localOrientation        = descentList[i].GetProperty<Quaternion>(Dali::Actor::Property::ORIENTATION);
324     Vector3    localScale              = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SCALE);
325
326     Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
327     if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent())
328     {
329       Matrix  localMatrix;
330       Vector3 parentSize = descentList[i + 1].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
331       if(inheritanceModeList[i] == INHERIT_ALL)
332       {
333         localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
334         localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
335
336         //Update the world matrix
337         Matrix tempMatrix;
338         Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
339         worldMatrix = tempMatrix;
340       }
341       else
342       {
343         Vector3    parentPosition, parentScale;
344         Quaternion parentOrientation;
345         worldMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
346
347         if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
348         {
349           //Don't inherit scale
350           localScale /= parentScale;
351         }
352
353         if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
354         {
355           //Don't inherit orientation
356           parentOrientation.Invert();
357           localOrientation = parentOrientation * localOrientation;
358         }
359
360         if((inheritanceModeList[i] & INHERIT_POSITION) == 0)
361         {
362           localMatrix.SetTransformComponents(localScale, localOrientation, Vector3::ZERO);
363           Matrix tempMatrix;
364           Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
365           worldMatrix = tempMatrix;
366           worldMatrix.SetTranslation(actorPosition + centerPosition);
367         }
368         else
369         {
370           localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
371           localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
372           Matrix tempMatrix;
373           Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
374           worldMatrix = tempMatrix;
375         }
376       }
377     }
378     else
379     {
380       localPosition = actorPosition + centerPosition;
381       worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
382     }
383   }
384
385   return worldMatrix;
386 }
387
388 Vector4 TransitionBase::GetWorldColor(Dali::Actor actor)
389 {
390   std::vector<Dali::Actor>     descentList;
391   std::vector<Dali::ColorMode> inheritanceModeList;
392   Dali::Actor                  currentActor = actor;
393   Dali::ColorMode              inheritance  = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA;
394   do
395   {
396     inheritance = currentActor.GetProperty<Dali::ColorMode>(Dali::Actor::Property::COLOR_MODE);
397     inheritanceModeList.push_back(inheritance);
398     descentList.push_back(currentActor);
399     currentActor = currentActor.GetParent();
400   } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor);
401
402   Vector4 worldColor;
403   for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i)
404   {
405     if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1)
406     {
407       worldColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
408     }
409     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA)
410     {
411       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
412       worldColor       = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a);
413     }
414     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR)
415     {
416       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
417       worldColor *= ownColor;
418     }
419   }
420
421   return worldColor;
422 }
423
424 } // namespace Internal
425
426 } // namespace Toolkit
427
428 } // namespace Dali