2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
18 #include <dali/integration-api/debug.h>
21 #include <dali-toolkit/internal/builder/builder-impl.h>
22 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
30 extern Animation CreateAnimation( const TreeNode& child );
31 extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
44 // Action quit; connected to signals
45 // TODO: MOVE TO BUILDER TEMPLATE
50 void operator()(void) {
51 // Dali::Application::Get().Quit();
55 // Action on child actor. The child is found by alias so can be 'previous' etc.
56 struct ChildActorAction
58 std::string actorName;
59 std::string actionName;
60 std::string childAlias;
61 std::vector<Property::Value> parameters;
65 Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
69 Actor child_actor = actor.FindChildByAlias(childAlias);
73 child_actor.DoAction(actionName, parameters);
77 DALI_SCRIPT_WARNING("Could not find child by alias '%s'\n", childAlias.c_str());
83 // Action to set a property
84 struct PropertySetAction
86 std::string actorName;
87 std::string propertyName;
88 Property::Value value;
92 Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
96 Property::Index idx = actor.GetPropertyIndex(propertyName);
98 if( idx != Property::INVALID_INDEX )
100 if( actor.GetPropertyType(idx) != value.GetType() )
102 DALI_SCRIPT_WARNING("Set property action has different type for property '%s'\n", propertyName.c_str());
106 actor.SetProperty( idx, value );
111 DALI_SCRIPT_WARNING("Set property action cannot find property '%s'\n", propertyName.c_str());
117 // Generic action on a handle (Animation & Actor)
120 std::string actorName;
121 std::string actionName;
122 std::vector<Property::Value> parameters;
124 void operator()(void)
126 Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
129 actor.DoAction(actionName, parameters);
135 // Delay an animation play; ie wait as its not on stage yet
136 struct DelayedAnimationPlay
138 Toolkit::JsonParser memento;
140 void operator()(void)
142 Animation anim = Toolkit::Internal::CreateAnimation(*memento.GetRoot());
151 * Gets Property::Value from child
153 Property::Value GetPropertyValue(const TreeNode &child)
155 size_t nChildren = child.Size();
161 // cast away unused return for static analyzers
162 static_cast<void>( Dali::Toolkit::Internal::SetPropertyFromNode( child, ret ) );
164 else if(1 == nChildren)
166 // {"property": {"quaternion":[1,2,3,4]} }
167 // {"property": {"angle":22, "axis": [1,2,3]} }
169 OptionalChild quaternion = IsChild(&child, "quaternion");
170 OptionalChild axis = IsChild(&child, "axis");
171 OptionalChild angle = IsChild(&child, "angle");
175 ret = Property::Value(Quaternion(GetVector4(*quaternion)));
177 else if(axis && angle)
179 ret = Property::Value(AngleAxis(Degree(GetFloat(*angle)), GetVector3(*axis)));
182 else if(2 == nChildren)
184 // {"property": [1,2]}
185 ret = Property::Value(GetVector2(child));
187 else if(3 == nChildren)
189 // {"property": [1,2,3]}
190 ret = Property::Value(GetVector3(child));
192 else if(4 == nChildren)
194 // {"property": [1,2,3,4]}
195 ret = Property::Value(GetVector4(child));
203 * Gets Parmeter list from child
204 * params is be cleared before insertion
206 void GetParameters(const TreeNode &child, std::vector<Property::Value> ¶ms)
208 if( OptionalChild c = IsChild(child, "parameters") )
210 const TreeNode& node = *c;
214 GetPropertyValue(node);
219 params.reserve(node.Size());
221 for(TreeNode::ConstIterator iter(node.CBegin()); iter != node.CEnd(); ++iter)
223 params.push_back( GetPropertyValue( (*iter).second ) );
229 void DoNothing(void) {};
232 * Get an action as boost function callback
234 boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &child, Actor actor)
236 OptionalString childActorName(IsString( IsChild(&child, "child-actor")) );
237 OptionalString actorName(IsString( IsChild(&child, "actor")) );
238 OptionalString propertyName(IsString( IsChild(&child, "property")) );
239 OptionalChild valueChild( IsChild(&child, "value") );
241 OptionalString actionName = IsString( IsChild(&child, "action") );
242 DALI_ASSERT_ALWAYS(actionName && "Signal must have an action");
244 boost::function<void(void)> callback = DoNothing;
248 ChildActorAction action;
249 action.actorName = *actorName;
250 action.childAlias = *childActorName;
251 action.actionName = *actionName;
252 GetParameters(child, action.parameters);
257 if(propertyName && valueChild && ("set" == *actionName) )
259 PropertySetAction action;
260 action.actorName = *actorName;
261 action.propertyName = *propertyName;
262 // actor may not exist yet so we can't check the property type
263 if( !Dali::Toolkit::Internal::SetPropertyFromNode( *valueChild, action.value ) )
265 DALI_SCRIPT_WARNING("Cannot set property for set property action\n");
271 GenericAction action;
272 action.actorName = *actorName;
273 action.actionName = *actionName;
274 GetParameters(child, action.parameters);
278 else if("quit" == *actionName)
280 callback = ActionQuit();
282 else if("play" == *actionName)
284 OptionalChild animations = IsChild( root, "animations" );
285 OptionalString animationName = IsString( IsChild(child, "animation") );
286 if( animations && animationName )
288 if( OptionalChild animNode = IsChild(*animations, *animationName) )
290 DelayedAnimationPlay action;
291 action.memento = Toolkit::JsonParser::New(*animNode);
292 // @todo; put constants into the map
297 DALI_SCRIPT_WARNING("Cannot find animation '%s'\n", (*animationName).c_str());
302 DALI_SCRIPT_WARNING("Cannot find animations section\n");
307 // no named actor; presume self
308 GenericAction action;
309 action.actorName = actor.GetName();
310 action.actionName = *actionName;
311 GetParameters(child, action.parameters);
320 * Get a notification condition argument0 as 'arg0' 'value' or 'min'
322 float GetConditionArg0(const TreeNode &child)
324 OptionalFloat f = IsFloat( IsChild(child, "arg0") );
325 // allowing some human preferable alternatives
328 f = IsFloat( IsChild(child, "value") );
332 f = IsFloat( IsChild(child, "min") );
334 DALI_ASSERT_ALWAYS(f && "Notification condition for arg0 not specified");
346 * Get a notification condition argument1 as 'arg1' or 'max'
348 float GetConditionArg1(const TreeNode &child)
350 OptionalFloat f = IsFloat( IsChild(child, "arg1") );
351 // allowing some human preferable alternatives
354 f = IsFloat( IsChild(child, "max") );
356 DALI_ASSERT_ALWAYS(f && "Notification condition for arg1 not specified");
378 Actor SetupSignalAction(const TreeNode &child, Actor actor);
379 Actor SetupPropertyNotification(const TreeNode &child, Actor actor);
382 * Setup signals and actions on an actor
384 Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor)
386 DALI_ASSERT_ALWAYS(actor);
388 if(OptionalChild signalsChild = IsChild(child, "signals"))
390 const TreeNode& signalsNode = *signalsChild;
391 const TreeConstIter endIter = signalsNode.CEnd();
392 for( TreeConstIter iter = signalsNode.CBegin(); endIter != iter; ++iter )
394 const TreeNode::KeyNodePair& key_child = *iter;
396 DALI_SCRIPT_INFO(" Creating Signal for: %s\n", actor.GetName().c_str());
398 OptionalString name( IsString( IsChild( key_child.second, "name")) );
399 DALI_ASSERT_ALWAYS(name && "Signal must have a name");
401 boost::function<void (void)> callback = GetAction(root, key_child.second, actor);
403 actor.ConnectSignal(tracker, *name, callback);
411 * Setup Property notifications for an actor
413 Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor)
415 DALI_ASSERT_ALWAYS(actor);
417 if(OptionalChild notificationsChild = IsChild(child,"notifications"))
419 const TreeNode& notificationsNode = *notificationsChild;
420 const TreeNode::ConstIterator endIter = notificationsNode.CEnd();
421 for( TreeNode::ConstIterator iter = notificationsNode.CBegin(); endIter != iter; ++iter )
423 const TreeNode::KeyNodePair& key_child = *iter;
425 // Actor actions reference by pointer because of circular reference actor->signal
426 // So this callback should only go onto the actor maintained list.
427 boost::function<void (void)> callback = GetAction(root, key_child.second, actor);
429 OptionalString prop(IsString( IsChild(key_child.second, "property")) );
430 DALI_ASSERT_ALWAYS(prop && "Notification signal must specify a property");
432 Property::Index prop_index = actor.GetPropertyIndex(*prop);
433 DALI_ASSERT_ALWAYS(prop_index != Property::INVALID_INDEX && "Notification signal specifies an unknown property");
435 OptionalString cond(IsString( IsChild(key_child.second, "condition")));
436 DALI_ASSERT_ALWAYS(cond && "Notification signal must specify a condition");
440 PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
441 LessThanCondition(1.f) );
442 notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
444 else if("LessThan" == *cond)
446 PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
447 LessThanCondition(GetConditionArg0(key_child.second)) );
448 notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
450 else if("GreaterThan" == *cond)
452 PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
453 GreaterThanCondition(GetConditionArg0(key_child.second)) );
454 notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
456 else if("Inside" == *cond)
458 PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
459 InsideCondition(GetConditionArg0(key_child.second),
460 GetConditionArg1(key_child.second)) );
461 notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
463 else if("Outside" == *cond)
465 PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
466 OutsideCondition(GetConditionArg0(key_child.second),
467 GetConditionArg1(key_child.second)) );
468 notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
472 DALI_ASSERT_ALWAYS(!"Unknown condition");
475 } // if notifications
479 } // AddPropertyNotification
482 } // namespace Internal
483 } // namespace Toolkit