uiacceltk/hitchcock/coretoolkit/inc/HuiFxTimeLine.inl
changeset 0 15bf7259bb7c
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #ifndef HUIFXTIMELINE_INL_
       
    21 #define HUIFXTIMELINE_INL_
       
    22 
       
    23 #include <e32def.h>
       
    24 #include "uiacceltk/huifixmath.h"
       
    25 
       
    26 template <typename TYPE, typename FPTYPE>
       
    27 RHuiFxTimeLine<TYPE, FPTYPE>::RHuiFxTimeLine():
       
    28     iLastIndex(0),
       
    29     iDuration(5.0f),
       
    30     iLoopStart(0.0f),
       
    31     iLoopEnd(0.0f),
       
    32     iLoopingMode(ELoopingModeNone),
       
    33     iInterpolationMode(EInterpolationModeHold)
       
    34     {
       
    35     }
       
    36 
       
    37 template <typename TYPE, typename FPTYPE>
       
    38 RHuiFxTimeLine<TYPE, FPTYPE>::~RHuiFxTimeLine()
       
    39     {
       
    40     iKeyFrames.Close();
       
    41     }
       
    42 
       
    43 template <typename TYPE, typename FPTYPE>
       
    44 void RHuiFxTimeLine<TYPE, FPTYPE>::SetLoopStart(TReal32 aTime)
       
    45     {
       
    46     iLoopStart = aTime;
       
    47     }
       
    48 
       
    49 template <typename TYPE, typename FPTYPE>
       
    50 TReal32 RHuiFxTimeLine<TYPE, FPTYPE>::LoopStart() const
       
    51     {
       
    52     return iLoopStart;
       
    53     }
       
    54 
       
    55 template <typename TYPE, typename FPTYPE>
       
    56 void RHuiFxTimeLine<TYPE, FPTYPE>::SetLoopEnd(TReal32 aTime)
       
    57     {
       
    58     iLoopEnd = aTime;
       
    59     }
       
    60 
       
    61 template <typename TYPE, typename FPTYPE>
       
    62 TReal32 RHuiFxTimeLine<TYPE, FPTYPE>::LoopEnd() const
       
    63     {
       
    64     return iLoopEnd;
       
    65     }
       
    66 
       
    67 template <typename TYPE, typename FPTYPE>
       
    68 void RHuiFxTimeLine<TYPE, FPTYPE>::SetDuration(TReal32 aDuration)
       
    69     {
       
    70     // Can't change this when keyframes have been defined
       
    71     __ASSERT_DEBUG(iKeyFrames.Count() == 0, User::Invariant());
       
    72     iDuration = aDuration;
       
    73     }
       
    74 
       
    75 template <typename TYPE, typename FPTYPE>
       
    76 TReal32 RHuiFxTimeLine<TYPE, FPTYPE>::Duration() const
       
    77     {
       
    78     return iDuration;
       
    79     }
       
    80 
       
    81 template <typename TYPE, typename FPTYPE>
       
    82 void RHuiFxTimeLine<TYPE, FPTYPE>::SetInterpolationMode(THuiFxInterpolationMode aMode)
       
    83     {
       
    84     iInterpolationMode = aMode;
       
    85     }
       
    86 
       
    87 template <typename TYPE, typename FPTYPE>
       
    88 THuiFxInterpolationMode RHuiFxTimeLine<TYPE, FPTYPE>::InterpolationMode() const
       
    89     {
       
    90     return iInterpolationMode;
       
    91     }
       
    92 
       
    93 template <typename TYPE, typename FPTYPE>
       
    94 void RHuiFxTimeLine<TYPE, FPTYPE>::SetLoopingMode(THuiFxLoopingMode aMode)
       
    95     {
       
    96     iLoopingMode = aMode;
       
    97     }
       
    98 
       
    99 template <typename TYPE, typename FPTYPE>
       
   100 THuiFxLoopingMode RHuiFxTimeLine<TYPE, FPTYPE>::LoopingMode() const
       
   101     {
       
   102     return iLoopingMode;
       
   103     }
       
   104 
       
   105 template <typename TYPE, typename FPTYPE>
       
   106 void RHuiFxTimeLine<TYPE, FPTYPE>::AppendKeyFrameL(TReal32 aTime, TYPE aValue)
       
   107     {
       
   108     // The aux values don't matter (non-bezier), just pass aValue
       
   109     AppendKeyFrameL(aTime, aValue, aValue, aValue);
       
   110     }
       
   111 
       
   112 template <typename TYPE, typename FPTYPE>
       
   113 void RHuiFxTimeLine<TYPE, FPTYPE>::AppendKeyFrameL(TReal32 aTime, TYPE aValue, TYPE aAuxValue1)
       
   114     {
       
   115     // The second aux value doesn't matter (quad bezier), just pass aValue
       
   116     AppendKeyFrameL(aTime, aValue, aAuxValue1, aValue);
       
   117     }
       
   118 
       
   119 template <typename TYPE, typename FPTYPE>
       
   120 void RHuiFxTimeLine<TYPE, FPTYPE>::AppendKeyFrameL(TReal32 aTime, TYPE aValue, TYPE aAuxValue1, TYPE aAuxValue2)
       
   121     {
       
   122     aTime *= iDuration;
       
   123     
       
   124     // Don't allow out of order keyframes
       
   125     if (iKeyFrames.Count() &&
       
   126         iKeyFrames[iKeyFrames.Count() - 1].iTime >= aTime)
       
   127         {
       
   128         User::Leave(KErrArgument);
       
   129         }
       
   130     
       
   131     TKeyFrame k;
       
   132     k.iTime = aTime;
       
   133     k.iFpTime = (TInt)(k.iTime * 0x10000);
       
   134     k.iValue = aValue;
       
   135     k.iFpValue = ToFixedPoint(aValue);
       
   136     k.iAuxValue[0] = aAuxValue1;
       
   137     k.iAuxValue[1] = aAuxValue2;
       
   138     k.iFpAuxValue[0] = ToFixedPoint(aAuxValue1);
       
   139     k.iFpAuxValue[1] = ToFixedPoint(aAuxValue2);
       
   140     iKeyFrames.AppendL(k);
       
   141     }
       
   142 
       
   143 template <typename TYPE, typename FPTYPE>
       
   144 TYPE RHuiFxTimeLine<TYPE, FPTYPE>::ValueAt(TReal32 aTime)
       
   145     {
       
   146     TInt i;
       
   147     
       
   148     if (!iKeyFrames.Count())
       
   149         {
       
   150         return 0;
       
   151         }
       
   152     
       
   153     // Can we use the last index?
       
   154     if (iLastIndex < iKeyFrames.Count() - 1 &&
       
   155         iKeyFrames[iLastIndex].iTime <= aTime)
       
   156         {
       
   157         i = iLastIndex;
       
   158         }
       
   159     else
       
   160         {
       
   161         i = 0;
       
   162         }
       
   163     
       
   164     for (; i < iKeyFrames.Count() - 1; i++)
       
   165         {
       
   166         if (iKeyFrames[i + 1].iTime > aTime)
       
   167             {
       
   168             break;
       
   169             }
       
   170         }
       
   171     
       
   172     iLastIndex = i;
       
   173     
       
   174     if (iInterpolationMode == EInterpolationModeHold ||
       
   175         i == iKeyFrames.Count() - 1)
       
   176         {
       
   177         return iKeyFrames[i].iValue;
       
   178         }
       
   179     
       
   180     ASSERT(i < iKeyFrames.Count() - 1);
       
   181     TInt dt = iKeyFrames[i + 1].iFpTime - iKeyFrames[i].iFpTime;
       
   182     TInt t = (TInt)(aTime * 0x10000); 
       
   183 
       
   184     ASSERT(dt > 0);
       
   185     t -= iKeyFrames[i].iFpTime;
       
   186     TInt64 t2 = t;
       
   187     t = (TInt)((t2 << 16) / dt);
       
   188     ASSERT(t >= 0 && t <= 0x10000);
       
   189 
       
   190     FPTYPE a = iKeyFrames[i].iFpValue;
       
   191     FPTYPE b = iKeyFrames[i + 1].iFpValue;
       
   192     FPTYPE c = 0; // only used for Bezier
       
   193     TInt64 t64 = t; // time as 64bit integer
       
   194 //    TInt angle = 0; // used for sine curves
       
   195 //    TInt anglePos = 0; // used for sine curves
       
   196     
       
   197     switch (iInterpolationMode)
       
   198         {
       
   199         case EInterpolationModeLinear:
       
   200             { 
       
   201             return FromFixedPoint(Blend(a, b, t));
       
   202             break;
       
   203             }
       
   204             
       
   205         case EInterpolationModeQuadraticBezier:
       
   206             {
       
   207             // a has been set outside the switch to iKeyFrames[i].iFpValue
       
   208             b = iKeyFrames[i].iFpAuxValue[0];
       
   209             c = iKeyFrames[i + 1].iFpValue;
       
   210             TInt64 oneminust = 0x10000 - t;
       
   211 
       
   212             ASSERT(0 <= oneminust && oneminust <= 0x10000);
       
   213             
       
   214             TInt64 wa = ((oneminust * oneminust) >> 16);            // (1 - t)^2
       
   215             TInt64 wb = (t64 * oneminust) >> 15;                    // 2t(1 - t)
       
   216             TInt64 wc = (t64 * t64) >> 16; wc = (wc * t64) >> 16;   // t^2
       
   217             
       
   218             // All weights [0,1]
       
   219             ASSERT(0 <= wa && wa <= 0x10000);
       
   220             ASSERT(0 <= wb && wb <= 0x10000);
       
   221             ASSERT(0 <= wc && wc <= 0x10000);
       
   222             return FromFixedPoint(WeightedSum4(a, b, c, a, (TInt)wa, (TInt)wb, (TInt)wc, 0));
       
   223             }
       
   224             break;
       
   225             
       
   226         case EInterpolationModeCubicBezier:
       
   227             {
       
   228             // a has been set outside the switch to iKeyFrames[i].iFpValue
       
   229             b = iKeyFrames[i].iFpAuxValue[0];
       
   230             c = iKeyFrames[i].iFpAuxValue[1];
       
   231             FPTYPE d = iKeyFrames[i + 1].iFpValue;
       
   232             TInt64 oneminust = 0x10000 - t;
       
   233             
       
   234             ASSERT(0 <= oneminust && oneminust <= 0x10000);
       
   235 
       
   236             TInt64 tsq = t64 * t64;
       
   237             TInt64 oneminustsq = oneminust * oneminust;
       
   238             
       
   239             // (1 - t)^3 (48 bits if t = 0)
       
   240             TInt64 wa = (oneminust * oneminustsq) >> 32;
       
   241             // 3t(1 - t)^2
       
   242             TInt64 wb = (3 * t64 * oneminustsq) >> 32;
       
   243             // 3t^2(1 - t)
       
   244             TInt64 wc = (3 * tsq * oneminust) >> 32;
       
   245             // t^3
       
   246             TInt64 wd = (t64 * tsq) >> 32;
       
   247             
       
   248             // All weights [0,1]
       
   249             ASSERT(0 <= wa && wa <= 0x10000);
       
   250             ASSERT(0 <= wb && wb <= 0x10000);
       
   251             ASSERT(0 <= wc && wc <= 0x10000);
       
   252             ASSERT(0 <= wd && wd <= 0x10000);
       
   253             return FromFixedPoint(WeightedSum4(a, b, c, d, wa, wb, wc, wd));
       
   254             }
       
   255             break;
       
   256             
       
   257         case EInterpolationModeInQuad:
       
   258             {
       
   259             // definition: c*(t/=d)*t + b
       
   260             TInt quadt = (t64 * t64) >> 16;
       
   261             return FromFixedPoint(Blend(a, b, quadt));
       
   262             break;
       
   263             }
       
   264         case EInterpolationModeOutQuad:
       
   265             {
       
   266             // definition: -c *(t/=d)*(t-2) + b
       
   267             // our t is aldready divided by d, so the coefficient becomes
       
   268             // (2 - t)*t = 2*t - t*t
       
   269             TInt quadt = (t64 * t64) >> 16;
       
   270             TInt twot = t << 1; // t*2
       
   271             twot = twot - quadt;
       
   272             return FromFixedPoint(Blend(a, b, twot));
       
   273             }
       
   274             break;
       
   275         case EInterpolationModeInOutQuad:
       
   276             {
       
   277             // acceleration until halfway, then deceleration
       
   278             // if((t/=d/2) < 1 c/2*t*t + b
       
   279             // else -c/2 *((--t)*(t-2) - 1) + b
       
   280             // Out t has been divided by d, but it must be multiplied by 2 to get t/=d/2
       
   281             TInt64 twot = t64 << 1; // t*2 (t/=d/2), this is what is used instead of t in the following equations
       
   282             
       
   283             TInt64 quadt = (twot * twot) >> 17; // (t*t)/2;
       
   284             if ( twot < 0x10000 )
       
   285                 {
       
   286                 return FromFixedPoint(Blend(a, b, quadt));
       
   287                 }
       
   288             else
       
   289                 {
       
   290                 // -((t-1)*(t-1-2)-1)/2 = -((t-1)*(t-3)-1)/2 = -((t*t-4*t+3)-1)/2
       
   291                 // = -(t*t-4*t+2)/2 = 2*t-t*t/2-1
       
   292                 twot = (twot << 1) - quadt - 0x10000; 
       
   293                 return FromFixedPoint(Blend(a, b, (TInt)twot));
       
   294                 }
       
   295             }
       
   296             break;
       
   297         case EInterpolationModeOutInQuad:
       
   298             {
       
   299             // decleration until halfway, then acceleration
       
   300             // Out t has been divided by d, but it must be multiplied by 2 to get t/=d/2
       
   301             
       
   302             TInt64 twot = t64 << 1; // t*2 (t/=d/2), this is what is used instead of t in the following equations
       
   303 
       
   304             if ( twot < 0x10000 )
       
   305                 {
       
   306                 TInt64 quadt = (twot * twot) >> 16;
       
   307                 twot = twot << 1; // t*2
       
   308                 twot = twot - quadt;
       
   309                 b = ( a + b ) / 2;
       
   310                 return FromFixedPoint(Blend(a, b, (TInt)twot));
       
   311                 }
       
   312             else
       
   313                 {
       
   314                 twot = twot - 0x10000;
       
   315                 TInt64 quadt = (twot * twot) >> 16;
       
   316                 a = ( a + b ) / 2;
       
   317                 return FromFixedPoint(Blend(a, b, (TInt)quadt));
       
   318                 }
       
   319             }
       
   320             break;
       
   321         case EInterpolationModeInBack:
       
   322             {
       
   323             // Easing equation function for a back (overshooting cubic easing:
       
   324             // (s+1)*t^3 - s*t^2 easing in: accelerating from zero velocity.
       
   325             c = iKeyFrames[i].iFpAuxValue[0];  // This is already scaled to the same fixed scale as time
       
   326             TInt64 quadt = (t64 * t64) >> 16;
       
   327             TInt64 cubict = (quadt * t64) >> 16;
       
   328             TInt64 splusone = c + 0x10000;
       
   329             c = (splusone * cubict + c * quadt) >> 16;
       
   330             
       
   331             return FromFixedPoint(Blend(a, b, c));
       
   332             }
       
   333             break;
       
   334         case EInterpolationModeOutBack:
       
   335             {
       
   336             // Easing equation function for a back (overshooting cubic easing:
       
   337             // (s+1)*t^3 - s*t^2 easing out: decelerating from zero velocity.
       
   338             
       
   339             // definition: c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b (note variable names not ours)
       
   340             // this becomes (s+1)*(t-1)^3 + s*(t-1)^2 + 1
       
   341             c = iKeyFrames[i].iFpAuxValue[0]; // this is s
       
   342             
       
   343             TInt64 tminusone = t - 0x10000;
       
   344             TInt64 quadt = (tminusone * tminusone) >> 16;
       
   345             TInt64 cubict = (quadt * tminusone) >> 16;
       
   346             TInt64 splusone = c + 0x10000;
       
   347             c = ((splusone * cubict + c * quadt) >> 16) + 0x10000; // TP 1 => 0x10000
       
   348             
       
   349             return FromFixedPoint(Blend(a, b, c));
       
   350             }
       
   351             break;
       
   352         case EInterpolationModeInOutBack:
       
   353             {
       
   354             // Easing equation function for a back (overshooting cubic easing:
       
   355             // (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
       
   356             
       
   357             // definition (note variable names not ours):
       
   358             // if((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b
       
   359             // else return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b
       
   360 
       
   361             // Out t has been divided by d, but it must be multiplied by 2 to get t/=d/2
       
   362             TInt64 twot = t64 << 1; // t*2 (t/=d/2), this is what is used instead of t in the following equations
       
   363 
       
   364             c = iKeyFrames[i].iFpAuxValue[0];
       
   365             TInt64 magic1 = ToFixedPoint( 1.525 );
       
   366             c = ( magic1 * c ) >> 16;
       
   367             
       
   368             if ( twot < 0x10000 )
       
   369                 {
       
   370                 // ((s+1)*t^3 - s*t^2)/2
       
   371                 TInt64 quadt = (twot * twot) >> 16;
       
   372                 TInt64 cubict = (quadt * twot) >> 16;
       
   373                 quadt = (c * quadt) >> 16;
       
   374                 cubict = ((c + 0x10000) * cubict) >> 16;
       
   375                 c = (cubict - quadt) >> 1;
       
   376                 return FromFixedPoint(Blend(a, b, c));
       
   377                 }
       
   378             else
       
   379                 {
       
   380                 twot = twot - 0x20000; // t-=2
       
   381                 // ((s+1)*t^3 - s*t^2 + 2)/2
       
   382                 TInt64 quadt = (twot * twot) >> 16;
       
   383                 TInt64 cubict = (quadt * twot) >> 16;
       
   384                 quadt = (c * quadt) >> 16;
       
   385                 cubict = ((c + 0x10000) * cubict) >> 16;
       
   386                 c = (cubict - quadt + 0x20000) >> 1;
       
   387                 return FromFixedPoint(Blend(a, b, c));
       
   388                 }
       
   389             }
       
   390             break;
       
   391         case EInterpolationModeOutInBack:
       
   392             {
       
   393             // Easing equation function for a back (overshooting cubic easing:
       
   394             // (s+1)*t^3 - s*t^2 easing out/in: deceleration until halfway, then acceleration.
       
   395             c = iKeyFrames[i].iFpAuxValue[0];
       
   396             TInt64 twot = t64 << 1; // t*2
       
   397             
       
   398             if ( twot < 0x10000 ) // TP t => twot (NOTE, THIS CHANGE IS STILL UNCERTAIN IF IT IS VALID!)
       
   399                 {
       
   400                 // outback
       
   401                 // (s+1)*(t-1)^3 + s*(t-1)^2 + 1
       
   402                 TInt64 tminusone = twot - 0x10000;
       
   403                 TInt64 quadt = (tminusone * tminusone) >> 16;
       
   404                 TInt64 cubict = (quadt * tminusone) >> 16;
       
   405                 TInt64 splusone = c + 0x10000;
       
   406                 c = ((splusone * cubict + c * quadt) >> 16) + 0x10000; // TP 1 => 0x10000
       
   407                 b = ( a + b ) / 2;
       
   408                 return FromFixedPoint(Blend(a, b, c));
       
   409                 }
       
   410             else
       
   411                 {
       
   412                 // inback
       
   413                 //["inback"]((t*2)-d, b+c/2, c/2, d, s)
       
   414                 // (s+1)*t^3 - s*t^2
       
   415                 twot = twot - 0x10000;
       
   416                 TInt64 quadt = (twot * twot) >> 16;
       
   417                 TInt64 cubict = (quadt * twot) >> 16;
       
   418                 TInt64 splusone = c + 0x10000;
       
   419                 c = (splusone * cubict + c * quadt) >> 16;
       
   420                 a = ( a + b ) / 2;
       
   421                 return FromFixedPoint(Blend(a, b, c));
       
   422                 }
       
   423             break;
       
   424             }
       
   425 /*            
       
   426         case EInterpolationModeDecelerate:
       
   427             {
       
   428             // Decelerating quarter of a sine wave.
       
   429             angle = HuiFixMath::FixMul((t/2)+32768,KFixPi);
       
   430             anglePos = HuiFixMath::FixCos(angle);
       
   431             t = (((65536 - anglePos) / 2) - 32768) * 2;
       
   432             return FromFixedPoint(Blend(a, b, t));
       
   433             }
       
   434             break;
       
   435         case EInterpolationModeAccelerate:
       
   436             {
       
   437             // Accelerating quarter of a sine wave.
       
   438             angle = HuiFixMath::FixMul( ( t / 2 ), KFixPi );
       
   439             anglePos = HuiFixMath::FixCos( angle );
       
   440             t = 65536 - anglePos;
       
   441             return FromFixedPoint( Blend( a, b, t ) );
       
   442             }
       
   443             break;
       
   444         case EInterpolationModeImpulse:
       
   445             {
       
   446             // Sine wave curve.
       
   447             angle = HuiFixMath::FixMul( t, KFixPi );
       
   448             anglePos = HuiFixMath::FixCos( angle );
       
   449             t = ( 65536 - anglePos ) / 2;
       
   450             return FromFixedPoint( Blend( a, b, t ) );
       
   451             }
       
   452             break;
       
   453 */            
       
   454         default:
       
   455             {
       
   456             // Unsupported interpolation modes default to linear
       
   457             return FromFixedPoint(Blend(a, b, t));
       
   458             }
       
   459             break;
       
   460         }
       
   461     // not reached
       
   462     return 0;
       
   463     }
       
   464 
       
   465 template <typename TYPE, typename FPTYPE>
       
   466 RHuiFxTimeLine<TYPE, FPTYPE>* RHuiFxTimeLine<TYPE, FPTYPE>::CloneL()
       
   467     {
       
   468     RHuiFxTimeLine* dup = new (ELeave) RHuiFxTimeLine;
       
   469     
       
   470     dup->iTime = iTime;
       
   471     dup->iDuration = iDuration;
       
   472     
       
   473     TInt err = KErrNone;
       
   474     for (TInt i = 0; i < iKeyFrames.Count() && err == KErrNone; ++i)
       
   475         {
       
   476         err = dup->iKeyFrames.Append(iKeyFrames[i]);
       
   477         }
       
   478     if ( err != KErrNone )
       
   479         {
       
   480         delete dup;
       
   481         User::Leave( err );
       
   482         }
       
   483     
       
   484     dup->iLastIndex = iLastIndex;
       
   485     dup->iLoopStart = iLoopStart;
       
   486     dup->iLoopEnd = iLoopEnd;
       
   487     dup->iLoopingMode = iLoopingMode;
       
   488     dup->iInterpolationMode = iInterpolationMode;
       
   489     
       
   490     return dup;
       
   491     }
       
   492 
       
   493 #endif /*HUIFXTIMELINE_INL_*/