[dali_2.3.20] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / transition / transition-base-impl.cpp
1 /*
2  * Copyright (c) 2022 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 Property::Map GetOriginalProperties(Dali::Toolkit::Control control)
40 {
41   Property::Map propertyMap;
42   propertyMap.Insert(Dali::Actor::Property::ANCHOR_POINT, control[Dali::Actor::Property::ANCHOR_POINT]);
43   propertyMap.Insert(Dali::Actor::Property::PARENT_ORIGIN, control[Dali::Actor::Property::PARENT_ORIGIN]);
44   propertyMap.Insert(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT, control[Dali::Actor::Property::POSITION_USES_ANCHOR_POINT]);
45   propertyMap.Insert(Dali::Actor::Property::INHERIT_POSITION, control[Dali::Actor::Property::INHERIT_POSITION]);
46   propertyMap.Insert(Dali::Actor::Property::INHERIT_ORIENTATION, control[Dali::Actor::Property::INHERIT_ORIENTATION]);
47   propertyMap.Insert(Dali::Actor::Property::INHERIT_SCALE, control[Dali::Actor::Property::INHERIT_SCALE]);
48   propertyMap.Insert(Dali::Actor::Property::COLOR_MODE, control[Dali::Actor::Property::COLOR_MODE]);
49   propertyMap.Insert(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, control[Dali::Actor::Property::HEIGHT_RESIZE_POLICY]);
50   propertyMap.Insert(Dali::Actor::Property::WIDTH_RESIZE_POLICY, control[Dali::Actor::Property::WIDTH_RESIZE_POLICY]);
51   propertyMap.Insert(Dali::Actor::Property::POSITION, control[Dali::Actor::Property::POSITION]);
52   propertyMap.Insert(Dali::Actor::Property::ORIENTATION, control[Dali::Actor::Property::ORIENTATION]);
53   propertyMap.Insert(Dali::Actor::Property::SCALE, control[Dali::Actor::Property::SCALE]);
54   propertyMap.Insert(Dali::Actor::Property::COLOR, control[Dali::Actor::Property::COLOR]);
55
56   return propertyMap;
57 }
58 } // anonymous namespace
59
60 TransitionBasePtr TransitionBase::New()
61 {
62   TransitionBasePtr transition = new TransitionBase();
63
64   // Second-phase construction
65   transition->Initialize();
66
67   return transition;
68 }
69
70 TransitionBase::TransitionBase()
71 : mAlphaFunction(Dali::AlphaFunction::DEFAULT),
72   mTimePeriod(TimePeriod(0.0f)),
73   mTransitionWithChild(false),
74   mMoveTargetChildren(false),
75   mIsAppearingTransition(true),
76   mIsPairTransition(false)
77 {
78 }
79
80 void TransitionBase::Initialize()
81 {
82   RegisterObject();
83 }
84
85 void TransitionBase::SetTimePeriod(const Dali::TimePeriod& timePeriod)
86 {
87   if(timePeriod.durationSeconds < 0.0f)
88   {
89     DALI_LOG_WARNING("Duration should be greater than 0.0f.\n");
90   }
91   else
92   {
93     mTimePeriod.durationSeconds = timePeriod.durationSeconds;
94   }
95
96   if(timePeriod.delaySeconds < 0.0f)
97   {
98     DALI_LOG_WARNING("Delay should be greater than 0.0f.\n");
99     return;
100   }
101   else
102   {
103     mTimePeriod.delaySeconds = timePeriod.delaySeconds;
104   }
105 }
106
107 Dali::TimePeriod TransitionBase::GetTimePeriod() const
108 {
109   return mTimePeriod;
110 }
111
112 void TransitionBase::TransitionWithChild(bool transitionWithChild)
113 {
114   mTransitionWithChild = transitionWithChild;
115 }
116
117 void TransitionBase::PreProcess(Dali::Animation animation)
118 {
119   mAnimation = animation;
120   // Retrieve original property map of mTarget to backup and to reset after transition is finished.
121   mOriginalPropertyMap = GetOriginalProperties(mTarget);
122   mMoveTargetChildren  = false;
123   if(!mTransitionWithChild && mTarget.GetChildCount() > 0)
124   {
125     mMoveTargetChildren = true;
126     CopyTarget();
127   }
128   GetImplementation(mTarget).SetTransparent(false);
129 }
130
131 void TransitionBase::Play()
132 {
133   if(!mTarget[Dali::Actor::Property::CONNECTED_TO_SCENE])
134   {
135     DALI_LOG_ERROR("The target is not added on the window\n");
136     return;
137   }
138
139   // Set world transform and color to the target control to make it independent of the parent control and its transition.
140   // The properties will be returned at the TransitionFinished() method.
141   Matrix     targetWorldTransform = DevelActor::GetWorldTransform(mTarget);
142   Vector3    targetPosition, targetScale;
143   Quaternion targetOrientation;
144   targetWorldTransform.GetTransformComponents(targetPosition, targetOrientation, targetScale);
145   Vector4 targetColor = DevelActor::GetWorldColor(mTarget);
146
147   mTarget[Dali::Actor::Property::ANCHOR_POINT]               = AnchorPoint::CENTER;
148   mTarget[Dali::Actor::Property::PARENT_ORIGIN]              = ParentOrigin::CENTER;
149   mTarget[Dali::Actor::Property::POSITION_USES_ANCHOR_POINT] = true;
150   mTarget[Dali::Actor::Property::INHERIT_POSITION]           = false;
151   mTarget[Dali::Actor::Property::INHERIT_ORIENTATION]        = false;
152   mTarget[Dali::Actor::Property::INHERIT_SCALE]              = false;
153   mTarget[Dali::Actor::Property::COLOR_MODE]                 = Dali::ColorMode::USE_OWN_COLOR;
154
155   mTarget[Dali::Actor::Property::POSITION]    = targetPosition;
156   mTarget[Dali::Actor::Property::SCALE]       = targetScale;
157   mTarget[Dali::Actor::Property::ORIENTATION] = targetOrientation;
158   mTarget[Dali::Actor::Property::COLOR]       = targetColor;
159
160   OnPlay();
161
162   SetAnimation();
163 }
164
165 void TransitionBase::SetAnimation()
166 {
167   if(!mAnimation)
168   {
169     DALI_LOG_ERROR("animation is not initialized\n");
170     return;
171   }
172
173   for(uint32_t i = 0; i < mStartPropertyMap.Count(); ++i)
174   {
175     Property::Value* finishValue = mFinishPropertyMap.Find(mStartPropertyMap.GetKeyAt(i).indexKey);
176     if(finishValue)
177     {
178       // If this transition is appearing transition, this property keeps start value during delay.
179       // If multiple transitions are applied to this Control and others run before this transition,
180       // this property should keep start value until this transition starts.
181       if(!IsPairTransition() && IsAppearingTransition() && mTimePeriod.delaySeconds > Dali::Math::MACHINE_EPSILON_10)
182       {
183         mTarget.SetProperty(mStartPropertyMap.GetKeyAt(i).indexKey, mStartPropertyMap.GetValue(i));
184       }
185       AnimateBetween(mTarget, mStartPropertyMap.GetKeyAt(i).indexKey, mStartPropertyMap.GetValue(i), *finishValue);
186     }
187   }
188 }
189
190 void TransitionBase::AnimateBetween(Dali::Toolkit::Control target, Property::Index index, Property::Value sourceValue, Property::Value destinationValue)
191 {
192   if(mAnimation)
193   {
194     // To make each property keep start value during delay time.
195     // When this transition is not Pair transition, it is not required.
196     // (For appearing transition, the mTarget control will not be shown during delay time,
197     //  For disapplearing transition, the property of mTarget control keeps current value during delay time)
198     if(IsPairTransition() && mTimePeriod.delaySeconds > Dali::Math::MACHINE_EPSILON_10)
199     {
200       Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
201       initialKeyframes.Add(0.0f, sourceValue);
202       initialKeyframes.Add(1.0f, sourceValue);
203       mAnimation.AnimateBetween(Property(target, index), initialKeyframes, TimePeriod(mTimePeriod.delaySeconds));
204     }
205     Dali::KeyFrames keyframes = Dali::KeyFrames::New();
206     keyframes.Add(0.0f, sourceValue);
207     keyframes.Add(1.0f, destinationValue);
208     mAnimation.AnimateBetween(Property(target, index), keyframes, mAlphaFunction, mTimePeriod);
209   }
210 }
211
212 void TransitionBase::CopyTarget()
213 {
214   mCopiedActor = Dali::Actor::New();
215   mTarget.GetParent().Add(mCopiedActor);
216
217   mCopiedActor[Dali::DevelActor::Property::SIBLING_ORDER] = static_cast<int32_t>(mTarget[Dali::DevelActor::Property::SIBLING_ORDER]) + 1;
218   while(mTarget.GetChildCount() > 0)
219   {
220     Dali::Actor child = mTarget.GetChildAt(0);
221     Dali::DevelActor::SwitchParent(child, mCopiedActor);
222   }
223
224   // Copy Size property to mCopiedActor because Size is not included mOriginalPropertyMap.
225   mCopiedActor[Dali::Actor::Property::SIZE] = mTarget.GetProperty<Vector3>(Dali::Actor::Property::SIZE);
226   mCopiedActor.SetProperties(mOriginalPropertyMap);
227 }
228
229 void TransitionBase::TransitionFinished()
230 {
231   OnFinished();
232
233   mTarget.SetProperties(mOriginalPropertyMap);
234   if(mMoveTargetChildren)
235   {
236     while(mCopiedActor.GetChildCount() > 0)
237     {
238       Dali::Actor child = mCopiedActor.GetChildAt(0);
239       Dali::DevelActor::SwitchParent(child, mTarget);
240     }
241     mCopiedActor.Unparent();
242     mCopiedActor.Reset();
243   }
244   mAnimation.Reset();
245 }
246
247 } // namespace Internal
248
249 } // namespace Toolkit
250
251 } // namespace Dali