language: C++ 4.7.2 (gcc-4.7.2)
date: 108 days 17 hours ago
link:
visibility: public
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//Returns the hill of a specific bounce, working backwards and excluding the final half-bounce.
//0 = the last bounce, excluding the final half-bounce.
//1 = the second-to-last bounce.
float priv_Bounce_GetBounceWidth(unsigned bounce)
{
    //Each bounce is half the width of the previous bounce.
    //The first bounce (excluding the half-bounce) is 1.0f,
    //The second bounce is 0.5f, the third is 0.25f, and so on.
    return std::pow(0.5f, float(bounce));
}
 
//Returns the height of a specific bounce, working backwards and excluding the final half-bounce.
//0 = the last bounce, excluding the final half-bounce.
//1 = the second-to-last bounce.
//
//'bounciness' is a value from 0.0 to 1.0, describing how (from the half-bounce on down)
//small the size of each bounce becomes, relative to the previous.
float priv_Bounce_GetBounceHeight(unsigned bounce, float bounciness)
{
    return std::pow(bounciness, float(bounce+1));
}
 
float priv_Bounce_GetBouncePosition(unsigned bounce)
{
    float position = 1.0f; //The final half-bounce.
    for(unsigned i = 0; i < bounce; i++)
    {
        //Add up the width of all the bounces before this one.
        position += priv_Bounce_GetBounceWidth(i);
    }
 
    return position;
}
 
float priv_Bounce_GetBounceHalfwayPoint(unsigned bounce)
{
    return (priv_Bounce_GetBouncePosition(bounce) + (priv_Bounce_GetBounceWidth(bounce) * 0.5f));
}
 
//Gets the amount we need to offset the bounces by, to make them be at the 'bottom' of the ease.
float priv_Bounce_GetVerticalBounceOffset(unsigned bounce, float bounciness)
{
    const float inverseBounciness = (1.0f - bounciness);
    float offset = 0.0f;
    
    for(unsigned i = 0; i <= bounce; i++)
    {
        //For each bounce, add 0.75f (or whatever (1.0f - bounciness) is) of the remaining height. (Since Each bounce is 0.25f of the previous).
        offset += (inverseBounciness * (1.0f - offset));
    }
 
    return offset;
}
 
//Returns the total width of all the bounces, plus the final half-bounce.
float priv_Bounce_TotalWidth(unsigned bounces)
{
    float totalWidth = 1.0f; //The final half-bounce.
    for(unsigned bounce = 0; bounce < bounces; bounce++)
    {
        //The First bounce added, adds '1.0f'. Second bounce adds '0.5f', the next adds '0.25f', and so on.
        totalWidth += priv_Bounce_GetBounceWidth(bounce);
    }
 
    return totalWidth;
}
 
float CustomBounceEase(float position, int bounces, float bounciness)
{
    //Optimization for end points, which are the most common spots.
    if(position == 0.0f || position == 1.0f)
    {
        return position;
    }
    
    //I don't know the purpose this constant serves in the original ease equation.
    const float UnknownVar = 7.5625f;
    
    //Calculate the total width needed for all the bounces.
    const float TotalWidth = priv_Bounce_TotalWidth(bounces);
    
    for(unsigned int bounce = bounces; bounce-- > 0; )
    {
        float bouncePos = priv_Bounce_GetBouncePosition(bounce);
        
        if(position > (bouncePos / TotalWidth))
        {
            position -= (priv_Bounce_GetBounceHalfwayPoint(bounce) / TotalWidth);
            float verticalOffset = priv_Bounce_GetVerticalBounceOffset(bounce, bounciness);
            
            return ((UnknownVar * position * position) + verticalOffset);
        }
    }
    
    //The final half-bounce:
    return (UnknownVar * position * position);
}