Revert to tizen branch.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / builder-animations.cpp
index b8ea43e..bea8368 100644 (file)
@@ -1,35 +1,39 @@
-//
-// 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) 2014 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 <dali/public-api/actors/layer.h>
+#include <dali/public-api/actors/renderable-actor.h>
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/builder/builder-impl.h>
 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
+#include <dali-toolkit/internal/builder/replacement.h>
 
 namespace // unnamed namespace
 {
 
 using namespace Dali;
 
-TimePeriod GetTimePeriod( const TreeNode& child )
+TimePeriod GetTimePeriod( const TreeNode& child, const Toolkit::Internal::Replacement& constant )
 {
-  OptionalFloat delay      = IsFloat( IsChild(child, "delay" ) );
-  OptionalFloat duration   = IsFloat( IsChild(child, "duration" ) );
+  OptionalFloat delay      = constant.IsFloat( IsChild(child, "delay" ) );
+  OptionalFloat duration   = constant.IsFloat( IsChild(child, "duration" ) );
   DALI_ASSERT_ALWAYS( duration && "Time period must have at least a duration" );
 
   if( delay )
@@ -94,7 +98,6 @@ Property::Value GetPropertyValue( const Property::Type& propType, const TreeNode
     default:
     {
       DALI_ASSERT_ALWAYS( !"Property type incorrect" );
-      return Property::Value();
     }
   }
 }
@@ -107,20 +110,34 @@ AlphaFunction GetAlphaFunction( const std::string& alphaFunction )
   if( 0 == alphaFunctionLut.size() )
   {
     // coding convention is uppercase enums
-    alphaFunctionLut["DEFAULT"]         = Dali::AlphaFunctions::Default;
-    alphaFunctionLut["LINEAR"]          = Dali::AlphaFunctions::Linear;
-    alphaFunctionLut["REVERSE"]         = Dali::AlphaFunctions::Reverse;
-    alphaFunctionLut["EASE_IN"]         = Dali::AlphaFunctions::EaseIn;
-    alphaFunctionLut["EASE_OUT"]        = Dali::AlphaFunctions::EaseOut;
-    alphaFunctionLut["EASE_IN_OUT"]     = Dali::AlphaFunctions::EaseInOut;
-    alphaFunctionLut["EASE_IN_SINE"]    = Dali::AlphaFunctions::EaseInSine;
-    alphaFunctionLut["EASE_OUT_SINE"]   = Dali::AlphaFunctions::EaseOutSine;
-    alphaFunctionLut["EASE_IN_OUT_SINE"]= Dali::AlphaFunctions::EaseInOutSine;
-    alphaFunctionLut["BOUNCE"]          = Dali::AlphaFunctions::Bounce;
-    alphaFunctionLut["BOUNCE_BACK"]     = Dali::AlphaFunctions::BounceBack;
-    alphaFunctionLut["EASE_OUT_BACK"]   = Dali::AlphaFunctions::EaseOutBack;
-    alphaFunctionLut["SIN"]             = Dali::AlphaFunctions::Sin;
-    alphaFunctionLut["SIN2X"]           = Dali::AlphaFunctions::Sin;
+    alphaFunctionLut["DEFAULT"]                    = AlphaFunctions::Default;
+    alphaFunctionLut["LINEAR"]                     = AlphaFunctions::Linear;
+    alphaFunctionLut["SQUARE"]                     = AlphaFunctions::Square;
+    alphaFunctionLut["REVERSE"]                    = AlphaFunctions::Reverse;
+    alphaFunctionLut["EASE_IN"]                    = AlphaFunctions::EaseIn;
+    alphaFunctionLut["EASE_OUT"]                   = AlphaFunctions::EaseOut;
+    alphaFunctionLut["EASE_IN_OUT"]                = AlphaFunctions::EaseInOut;
+    alphaFunctionLut["EASE_IN_SINE"]               = AlphaFunctions::EaseInSine;
+    alphaFunctionLut["EASE_OUT_SINE"]              = AlphaFunctions::EaseOutSine;
+    alphaFunctionLut["EASE_IN_OUT_SINE"]           = AlphaFunctions::EaseInOutSine;
+    alphaFunctionLut["EASE_IN_SINE_33"]            = AlphaFunctions::EaseInSine33;
+    alphaFunctionLut["EASE_OUT_SINE_33"]           = AlphaFunctions::EaseOutSine33;
+    alphaFunctionLut["EASE_IN_OUT_SINE_33"]        = AlphaFunctions::EaseInOutSine33;
+    alphaFunctionLut["EASE_IN_OUT_SINE_50"]        = AlphaFunctions::EaseInOutSine50;
+    alphaFunctionLut["EASE_IN_OUT_SINE_60"]        = AlphaFunctions::EaseInOutSine60;
+    alphaFunctionLut["EASE_IN_OUT_SINE_70"]        = AlphaFunctions::EaseInOutSine70;
+    alphaFunctionLut["EASE_IN_OUT_SINE_80"]        = AlphaFunctions::EaseInOutSine80;
+    alphaFunctionLut["EASE_IN_OUT_SINE_90"]        = AlphaFunctions::EaseInOutSine90;
+    alphaFunctionLut["DOUBLE_EASE_IN_OUT_SINE_60"] = AlphaFunctions::DoubleEaseInOutSine60;
+    alphaFunctionLut["EASE_OUT_QUINT_50"]          = AlphaFunctions::EaseOutQuint50;
+    alphaFunctionLut["EASE_OUT_QUINT_80"]          = AlphaFunctions::EaseOutQuint80;
+    alphaFunctionLut["BOUNCE"]                     = AlphaFunctions::Bounce;
+    alphaFunctionLut["BOUNCE_BACK"]                = AlphaFunctions::BounceBack;
+    alphaFunctionLut["EASE_IN_BACK"]               = AlphaFunctions::EaseInBack;
+    alphaFunctionLut["EASE_OUT_BACK"]              = AlphaFunctions::EaseOutBack;
+    alphaFunctionLut["EASE_IN_OUT_BACK"]           = AlphaFunctions::EaseInOutBack;
+    alphaFunctionLut["SIN"]                        = AlphaFunctions::Sin;
+    alphaFunctionLut["SIN2X"]                      = AlphaFunctions::Sin2x;
   }
 
   const AlphaFunctionLut::const_iterator iter( alphaFunctionLut.find( alphaFunction ) );
@@ -148,18 +165,28 @@ namespace Toolkit
 namespace Internal
 {
 
-Animation CreateAnimation( const TreeNode& child )
+Animation CreateAnimation( const TreeNode& child, const Replacement& constant, Dali::Actor searchRoot, Builder* const builder )
 {
   float durationSum = 0.f;
 
+  Dali::Actor searchActor = searchRoot ? searchRoot : Dali::Stage::GetCurrent().GetRootLayer();
+
   Animation animation( Animation::New( 0.f ) );
 
-  if( OptionalBoolean looping = IsBoolean(  IsChild(child, "loop" ) ) )
+  // duration needs to be set before AnimateTo calls for correct operation when AnimateTo has no "time-period".
+  OptionalFloat duration = constant.IsFloat( IsChild(child, "duration" ) );
+
+  if( duration )
+  {
+    animation.SetDuration( *duration );
+  }
+
+  if( OptionalBoolean looping = constant.IsBoolean(  IsChild(child, "loop" ) ) )
   {
     animation.SetLooping( *looping );
   }
 
-  if( OptionalString endAction = IsString(  IsChild(child, "end-action" ) ) )
+  if( OptionalString endAction = constant.IsString(  IsChild(child, "end-action" ) ) )
   {
     if("BAKE" == *endAction)
     {
@@ -169,17 +196,25 @@ Animation CreateAnimation( const TreeNode& child )
     {
       animation.SetEndAction( Animation::Discard );
     }
+    else if("BAKE_FINAL" == *endAction)
+    {
+      animation.SetEndAction( Animation::BakeFinal );
+    }
   }
 
-  if( OptionalString endAction = IsString(  IsChild(child, "destroy-action" ) ) )
+  if( OptionalString endAction = constant.IsString(  IsChild(child, "disconnect-action" ) ) )
   {
     if("BAKE" == *endAction)
     {
-      animation.SetDestroyAction( Animation::Bake );
+      animation.SetDisconnectAction( Animation::Bake );
     }
     else if("DISCARD" == *endAction)
     {
-      animation.SetDestroyAction( Animation::Discard );
+      animation.SetDisconnectAction( Animation::Discard );
+    }
+    else if("BAKE_FINAL" == *endAction)
+    {
+      animation.SetDisconnectAction( Animation::BakeFinal );
     }
   }
 
@@ -191,27 +226,42 @@ Animation CreateAnimation( const TreeNode& child )
     {
       const TreeNode::KeyNodePair& pKeyChild = *iter;
 
-      OptionalString actorName( IsString( pKeyChild.second, "actor" ) );
-      OptionalString property(  IsString( pKeyChild.second, "property" ) );
+      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" );
 
-      Actor targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName( *actorName );
-      DALI_ASSERT_ALWAYS( targetActor && "Actor must exist for property" );
+      Handle targetHandle = searchActor.FindChildByName( *actorName );
+      DALI_ASSERT_ALWAYS( targetHandle && "Actor must exist for property" );
 
-      Property::Index idx( targetActor.GetPropertyIndex( *property ) );
-
-      // A limitation here is that its possible that between binding to the signal and
-      // the signal call that the ShaderEffect of the targetActor has been changed.
-      // However this is a unlikely use case especially when using scripts.
-      if( idx == Property::INVALID_INDEX )
+      Property::Value propValue;
+      Property::Index propIndex = Property::INVALID_INDEX;
+      if( property )
       {
-        if( ShaderEffect effect = targetActor.GetShaderEffect() )
+        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 )
         {
-          idx = effect.GetPropertyIndex( *property );
-          if(idx != Property::INVALID_INDEX)
+          RenderableActor renderable = RenderableActor::DownCast( targetHandle );
+          if( renderable )
           {
-            targetActor = effect;
+            // 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() )
+            {
+              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
           {
@@ -219,40 +269,37 @@ Animation CreateAnimation( const TreeNode& child )
             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( targetActor, idx ) );
-      Property::Value propValue;
-
       // these are the defaults
       AlphaFunction alphaFunction( AlphaFunctions::Default );
       TimePeriod timePeriod( 0.f );
 
-      if( OptionalChild timeChild = IsChild( pKeyChild.second, "time-period" ) )
+      OptionalChild timeChild = IsChild( pKeyChild.second, "time-period" );
+
+      if( timeChild )
       {
-        timePeriod = GetTimePeriod( *timeChild );
+        timePeriod = GetTimePeriod( *timeChild, constant );
       }
 
       durationSum = std::max( durationSum, timePeriod.delaySeconds + timePeriod.durationSeconds );
 
-      if( OptionalString alphaChild = IsString( pKeyChild.second, "alpha-function" ) )
+      if( OptionalString alphaChild = constant.IsString( IsChild(pKeyChild.second, "alpha-function" ) ) )
       {
         alphaFunction = GetAlphaFunction( *alphaChild );
       }
 
       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();
@@ -260,7 +307,7 @@ Animation CreateAnimation( const TreeNode& child )
         {
           const TreeNode::KeyNodePair& kfKeyChild = *iter;
 
-          OptionalFloat kfProgress = IsFloat( kfKeyChild.second, "progress" );
+          OptionalFloat kfProgress = constant.IsFloat( IsChild(kfKeyChild.second, "progress" ) );
           DALI_ASSERT_ALWAYS( kfProgress && "Key frame entry must have 'progress'" );
 
           OptionalChild kfValue = IsChild( kfKeyChild.second, "value" );
@@ -280,7 +327,7 @@ Animation CreateAnimation( const TreeNode& child )
           }
 
           AlphaFunction kfAlphaFunction( AlphaFunctions::Default );
-          if( OptionalString alphaFuncStr = IsString( pKeyChild.second, "alpha-function") )
+          if( OptionalString alphaFuncStr = constant.IsString( IsChild(pKeyChild.second, "alpha-function") ) )
           {
             kfAlphaFunction = GetAlphaFunction( *alphaFuncStr );
           }
@@ -288,10 +335,54 @@ Animation CreateAnimation( const TreeNode& child )
           keyframes.Add( *kfProgress, propValue, kfAlphaFunction );
         }
 
-        animation.AnimateBetween( prop, keyframes, alphaFunction, timePeriod );
+        if( timeChild )
+        {
+          animation.AnimateBetween( prop, keyframes, alphaFunction, timePeriod );
+        }
+        else
+        {
+          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") );
@@ -304,23 +395,33 @@ Animation CreateAnimation( const TreeNode& child )
           throw;
         }
 
-        if( OptionalBoolean relative = IsBoolean(pKeyChild.second, "relative") )
+        if( OptionalBoolean relative = constant.IsBoolean( IsChild(pKeyChild.second, "relative") ) )
         {
-          animation.AnimateBy( prop, propValue, alphaFunction, timePeriod );
+          if( timeChild )
+          {
+            animation.AnimateBy( prop, propValue, alphaFunction, timePeriod );
+          }
+          else
+          {
+            animation.AnimateBy( prop, propValue, alphaFunction );
+          }
         }
         else
         {
-          animation.AnimateTo( prop, propValue, alphaFunction, timePeriod );
+          if( timeChild )
+          {
+            animation.AnimateTo( prop, propValue, alphaFunction, timePeriod );
+          }
+          else
+          {
+            animation.AnimateTo( prop, propValue, alphaFunction );
+          }
         }
       }
     }
   }
 
-  if( OptionalFloat duration = IsFloat( child, "duration" ) )
-  {
-    animation.SetDuration( *duration );
-  }
-  else
+  if( !duration )
   {
     animation.SetDuration( durationSum );
   }
@@ -328,6 +429,12 @@ Animation CreateAnimation( const TreeNode& child )
   return animation;
 }
 
+Animation CreateAnimation( const TreeNode& child, Builder* const builder )
+{
+  Replacement replacement;
+  return CreateAnimation( child, replacement, Stage::GetCurrent().GetRootLayer(), builder );
+}
+
 } // namespace Internal
 
 } // namespace Toolkit