Java Code Examples for org.chromium.chrome.browser.util.MathUtils#interpolate()

The following examples show how to use org.chromium.chrome.browser.util.MathUtils#interpolate() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ToolbarPhone.java    From AndroidChromium with Apache License 2.0 6 votes vote down vote up
/**
 * Calculate the bounds for the location bar background and set them to {@code out}.
 */
private void updateLocationBarBackgroundBounds(Rect out, VisualState visualState) {
    // Calculate the visible boundaries of the left and right most child views of the
    // location bar.
    float expansion = visualState == VisualState.NEW_TAB_NORMAL ? 1 : mUrlExpansionPercent;
    int leftViewPosition = (int) MathUtils.interpolate(
            getViewBoundsLeftOfLocationBar(visualState),
            -mLocationBarBackgroundCornerRadius,
            expansion);
    int rightViewPosition = (int) MathUtils.interpolate(
            getViewBoundsRightOfLocationBar(visualState),
            getWidth() + mLocationBarBackgroundCornerRadius,
            expansion);

    // The bounds are set by the following:
    // - The left most visible location bar child view.
    // - The top of the viewport is aligned with the top of the location bar.
    // - The right most visible location bar child view.
    // - The bottom of the viewport is aligned with the bottom of the location bar.
    // Additional padding can be applied for use during animations.
    int verticalMargin = (int) MathUtils.interpolate(mLocationBarVerticalMargin, 0, expansion);
    out.set(leftViewPosition,
            mLocationBar.getTop() + verticalMargin,
            rightViewPosition,
            mLocationBar.getBottom() - verticalMargin);
}
 
Example 2
Source File: ToolbarPhone.java    From delion with Apache License 2.0 6 votes vote down vote up
/**
 * Calculate the bounds for UrlViewport and set them to out rect.
 */
private void updateUrlViewportBounds(Rect out, VisualState visualState,
        boolean ignoreTranslationY) {
    // Calculate the visible boundaries of the left and right most child views
    // of the location bar.
    int leftViewPosition = (int) MathUtils.interpolate(
            getViewBoundsLeftOfLocationBar(visualState), 0f, mUrlExpansionPercent)
            - mUrlBackgroundPadding.left;
    int rightViewPosition = (int) MathUtils.interpolate(
            getViewBoundsRightOfLocationBar(visualState), getWidth(), mUrlExpansionPercent)
            + mUrlBackgroundPadding.right;

    // The bounds are set by the following:
    // - The left most visible location bar child view.
    // - The top of the viewport is aligned with the top of the location bar.
    // - The right most visible location bar child view.
    // - The bottom of the viewport is aligned with the bottom of the location bar.
    // Additional padding can be applied for use during animations.
    float yOffset = ignoreTranslationY ? mPhoneLocationBar.getTop() : mPhoneLocationBar.getY();

    out.set(leftViewPosition,
            (int) (yOffset - (mUrlBackgroundPadding.top * mUrlExpansionPercent)),
            rightViewPosition,
            (int) (yOffset + MathUtils.interpolate(mPhoneLocationBar.getMeasuredHeight(),
                    getHeight() + mUrlBackgroundPadding.bottom, mUrlExpansionPercent)));
}
 
Example 3
Source File: ToolbarPhone.java    From 365browser with Apache License 2.0 6 votes vote down vote up
/**
 * Calculate the bounds for the location bar background and set them to {@code out}.
 */
protected void updateLocationBarBackgroundBounds(Rect out, VisualState visualState) {
    // Calculate the visible boundaries of the left and right most child views of the
    // location bar.
    float expansion = getExpansionPercentForVisualState(visualState);
    int leftViewPosition = getLeftPositionOfLocationBarBackground(visualState);
    int rightViewPosition = getRightPositionOfLocationBarBackground(visualState);

    // The bounds are set by the following:
    // - The left most visible location bar child view.
    // - The top of the viewport is aligned with the top of the location bar.
    // - The right most visible location bar child view.
    // - The bottom of the viewport is aligned with the bottom of the location bar.
    // Additional padding can be applied for use during animations.
    int verticalMargin = (int) MathUtils.interpolate(mLocationBarVerticalMargin, 0, expansion);
    out.set(leftViewPosition,
            mLocationBar.getTop() + verticalMargin,
            rightViewPosition,
            mLocationBar.getBottom() - verticalMargin);
}
 
