X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fanimation%2Fanimation-impl.cpp;h=c27f31b3740b3aae0db2b0f82bc2a92c21da96ce;hb=641ea9391fdfc25a6836ffaa86b5c74e2a1f425c;hp=04e9ac943e8e78fc59f6395e33e56d6b05ab91ac;hpb=6018e61621a554eac34e853b668e396cee3dce9c;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/animation/animation-impl.cpp b/dali/internal/event/animation/animation-impl.cpp index 04e9ac9..c27f31b 100644 --- a/dali/internal/event/animation/animation-impl.cpp +++ b/dali/internal/event/animation/animation-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 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. @@ -22,21 +22,19 @@ // EXTERNAL INCLUDES // INTERNAL INCLUDES -#include #include #include #include #include #include #include -#include #include #include #include #include #include #include -#include +#include #include using Dali::Internal::SceneGraph::UpdateManager; @@ -122,11 +120,13 @@ Animation::Animation( EventThreadServices& eventThreadServices, AnimationPlaylis mFinishedCallbackObject( NULL ), mDurationSeconds( durationSeconds ), mSpeedFactor(1.0f), - mIsLooping( false ), + mLoopCount(1), + mCurrentLoop(0), mPlayRange( Vector2(0.0f,1.0f)), mEndAction( endAction ), mDisconnectAction( disconnectAction ), - mDefaultAlpha( defaultAlpha ) + mDefaultAlpha( defaultAlpha ), + mState(Dali::Animation::STOPPED) { } @@ -159,7 +159,7 @@ void Animation::CreateSceneObject() DALI_ASSERT_DEBUG( mAnimation == NULL ); // Create a new animation, temporarily owned - SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mIsLooping, mEndAction, mDisconnectAction ); + SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mLoopCount, mEndAction, mDisconnectAction ); // Keep a const pointer to the animation. mAnimation = animation; @@ -199,19 +199,33 @@ float Animation::GetDuration() const return mDurationSeconds; } -void Animation::SetLooping(bool looping) +void Animation::SetLooping(bool on) +{ + SetLoopCount( on ? 0 : 1 ); +} + +void Animation::SetLoopCount(int count) { // Cache for public getters - mIsLooping = looping; + mLoopCount = count; // mAnimation is being used in a separate thread; queue a message to set the value - SetLoopingMessage( mEventThreadServices, *mAnimation, looping ); + SetLoopingMessage( mEventThreadServices, *mAnimation, mLoopCount ); +} + +int Animation::GetLoopCount() +{ + return mLoopCount; +} + +int Animation::GetCurrentLoop() +{ + return mCurrentLoop; } bool Animation::IsLooping() const { - // This is not animatable; the cached value is up-to-date. - return mIsLooping; + return mLoopCount != 1; } void Animation::SetEndAction(EndAction action) @@ -249,6 +263,41 @@ void Animation::Play() // Update the current playlist mPlaylist.OnPlay( *this ); + mState = Dali::Animation::PLAYING; + + if( mEndAction != EndAction::Discard ) // If the animation is discarded, then we do not want to change the target values + { + unsigned int connectorTargetValuesIndex( 0 ); + unsigned int numberOfConnectorTargetValues = mConnectorTargetValues.size(); + + /* + * Loop through all Animator connectors, if connector index matches the current index stored in mConnectorTargetValues container then + * should apply target values for this index to the object. + */ + for ( unsigned int connectorIndex = 0; connectorIndex < mConnectors.Count(); connectorIndex ++) + { + // Use index to check if the current connector is next in the mConnectorTargetValues container, meaning targetValues have been pushed in AnimateXXFunction + if ( connectorTargetValuesIndex < numberOfConnectorTargetValues ) + { + ConnectorTargetValues& connectorPair = mConnectorTargetValues[ connectorTargetValuesIndex ]; + + if ( connectorPair.connectorIndex == connectorIndex ) + { + // Current connector index matches next in the stored connectors with target values so apply target value. + connectorTargetValuesIndex++; // Found a match for connector so increment index to next one + + AnimatorConnectorBase* connector = mConnectors[ connectorIndex ]; + + Object* object = connector->GetObject(); + if( object ) + { + object->NotifyPropertyAnimation( *this, connector->GetPropertyIndex(), connectorPair.targetValue ); + } + } + } + } + } + // mAnimation is being used in a separate thread; queue a Play message PlayAnimationMessage( mEventThreadServices, *mAnimation ); } @@ -260,6 +309,8 @@ void Animation::PlayFrom( float progress ) // Update the current playlist mPlaylist.OnPlay( *this ); + mState = Dali::Animation::PLAYING; + // mAnimation is being used in a separate thread; queue a Play message PlayAnimationFromMessage( mEventThreadServices, *mAnimation, progress ); } @@ -267,12 +318,21 @@ void Animation::PlayFrom( float progress ) void Animation::Pause() { + mState = Dali::Animation::PAUSED; + // mAnimation is being used in a separate thread; queue a Pause message PauseAnimationMessage( mEventThreadServices, *mAnimation ); } +Dali::Animation::State Animation::GetState() const +{ + return mState; +} + void Animation::Stop() { + mState = Dali::Animation::STOPPED; + // mAnimation is being used in a separate thread; queue a Stop message StopAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation ); } @@ -284,6 +344,9 @@ void Animation::Clear() // Remove all the connectors mConnectors.Clear(); + // Reset the connector target values + mConnectorTargetValues.clear(); + // Replace the old scene-object with a new one DestroySceneObject(); CreateSceneObject(); @@ -312,11 +375,14 @@ void Animation::AnimateBy(Property& target, Property::Value& relativeValue, Time void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period) { - Object& object = dynamic_cast( GetImplementation(target.object) ); + Object& object = GetImplementation( target.object ); + const Property::Type targetType = object.GetPropertyType( target.propertyIndex ); + const Property::Type destinationType = relativeValue.GetType(); + DALI_ASSERT_ALWAYS( targetType == destinationType && "Animated value and Property type don't match" ); ExtendDuration( period ); - switch ( relativeValue.GetType() ) + switch ( targetType ) { case Property::BOOLEAN: { @@ -398,8 +464,9 @@ void Animation::AnimateBy(Property& target, Property::Value& relativeValue, Alph } default: - DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here - break; + { + // non animatable types handled already + } } } @@ -420,28 +487,35 @@ void Animation::AnimateTo(Property& target, Property::Value& destinationValue, T void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period) { - Object& object = dynamic_cast( GetImplementation(target.object) ); + Object& object = GetImplementation(target.object); AnimateTo( object, target.propertyIndex, target.componentIndex, destinationValue, alpha, period ); } void Animation::AnimateTo(Object& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period) { - Property::Type type = targetObject.GetPropertyType(targetPropertyIndex); - if(componentIndex != Property::INVALID_COMPONENT_INDEX) + Property::Type targetType = targetObject.GetPropertyType(targetPropertyIndex); + if( componentIndex != Property::INVALID_COMPONENT_INDEX ) { - if( type == Property::VECTOR2 - || type == Property::VECTOR3 - || type == Property::VECTOR4 ) + if( ( targetType == Property::VECTOR2 ) || + ( targetType == Property::VECTOR3 ) || + ( targetType == Property::VECTOR4 ) ) { - type = Property::FLOAT; + targetType = Property::FLOAT; } } - DALI_ASSERT_ALWAYS( type == destinationValue.GetType() && "DestinationValue does not match Target Property type" ); + const Property::Type destinationType = destinationValue.GetType(); + DALI_ASSERT_ALWAYS( targetType == destinationType && "Animated value and Property type don't match" ); ExtendDuration( period ); - switch (destinationValue.GetType()) + // Store data to later notify the object that its property is being animated + ConnectorTargetValues connectorPair; + connectorPair.targetValue = destinationValue; + connectorPair.connectorIndex = mConnectors.Count(); + mConnectorTargetValues.push_back( connectorPair ); + + switch ( destinationType ) { case Property::BOOLEAN: { @@ -467,31 +541,6 @@ void Animation::AnimateTo(Object& targetObject, Property::Index targetPropertyIn case Property::FLOAT: { - if ( ( Dali::Actor::Property::SIZE_WIDTH == targetPropertyIndex ) || - ( Dali::Actor::Property::SIZE_HEIGHT == targetPropertyIndex ) || - ( Dali::Actor::Property::SIZE_DEPTH == targetPropertyIndex ) ) - { - // Test whether this is actually an Actor - Actor* maybeActor = dynamic_cast( &targetObject ); - if ( maybeActor ) - { - // Notify the actor that its size is being animated - maybeActor->NotifySizeAnimation( *this, destinationValue.Get(), targetPropertyIndex ); - } - } - else if ( ( Dali::Actor::Property::POSITION_X == targetPropertyIndex ) || - ( Dali::Actor::Property::POSITION_Y == targetPropertyIndex ) || - ( Dali::Actor::Property::POSITION_Z == targetPropertyIndex ) ) - { - // Test whether this is actually an Actor - Actor* maybeActor = dynamic_cast( &targetObject ); - if ( maybeActor ) - { - // Notify the actor that its position is being animated - maybeActor->NotifyPositionAnimation( *this, destinationValue.Get(), targetPropertyIndex ); - } - } - AddAnimatorConnector( AnimatorConnector::New( targetObject, targetPropertyIndex, componentIndex, @@ -514,27 +563,6 @@ void Animation::AnimateTo(Object& targetObject, Property::Index targetPropertyIn case Property::VECTOR3: { - if ( Dali::Actor::Property::SIZE == targetPropertyIndex ) - { - // Test whether this is actually an Actor - Actor* maybeActor = dynamic_cast( &targetObject ); - if ( maybeActor ) - { - // Notify the actor that its size is being animated - maybeActor->NotifySizeAnimation( *this, destinationValue.Get() ); - } - } - else if ( Dali::Actor::Property::POSITION == targetPropertyIndex ) - { - // Test whether this is actually an Actor - Actor* maybeActor = dynamic_cast( &targetObject ); - if ( maybeActor ) - { - // Notify the actor that its position is being animated - maybeActor->NotifyPositionAnimation( *this, destinationValue.Get() ); - } - } - AddAnimatorConnector( AnimatorConnector::New( targetObject, targetPropertyIndex, componentIndex, @@ -567,8 +595,9 @@ void Animation::AnimateTo(Object& targetObject, Property::Index targetPropertyIn } default: - DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here - break; + { + // non animatable types handled already + } } } @@ -609,7 +638,7 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation) { - Object& object = dynamic_cast( GetImplementation(target.object) ); + Object& object = GetImplementation( target.object ); ExtendDuration( period ); @@ -713,23 +742,29 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph break; } - default: // not all property types are animateable - break; + default: + { + // non animatable types handled by keyframes + } } } bool Animation::HasFinished() { bool hasFinished(false); - const int playCount(mAnimation->GetPlayCount()); + const int playedCount(mAnimation->GetPlayedCount()); // If the play count has been incremented, then another notification is required - if (playCount > mNotificationCount) + mCurrentLoop = mAnimation->GetCurrentLoop(); + + if (playedCount > mNotificationCount) { // Note that only one signal is emitted, if the animation has been played repeatedly - mNotificationCount = playCount; + mNotificationCount = playedCount; hasFinished = true; + + mState = Dali::Animation::STOPPED; } return hasFinished; @@ -758,7 +793,7 @@ void Animation::EmitSignalFinish() bool Animation::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) { bool connected( true ); - Animation* animation = dynamic_cast(object); + Animation* animation = static_cast< Animation* >(object); // TypeRegistry guarantees that this is the correct type. if( 0 == signalName.compare( SIGNAL_FINISHED ) ) {