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