[dali_2.3.20] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / transition / transition-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-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali/devel-api/actors/actor-devel.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/object/type-registry.h>
27
28 // INTERNAL INCLUDES
29 #include <dali-toolkit/devel-api/controls/control-devel.h>
30 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
31
32 namespace Dali
33 {
34 namespace Toolkit
35 {
36 namespace Internal
37 {
38 TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod)
39 {
40   float delaySeconds = timePeriod.delaySeconds;
41   if(delaySeconds < 0.0f)
42   {
43     DALI_LOG_WARNING("delay should be greater than 0.0f.\n");
44     delaySeconds = 0.0f;
45   }
46
47   float durationSeconds = timePeriod.durationSeconds;
48   if(durationSeconds < 0.0f)
49   {
50     DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
51     durationSeconds = 0.0f;
52   }
53
54   TransitionPtr transition = new Transition(source, destination, useDestinationTarget, TimePeriod(delaySeconds, durationSeconds));
55
56   // Second-phase construction
57   transition->Initialize();
58
59   return transition;
60 }
61
62 Transition::Transition(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod)
63 : TransitionBase(),
64   mUseDestinationTarget(useDestinationTarget),
65   mOriginalSize(),
66   mSourceControl(source),
67   mDestinationControl(destination)
68 {
69   SetTarget(mUseDestinationTarget ? destination : source);
70   SetTimePeriod(timePeriod);
71   SetPairTransition(true);
72 }
73
74 Transition::~Transition()
75 {
76 }
77
78 void Transition::OnPlay()
79 {
80   Dali::Toolkit::Control sourceControl      = mSourceControl.GetHandle();
81   Dali::Toolkit::Control destinationControl = mDestinationControl.GetHandle();
82   if(!sourceControl || !sourceControl[Dali::Actor::Property::CONNECTED_TO_SCENE] ||
83      !destinationControl || !destinationControl[Dali::Actor::Property::CONNECTED_TO_SCENE])
84   {
85     DALI_LOG_ERROR("The source or destination is not added on the window\n");
86     return;
87   }
88
89   //Make startPropertyMap and finishPropertyMap to use for property animation.
90   Matrix     sourceWorldTransform = DevelActor::GetWorldTransform(sourceControl);
91   Vector3    sourcePosition, sourceScale;
92   Quaternion sourceOrientation;
93   sourceWorldTransform.GetTransformComponents(sourcePosition, sourceOrientation, sourceScale);
94
95   Matrix     destinationWorldTransform = DevelActor::GetWorldTransform(destinationControl);
96   Vector3    destinationPosition, destinationScale;
97   Quaternion destinationOrientation;
98   destinationWorldTransform.GetTransformComponents(destinationPosition, destinationOrientation, destinationScale);
99
100   Property::Map startPropertyMap;
101   Property::Map finishPropertyMap;
102
103   // Set animation of Transform
104   startPropertyMap.Insert(Dali::Actor::Property::POSITION, sourcePosition);
105   finishPropertyMap.Insert(Dali::Actor::Property::POSITION, destinationPosition);
106
107   startPropertyMap.Insert(Dali::Actor::Property::ORIENTATION, sourceOrientation);
108   finishPropertyMap.Insert(Dali::Actor::Property::ORIENTATION, destinationOrientation);
109
110   startPropertyMap.Insert(Dali::Actor::Property::SCALE, sourceScale);
111   finishPropertyMap.Insert(Dali::Actor::Property::SCALE, destinationScale);
112
113   Vector4 sourceColor      = DevelActor::GetWorldColor(sourceControl);
114   Vector4 destinationColor = DevelActor::GetWorldColor(destinationControl);
115   startPropertyMap.Insert(Dali::Actor::Property::COLOR, sourceColor);
116   finishPropertyMap.Insert(Dali::Actor::Property::COLOR, destinationColor);
117
118   // Set animation for other properties if source and destination is different.
119   Vector3 sourceSize      = sourceControl[Dali::Actor::Property::SIZE];
120   Vector3 destinationSize = destinationControl[Dali::Actor::Property::SIZE];
121   if(sourceSize != destinationSize)
122   {
123     startPropertyMap.Insert(Dali::Actor::Property::SIZE, sourceSize);
124     finishPropertyMap.Insert(Dali::Actor::Property::SIZE, destinationSize);
125     if(!mUseDestinationTarget)
126     {
127       mOriginalSize = GetTargetControl().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
128     }
129   }
130
131   SetStartPropertyMap(startPropertyMap);
132   SetFinishPropertyMap(finishPropertyMap);
133
134   // source View becomes transparent during transition.
135   Dali::Toolkit::Control waitingControl = GetWaitingControl();
136   if(IsTransitionWithChild())
137   {
138     waitingControl[Dali::Actor::Property::VISIBLE] = false;
139   }
140   else
141   {
142     GetImplementation(waitingControl).SetTransparent(true);
143   }
144
145   Dali::Animation animation = GetAnimation();
146   if(!animation)
147   {
148     DALI_LOG_ERROR("animation is still not initialized\n");
149     return;
150   }
151
152   mOriginalVisualProperties.clear();
153   std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>> destinationVisualProperties;
154   Dali::Toolkit::Control                                             targetControl   = GetTargetControl();
155   Internal::Control&                                                 internalControl = Toolkit::Internal::GetImplementation(targetControl);
156   Internal::Control::Impl&                                           controlDataImpl = Toolkit::Internal::Control::Impl::Get(internalControl);
157   controlDataImpl.CreateTransitions(mOriginalVisualProperties, destinationVisualProperties, sourceControl, destinationControl);
158
159   for(uint32_t index = 0; index < mOriginalVisualProperties.size(); ++index)
160   {
161     Dali::Property::Map source      = mOriginalVisualProperties[index].second;
162     Dali::Property::Map destination = destinationVisualProperties[index].second;
163     for(size_t i = 0; i < source.Count(); ++i)
164     {
165       Dali::Property property = DevelControl::GetVisualProperty(targetControl, mOriginalVisualProperties[index].first, source.GetKeyAt(i));
166       if(GetTimePeriod().delaySeconds > 0.0f)
167       {
168         Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
169         initialKeyframes.Add(0.0f, source.GetValue(i));
170         animation.AnimateBetween(property, initialKeyframes, TimePeriod(GetTimePeriod().delaySeconds));
171       }
172       Dali::KeyFrames keyframes = Dali::KeyFrames::New();
173       keyframes.Add(0.0f, source.GetValue(i));
174       keyframes.Add(1.0f, destination.GetValue(i));
175       animation.AnimateBetween(property, keyframes, GetAlphaFunction(), GetTimePeriod());
176     }
177   }
178 }
179
180 void Transition::OnFinished()
181 {
182   Dali::Toolkit::Control waitingControl = GetWaitingControl();
183   if(!waitingControl)
184   {
185     return;
186   }
187
188   if(!mUseDestinationTarget)
189   {
190     Dali::Toolkit::Control target         = GetTargetControl();
191     Dali::Animation        resetAnimation = Dali::Animation::New(0.0f);
192     if(mOriginalSize != target.GetProperty<Vector3>(Dali::Actor::Property::SIZE))
193     {
194       // Use Animation not to notify size change and not to change width and height resize policy.
195       resetAnimation.AnimateTo(Dali::Property(target, Dali::Actor::Property::SIZE), mOriginalSize);
196     }
197     resetAnimation.Play();
198
199     Dali::Toolkit::Control   targetControl   = GetTargetControl();
200     Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(targetControl);
201     Internal::Control::Impl& controlDataImpl = Toolkit::Internal::Control::Impl::Get(internalControl);
202     controlDataImpl.UpdateVisualProperties(mOriginalVisualProperties);
203   }
204
205   if(IsTransitionWithChild())
206   {
207     waitingControl[Dali::Actor::Property::VISIBLE] = true;
208   }
209   else
210   {
211     GetImplementation(waitingControl).SetTransparent(false);
212   }
213 }
214
215 Dali::Toolkit::Control Transition::GetTargetControl()
216 {
217   Dali::Toolkit::Control target = mUseDestinationTarget ? mDestinationControl.GetHandle() : mSourceControl.GetHandle();
218   return target;
219 }
220
221 Dali::Toolkit::Control Transition::GetWaitingControl()
222 {
223   Dali::Toolkit::Control waitingControl = mUseDestinationTarget ? mSourceControl.GetHandle() : mDestinationControl.GetHandle();
224   return waitingControl;
225 }
226
227 } // namespace Internal
228
229 } // namespace Toolkit
230
231 } // namespace Dali