X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fbuilder%2Fbuilder-signals.cpp;h=55809bdc9bb81eeeda2883ef605a8a8010a7330c;hp=a7ed4c24733cb316dbd0392d5fcc6fdab00f9d1f;hb=54fbf47db890d0479d19d780de5ea5d860924632;hpb=e2eda444afbe82e9591fe198eef339227f90a616 diff --git a/dali-toolkit/internal/builder/builder-signals.cpp b/dali-toolkit/internal/builder/builder-signals.cpp index a7ed4c2..55809bd 100644 --- a/dali-toolkit/internal/builder/builder-signals.cpp +++ b/dali-toolkit/internal/builder/builder-signals.cpp @@ -1,21 +1,28 @@ -// -// Copyright (c) 2014 Samsung Electronics Co., Ltd. -// -// Licensed under the Flora License, Version 1.0 (the License); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://floralicense.org/license/ -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an AS IS BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ // EXTERNAL INCLUDES +#include +#include +#include +#include + #include +#include // INTERNAL INCLUDES #include @@ -27,8 +34,8 @@ namespace Toolkit { namespace Internal { -extern Animation CreateAnimation( const TreeNode& child ); -extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value ); +extern Animation CreateAnimation( const TreeNode& child, Dali::Toolkit::Internal::Builder* const builder ); +extern bool DeterminePropertyFromNode( const TreeNode& node, Property::Value& value ); } } } @@ -41,24 +48,13 @@ using namespace Dali; // Signal Actions // -// Action quit; connected to signals -// TODO: MOVE TO BUILDER TEMPLATE -struct ActionQuit -{ - ActionQuit(void) {}; - - void operator()(void) { - // Dali::Application::Get().Quit(); - }; -}; - -// Action on child actor. The child is found by alias so can be 'previous' etc. +// Action on child actor. The child is found by name struct ChildActorAction { std::string actorName; std::string actionName; - std::string childAlias; - std::vector parameters; + std::string childName; + Property::Map parameters; void operator()(void) { @@ -66,7 +62,7 @@ struct ChildActorAction if(actor) { - Actor child_actor = actor.FindChildByAlias(childAlias); + Actor child_actor = actor.FindChildByName(childName); if(child_actor) { @@ -74,7 +70,7 @@ struct ChildActorAction } else { - DALI_SCRIPT_WARNING("Could not find child by alias '%s'\n", childAlias.c_str()); + DALI_SCRIPT_WARNING("Could not find child by name '%s'\n", childName.c_str()); } } }; @@ -97,7 +93,18 @@ struct PropertySetAction if( idx != Property::INVALID_INDEX ) { - actor.SetProperty( idx, value ); + if( actor.GetPropertyType(idx) != value.GetType() ) + { + DALI_SCRIPT_WARNING("Set property action has different type for property '%s'\n", propertyName.c_str()); + } + else + { + actor.SetProperty( idx, value ); + } + } + else + { + DALI_SCRIPT_WARNING("Set property action cannot find property '%s'\n", propertyName.c_str()); } } }; @@ -108,7 +115,7 @@ struct GenericAction { std::string actorName; std::string actionName; - std::vector parameters; + Property::Map parameters; void operator()(void) { @@ -121,14 +128,25 @@ struct GenericAction }; }; +struct QuitAction +{ + Dali::IntrusivePtr builder; + + void operator()(void) + { + builder->EmitQuitSignal(); + } +}; + // Delay an animation play; ie wait as its not on stage yet struct DelayedAnimationPlay { - Toolkit::JsonParser memento; + OptionalChild animNode; + Dali::IntrusivePtr builder; void operator()(void) { - Animation anim = Toolkit::Internal::CreateAnimation(*memento.GetRoot()); + Animation anim = Toolkit::Internal::CreateAnimation(*animNode, builder.Get() ); if(anim) { anim.Play(); @@ -136,6 +154,182 @@ struct DelayedAnimationPlay }; }; +// Delay a pathConstrainer apply +struct DelayedConstrainerApply +{ + std::string constrainerName; + + std::vector targetActorNames; + std::vector sourceActorNames; + std::vector targetPropertyNames; + std::vector sourcePropertyNames; + std::vector ranges; + std::vector wrapRanges; + + Dali::IntrusivePtr builder; + + /* + * Helper function to get the parameters to apply each constraint + * @param[in] i i-essim element + * @param[out] tagetActor Target actor for the constraint + * @param[out] tagetPropertyIndex Target property index for the constraint + * @param[out] sourceActor Source actor for the constraint + * @param[out] sourcePropertyIndex Source property index for the constraint + */ + bool GetApplyParameters( size_t i, + Actor& targetActor, Property::Index& targetPropertyIndex, + Actor& sourceActor, Property::Index& sourcePropertyIndex) + { + + targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName(targetActorNames[i]); + targetPropertyIndex = Property::INVALID_INDEX; + if(targetActor) + { + targetPropertyIndex = targetActor.GetPropertyIndex(targetPropertyNames[i]); + if( targetPropertyIndex == Property::INVALID_INDEX ) + { + DALI_SCRIPT_WARNING("Property '%s' not founded in actor '%s'\n", targetPropertyNames[i].c_str(), targetActorNames[i].c_str() ); + return false; + } + } + else + { + DALI_SCRIPT_WARNING("Actor '%s' not founded\n", targetActorNames[i].c_str() ); + return false; + } + + + sourceActor = Stage::GetCurrent().GetRootLayer().FindChildByName(sourceActorNames[i]); + sourcePropertyIndex = Property::INVALID_INDEX; + if(sourceActor) + { + sourcePropertyIndex = sourceActor.GetPropertyIndex(sourcePropertyNames[i]); + if( sourcePropertyIndex == Property::INVALID_INDEX ) + { + DALI_SCRIPT_WARNING("Property '%s' not founded in actor '%s'\n", sourcePropertyNames[i].c_str(), sourceActorNames[i].c_str() ); + return false; + } + } + else + { + DALI_SCRIPT_WARNING("Actor '%s' not founded\n", targetActorNames[i].c_str() ); + return false; + } + return true; + } + + void operator()(void) + { + Actor sourceActor, targetActor; + Property::Index targetPropertyIndex(Property::INVALID_INDEX); + Property::Index sourcePropertyIndex(Property::INVALID_INDEX); + size_t actorCount( targetActorNames.size() ); + if( builder.Get()->IsPathConstrainer( constrainerName )) + { + PathConstrainer constrainer = builder.Get()->GetPathConstrainer(constrainerName); + if( constrainer ) + { + for(size_t i(0); iIsLinearConstrainer( constrainerName ) ) + { + Dali::LinearConstrainer constrainer( builder.Get()->GetLinearConstrainer(constrainerName)); + if( constrainer ) + { + for(size_t i(0); i targetActorNames; + Dali::IntrusivePtr builder; + + void operator()(void) + { + size_t actorCount( targetActorNames.size() ); + if( builder.Get()->IsPathConstrainer( constrainerName )) + { + PathConstrainer constrainer = builder.Get()->GetPathConstrainer(constrainerName); + if( constrainer ) + { + for(size_t i(0); iIsLinearConstrainer( constrainerName )) + { + LinearConstrainer constrainer = builder.Get()->GetLinearConstrainer(constrainerName); + if( constrainer ) + { + for(size_t i(0); i( Dali::Toolkit::Internal::SetPropertyFromNode( child, ret ) ); + static_cast( Dali::Toolkit::Internal::DeterminePropertyFromNode( child, ret ) ); } else if(1 == nChildren) { @@ -192,63 +386,106 @@ Property::Value GetPropertyValue(const TreeNode &child) * Gets Parmeter list from child * params is be cleared before insertion */ -void GetParameters(const TreeNode &child, std::vector ¶ms) +void GetParameters(const TreeNode& child, Property::Map& params) { if( OptionalChild c = IsChild(child, "parameters") ) { const TreeNode& node = *c; - if(0 == node.Size()) - { - GetPropertyValue(node); - } - else - { - params.clear(); - params.reserve(node.Size()); + params.Clear(); - for(TreeNode::ConstIterator iter(node.CBegin()); iter != node.CEnd(); ++iter) - { - params.push_back( GetPropertyValue( (*iter).second ) ); - } + for(TreeNode::ConstIterator iter(node.CBegin()); iter != node.CEnd(); ++iter) + { + params[ (*iter).first ] = GetPropertyValue( (*iter).second ); } } } -void DoNothing(void) {}; +// Shim for the property notifcation signal +template +struct PropertyNotifcationSignalShim +{ + T mFunctor; + + PropertyNotifcationSignalShim(T& functor) : mFunctor(functor) {} + + void operator()(PropertyNotification& /* source */) + { + mFunctor(); + } +}; + +// Specializations for the different signal connection calls between actor & PropertyNotification +template +struct SignalConnector {}; + +// Actor specialization +template <> +struct SignalConnector { + Actor& mActor; + ConnectionTracker* mTracker; + const std::string& mName; + + SignalConnector(ConnectionTracker* tracker, Actor& actor, const std::string& name) + : mActor(actor), mTracker(tracker), mName(name) {} + + template + void Connect(T& functor) + { + mActor.ConnectSignal( mTracker, mName, functor); + } +}; + +// PropertyNotification specialization +template <> +struct SignalConnector +{ + PropertyNotification& mNotification; + ConnectionTracker* mTracker; + + SignalConnector(ConnectionTracker* tracker, PropertyNotification ¬ification) + : mNotification(notification), mTracker(tracker) {} + + template + void Connect(T& functor) + { + mNotification.NotifySignal().Connect( mTracker, PropertyNotifcationSignalShim(functor) ); + } +}; /** - * Get an action as boost function callback + * Set an action functor on a signal */ -boost::function GetAction(const TreeNode &root, const TreeNode &child, Actor actor) +template +void SetActionOnSignal(const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder, SignalConnector& connector) { - OptionalString childActorName(IsString( IsChild(&child, "child-actor")) ); + OptionalString childActorName(IsString( IsChild(&child, "childActor")) ); OptionalString actorName(IsString( IsChild(&child, "actor")) ); OptionalString propertyName(IsString( IsChild(&child, "property")) ); - OptionalString valueChild(IsString( IsChild(&child, "value")) ); + OptionalChild valueChild( IsChild(&child, "value") ); OptionalString actionName = IsString( IsChild(&child, "action") ); DALI_ASSERT_ALWAYS(actionName && "Signal must have an action"); - boost::function callback = DoNothing; - if(childActorName) { ChildActorAction action; action.actorName = *actorName; - action.childAlias = *childActorName; + action.childName = *childActorName; action.actionName = *actionName; GetParameters(child, action.parameters); - callback = action; + connector.Connect( action ); } else if(actorName) { - if(propertyName && valueChild) + if(propertyName && valueChild && ("set" == *actionName) ) { PropertySetAction action; action.actorName = *actorName; action.propertyName = *propertyName; - callback = action; + // actor may not exist yet so we can't check the property type + Dali::Toolkit::Internal::DeterminePropertyFromNode( *valueChild, action.value ); + connector.Connect( action ); } else { @@ -256,12 +493,14 @@ boost::function GetAction(const TreeNode &root, const TreeNode &chi action.actorName = *actorName; action.actionName = *actionName; GetParameters(child, action.parameters); - callback = action; + connector.Connect( action ); } } else if("quit" == *actionName) { - callback = ActionQuit(); + QuitAction action; + action.builder = builder; + connector.Connect( action ); } else if("play" == *actionName) { @@ -272,8 +511,10 @@ boost::function GetAction(const TreeNode &root, const TreeNode &chi if( OptionalChild animNode = IsChild(*animations, *animationName) ) { DelayedAnimationPlay action; - action.memento = Toolkit::JsonParser::New(*animNode); - callback = action; + action.animNode = animNode; + action.builder = builder; + // @todo; put constants into the map + connector.Connect( action ); } else { @@ -285,6 +526,112 @@ boost::function GetAction(const TreeNode &root, const TreeNode &chi DALI_SCRIPT_WARNING("Cannot find animations section\n"); } } + else if("applyConstraint" == *actionName ) + { + OptionalString constrainerName = IsString( IsChild(child, "constrainer") ); + if( !constrainerName ) + { + DALI_SCRIPT_WARNING("Need to specify a constrainer\n"); + } + else + { + DelayedConstrainerApply action; + action.constrainerName = *constrainerName; + action.builder = builder; + OptionalChild propertiesNode = IsChild(child, "properties"); + if(propertiesNode) + { + const TreeNode::ConstIterator endIter = (*propertiesNode).CEnd(); + for( TreeNode::ConstIterator iter = (*propertiesNode).CBegin(); endIter != iter; ++iter ) + { + const TreeNode::KeyNodePair& pKeyChild = *iter; + OptionalString sourceActorName(IsString(IsChild(pKeyChild.second, "source"))); + if(!sourceActorName) + { + DALI_SCRIPT_WARNING("Need to specify source actor to apply the constraint\n"); + continue; + } + OptionalString sourcePropertyName( IsString( IsChild(pKeyChild.second, "sourceProperty" ) ) ); + if(!sourcePropertyName) + { + DALI_SCRIPT_WARNING("Need to specify source property to apply the constraint\n"); + continue; + } + + OptionalString targetActorName(IsString(IsChild(pKeyChild.second, "target"))); + if(!targetActorName) + { + DALI_SCRIPT_WARNING("Need to specify target actor to apply the constraint\n"); + continue; + } + + OptionalString targetPropertyName( IsString( IsChild(pKeyChild.second, "targetProperty" ) ) ); + if(!targetPropertyName) + { + DALI_SCRIPT_WARNING("Need to specify target property name to apply the constraint\n"); + continue; + } + + OptionalVector2 range(IsVector2(IsChild(pKeyChild.second, "range"))); + if(!range) + { + DALI_SCRIPT_WARNING("Constrainer range not specified\n"); + continue; + } + + Vector2 wrap(-std::numeric_limits::max(), std::numeric_limits::max()); + OptionalVector2 wrapRange(IsVector2(IsChild(pKeyChild.second, "wrap"))); + if(wrapRange) + { + wrap = *wrapRange; + } + + action.sourceActorNames.push_back(*sourceActorName); + action.sourcePropertyNames.push_back(*sourcePropertyName); + action.targetActorNames.push_back(*targetActorName); + action.targetPropertyNames.push_back(*targetPropertyName); + action.ranges.push_back(*range); + action.wrapRanges.push_back(wrap); + } + connector.Connect(action); + } + } + } + else if("removeConstraints" == *actionName ) + { + OptionalString constrainerName = IsString( IsChild(child, "constrainer") ); + if( !constrainerName ) + { + DALI_SCRIPT_WARNING("Need to specify a constrainer\n"); + } + else + { + + DelayedConstrainerRemove action; + action.constrainerName = *constrainerName; + action.builder = builder; + OptionalChild propertiesNode = IsChild(child, "properties"); + if(propertiesNode) + { + const TreeNode::ConstIterator endIter = (*propertiesNode).CEnd(); + for( TreeNode::ConstIterator iter = (*propertiesNode).CBegin(); endIter != iter; ++iter ) + { + const TreeNode::KeyNodePair& pKeyChild = *iter; + OptionalString targetActorName(IsString(IsChild(pKeyChild.second, "target"))); + if(targetActorName) + { + action.targetActorNames.push_back(*targetActorName); + } + else + { + DALI_SCRIPT_WARNING("Need to specify target actor to remove the constraint\n"); + continue; + } + } + } + connector.Connect(action); + } + } else { // no named actor; presume self @@ -292,10 +639,8 @@ boost::function GetAction(const TreeNode &root, const TreeNode &chi action.actorName = actor.GetName(); action.actionName = *actionName; GetParameters(child, action.parameters); - callback = action; + connector.Connect( action ); } - - return callback; } @@ -314,15 +659,10 @@ float GetConditionArg0(const TreeNode &child) { f = IsFloat( IsChild(child, "min") ); } + DALI_ASSERT_ALWAYS(f && "Notification condition for arg0 not specified"); - if(f) - { - return *f; - } - else - { - return 0.f; - } + + return *f; } /** @@ -336,15 +676,10 @@ float GetConditionArg1(const TreeNode &child) { f = IsFloat( IsChild(child, "max") ); } + DALI_ASSERT_ALWAYS(f && "Notification condition for arg1 not specified"); - if(f) - { - return *f; - } - else - { - return 0.f; - } + + return *f; } @@ -358,13 +693,13 @@ namespace Toolkit namespace Internal { -Actor SetupSignalAction(const TreeNode &child, Actor actor); -Actor SetupPropertyNotification(const TreeNode &child, Actor actor); +Actor SetupSignalAction(const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder ); +Actor SetupPropertyNotification(const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder ); /** * Setup signals and actions on an actor */ -Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor) +Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder ) { DALI_ASSERT_ALWAYS(actor); @@ -381,9 +716,8 @@ Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const OptionalString name( IsString( IsChild( key_child.second, "name")) ); DALI_ASSERT_ALWAYS(name && "Signal must have a name"); - boost::function callback = GetAction(root, key_child.second, actor); - - actor.ConnectSignal(tracker, *name, callback); + SignalConnector connector(tracker, actor, *name); + SetActionOnSignal(root, key_child.second, actor, builder, connector); } } @@ -393,7 +727,7 @@ Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const /** * Setup Property notifications for an actor */ -Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor) +Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder ) { DALI_ASSERT_ALWAYS(actor); @@ -405,10 +739,6 @@ Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root { const TreeNode::KeyNodePair& key_child = *iter; - // Actor actions reference by pointer because of circular reference actor->signal - // So this callback should only go onto the actor maintained list. - boost::function callback = GetAction(root, key_child.second, actor); - OptionalString prop(IsString( IsChild(key_child.second, "property")) ); DALI_ASSERT_ALWAYS(prop && "Notification signal must specify a property"); @@ -422,33 +752,38 @@ Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root { PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop), LessThanCondition(1.f) ); - notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) ); + SignalConnector connector(tracker, notification); + SetActionOnSignal(root, key_child.second, actor, builder, connector); } else if("LessThan" == *cond) { PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop), LessThanCondition(GetConditionArg0(key_child.second)) ); - notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) ); + SignalConnector connector(tracker, notification); + SetActionOnSignal(root, key_child.second, actor, builder, connector); } else if("GreaterThan" == *cond) { PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop), GreaterThanCondition(GetConditionArg0(key_child.second)) ); - notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) ); + SignalConnector connector(tracker, notification); + SetActionOnSignal(root, key_child.second, actor, builder, connector); } else if("Inside" == *cond) { PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop), InsideCondition(GetConditionArg0(key_child.second), GetConditionArg1(key_child.second)) ); - notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) ); + SignalConnector connector(tracker, notification); + SetActionOnSignal(root, key_child.second, actor, builder, connector); } else if("Outside" == *cond) { PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop), OutsideCondition(GetConditionArg0(key_child.second), GetConditionArg1(key_child.second)) ); - notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) ); + SignalConnector connector(tracker, notification); + SetActionOnSignal(root, key_child.second, actor, builder, connector); } else {