Example 4
Source File: ContextualSearchPanel.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
@Override
protected float calculateBarShadowOpacity() {
    float barShadowOpacity = 0.f;
    if (getPromoHeightPx() > 0.f) {
        float threshold = 2 * mBarShadowHeightPx;
        barShadowOpacity = getPromoHeightPx() > mBarShadowHeightPx ? 1.f
                : MathUtils.interpolate(0.f, 1.f, getPromoHeightPx() / threshold);
    }
    return barShadowOpacity;
}
 
Example 5
Source File: ContextualSearchPeekPromoControl.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
/**
 * Updates the UI for the appearance animation.
 *
 * @param percentage The completion percentage.
 */
private void updateForAppearanceAnimation(float percentage) {
    mRippleWidthPx = Math.round(MathUtils.interpolate(
            mRippleMinimumWidthPx, mRippleMaximumWidthPx, percentage));

    mRippleOpacity = MathUtils.interpolate(0.f, 1.f, percentage);

    float textOpacityDelay = 0.5f;
    float textOpacityPercentage =
            Math.max(0, percentage - textOpacityDelay) / (1.f - textOpacityDelay);
    mTextOpacity = MathUtils.interpolate(0.f, 1.f, textOpacityPercentage);
}
 
Example 6
Source File: ContextualSearchPeekPromoControl.java    From 365browser with Apache License 2.0 5 votes vote down vote up
/**
 * Updates the UI for the appearance animation.
 *
 * @param percentage The completion percentage.
 */
private void updateForAppearanceAnimation(float percentage) {
    mRippleWidthPx = Math.round(MathUtils.interpolate(
            mRippleMinimumWidthPx, mRippleMaximumWidthPx, percentage));

    mRippleOpacity = MathUtils.interpolate(0.f, 1.f, percentage);

    float textOpacityDelay = 0.5f;
    float textOpacityPercentage =
            Math.max(0, percentage - textOpacityDelay) / (1.f - textOpacityDelay);
    mTextOpacity = MathUtils.interpolate(0.f, 1.f, textOpacityPercentage);
}
 
Example 7
Source File: ContextualSearchPeekPromoControl.java    From delion with Apache License 2.0 5 votes vote down vote up
/**
 * Interpolates the UI from states Peeked to Expanded.
 *
 * @param percentage The completion percentage.
 */
public void onUpdateFromPeekToExpand(float percentage) {
    if (!isVisible()) return;

    mHeightPx = Math.round(MathUtils.interpolate(mDefaultHeightPx, 0.f, percentage));
    mTextOpacity = MathUtils.interpolate(1.f, 0.f, percentage);
}
 
Example 8
Source File: BottomToolbarPhone.java    From 365browser with Apache License 2.0 5 votes vote down vote up
@Override
protected int getRightPositionOfLocationBarBackground(VisualState visualState) {
    if (!mAnimatingToolbarButtonAppearance && !mAnimatingToolbarButtonDisappearance) {
        mLocationBarBackgroundRightPosition =
                super.getRightPositionOfLocationBarBackground(visualState);
    } else {
        int targetPosition = getViewBoundsRightOfLocationBar(visualState);
        int currentPosition = targetPosition - getLocationBarBackgroundRightOffset();
        mLocationBarBackgroundRightPosition = (int) MathUtils.interpolate(
                targetPosition, currentPosition, mToolbarButtonVisibilityPercent);
    }

    return mLocationBarBackgroundRightPosition;
}
 
Example 9
Source File: ToolbarPhone.java    From 365browser with Apache License 2.0 5 votes vote down vote up
/**
 * @param visualState The current {@link VisualState} of the toolbar.
 * @return The right drawing position for the location bar background.
 */
protected int getRightPositionOfLocationBarBackground(VisualState visualState) {
    float expansion = getExpansionPercentForVisualState(visualState);
    int rightViewPosition =
            (int) MathUtils.interpolate(getViewBoundsRightOfLocationBar(visualState),
                    getWidth() + mLocationBarBackgroundCornerRadius, expansion);

    return rightViewPosition;
}
 
