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/integration-api/debug.h>
22 #include <dali-toolkit/internal/builder/builder-impl.h>
23 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
31 extern Animation CreateAnimation( const TreeNode& child );
32 extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
45 // Action quit; connected to signals
46 // TODO: MOVE TO BUILDER TEMPLATE
51 void operator()(void) {
52 // Dali::Application::Get().Quit();
56 // Action on child actor. The child is found by alias so can be 'previous' etc.
57 struct ChildActorAction
59 std::string actorName;
60 std::string actionName;
61 std::string childAlias;
62 std::vector<Property::Value> parameters;
66 Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
70 Actor child_actor = actor.FindChildByAlias(childAlias);
74 child_actor.DoAction(actionName, parameters);
78 DALI_SCRIPT_WARNING("Could not find child by alias '%s'\n", childAlias.c_str());
84 // Action to set a property
85 struct PropertySetAction
87 std::string actorName;
88 std::string propertyName;
89 Property::Value value;
93 Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
97 Property::Index idx = actor.GetPropertyIndex(propertyName);
99 if( idx != Property::INVALID_INDEX )
101 if( actor.GetPropertyType(idx) != value.GetType() )
103 DALI_SCRIPT_WARNING("Set property action has different type for property '%s'\n", propertyName.c_str());
107 actor.SetProperty( idx, value );
112 DALI_SCRIPT_WARNING("Set property action cannot find property '%s'\n", propertyName.c_str());
118 // Generic action on a handle (Animation & Actor)
121 std::string actorName;
122 std::string actionName;
123 std::vector<Property::Value> parameters;
125 void operator()(void)
127 Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
130 actor.DoAction(actionName, parameters);
136 // Delay an animation play; ie wait as its not on stage yet
137 struct DelayedAnimationPlay
139 Toolkit::JsonParser memento;
141 void operator()(void)
143 Animation anim = Toolkit::Internal::CreateAnimation(*memento.GetRoot());
152 * Gets Property::Value from child
154 Property::Value GetPropertyValue(const TreeNode &child)
156 size_t nChildren = child.Size();
162 // cast away unused return for static analyzers
163 static_cast<void>( Dali::Toolkit::Internal::SetPropertyFromNode( child, ret ) );
165 else if(1 == nChildren)
167 // {"property": {"quaternion":[1,2,3,4]} }
168 // {"property": {"angle":22, "axis": [1,2,3]} }
170 OptionalChild quaternion = IsChild(&child, "quaternion");
171 OptionalChild axis = IsChild(&child, "axis");
172 OptionalChild angle = IsChild(&child, "angle");
176 ret = Property::Value(Quaternion(GetVector4(*quaternion)));
178 else if(axis && angle)
180 ret = Property::Value(AngleAxis(Degree(GetFloat(*angle)), GetVector3(*axis)));
183 else if(2 == nChildren)
185 // {"property": [1,2]}
186 ret = Property::Value(GetVector2(child));
188 else if(3 == nChildren)
190 // {"property": [1,2,3]}
191 ret = Property::Value(GetVector3(child));
193 else if(4 == nChildren)
195 // {"property": [1,2,3,4]}
196 ret = Property::Value(GetVector4(child));
204 * Gets Parmeter list from child
205 * params is be cleared before insertion
207 void GetParameters(const TreeNode &child, std::vector<Property::Value> ¶ms)
209 if( OptionalChild c = IsChild(child, "parameters") )
211 const TreeNode& node = *c;
215 GetPropertyValue(node);
220 params.reserve(node.Size());
222 for(TreeNode::ConstIterator iter(node.CBegin()); iter != node.CEnd(); ++iter)
224 params.push_back( GetPropertyValue( (*iter).second ) );
230 void DoNothing(void) {};
233 * Get an action as boost function callback
235 boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &child, Actor actor)
237 OptionalString childActorName(IsString( IsChild(&child, "child-actor")) );
238 OptionalString actorName(IsString( IsChild(&child, "actor")) );
239 OptionalString propertyName(IsString( IsChild(&child, "property")) );
240 OptionalChild valueChild( IsChild(&child, "value") );
242 OptionalString actionName = IsString( IsChild(&child, "action") );
243 DALI_ASSERT_ALWAYS(actionName && "Signal must have an action");
245 boost::function<void(void)> callback = DoNothing;
249 ChildActorAction action;
250 action.actorName = *actorName;
251 action.childAlias = *childActorName;
252 action.actionName = *actionName;
253 GetParameters(child, action.parameters);
258 if(propertyName && valueChild && ("set" == *actionName) )
260 PropertySetAction action;
261 action.actorName = *actorName;
262 action.propertyName = *propertyName;
263 // actor may not exist yet so we can't check the property type
264 if( !Dali::Toolkit::Internal::SetPropertyFromNode( *valueChild, action.value ) )
266 DALI_SCRIPT_WARNING("Cannot set property for set property action\n");
272 GenericAction action;
273 action.actorName = *actorName;
274 action.actionName = *actionName;
275 GetParameters(child, action.parameters);
279 else if("quit" == *actionName)
281 callback = ActionQuit();
283 else if("play" == *actionName)
285 OptionalChild animations = IsChild( root, "animations" );
286 OptionalString animationName = IsString( IsChild(child, "animation") );
287 if( animations && animationName )
289 if( OptionalChild animNode = IsChild(*animations, *animationName) )
291 DelayedAnimationPlay action;
292 action.memento = Toolkit::JsonParser::New(*animNode);
293 // @todo; put constants into the map
298 DALI_SCRIPT_WARNING("Cannot find animation '%s'\n", (*animationName).c_str());
303 DALI_SCRIPT_WARNING("Cannot find animations section\n");
308 // no named actor; presume self
309 GenericAction action;
310 action.actorName = actor.GetName();
311 action.actionName = *actionName;
312 GetParameters(child, action.parameters);
321 * Get a notification condition argument0 as 'arg0' 'value' or 'min'
323 float GetConditionArg0(const TreeNode &child)
325 OptionalFloat f = IsFloat( IsChild(child, "arg0") );
326 // allowing some human preferable alternatives
329 f = IsFloat( IsChild(child, "value") );
333 f = IsFloat( IsChild(child, "min") );
335 DALI_ASSERT_ALWAYS(f && "Notification condition for arg0 not specified");
347 * Get a notification condition argument1 as 'arg1' or 'max'
349 float GetConditionArg1(const TreeNode &child)
351 OptionalFloat f = IsFloat( IsChild(child, "arg1") );
352 // allowing some human preferable alternatives
355 f = IsFloat( IsChild(child, "max") );
357 DALI_ASSERT_ALWAYS(f && "Notification condition for arg1 not specified");
379 Actor SetupSignalAction(const TreeNode &child, Actor actor);
380 Actor SetupPropertyNotification(const TreeNode &child, Actor actor);
383 * Setup signals and actions on an actor
385 Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor)
387 DALI_ASSERT_ALWAYS(actor);
389 if(OptionalChild signalsChild = IsChild(child, "signals"))
391 const TreeNode& signalsNode = *signalsChild;
392 const TreeConstIter endIter = signalsNode.CEnd();
393 for( TreeConstIter iter = signalsNode.CBegin(); endIter != iter; ++iter )
395 const TreeNode::KeyNodePair& key_child = *iter;
397 DALI_SCRIPT_INFO(" Creating Signal for: %s\n", actor.GetName().c_str());
399 OptionalString name( IsString( IsChild( key_child.second, "name")) );
400 DALI_ASSERT_ALWAYS(name && "Signal must have a name");
402 boost::function<void (void)> callback = GetAction(root, key_child.second, actor);
404 actor.ConnectSignal(tracker, *name, callback);
412 * Setup Property notifications for an actor
414 Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor)
416 DALI_ASSERT_ALWAYS(actor);
418 if(OptionalChild notificationsChild = IsChild(child,"notifications"))
420 const TreeNode& notificationsNode = *notificationsChild;
421 const TreeNode::ConstIterator endIter = notificationsNode.CEnd();
422 for( TreeNode::ConstIterator iter = notificationsNode.CBegin(); endIter != iter; ++iter )
424 const TreeNode::KeyNodePair& key_child = *iter;
426 // Actor actions reference by pointer because of circular reference actor->signal
427 // So this callback should only go onto the actor maintained list.
428 boost::function<void (void)> callback = GetAction(root, key_child.second, actor);
430 OptionalString prop(IsString( IsChild(key_child.second, "property")) );
431 DALI_ASSERT_ALWAYS(prop && "Notification signal must specify a property");
433 Property::Index prop_index = actor.GetPropertyIndex(*prop);
434 DALI_ASSERT_ALWAYS(prop_index != Property::INVALID_INDEX && "Notification signal specifies an unknown property");
436 OptionalString cond(IsString( IsChild(key_child.second, "condition")));
437 DALI_ASSERT_ALWAYS(cond && "Notification signal must specify a condition");
441 PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
442 LessThanCondition(1.f) );
443 notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
445 else if("LessThan" == *cond)
447 PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
448 LessThanCondition(GetConditionArg0(key_child.second)) );
449 notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
451 else if("GreaterThan" == *cond)
453 PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
454 GreaterThanCondition(GetConditionArg0(key_child.second)) );
455 notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
457 else if("Inside" == *cond)
459 PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
460 InsideCondition(GetConditionArg0(key_child.second),
461 GetConditionArg1(key_child.second)) );
462 notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
464 else if("Outside" == *cond)
466 PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
467 OutsideCondition(GetConditionArg0(key_child.second),
468 GetConditionArg1(key_child.second)) );
469 notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
473 DALI_ASSERT_ALWAYS(!"Unknown condition");
476 } // if notifications
480 } // AddPropertyNotification
483 } // namespace Internal
484 } // namespace Toolkit