2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/transition/transition-base-impl.h>
22 #include <dali-toolkit/public-api/controls/control-impl.h>
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>
39 static constexpr float OPACITY_TRANSPARENT = 0.0f;
41 const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION(Dali::AlphaFunction::DEFAULT);
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},
53 Property::Map GetOriginalProperties(Dali::Toolkit::Control control)
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]);
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.
81 Vector3 CalculateCenterPosition(
82 const Vector3& anchorPoint,
83 const bool positionUsesAnchorPoint,
86 const Quaternion& orientation)
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;
95 // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
96 if(!positionUsesAnchorPoint)
98 centerPosition -= (topLeft - anchorPoint) * size;
100 return centerPosition;
103 } // anonymous namespace
105 TransitionBasePtr TransitionBase::New()
107 TransitionBasePtr transition = new TransitionBase();
109 // Second-phase construction
110 transition->Initialize();
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)
125 void TransitionBase::Initialize()
130 void TransitionBase::SetTimePeriod(const Dali::TimePeriod& timePeriod)
132 if(timePeriod.durationSeconds < 0.0f)
134 DALI_LOG_WARNING("Duration should be greater than 0.0f.\n");
138 mTimePeriod.durationSeconds = timePeriod.durationSeconds;
141 if(timePeriod.delaySeconds < 0.0f)
143 DALI_LOG_WARNING("Delay should be greater than 0.0f.\n");
148 mTimePeriod.delaySeconds = timePeriod.delaySeconds;
152 Dali::TimePeriod TransitionBase::GetTimePeriod() const
157 void TransitionBase::TransitionWithChild(bool transitionWithChild)
159 mTransitionWithChild = transitionWithChild;
162 void TransitionBase::PreProcess(Dali::Animation animation)
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)
170 mMoveTargetChildren = true;
173 GetImplementation(mTarget).SetTransparent(false);
176 void TransitionBase::Play()
178 if(!mTarget[Dali::Actor::Property::CONNECTED_TO_SCENE])
180 DALI_LOG_ERROR("The target is not added on the window\n");
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);
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;
203 void TransitionBase::SetAnimation()
207 DALI_LOG_ERROR("animation is not initialized\n");
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)
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));
222 for(uint32_t i = 0; i < mStartPropertyMap.Count(); ++i)
224 Property::Value* finishValue = mFinishPropertyMap.Find(mStartPropertyMap.GetKeyAt(i).indexKey);
227 AnimateBetween(mTarget, mStartPropertyMap.GetKeyAt(i).indexKey, mStartPropertyMap.GetValue(i), *finishValue);
232 void TransitionBase::AnimateBetween(Dali::Toolkit::Control target, Property::Index index, Property::Value sourceValue, Property::Value destinationValue)
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)
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));
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);
254 void TransitionBase::CopyTarget()
256 mCopiedActor = Dali::Actor::New();
257 mTarget.GetParent().Add(mCopiedActor);
259 mCopiedActor[Dali::DevelActor::Property::SIBLING_ORDER] = static_cast<int32_t>(mTarget[Dali::DevelActor::Property::SIBLING_ORDER]) + 1;
260 while(mTarget.GetChildCount() > 0)
262 Dali::Actor child = mTarget.GetChildAt(0);
263 Dali::DevelActor::SwitchParent(child, mCopiedActor);
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);
271 void TransitionBase::TransitionFinished()
275 mTarget.SetProperties(mOriginalPropertyMap);
276 if(mMoveTargetChildren)
278 while(mCopiedActor.GetChildCount() > 0)
280 Dali::Actor child = mCopiedActor.GetChildAt(0);
281 Dali::DevelActor::SwitchParent(child, mTarget);
283 mCopiedActor.Unparent();
284 mCopiedActor.Reset();
289 Matrix TransitionBase::GetWorldTransform(Dali::Actor actor)
293 DONT_INHERIT_TRANSFORM = 0,
294 INHERIT_POSITION = 1,
296 INHERIT_ORIENTATION = 4,
297 INHERIT_ALL = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION,
300 std::vector<Dali::Actor> descentList;
301 std::vector<InheritanceMode> inheritanceModeList;
302 Dali::Actor currentActor = actor;
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);
315 Vector3 localPosition;
316 for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i)
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);
326 Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
327 if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent())
330 Vector3 parentSize = descentList[i + 1].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
331 if(inheritanceModeList[i] == INHERIT_ALL)
333 localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
334 localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
336 //Update the world matrix
338 Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
339 worldMatrix = tempMatrix;
343 Vector3 parentPosition, parentScale;
344 Quaternion parentOrientation;
345 worldMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
347 if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
349 //Don't inherit scale
350 localScale /= parentScale;
353 if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
355 //Don't inherit orientation
356 parentOrientation.Invert();
357 localOrientation = parentOrientation * localOrientation;
360 if((inheritanceModeList[i] & INHERIT_POSITION) == 0)
362 localMatrix.SetTransformComponents(localScale, localOrientation, Vector3::ZERO);
364 Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
365 worldMatrix = tempMatrix;
366 worldMatrix.SetTranslation(actorPosition + centerPosition);
370 localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
371 localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
373 Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
374 worldMatrix = tempMatrix;
380 localPosition = actorPosition + centerPosition;
381 worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
388 Vector4 TransitionBase::GetWorldColor(Dali::Actor actor)
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;
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);
403 for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i)
405 if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1)
407 worldColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
409 else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA)
411 Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
412 worldColor = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a);
414 else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR)
416 Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
417 worldColor *= ownColor;
424 } // namespace Internal
426 } // namespace Toolkit