Example 10
Source File: ContextualSearchPanel.java    From 365browser with Apache License 2.0 5 votes vote down vote up
@Override
protected float calculateBarShadowOpacity() {
    float barShadowOpacity = 0.f;
    if (getPromoHeightPx() > 0.f) {
        float threshold = 2 * mBarShadowHeightPx;
        barShadowOpacity = getPromoHeightPx() > mBarShadowHeightPx ? 1.f
                : MathUtils.interpolate(0.f, 1.f, getPromoHeightPx() / threshold);
    }
    return barShadowOpacity;
}
 
Example 11
Source File: ToolbarPhone.java    From delion with Apache License 2.0 4 votes vote down vote up
private boolean drawLocationBar(Canvas canvas, long drawingTime) {
    boolean clipped = false;

    if (mLocationBarBackground != null && (!mIsInTabSwitcherMode || mTextureCaptureMode)) {
        canvas.save();
        int backgroundAlpha;
        if (mTabSwitcherModeAnimation != null) {
            // Fade out/in the location bar towards the beginning of the animations to avoid
            // large jumps of stark white.
            backgroundAlpha =
                    (int) (Math.pow(mPhoneLocationBar.getAlpha(), 3) * mUrlBackgroundAlpha);
        } else if (getToolbarDataProvider().isUsingBrandColor()
                && !mBrandColorTransitionActive) {
            backgroundAlpha = mUnfocusedLocationBarUsesTransparentBg
                    ? (int) (MathUtils.interpolate(LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA,
                            255, mUrlExpansionPercent))
                    : 255;
        } else {
            backgroundAlpha = mUrlBackgroundAlpha;
        }
        mLocationBarBackground.setAlpha(backgroundAlpha);

        if ((mPhoneLocationBar.getAlpha() > 0 || mForceDrawLocationBarBackground)
                && !mTextureCaptureMode) {
            mLocationBarBackground.setBounds(
                    mUrlViewportBounds.left + mLocationBarBackgroundOffset.left,
                    mUrlViewportBounds.top + mLocationBarBackgroundOffset.top,
                    mUrlViewportBounds.right + mLocationBarBackgroundOffset.right,
                    mUrlViewportBounds.bottom + mLocationBarBackgroundOffset.bottom);
            mLocationBarBackground.draw(canvas);
        }

        float locationBarClipLeft = mUrlViewportBounds.left
                + mPhoneLocationBar.getPaddingLeft() + mLocationBarBackgroundOffset.left;
        float locationBarClipRight = mUrlViewportBounds.right
                - mPhoneLocationBar.getPaddingRight() + mLocationBarBackgroundOffset.right;
        float locationBarClipTop = mUrlViewportBounds.top + mPhoneLocationBar.getPaddingTop()
                + mLocationBarBackgroundOffset.top;
        float locationBarClipBottom = mUrlViewportBounds.bottom
                - mPhoneLocationBar.getPaddingBottom() + mLocationBarBackgroundOffset.bottom;

        // When unexpanded, the location bar's visible content boundaries are inset from the
        // viewport used to draw the background.  During expansion transitions, compensation
        // is applied to increase the clip regions such that when the location bar converts
        // to the narrower collapsed layout that the visible content is the same.
        if (mUrlExpansionPercent != 1f) {
            int leftDelta = mUnfocusedLocationBarLayoutLeft
                    - getViewBoundsLeftOfLocationBar(mVisualState);
            int rightDelta = getViewBoundsRightOfLocationBar(mVisualState)
                    - mUnfocusedLocationBarLayoutLeft
                    - mUnfocusedLocationBarLayoutWidth;
            float inversePercent = 1f - mUrlExpansionPercent;
            locationBarClipLeft += leftDelta * inversePercent;
            locationBarClipRight -= rightDelta * inversePercent;
        }

        // Clip the location bar child to the URL viewport calculated in onDraw.
        canvas.clipRect(
                locationBarClipLeft, locationBarClipTop,
                locationBarClipRight, locationBarClipBottom);
        clipped = true;
    }

    boolean retVal = super.drawChild(canvas, mPhoneLocationBar, drawingTime);

    if (clipped) canvas.restore();
    return retVal;
}
 
Example 12
Source File: OverlayPanelBase.java    From AndroidChromium with Apache License 2.0 4 votes vote down vote up
/**
 * Updates the UI state for the peeked to expanded transition (and vice
 * versa), according to a completion |percentage|.
 *
 * Note that this method will never be called with percentage = 0.f. Once the panel
 * reaches the peeked state #updatePanelForCloseOrPeek() will be called instead of this method
 * because the end panel state for transitions is calculated based on the panel height.
 *
 * @param percentage The completion percentage.
 */
