From: Ferran Sole Date: Fri, 21 Nov 2014 12:45:04 +0000 (+0000) Subject: Adding support in Builder for path animations X-Git-Tag: dali_1.0.20~2^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F48%2F30648%2F7;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git Adding support in Builder for path animations Added a new section called "paths" where paths are specified "paths": { "path0": { "points":[ [100,100,0],[200,0,0],[300,100,0] ], "curvature": 0.25 } } To create an animation: "anim0": { "duration":1.0, "properties": [ { "actor":myActor, "path":"path0", "forward":[1,0,0] } ] } Change-Id: I11ac1804fe4e005107f42e8d8767cb692fce2d4a --- diff --git a/base/dali-toolkit/internal/builder/builder-animations.cpp b/base/dali-toolkit/internal/builder/builder-animations.cpp index 7714541ac2..787813ef50 100644 --- a/base/dali-toolkit/internal/builder/builder-animations.cpp +++ b/base/dali-toolkit/internal/builder/builder-animations.cpp @@ -163,7 +163,7 @@ namespace Toolkit namespace Internal { -Animation CreateAnimation( const TreeNode& child, const Replacement& constant, Dali::Actor searchRoot ) +Animation CreateAnimation( const TreeNode& child, const Replacement& constant, Dali::Actor searchRoot, Builder* const builder ) { float durationSum = 0.f; @@ -227,53 +227,54 @@ Animation CreateAnimation( const TreeNode& child, const Replacement& constant, D OptionalString actorName( constant.IsString( IsChild(pKeyChild.second, "actor" ) ) ); OptionalString property( constant.IsString( IsChild(pKeyChild.second, "property" ) ) ); DALI_ASSERT_ALWAYS( actorName && "Animation must specify actor name" ); - DALI_ASSERT_ALWAYS( property && "Animation must specify a property name" ); Handle targetHandle = searchActor.FindChildByName( *actorName ); DALI_ASSERT_ALWAYS( targetHandle && "Actor must exist for property" ); - Property::Index idx( targetHandle.GetPropertyIndex( *property ) ); - - // if the property is not found from the (actor) handle, try to downcast it to renderable actor - // to allow animating shader uniforms - if( idx == Property::INVALID_INDEX ) + Property::Value propValue; + Property::Index propIndex; + if( property ) { - RenderableActor renderable = RenderableActor::DownCast( targetHandle ); - if( renderable ) + propIndex = targetHandle.GetPropertyIndex( *property ); + + // if the property is not found from the (actor) handle, try to downcast it to renderable actor + // to allow animating shader uniforms + if( propIndex == Property::INVALID_INDEX ) { - // A limitation here is that its possible that between creation of animation - // and running it the ShaderEffect of the actor has been changed. - // However this is a unlikely use case especially when using scripts. - if( ShaderEffect effect = renderable.GetShaderEffect() ) + RenderableActor renderable = RenderableActor::DownCast( targetHandle ); + if( renderable ) { - idx = effect.GetPropertyIndex( *property ); - if(idx != Property::INVALID_INDEX) + // A limitation here is that its possible that between creation of animation + // and running it the ShaderEffect of the actor has been changed. + // However this is a unlikely use case especially when using scripts. + if( ShaderEffect effect = renderable.GetShaderEffect() ) { - targetHandle = effect; - } - else - { - DALI_SCRIPT_WARNING( "Cannot find property on object or ShaderEffect\n" ); - continue; + propIndex = effect.GetPropertyIndex( *property ); + if(propIndex != Property::INVALID_INDEX) + { + targetHandle = effect; + } + else + { + DALI_SCRIPT_WARNING( "Cannot find property on object or ShaderEffect\n" ); + continue; + } } } + else + { + DALI_SCRIPT_WARNING( "Cannot find property on object or ShaderEffect\n" ); + continue; + } } - else + + if( propIndex == Property::INVALID_INDEX) { - DALI_SCRIPT_WARNING( "Cannot find property on object or ShaderEffect\n" ); + DALI_ASSERT_ALWAYS( propIndex != Property::INVALID_INDEX && "Animation must specify a valid property" ); continue; } } - if( idx == Property::INVALID_INDEX) - { - DALI_ASSERT_ALWAYS( idx != Property::INVALID_INDEX && "Animation must specify a valid property" ); - continue; - } - - Property prop( Property( targetHandle, idx ) ); - Property::Value propValue; - // these are the defaults AlphaFunction alphaFunction( AlphaFunctions::Default ); TimePeriod timePeriod( 0.f ); @@ -294,6 +295,9 @@ Animation CreateAnimation( const TreeNode& child, const Replacement& constant, D if( OptionalChild keyFrameChild = IsChild(pKeyChild.second, "key-frames") ) { + DALI_ASSERT_ALWAYS( property && "Animation must specify a property name" ); + Property prop = Property( targetHandle, propIndex ); + KeyFrames keyframes = KeyFrames::New(); const TreeNode::ConstIterator endIter = (*keyFrameChild).CEnd(); @@ -338,8 +342,45 @@ Animation CreateAnimation( const TreeNode& child, const Replacement& constant, D animation.AnimateBetween( prop, keyframes, alphaFunction ); } } + else if( OptionalString pathChild = IsString(pKeyChild.second, "path") ) + { + //Get path + Path path = builder->GetPath(*pathChild); + if( path ) + { + //Get forward vector if specified + Vector3 forward( 0.0f, 0.0f, 0.0f ); + OptionalVector3 forwardProperty = constant.IsVector3( IsChild(pKeyChild.second, "forward" ) ); + if( forwardProperty ) + { + forward = *forwardProperty; + } + + Actor actor = Actor::DownCast( targetHandle ); + if( actor ) + { + if( timeChild ) + { + animation.Animate( actor, path, forward, alphaFunction, timePeriod ); + } + else + { + animation.Animate( actor, path, forward, alphaFunction ); + } + + } + } + else + { + //Path not found + DALI_SCRIPT_WARNING( "Cannot find animation path '%s'\n", (*pathChild).c_str() ); + } + } else { + DALI_ASSERT_ALWAYS( property && "Animation must specify a property name" ); + + Property prop = Property( targetHandle, propIndex ); try { propValue = GetPropertyValue( prop.object.GetPropertyType(prop.propertyIndex), *IsChild(pKeyChild.second, "value") ); @@ -386,10 +427,10 @@ Animation CreateAnimation( const TreeNode& child, const Replacement& constant, D return animation; } -Animation CreateAnimation( const TreeNode& child ) +Animation CreateAnimation( const TreeNode& child, Builder* const builder ) { Replacement replacement; - return CreateAnimation( child, replacement, Stage::GetCurrent().GetRootLayer() ); + return CreateAnimation( child, replacement, Stage::GetCurrent().GetRootLayer(), builder ); } } // namespace Internal diff --git a/base/dali-toolkit/internal/builder/builder-impl.cpp b/base/dali-toolkit/internal/builder/builder-impl.cpp index ba3678b942..ab40d18054 100644 --- a/base/dali-toolkit/internal/builder/builder-impl.cpp +++ b/base/dali-toolkit/internal/builder/builder-impl.cpp @@ -44,13 +44,13 @@ namespace Internal { class Replacement; -extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot ); +extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot, Builder* const builder ); extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value ); extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value, const Replacement& replacements ); extern bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value ); extern bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value, const Replacement& replacements ); -extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function quitAction); -extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function quitAction); +extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function quitAction, Dali::Toolkit::Internal::Builder* const builder); +extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function quitAction, Dali::Toolkit::Internal::Builder* const builder); extern Actor SetupActor( const TreeNode& node, Actor& actor, const Replacement& constant ); #if defined(DEBUG_ENABLED) @@ -355,8 +355,8 @@ void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node, // add signals QuitAction quitAction( *this ); - SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction ); - SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction ); + SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction, this ); + SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction, this ); } } else @@ -745,6 +745,69 @@ FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Re return ret; } +Path Builder::GetPath( const std::string& name ) +{ + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + + Path ret; + + PathLut::const_iterator iter( mPathLut.find( name ) ); + if( iter != mPathLut.end() ) + { + ret = iter->second; + } + else + { + if( OptionalChild paths = IsChild( *mParser.GetRoot(), "paths") ) + { + if( OptionalChild path = IsChild( *paths, name ) ) + { + //points property + if( OptionalChild pointsProperty = IsChild( *path, "points") ) + { + Dali::Property::Value points(Property::ARRAY); + if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret = Path::New(); + ret.SetProperty( Path::POINTS, points); + + //control-points property + if( OptionalChild pointsProperty = IsChild( *path, "control-points") ) + { + Dali::Property::Value points(Property::ARRAY); + if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret.SetProperty( Path::CONTROL_POINTS, points); + } + } + else + { + //Curvature + float curvature(0.25f); + if( OptionalFloat pointsProperty = IsFloat( *path, "curvature") ) + { + curvature = *pointsProperty; + } + ret.GenerateControlPoints(curvature); + } + + //Add the new path to the hash table for paths + mPathLut[ name ] = ret; + } + } + else + { + //Interpolation points not specified + DALI_SCRIPT_WARNING("Interpolation points not specified for path '%s'\n", name.c_str() ); + } + } + + } + } + + return ret; +} + Toolkit::Builder::Signal& Builder::QuitSignal() { return mQuitSignal; @@ -808,7 +871,7 @@ Animation Builder::CreateAnimation( const std::string& animationName, const Repl { if( OptionalChild animation = IsChild(*animations, animationName) ) { - anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor ); + anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor, this ); } else { diff --git a/base/dali-toolkit/internal/builder/builder-impl.h b/base/dali-toolkit/internal/builder/builder-impl.h index 477f1aad6c..a51a35054f 100644 --- a/base/dali-toolkit/internal/builder/builder-impl.h +++ b/base/dali-toolkit/internal/builder/builder-impl.h @@ -179,6 +179,10 @@ public: */ FrameBufferImage GetFrameBufferImage( const std::string &name, const Replacement& constant ); + /** + * @copydoc Toolkit::Builder::GetPath + */ + Path GetPath( const std::string &name ); /** * @copydoc Toolkit::Builder::QuitSignal */ @@ -209,6 +213,9 @@ private: typedef std::map ShaderEffectLut; ShaderEffectLut mShaderEffectLut; + typedef std::map PathLut; + PathLut mPathLut; + SlotDelegate mSlotDelegate; Property::Map mReplacementMap; diff --git a/base/dali-toolkit/internal/builder/builder-signals.cpp b/base/dali-toolkit/internal/builder/builder-signals.cpp index c323fab2ea..40428e34aa 100644 --- a/base/dali-toolkit/internal/builder/builder-signals.cpp +++ b/base/dali-toolkit/internal/builder/builder-signals.cpp @@ -29,7 +29,7 @@ namespace Toolkit { namespace Internal { -extern Animation CreateAnimation( const TreeNode& child ); +extern Animation CreateAnimation( const TreeNode& child, Dali::Toolkit::Internal::Builder* const builder ); extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value ); } } @@ -126,11 +126,12 @@ struct GenericAction // 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(); @@ -222,7 +223,7 @@ void DoNothing(void) {}; /** * Get an action as boost function callback */ -boost::function GetAction(const TreeNode &root, const TreeNode &child, Actor actor, boost::function quitAction) +boost::function GetAction(const TreeNode &root, const TreeNode &child, Actor actor, boost::function quitAction, Dali::Toolkit::Internal::Builder* const builder) { OptionalString childActorName(IsString( IsChild(&child, "child-actor")) ); OptionalString actorName(IsString( IsChild(&child, "actor")) ); @@ -279,7 +280,8 @@ boost::function GetAction(const TreeNode &root, const TreeNode &chi if( OptionalChild animNode = IsChild(*animations, *animationName) ) { DelayedAnimationPlay action; - action.memento = Toolkit::JsonParser::New(*animNode); + action.animNode = animNode; + action.builder = builder; // @todo; put constants into the map callback = action; } @@ -356,13 +358,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, boost::function quitAction) +Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function quitAction, Dali::Toolkit::Internal::Builder* const builder ) { DALI_ASSERT_ALWAYS(actor); @@ -379,7 +381,7 @@ 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, quitAction); + boost::function callback = GetAction(root, key_child.second, actor, quitAction, builder ); actor.ConnectSignal(tracker, *name, callback); } @@ -391,7 +393,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, boost::function quitAction) +Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function quitAction, Dali::Toolkit::Internal::Builder* const builder ) { DALI_ASSERT_ALWAYS(actor); @@ -405,7 +407,7 @@ Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root // 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, quitAction); + boost::function callback = GetAction(root, key_child.second, actor, quitAction, builder ); OptionalString prop(IsString( IsChild(key_child.second, "property")) ); DALI_ASSERT_ALWAYS(prop && "Notification signal must specify a property"); diff --git a/base/dali-toolkit/public-api/builder/builder.cpp b/base/dali-toolkit/public-api/builder/builder.cpp index 3f531a3d0f..bd85719c44 100644 --- a/base/dali-toolkit/public-api/builder/builder.cpp +++ b/base/dali-toolkit/public-api/builder/builder.cpp @@ -144,6 +144,11 @@ FrameBufferImage Builder::GetFrameBufferImage( const std::string &name ) return GetImpl(*this).GetFrameBufferImage( name ); } +Path Builder::GetPath( const std::string &name ) +{ + return GetImpl(*this).GetPath( name ); +} + Builder::Signal& Builder::QuitSignal() { return GetImpl( *this ).QuitSignal(); diff --git a/base/dali-toolkit/public-api/builder/builder.h b/base/dali-toolkit/public-api/builder/builder.h index 65ece45640..98d3d8c821 100644 --- a/base/dali-toolkit/public-api/builder/builder.h +++ b/base/dali-toolkit/public-api/builder/builder.h @@ -399,6 +399,15 @@ class DALI_IMPORT_API Builder : public BaseHandle */ FrameBufferImage GetFrameBufferImage( const std::string &name ); + /** + * Get or create Path from the Path instance library. + * An empty handle is returned otherwise. + * @pre The Builder has been initialized. + * @param name The name of a Path in the loaded representation + * @return A handle to a Path if found, otherwise empty + */ + Path GetPath( const std::string &name ); + // Signals /**