2 * Copyright (c) 2014 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/devel-api/common/stage.h>
20 #include <dali/integration-api/debug.h>
21 #include <dali/public-api/actors/layer.h>
24 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
25 #include <dali-toolkit/internal/builder/builder-impl.h>
26 #include <dali-toolkit/internal/builder/replacement.h>
28 namespace // unnamed namespace
32 TimePeriod GetTimePeriod(const TreeNode& child, const Toolkit::Internal::Replacement& constant)
34 OptionalFloat delay = constant.IsFloat(IsChild(child, "delay"));
35 OptionalFloat duration = constant.IsFloat(IsChild(child, "duration"));
36 DALI_ASSERT_ALWAYS(duration && "Time period must have at least a duration");
40 return TimePeriod(*delay, *duration);
44 return TimePeriod(*duration);
48 Property::Value GetPropertyValue(const Property::Type& propType, const TreeNode& child)
52 case Property::BOOLEAN:
54 return Property::Value(GetBoolean(child));
59 return Property::Value(GetFloat(child));
62 case Property::VECTOR2:
64 return Property::Value(GetVector2(child));
67 case Property::VECTOR3:
69 return Property::Value(GetVector3(child));
72 case Property::VECTOR4:
74 return Property::Value(GetVector4(child));
77 case Property::ROTATION:
81 Vector4 v(GetVector4(child));
82 // angle, axis as per spec
83 return Property::Value(Quaternion(Radian(Degree(v[3])),
84 Vector3(v[0], v[1], v[2])));
88 // degrees as per spec
89 Vector3 rotation = GetVector3(child);
90 return Property::Value(Quaternion(Radian(Degree(rotation.x)),
91 Radian(Degree(rotation.y)),
92 Radian(Degree(rotation.z))));
96 case Property::NONE: // fall
99 DALI_ASSERT_ALWAYS(!"Property type incorrect");
104 AlphaFunction GetAlphaFunction(const std::string& alphaFunction)
106 typedef std::map<const std::string, Dali::AlphaFunction> AlphaFunctionLut;
107 static AlphaFunctionLut alphaFunctionLut;
109 if(0 == alphaFunctionLut.size())
111 // coding convention is uppercase enums
112 alphaFunctionLut["DEFAULT"] = AlphaFunction(AlphaFunction::DEFAULT);
113 alphaFunctionLut["LINEAR"] = AlphaFunction(AlphaFunction::LINEAR);
114 alphaFunctionLut["REVERSE"] = AlphaFunction(AlphaFunction::REVERSE);
115 alphaFunctionLut["EASE_IN_SQUARE"] = AlphaFunction(AlphaFunction::EASE_IN_SQUARE);
116 alphaFunctionLut["EASE_OUT_SQUARE"] = AlphaFunction(AlphaFunction::EASE_OUT_SQUARE);
117 alphaFunctionLut["EASE_IN"] = AlphaFunction(AlphaFunction::EASE_IN);
118 alphaFunctionLut["EASE_OUT"] = AlphaFunction(AlphaFunction::EASE_OUT);
119 alphaFunctionLut["EASE_IN_OUT"] = AlphaFunction(AlphaFunction::EASE_IN_OUT);
120 alphaFunctionLut["EASE_IN_SINE"] = AlphaFunction(AlphaFunction::EASE_IN_SINE);
121 alphaFunctionLut["EASE_OUT_SINE"] = AlphaFunction(AlphaFunction::EASE_OUT_SINE);
122 alphaFunctionLut["EASE_IN_OUT_SINE"] = AlphaFunction(AlphaFunction::EASE_IN_OUT_SINE);
123 alphaFunctionLut["BOUNCE"] = AlphaFunction(AlphaFunction::BOUNCE);
124 alphaFunctionLut["SIN"] = AlphaFunction(AlphaFunction::SIN);
125 alphaFunctionLut["EASE_OUT_BACK"] = AlphaFunction(AlphaFunction::EASE_OUT_BACK);
128 const AlphaFunctionLut::const_iterator iter(alphaFunctionLut.find(alphaFunction));
130 if(iter != alphaFunctionLut.end())
136 DALI_ASSERT_ALWAYS(iter != alphaFunctionLut.end() && "Unknown Alpha Constant");
137 return Dali::AlphaFunction::DEFAULT;
141 } // unnamed namespace
149 Animation CreateAnimation(const TreeNode& child, const Replacement& constant, Dali::Actor searchRoot, Builder* const builder)
151 float durationSum = 0.f;
153 Dali::Actor searchActor = searchRoot ? searchRoot : Dali::Stage::GetCurrent().GetRootLayer();
155 Animation animation(Animation::New(0.f));
157 // duration needs to be set before AnimateTo calls for correct operation when AnimateTo has no "timePeriod".
158 OptionalFloat duration = constant.IsFloat(IsChild(child, "duration"));
162 animation.SetDuration(*duration);
165 if(OptionalBoolean looping = constant.IsBoolean(IsChild(child, "loop")))
167 animation.SetLooping(*looping);
170 if(OptionalString endAction = constant.IsString(IsChild(child, "endAction")))
172 if("BAKE" == *endAction)
174 animation.SetEndAction(Animation::BAKE);
176 else if("DISCARD" == *endAction)
178 animation.SetEndAction(Animation::DISCARD);
180 else if("BAKE_FINAL" == *endAction)
182 animation.SetEndAction(Animation::BAKE_FINAL);
186 if(OptionalString endAction = constant.IsString(IsChild(child, "disconnectAction")))
188 if("BAKE" == *endAction)
190 animation.SetDisconnectAction(Animation::BAKE);
192 else if("DISCARD" == *endAction)
194 animation.SetDisconnectAction(Animation::DISCARD);
196 else if("BAKE_FINAL" == *endAction)
198 animation.SetDisconnectAction(Animation::BAKE_FINAL);
202 OptionalChild propertiesNode = IsChild(child, "properties");
205 const TreeNode::ConstIterator endIter = (*propertiesNode).CEnd();
206 for(TreeNode::ConstIterator iter = (*propertiesNode).CBegin(); endIter != iter; ++iter)
208 const TreeNode::KeyNodePair& pKeyChild = *iter;
210 OptionalString actorName(constant.IsString(IsChild(pKeyChild.second, "actor")));
211 OptionalString property(constant.IsString(IsChild(pKeyChild.second, "property")));
212 DALI_ASSERT_ALWAYS(actorName && "Animation must specify actor name");
214 Handle targetHandle = searchActor.FindChildByName(*actorName);
215 DALI_ASSERT_ALWAYS(targetHandle && "Actor must exist for property");
217 Property::Value propValue;
218 Property::Index propIndex = Property::INVALID_INDEX;
221 propIndex = targetHandle.GetPropertyIndex(*property);
223 // if the property is not found from the (actor) handle, try to downcast it to renderable actor
224 // to allow animating shader uniforms
225 if(propIndex == Property::INVALID_INDEX)
227 DALI_SCRIPT_WARNING("Cannot find property on object\n");
232 // these are the defaults
233 AlphaFunction alphaFunction(AlphaFunction::DEFAULT);
234 TimePeriod timePeriod(0.f);
236 OptionalChild timeChild = IsChild(pKeyChild.second, "timePeriod");
240 timePeriod = GetTimePeriod(*timeChild, constant);
243 durationSum = std::max(durationSum, timePeriod.delaySeconds + timePeriod.durationSeconds);
245 if(OptionalString alphaChild = constant.IsString(IsChild(pKeyChild.second, "alphaFunction")))
247 alphaFunction = GetAlphaFunction(*alphaChild);
250 if(OptionalChild keyFrameChild = IsChild(pKeyChild.second, "keyFrames"))
252 DALI_ASSERT_ALWAYS(property && "Animation must specify a property name");
253 Property prop = Property(targetHandle, propIndex);
255 KeyFrames keyframes = KeyFrames::New();
257 const TreeNode::ConstIterator endIter = (*keyFrameChild).CEnd();
258 for(TreeNode::ConstIterator iter = (*keyFrameChild).CBegin(); endIter != iter; ++iter)
260 const TreeNode::KeyNodePair& kfKeyChild = *iter;
262 OptionalFloat kfProgress = constant.IsFloat(IsChild(kfKeyChild.second, "progress"));
263 DALI_ASSERT_ALWAYS(kfProgress && "Key frame entry must have 'progress'");
265 OptionalChild kfValue = IsChild(kfKeyChild.second, "value");
266 DALI_ASSERT_ALWAYS(kfValue && "Key frame entry must have 'value'");
270 propValue = GetPropertyValue(prop.object.GetPropertyType(prop.propertyIndex), *kfValue);
274 DALI_LOG_WARNING("Property:'%s' type does not match value type '%s'\n",
276 PropertyTypes::GetName(prop.object.GetPropertyType(prop.propertyIndex)));
281 AlphaFunction kfAlphaFunction(AlphaFunction::DEFAULT);
282 if(OptionalString alphaFuncStr = constant.IsString(IsChild(pKeyChild.second, "alphaFunction")))
284 kfAlphaFunction = GetAlphaFunction(*alphaFuncStr);
287 keyframes.Add(*kfProgress, propValue, kfAlphaFunction);
292 animation.AnimateBetween(prop, keyframes, alphaFunction, timePeriod);
296 animation.AnimateBetween(prop, keyframes, alphaFunction);
299 else if(OptionalString pathChild = IsString(pKeyChild.second, "path"))
302 Path path = builder->GetPath(*pathChild);
305 //Get forward vector if specified
306 Vector3 forward(0.0f, 0.0f, 0.0f);
307 OptionalVector3 forwardProperty = constant.IsVector3(IsChild(pKeyChild.second, "forward"));
310 forward = *forwardProperty;
313 Actor actor = Actor::DownCast(targetHandle);
318 animation.Animate(actor, path, forward, alphaFunction, timePeriod);
322 animation.Animate(actor, path, forward, alphaFunction);
329 DALI_SCRIPT_WARNING("Cannot find animation path '%s'\n", (*pathChild).c_str());
334 DALI_ASSERT_ALWAYS(property && "Animation must specify a property name");
336 Property prop = Property(targetHandle, propIndex);
339 propValue = GetPropertyValue(prop.object.GetPropertyType(prop.propertyIndex), *IsChild(pKeyChild.second, "value"));
343 DALI_LOG_WARNING("Property:'%s' type does not match value type '%s'\n", (*property).c_str(), PropertyTypes::GetName(prop.object.GetPropertyType(prop.propertyIndex)));
348 if(OptionalBoolean relative = constant.IsBoolean(IsChild(pKeyChild.second, "relative")))
352 animation.AnimateBy(prop, propValue, alphaFunction, timePeriod);
356 animation.AnimateBy(prop, propValue, alphaFunction);
363 animation.AnimateTo(prop, propValue, alphaFunction, timePeriod);
367 animation.AnimateTo(prop, propValue, alphaFunction);
376 animation.SetDuration(durationSum);
382 Animation CreateAnimation(const TreeNode& child, Builder* const builder)
384 Replacement replacement;
385 return CreateAnimation(child, replacement, Stage::GetCurrent().GetRootLayer(), builder);
388 } // namespace Internal
390 } // namespace Toolkit