protected void updatePanelForExpansion(float percentage) {
    // Base page offset.
    mBasePageY = MathUtils.interpolate(
            0.f,
            getBasePageTargetY(),
            percentage);

    // Base page brightness.
    mBasePageBrightness = MathUtils.interpolate(
            BASE_PAGE_BRIGHTNESS_STATE_PEEKED,
            BASE_PAGE_BRIGHTNESS_STATE_EXPANDED,
            percentage);

    // Bar height.
    mBarHeight = Math.round(MathUtils.interpolate(
            mBarHeightPeeking,
            getBarHeightExpanded(),
            percentage));

    // Bar border.
    mIsBarBorderVisible = true;

    // Determine fading element opacities. The arrow icon needs to finish fading out before
    // the close icon starts fading in. Any other elements fading in or fading out should use
    // the same percentage.
    float fadingOutPercentage = Math.min(percentage, .5f) / .5f;
    float fadingInPercentage = Math.max(percentage - .5f, 0.f) / .5f;

    // Arrow Icon.
    mArrowIconOpacity = MathUtils.interpolate(
            ARROW_ICON_OPACITY_STATE_PEEKED,
            ARROW_ICON_OPACITY_STATE_EXPANDED,
            fadingOutPercentage);

    // Close Icon.
    mCloseIconOpacity = MathUtils.interpolate(
            CLOSE_ICON_OPACITY_STATE_PEEKED,
            CLOSE_ICON_OPACITY_STATE_EXPANDED,
            fadingInPercentage);

    // Progress Bar.
    float peekedHeight = getPanelHeightFromState(PanelState.PEEKED);
    float threshold = PROGRESS_BAR_VISIBILITY_THRESHOLD_DP / mPxToDp;
    float diff = Math.min(mHeight - peekedHeight, threshold);
    // Fades the Progress Bar the closer it gets to the bottom of the
    // screen.
    mProgressBarOpacity = MathUtils.interpolate(0.f, 1.f, diff / threshold);

    // Update the Bar Shadow.
    updateBarShadow();
}
 
Example 13
Source File: OverlayPanelBase.java    From 365browser with Apache License 2.0 4 votes vote down vote up
/**
 * Updates the UI state for the expanded to maximized transition (and vice
 * versa), according to a completion |percentage|.
 *
 * @param percentage The completion percentage.
 */
protected void updatePanelForMaximization(float percentage) {
    boolean supportsExpandedState = isSupportedState(PanelState.EXPANDED);

    // Base page offset.
    float startTargetY = supportsExpandedState ? getBasePageTargetY() : 0.0f;
    mBasePageY = MathUtils.interpolate(
            startTargetY,
            getBasePageTargetY(),
            percentage);

    // Base page brightness.
    float startBrightness = supportsExpandedState
            ? BASE_PAGE_BRIGHTNESS_STATE_EXPANDED : BASE_PAGE_BRIGHTNESS_STATE_PEEKED;
    mBasePageBrightness = MathUtils.interpolate(
            startBrightness,
            BASE_PAGE_BRIGHTNESS_STATE_MAXIMIZED,
            percentage);

    // Bar height.
    float startBarHeight = supportsExpandedState
            ? getBarHeightExpanded() : getBarHeightPeeking();
    mBarHeight = Math.round(MathUtils.interpolate(
            startBarHeight,
            getBarHeightMaximized(),
            percentage));

    // Bar border.
    mIsBarBorderVisible = true;

    // Arrow Icon.
    mArrowIconOpacity = ARROW_ICON_OPACITY_STATE_MAXIMIZED;

    // Close Icon.
    mCloseIconOpacity = CLOSE_ICON_OPACITY_STATE_MAXIMIZED;

    // Progress Bar.
    mProgressBarOpacity = 1.f;

    // Update the Bar Shadow.
    updateBarShadow();
}
 
Example 14
Source File: OverlayPanelBase.java    From 365browser with Apache License 2.0 4 votes vote down vote up
/**
 * Updates the UI state for the peeked to expanded transition (and vice
 * versa), according to a completion |percentage|.
 *
 * Note that this method will never be called with percentage = 0.f. Once the panel
 * reaches the peeked state #updatePanelForCloseOrPeek() will be called instead of this method
 * because the end panel state for transitions is calculated based on the panel height.
 *
 * @param percentage The completion percentage.
 */
