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