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/public-api/actors/layer.h>
20 #include <dali/public-api/actors/image-actor.h>
21 #include <dali/integration-api/debug.h>
24 #include <dali-toolkit/internal/builder/builder-impl.h>
25 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
26 #include <dali-toolkit/internal/builder/replacement.h>
28 namespace // unnamed namespace
33 TimePeriod GetTimePeriod( const TreeNode& child, const Toolkit::Internal::Replacement& constant )
35 OptionalFloat delay = constant.IsFloat( IsChild(child, "delay" ) );
36 OptionalFloat duration = constant.IsFloat( IsChild(child, "duration" ) );
37 DALI_ASSERT_ALWAYS( duration && "Time period must have at least a duration" );
41 return TimePeriod( *delay, *duration );
45 return TimePeriod( *duration );
49 Property::Value GetPropertyValue( const Property::Type& propType, const TreeNode& child )
53 case Property::BOOLEAN:
55 return Property::Value( GetBoolean( child ) );
60 return Property::Value( GetFloat( child ) );
63 case Property::VECTOR2:
65 return Property::Value( GetVector2( child ) );
68 case Property::VECTOR3:
70 return Property::Value( GetVector3( child ) );
73 case Property::VECTOR4:
75 return Property::Value( GetVector4( child ) );
78 case Property::ROTATION:
80 if( 4 == child.Size() )
82 Vector4 v(GetVector4(child));
83 // angle, axis as per spec
84 return Property::Value( Quaternion(Radian(Degree(v[3])),
85 Vector3(v[0],v[1],v[2])) );
89 // degrees as per spec
90 Vector3 rotation = GetVector3( child );
91 return Property::Value( Quaternion(Radian(Degree(rotation.x)),
92 Radian(Degree(rotation.y)),
93 Radian(Degree(rotation.z))) );
97 case Property::NONE: // fall
100 DALI_ASSERT_ALWAYS( !"Property type incorrect" );
105 AlphaFunction GetAlphaFunction( const std::string& alphaFunction )
107 typedef std::map< const std::string, Dali::AlphaFunction > AlphaFunctionLut;
108 static AlphaFunctionLut alphaFunctionLut;
110 if( 0 == alphaFunctionLut.size() )
112 // coding convention is uppercase enums
113 alphaFunctionLut["DEFAULT"] = AlphaFunction(AlphaFunction::DEFAULT);
114 alphaFunctionLut["LINEAR"] = AlphaFunction(AlphaFunction::LINEAR);
115 alphaFunctionLut["REVERSE"] = AlphaFunction(AlphaFunction::REVERSE);
116 alphaFunctionLut["EASE_IN_SQUARE"] = AlphaFunction(AlphaFunction::EASE_IN_SQUARE);
117 alphaFunctionLut["EASE_OUT_SQUARE"] = AlphaFunction(AlphaFunction::EASE_OUT_SQUARE);
118 alphaFunctionLut["EASE_IN"] = AlphaFunction(AlphaFunction::EASE_IN);
119 alphaFunctionLut["EASE_OUT"] = AlphaFunction(AlphaFunction::EASE_OUT);
120 alphaFunctionLut["EASE_IN_OUT"] = AlphaFunction(AlphaFunction::EASE_IN_OUT);
121 alphaFunctionLut["EASE_IN_SINE"] = AlphaFunction(AlphaFunction::EASE_IN_SINE);
122 alphaFunctionLut["EASE_OUT_SINE"] = AlphaFunction(AlphaFunction::EASE_OUT_SINE);
123 alphaFunctionLut["EASE_IN_OUT_SINE"] = AlphaFunction(AlphaFunction::EASE_IN_OUT_SINE);
124 alphaFunctionLut["BOUNCE"] = AlphaFunction(AlphaFunction::BOUNCE);
125 alphaFunctionLut["SIN"] = AlphaFunction(AlphaFunction::SIN);
126 alphaFunctionLut["EASE_OUT_BACK"] = AlphaFunction(AlphaFunction::EASE_OUT_BACK);
129 const AlphaFunctionLut::const_iterator iter( alphaFunctionLut.find( alphaFunction ) );
131 if( iter != alphaFunctionLut.end() )
137 DALI_ASSERT_ALWAYS( iter != alphaFunctionLut.end() && "Unknown Alpha Constant" );
138 return Dali::AlphaFunction::DEFAULT;
142 } // unnamed namespace
154 Animation CreateAnimation( const TreeNode& child, const Replacement& constant, Dali::Actor searchRoot, Builder* const builder )
156 float durationSum = 0.f;
158 Dali::Actor searchActor = searchRoot ? searchRoot : Dali::Stage::GetCurrent().GetRootLayer();
160 Animation animation( Animation::New( 0.f ) );
162 // duration needs to be set before AnimateTo calls for correct operation when AnimateTo has no "timePeriod".
163 OptionalFloat duration = constant.IsFloat( IsChild(child, "duration" ) );
167 animation.SetDuration( *duration );
170 if( OptionalBoolean looping = constant.IsBoolean( IsChild(child, "loop" ) ) )
172 animation.SetLooping( *looping );
175 if( OptionalString endAction = constant.IsString( IsChild(child, "endAction" ) ) )
177 if("BAKE" == *endAction)
179 animation.SetEndAction( Animation::Bake );
181 else if("DISCARD" == *endAction)
183 animation.SetEndAction( Animation::Discard );
185 else if("BAKE_FINAL" == *endAction)
187 animation.SetEndAction( Animation::BakeFinal );
191 if( OptionalString endAction = constant.IsString( IsChild(child, "disconnectAction" ) ) )
193 if("BAKE" == *endAction)
195 animation.SetDisconnectAction( Animation::Bake );
197 else if("DISCARD" == *endAction)
199 animation.SetDisconnectAction( Animation::Discard );
201 else if("BAKE_FINAL" == *endAction)
203 animation.SetDisconnectAction( Animation::BakeFinal );
207 OptionalChild propertiesNode = IsChild(child, "properties" );
210 const TreeNode::ConstIterator endIter = (*propertiesNode).CEnd();
211 for( TreeNode::ConstIterator iter = (*propertiesNode).CBegin(); endIter != iter; ++iter )
213 const TreeNode::KeyNodePair& pKeyChild = *iter;
215 OptionalString actorName( constant.IsString( IsChild(pKeyChild.second, "actor" ) ) );
216 OptionalString property( constant.IsString( IsChild(pKeyChild.second, "property" ) ) );
217 DALI_ASSERT_ALWAYS( actorName && "Animation must specify actor name" );
219 Handle targetHandle = searchActor.FindChildByName( *actorName );
220 DALI_ASSERT_ALWAYS( targetHandle && "Actor must exist for property" );
222 Property::Value propValue;
223 Property::Index propIndex = Property::INVALID_INDEX;
226 propIndex = targetHandle.GetPropertyIndex( *property );
228 // if the property is not found from the (actor) handle, try to downcast it to renderable actor
229 // to allow animating shader uniforms
230 if( propIndex == Property::INVALID_INDEX )
232 ImageActor imageActor = ImageActor::DownCast( targetHandle );
235 // A limitation here is that its possible that between creation of animation
236 // and running it the ShaderEffect of the actor has been changed.
237 // However this is a unlikely use case especially when using scripts.
238 if( ShaderEffect effect = imageActor.GetShaderEffect() )
240 propIndex = effect.GetPropertyIndex( *property );
241 if(propIndex != Property::INVALID_INDEX)
243 targetHandle = effect;
247 DALI_SCRIPT_WARNING( "Cannot find property on object or ShaderEffect\n" );
254 DALI_SCRIPT_WARNING( "Cannot find property on object or ShaderEffect\n" );
259 if( propIndex == Property::INVALID_INDEX)
261 DALI_ASSERT_ALWAYS( propIndex != Property::INVALID_INDEX && "Animation must specify a valid property" );
266 // these are the defaults
267 AlphaFunction alphaFunction( AlphaFunction::DEFAULT );
268 TimePeriod timePeriod( 0.f );
270 OptionalChild timeChild = IsChild( pKeyChild.second, "timePeriod" );
274 timePeriod = GetTimePeriod( *timeChild, constant );
277 durationSum = std::max( durationSum, timePeriod.delaySeconds + timePeriod.durationSeconds );
279 if( OptionalString alphaChild = constant.IsString( IsChild(pKeyChild.second, "alphaFunction" ) ) )
281 alphaFunction = GetAlphaFunction( *alphaChild );
284 if( OptionalChild keyFrameChild = IsChild(pKeyChild.second, "keyFrames") )
286 DALI_ASSERT_ALWAYS( property && "Animation must specify a property name" );
287 Property prop = Property( targetHandle, propIndex );
289 KeyFrames keyframes = KeyFrames::New();
291 const TreeNode::ConstIterator endIter = (*keyFrameChild).CEnd();
292 for( TreeNode::ConstIterator iter = (*keyFrameChild).CBegin(); endIter != iter; ++iter )
294 const TreeNode::KeyNodePair& kfKeyChild = *iter;
296 OptionalFloat kfProgress = constant.IsFloat( IsChild(kfKeyChild.second, "progress" ) );
297 DALI_ASSERT_ALWAYS( kfProgress && "Key frame entry must have 'progress'" );
299 OptionalChild kfValue = IsChild( kfKeyChild.second, "value" );
300 DALI_ASSERT_ALWAYS( kfValue && "Key frame entry must have 'value'" );
304 propValue = GetPropertyValue( prop.object.GetPropertyType(prop.propertyIndex), *kfValue );
308 DALI_LOG_WARNING( "Property:'%s' type does not match value type '%s'\n",
310 PropertyTypes::GetName(prop.object.GetPropertyType(prop.propertyIndex)) );
315 AlphaFunction kfAlphaFunction( AlphaFunction::DEFAULT );
316 if( OptionalString alphaFuncStr = constant.IsString( IsChild(pKeyChild.second, "alphaFunction") ) )
318 kfAlphaFunction = GetAlphaFunction( *alphaFuncStr );
321 keyframes.Add( *kfProgress, propValue, kfAlphaFunction );
326 animation.AnimateBetween( prop, keyframes, alphaFunction, timePeriod );
330 animation.AnimateBetween( prop, keyframes, alphaFunction );
333 else if( OptionalString pathChild = IsString(pKeyChild.second, "path") )
336 Path path = builder->GetPath(*pathChild);
339 //Get forward vector if specified
340 Vector3 forward( 0.0f, 0.0f, 0.0f );
341 OptionalVector3 forwardProperty = constant.IsVector3( IsChild(pKeyChild.second, "forward" ) );
342 if( forwardProperty )
344 forward = *forwardProperty;
347 Actor actor = Actor::DownCast( targetHandle );
352 animation.Animate( actor, path, forward, alphaFunction, timePeriod );
356 animation.Animate( actor, path, forward, alphaFunction );
364 DALI_SCRIPT_WARNING( "Cannot find animation path '%s'\n", (*pathChild).c_str() );
369 DALI_ASSERT_ALWAYS( property && "Animation must specify a property name" );
371 Property prop = Property( targetHandle, propIndex );
374 propValue = GetPropertyValue( prop.object.GetPropertyType(prop.propertyIndex), *IsChild(pKeyChild.second, "value") );
378 DALI_LOG_WARNING( "Property:'%s' type does not match value type '%s'\n", (*property).c_str(),
379 PropertyTypes::GetName( prop.object.GetPropertyType(prop.propertyIndex) ) );
384 if( OptionalBoolean relative = constant.IsBoolean( IsChild(pKeyChild.second, "relative") ) )
388 animation.AnimateBy( prop, propValue, alphaFunction, timePeriod );
392 animation.AnimateBy( prop, propValue, alphaFunction );
399 animation.AnimateTo( prop, propValue, alphaFunction, timePeriod );
403 animation.AnimateTo( prop, propValue, alphaFunction );
412 animation.SetDuration( durationSum );
418 Animation CreateAnimation( const TreeNode& child, Builder* const builder )
420 Replacement replacement;
421 return CreateAnimation( child, replacement, Stage::GetCurrent().GetRootLayer(), builder );
424 } // namespace Internal
426 } // namespace Toolkit