protected void updatePanelForExpansion(float percentage) {
    // Base page offset.
    mBasePageY = MathUtils.interpolate(
            0.f,
            getBasePageTargetY(),
            percentage);

    // Base page brightness.
    mBasePageBrightness = MathUtils.interpolate(
            BASE_PAGE_BRIGHTNESS_STATE_PEEKED,
            BASE_PAGE_BRIGHTNESS_STATE_EXPANDED,
            percentage);

    // Bar height.
    mBarHeight = Math.round(MathUtils.interpolate(
            mBarHeightPeeking,
            getBarHeightExpanded(),
            percentage));

    // Bar border.
    mIsBarBorderVisible = true;

    // Determine fading element opacities. The arrow icon needs to finish fading out before
    // the close icon starts fading in. Any other elements fading in or fading out should use
    // the same percentage.
    float fadingOutPercentage = Math.min(percentage, .5f) / .5f;
    float fadingInPercentage = Math.max(percentage - .5f, 0.f) / .5f;

    // Arrow Icon.
    mArrowIconOpacity = MathUtils.interpolate(
            ARROW_ICON_OPACITY_STATE_PEEKED,
            ARROW_ICON_OPACITY_STATE_EXPANDED,
            fadingOutPercentage);

    // Close Icon.
    mCloseIconOpacity = MathUtils.interpolate(
            CLOSE_ICON_OPACITY_STATE_PEEKED,
            CLOSE_ICON_OPACITY_STATE_EXPANDED,
            fadingInPercentage);

    // Progress Bar.
    float peekedHeight = getPanelHeightFromState(PanelState.PEEKED);
    float threshold = PROGRESS_BAR_VISIBILITY_THRESHOLD_DP / mPxToDp;
    float diff = Math.min(mHeight - peekedHeight, threshold);
    // Fades the Progress Bar the closer it gets to the bottom of the
    // screen.
    mProgressBarOpacity = MathUtils.interpolate(0.f, 1.f, diff / threshold);

    // Update the Bar Shadow.
    updateBarShadow();
}
 
Example 15
Source File: OverlayPanelBase.java    From delion with Apache License 2.0 4 votes vote down vote up
/**
 * Updates the UI state for the peeked to expanded transition (and vice
 * versa), according to a completion |percentage|.
 *
 * @param percentage The completion percentage.
 */
protected void updatePanelForExpansion(float percentage) {
    // Base page offset.
    mBasePageY = MathUtils.interpolate(
            0.f,
            getBasePageTargetY(),
            percentage);

    // Base page brightness.
    mBasePageBrightness = MathUtils.interpolate(
            BASE_PAGE_BRIGHTNESS_STATE_PEEKED,
            BASE_PAGE_BRIGHTNESS_STATE_EXPANDED,
            percentage);

    // Bar height.
    mBarHeight = Math.round(MathUtils.interpolate(
            mBarHeightPeeking,
            getBarHeightExpanded(),
            percentage));

    // Bar border.
    mIsBarBorderVisible = true;

    // Determine fading element opacities. The arrow icon needs to finish fading out before
    // the close icon starts fading in. Any other elements fading in or fading out should use
    // the same percentage.
    float fadingOutPercentage = Math.min(percentage, .5f) / .5f;
    float fadingInPercentage = Math.max(percentage - .5f, 0.f) / .5f;

    // Arrow Icon.
    mArrowIconOpacity = MathUtils.interpolate(
            ARROW_ICON_OPACITY_STATE_PEEKED,
            ARROW_ICON_OPACITY_STATE_EXPANDED,
            fadingOutPercentage);

    // Close Icon.
    mCloseIconOpacity = MathUtils.interpolate(
            CLOSE_ICON_OPACITY_STATE_PEEKED,
            CLOSE_ICON_OPACITY_STATE_EXPANDED,
            fadingInPercentage);

    // Progress Bar.
    float peekedHeight = getPanelHeightFromState(PanelState.PEEKED);
    float threshold = PROGRESS_BAR_VISIBILITY_THRESHOLD_DP / mPxToDp;
    float diff = Math.min(mHeight - peekedHeight, threshold);
    // Fades the Progress Bar the closer it gets to the bottom of the
    // screen.
    mProgressBarOpacity = MathUtils.interpolate(0.f, 1.f, diff / threshold);

    // Update the Bar Shadow.
    updateBarShadow();
}
 
