HRESULT CApplication::CreateLinearAnimation(float beginValue, float endValue, float beginTime, float endTime, IDCompositionAnimation **linearAnimation)
{
    HRESULT hr = (linearAnimation == nullptr) ? E_POINTER : S_OK;

    if (SUCCEEDED(hr))
    {
        *linearAnimation = nullptr;

        hr = (_device == nullptr) ? E_UNEXPECTED : S_OK;
    }

    CComPtr<IDCompositionAnimation> animation;

    if (SUCCEEDED(hr))
    {
        hr = _device->CreateAnimation(&animation);
    }

    // Ensures animation start value takes effect immediately
    if (SUCCEEDED(hr))
    {
        if (beginTime > 0.0)
        {
            hr = animation->AddCubic(0.0, beginValue, 0.0f, 0.0f, 0.0f);
        }
    }

    if (SUCCEEDED(hr))
    {
        hr = animation->AddCubic(beginTime, beginValue, (endValue - beginValue) / (endTime - beginTime), 0.0f, 0.0f);
    }

    if (SUCCEEDED(hr))
    {
        hr = animation->End(endTime, endValue);
    }

    if (SUCCEEDED(hr))
    {
        *linearAnimation = animation.Detach();
    }

    return hr;
}