Example 16
Source File: Stack.java    From delion with Apache License 2.0 3 votes vote down vote up
/**
 * Computes the scale of the tab based on its discard status.
 *
 * @param amount    The discard amount.
 * @param range     The range of the absolute value of discard amount.
 * @param fromClick Whether or not the discard was from a click or a swipe.
 * @return          The scale of the tab to use to draw the tab.
 */
public static float computeDiscardScale(float amount, float range, boolean fromClick) {
    if (Math.abs(amount) < 1.0f) return 1.0f;
    float t = amount / range;
    float endScale = fromClick ? DISCARD_END_SCALE_CLICK : DISCARD_END_SCALE_SWIPE;
    return MathUtils.interpolate(1.0f, endScale, Math.abs(t));
}
 
Example 17
Source File: Stack.java    From AndroidChromium with Apache License 2.0 2 votes vote down vote up
/**
 * Smoothes input signal. The definition of the input is lower than the
 * pixel density of the screen so we need to smooth the input to give the illusion of smooth
 * animation on screen from chunky inputs.
 * The combination of 20 pixels and 0.9f ensures that the output is not more than 2 pixels away
 * from the target.
 * TODO: This has nothing to do with time, just draw rate.
 *       Is this okay or do we want to have the interpolation based on the time elapsed?
 * @param current   The current value of the signal.
 * @param input     The raw input value.
 * @return          The smoothed signal.
 */
private float smoothInput(float current, float input) {
    current = MathUtils.clamp(current, input - 20, input + 20);
    return MathUtils.interpolate(current, input, 0.9f);
}
 
Example 18
Source File: ToolbarSwipeLayout.java    From 365browser with Apache License 2.0 2 votes vote down vote up
/**
 * Smoothes input signal. The definition of the input is lower than the
 * pixel density of the screen so we need to smooth the input to give the illusion of smooth
 * animation on screen from chunky inputs.
 * The combination of 30 pixels and 0.8f ensures that the output is not more than 6 pixels away
 * from the target.
 * TODO(dtrainor): This has nothing to do with time, just draw rate.
 *       Is this okay or do we want to have the interpolation based on the time elapsed?
 * @param current The current value of the signal.
 * @param input The raw input value.
 * @return The smoothed signal.
 */
private float smoothInput(float current, float input) {
    current = MathUtils.clamp(current, input - 30, input + 30);
    return MathUtils.interpolate(current, input, 0.8f);
}
 
Example 19
Source File: Stack.java    From 365browser with Apache License 2.0 2 votes vote down vote up
/**
 * Smoothes input signal. The definition of the input is lower than the
 * pixel density of the screen so we need to smooth the input to give the illusion of smooth
 * animation on screen from chunky inputs.
 * The combination of 20 pixels and 0.9f ensures that the output is not more than 2 pixels away
 * from the target.
 * TODO: This has nothing to do with time, just draw rate.
 *       Is this okay or do we want to have the interpolation based on the time elapsed?
 * @param current   The current value of the signal.
 * @param input     The raw input value.
 * @return          The smoothed signal.
 */
private float smoothInput(float current, float input) {
    current = MathUtils.clamp(current, input - 20, input + 20);
    return MathUtils.interpolate(current, input, 0.9f);
}
 
Example 20
Source File: Stack.java    From delion with Apache License 2.0 2 votes vote down vote up
/**
 * Smoothes input signal. The definition of the input is lower than the
 * pixel density of the screen so we need to smooth the input to give the illusion of smooth
 * animation on screen from chunky inputs.
 * The combination of 20 pixels and 0.9f ensures that the output is not more than 2 pixels away
 * from the target.
 * TODO: This has nothing to do with time, just draw rate.
 *       Is this okay or do we want to have the interpolation based on the time elapsed?
 * @param current   The current value of the signal.
 * @param input     The raw input value.
 * @return          The smoothed signal.
 */
private float smoothInput(float current, float input) {
    current = MathUtils.clamp(current, input - 20, input + 20);
    return MathUtils.interpolate(current, input, 0.9f);
}