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

The following examples show how to use org.chromium.chrome.browser.util.MathUtils#clamp() . 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: CardViewHolder.java    From AndroidChromium with Apache License 2.0 6 votes vote down vote up
/**
 * Change the width, padding and child opacity of the card to give a smooth transition as the
 * user scrolls.
 * @param availableSpace space (pixels) available between the bottom of the screen and the
 *                       above-the-fold section, where the card can peek.
 * @param canPeek whether the screen size allows having a peeking card.
 */
public void updatePeek(int availableSpace, boolean canPeek) {
    float peekingPercentage;

    if (!canPeek) {
        peekingPercentage = 0f;
    } else {
        // If 1 padding unit (|mMaxPeekPadding|) is visible, the card is fully peeking. This is
        // reduced as the card is scrolled up, until 2 padding units are visible and the card is
        // not peeking anymore at all. Anything not between 0 and 1 is clamped.
        peekingPercentage =
                MathUtils.clamp(2f - (float) availableSpace / mMaxPeekPadding, 0f, 1f);
    }

    setPeekingPercentage(peekingPercentage);
}
 
Example 2
Source File: StackLayout.java    From 365browser with Apache License 2.0 6 votes vote down vote up
@Override
public void fling(float x, float y, float velocityX, float velocityY) {
    long time = time();
    float vx = velocityX;
    float vy = velocityY;

    if (mInputMode == SwipeMode.NONE) {
        mInputMode = computeInputMode(
                time, x, y, vx * SWITCH_STACK_FLING_DT, vy * SWITCH_STACK_FLING_DT);
    }

    if (mInputMode == SwipeMode.SEND_TO_STACK) {
        mStacks[getTabStackIndex()].fling(time, x, y, vx, vy);
    } else if (mInputMode == SwipeMode.SWITCH_STACK) {
        final float velocity = getOrientation() == Orientation.PORTRAIT ? vx : vy;
        final float origin = getOrientation() == Orientation.PORTRAIT ? x : y;
        final float max =
                getOrientation() == Orientation.PORTRAIT ? getWidth() : getHeight();
        final float predicted = origin + velocity * SWITCH_STACK_FLING_DT;
        final float delta = MathUtils.clamp(predicted, 0, max) - origin;
        scrollStacks(delta);
    }
    requestStackUpdate();
}
 
Example 3
Source File: Stack.java    From 365browser with Apache License 2.0 6 votes vote down vote up
/**
 * Whether or not the tab positions warp from linear to nonlinear as the tabs approach the edge
 * of the screen.  This allows us to move the tabs to linear space to track finger movements,
 * but also move them back to non-linear space without any visible change to the user.
 * @param canWarp           Whether or not the tabs are allowed to warp.
 * @param adjustCurrentTabs Whether or not to change the tab positions so there's no visible
 *                          difference after the change.
 */
private void setWarpState(boolean canWarp, boolean adjustCurrentTabs) {
    float warp = canWarp ? getScrollDimensionSize() * SCROLL_WARP_PCTG : 0.f;

    if (mStackTabs != null && adjustCurrentTabs && Float.compare(warp, mWarpSize) != 0) {
        float scrollOffset =
                MathUtils.clamp(mScrollOffset, getMinScroll(false), getMaxScroll(false));
        for (int i = 0; i < mStackTabs.length; i++) {
            StackTab tab = mStackTabs[i];
            float tabScrollOffset = tab.getScrollOffset();
            float tabScrollSpace = tabScrollOffset + scrollOffset;
            float tabScreen = StackTab.scrollToScreen(tabScrollSpace, mWarpSize);
            float tabScrollSpaceFinal = StackTab.screenToScroll(tabScreen, warp);
            float scrollDelta = tabScrollSpaceFinal - tabScrollSpace;
            tab.setScrollOffset(tabScrollOffset + scrollDelta);
        }
    }

    mWarpSize = warp;
}
 
Example 4
Source File: FontSizePrefs.java    From AndroidChromium with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the userFontScaleFactor. This is the value that should be displayed to the user.
 */
public float getUserFontScaleFactor() {
    float userFontScaleFactor = mSharedPreferences.getFloat(PREF_USER_FONT_SCALE_FACTOR, 0f);
    if (userFontScaleFactor == 0f) {
        float fontScaleFactor = getFontScaleFactor();

        if (Math.abs(fontScaleFactor - 1f) <= EPSILON) {
            // If the font scale factor is 1, assume that the user hasn't customized their font
            // scale and/or wants the default value
            userFontScaleFactor = 1f;
        } else {
            // Initialize userFontScaleFactor based on fontScaleFactor, since
            // userFontScaleFactor was added long after fontScaleFactor.
            userFontScaleFactor =
                    MathUtils.clamp(fontScaleFactor / getSystemFontScale(), 0.5f, 2f);
        }
        SharedPreferences.Editor sharedPreferencesEditor = mSharedPreferences.edit();
        sharedPreferencesEditor.putFloat(PREF_USER_FONT_SCALE_FACTOR, userFontScaleFactor);
        sharedPreferencesEditor.apply();
    }
    return userFontScaleFactor;
}
 
Example 5
Source File: Stack.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
/**
 * ComputeTabPosition pass 6:
 * Updates the visibility sorting value to use to figure out which thumbnails to load.
 *
 * @param stackRect The frame of the stack.
 */
private void computeTabVisibilitySortingHelper(RectF stackRect) {
    int referenceIndex = mReferenceOrderIndex;
    if (referenceIndex == -1) {
        int centerIndex =
                getTabIndexAtPositon(mLayout.getWidth() / 2.0f, mLayout.getHeight() / 2.0f);
        // Alter the center to take into account the scrolling direction.
        if (mCurrentScrollDirection > 0) centerIndex++;
        if (mCurrentScrollDirection < 0) centerIndex--;
        referenceIndex = MathUtils.clamp(centerIndex, 0, mStackTabs.length - 1);
    }

    final float width = mLayout.getWidth();
    final float height = mLayout.getHeight();
    final float left = MathUtils.clamp(stackRect.left, 0, width);
    final float right = MathUtils.clamp(stackRect.right, 0, width);
    final float top = MathUtils.clamp(stackRect.top, 0, height);
    final float bottom = MathUtils.clamp(stackRect.bottom, 0, height);
    final float stackArea = (right - left) * (bottom - top);
    final float layoutArea = Math.max(width * height, 1.0f);
    final float stackVisibilityMultiplier = stackArea / layoutArea;

    for (int i = 0; i < mStackTabs.length; i++) {
        mStackTabs[i].updateStackVisiblityValue(stackVisibilityMultiplier);
        mStackTabs[i].updateVisiblityValue(referenceIndex);
    }
}
 
Example 6
Source File: ItemChooserDialog.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
@VisibleForTesting
static int getListHeight(int decorHeight, float density) {
    float heightDp = decorHeight / density * LISTVIEW_HEIGHT_PERCENT;
    // Round to (an integer + 0.5) times LIST_ROW_HEIGHT.
    heightDp = (Math.round(heightDp / LIST_ROW_HEIGHT_DP - 0.5f) + 0.5f) * LIST_ROW_HEIGHT_DP;
    heightDp = MathUtils.clamp(heightDp, MIN_HEIGHT_DP, MAX_HEIGHT_DP);
    return (int) Math.round(heightDp * density);
}
 
Example 7
Source File: StripLayoutHelper.java    From 365browser with Apache License 2.0 5 votes vote down vote up
private void computeAndUpdateTabWidth(boolean animate) {
    // Remove any queued resize messages.
    mStripTabEventHandler.removeMessages(MESSAGE_RESIZE);

    int numTabs = Math.max(mStripTabs.length, 1);

    // 1. Compute the width of the available space for all tabs.
    float stripWidth = mWidth - mLeftMargin - mRightMargin;

    // 2. Compute additional width we gain from overlapping the tabs.
    float overlapWidth = mTabOverlapWidth * (numTabs - 1);

    // 3. Calculate the optimal tab width.
    float optimalTabWidth = (stripWidth + overlapWidth) / numTabs;

    // 4. Calculate the realistic tab width.
    mCachedTabWidth = MathUtils.clamp(optimalTabWidth, mMinTabWidth, mMaxTabWidth);

    // 5. Propagate the tab width to all tabs.
    for (int i = 0; i < mStripTabs.length; i++) {
        StripLayoutTab tab = mStripTabs[i];
        if (tab.isDying()) continue;

        // 5.a. Cancel any outstanding tab width animations.
        cancelAnimation(mStripTabs[i], StripLayoutTab.Property.WIDTH);

        if (animate && !mAnimationsDisabledForTesting) {
            startAnimation(buildTabResizeAnimation(tab, mCachedTabWidth), false);
        } else {
            mStripTabs[i].setWidth(mCachedTabWidth);
        }
    }
}
 
Example 8
Source File: StripLayoutHelper.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
private void updateScrollOffsetPosition(int pos) {
    int oldScrollOffset = mScrollOffset;
    mScrollOffset = MathUtils.clamp(pos, (int) mMinScrollOffset, 0);

    if (mInReorderMode && mScroller.isFinished()) {
        int delta = MathUtils.flipSignIf(
                oldScrollOffset - mScrollOffset, LocalizationUtils.isLayoutRtl());
        updateReorderPosition(delta);
    }
}
 
Example 9
Source File: TabModelImpl.java    From 365browser with Apache License 2.0 5 votes vote down vote up
@Override
public void setIndex(int i, final TabSelectionType type) {
    try {
        TraceEvent.begin("TabModelImpl.setIndex");
        int lastId = getLastId(type);

        if (!isCurrentModel()) {
            mModelDelegate.selectModel(isIncognito());
        }

        if (!hasValidTab()) {
            mIndex = INVALID_TAB_INDEX;
        } else {
            mIndex = MathUtils.clamp(i, 0, mTabs.size() - 1);
        }

        Tab tab = TabModelUtils.getCurrentTab(this);

        mModelDelegate.requestToShowTab(tab, type);

        if (tab != null) {
            for (TabModelObserver obs : mObservers) obs.didSelectTab(tab, type, lastId);

            boolean wasAlreadySelected = tab.getId() == lastId;
            if (!wasAlreadySelected && type == TabSelectionType.FROM_USER && mUma != null) {
                // We only want to record when the user actively switches to a different tab.
                mUma.userSwitchedToTab();
            }
        }

    } finally {
        TraceEvent.end("TabModelImpl.setIndex");
    }
}
 
Example 10
Source File: NewTabPageView.java    From delion with Apache License 2.0 5 votes vote down vote up
private void updateSearchBoxOnScroll() {
    if (mDisableUrlFocusChangeAnimations) return;

    float toolbarTransitionPercentage;
    // During startup the view may not be fully initialized, so we only calculate the current
    // percentage if some basic view properties are sane.
    if (getWrapperView().getHeight() == 0 || mSearchBoxView.getTop() == 0) {
        toolbarTransitionPercentage = 0f;
    } else if (!mUseCardsUi) {
        toolbarTransitionPercentage =
                MathUtils.clamp(getVerticalScroll() / (float) mSearchBoxView.getTop(), 0f, 1f);
    } else {
        if (!mRecyclerView.isFirstItemVisible()) {
            // getVerticalScroll is valid only for the RecyclerView if the first item is
            // visible. Luckily, if the first item is not visible, we know the toolbar
            // transition should be 100%.
            toolbarTransitionPercentage = 1f;
        } else {
            final int scrollY = getVerticalScroll();
            final int top = mSearchBoxView.getTop();  // Relative to mNewTabPageLayout.
            final int transitionLength = getResources()
                    .getDimensionPixelSize(R.dimen.ntp_search_box_transition_length);

            // |scrollY - top| gives the distance the search bar is from the top of the screen.
            toolbarTransitionPercentage = MathUtils.clamp(
                    (scrollY - top + transitionLength) / (float) transitionLength, 0f, 1f);
        }
    }

    updateVisualsForToolbarTransition(toolbarTransitionPercentage);

    if (mSearchBoxScrollListener != null) {
        mSearchBoxScrollListener.onNtpScrollChanged(toolbarTransitionPercentage);
    }
}
 
Example 11
Source File: OverlayPanelBase.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
/**
 * Sets the last panel height within the limits allowable by our UI.
 *
 * @param height The height of the panel in dps.
 */
protected void setClampedPanelHeight(float height) {
    final float clampedHeight = MathUtils.clamp(height,
            getPanelHeightFromState(getMaximumSupportedState()),
            getPanelHeightFromState(PanelState.PEEKED));
    setPanelHeight(clampedHeight);
}
 
Example 12
Source File: StripLayoutHelper.java    From delion with Apache License 2.0 5 votes vote down vote up
private void computeAndUpdateTabWidth(boolean animate) {
    // Remove any queued resize messages.
    mStripTabEventHandler.removeMessages(MESSAGE_RESIZE);

    int numTabs = Math.max(mStripTabs.length, 1);

    // 1. Compute the width of the available space for all tabs.
    float stripWidth = mWidth - mLeftMargin - mRightMargin;

    // 2. Compute additional width we gain from overlapping the tabs.
    float overlapWidth = mTabOverlapWidth * (numTabs - 1);

    // 3. Calculate the optimal tab width.
    float optimalTabWidth = (stripWidth + overlapWidth) / numTabs;

    // 4. Calculate the realistic tab width.
    mCachedTabWidth = MathUtils.clamp(optimalTabWidth, mMinTabWidth, mMaxTabWidth);

    // 5. Propagate the tab width to all tabs.
    for (int i = 0; i < mStripTabs.length; i++) {
        StripLayoutTab tab = mStripTabs[i];
        if (tab.isDying()) continue;

        // 5.a. Cancel any outstanding tab width animations.
        cancelAnimation(mStripTabs[i], StripLayoutTab.Property.WIDTH);

        if (animate) {
            startAnimation(buildTabResizeAnimation(tab, mCachedTabWidth), false);
        } else {
            mStripTabs[i].setWidth(mCachedTabWidth);
        }
    }
}
 
Example 13
Source File: StripLayoutTab.java    From AndroidChromium with Apache License 2.0 4 votes vote down vote up
/**
 * @param offsetX How far to offset the tab content (favicons and title).
 */
public void setContentOffsetX(float offsetX) {
    mContentOffsetX = MathUtils.clamp(offsetX, 0.f, mWidth);
}
 
Example 14
Source File: MostVisitedLayout.java    From AndroidChromium with Apache License 2.0 4 votes vote down vote up
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int totalWidth = resolveSize(mMaxWidth, widthMeasureSpec);
    int childCount = getChildCount();
    if (childCount == 0) {
        setMeasuredDimension(totalWidth, resolveSize(0, heightMeasureSpec));
        return;
    }

    // Measure the children.
    for (int i = 0; i < childCount; i++) {
        measureChild(getChildAt(i), MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
    }

    // Determine the number of columns that will fit.
    int gridWidth = totalWidth - ApiCompatibilityUtils.getPaddingStart(this)
            - ApiCompatibilityUtils.getPaddingEnd(this);
    int childHeight = getChildAt(0).getMeasuredHeight();
    int childWidth = getChildAt(0).getMeasuredWidth();
    int numColumns = MathUtils.clamp(
            (gridWidth + mMinHorizontalSpacing) / (childWidth + mMinHorizontalSpacing),
            1, MAX_COLUMNS);

    // Ensure column spacing isn't greater than mMaxHorizontalSpacing.
    int gridWidthMinusColumns = Math.max(0, gridWidth - numColumns * childWidth);
    int gridSidePadding = gridWidthMinusColumns - mMaxHorizontalSpacing * (numColumns - 1);

    int gridStart = 0;
    float horizontalSpacing;
    if (gridSidePadding > 0) {
        horizontalSpacing = mMaxHorizontalSpacing;
        gridStart = gridSidePadding / 2;
    } else {
        horizontalSpacing = (float) gridWidthMinusColumns / Math.max(1, numColumns - 1);
    }

    // Limit the number of rows to mMaxRows.
    int visibleChildCount = Math.min(childCount, mMaxRows * numColumns);

    // Arrange the visible children in a grid.
    int numRows = (visibleChildCount + numColumns - 1) / numColumns;
    int paddingTop = getPaddingTop();
    boolean isRtl = ApiCompatibilityUtils.isLayoutRtl(this);
    for (int i = 0; i < visibleChildCount; i++) {
        View child = getChildAt(i);
        child.setVisibility(View.VISIBLE);
        int row = i / numColumns;
        int column = i % numColumns;
        int verticalOffset = Math.round(mExtraVerticalSpacing * ((float) (row + 1) / numRows));
        int childTop = row * (childHeight + mVerticalSpacing) + verticalOffset;
        int childStart = gridStart + Math.round(column * (childWidth + horizontalSpacing));
        MarginLayoutParams layoutParams = (MarginLayoutParams) child.getLayoutParams();
        layoutParams.setMargins(isRtl ? 0 : childStart, childTop, isRtl ? childStart : 0, 0);
        child.setLayoutParams(layoutParams);
    }

    // Hide any extra children in case there are more than needed for the maximum number of
    // rows.
    for (int i = visibleChildCount; i < childCount; i++) {
        getChildAt(i).setVisibility(View.GONE);
    }

    int totalHeight = paddingTop + getPaddingBottom() + numRows * childHeight
            + (numRows - 1) * mVerticalSpacing + mExtraVerticalSpacing;

    setMeasuredDimension(totalWidth, resolveSize(totalHeight, heightMeasureSpec));
}
 
Example 15
Source File: ToolbarSwipeLayout.java    From delion with Apache License 2.0 4 votes vote down vote up
@Override
public void swipeUpdated(long time, float x, float y, float dx, float dy, float tx, float ty) {
    mOffsetTarget = MathUtils.clamp(mOffsetStart + tx, 0, getWidth()) - mOffsetStart;
    requestUpdate();
}
 
Example 16
Source File: ToolbarSwipeLayout.java    From 365browser with Apache License 2.0 4 votes vote down vote up
@Override
public void swipeUpdated(long time, float x, float y, float dx, float dy, float tx, float ty) {
    mOffsetTarget = MathUtils.clamp(mOffsetStart + tx, 0, getWidth()) - mOffsetStart;
    requestUpdate();
}
 
Example 17
Source File: StackAnimationLandscape.java    From delion with Apache License 2.0 4 votes vote down vote up
@Override
protected ChromeAnimation<?> createTabFocusedAnimatorSet(
        StackTab[] tabs, int focusIndex, int spacing, float warpSize) {
    ChromeAnimation<Animatable<?>> set = new ChromeAnimation<Animatable<?>>();
    for (int i = 0; i < tabs.length; ++i) {
        StackTab tab = tabs[i];
        LayoutTab layoutTab = tab.getLayoutTab();

        addTiltScrollAnimation(set, layoutTab, 0.0f, TAB_FOCUSED_ANIMATION_DURATION, 0);
        addAnimation(set, tab, DISCARD_AMOUNT, tab.getDiscardAmount(), 0.0f,
                TAB_FOCUSED_ANIMATION_DURATION, 0);

        if (i < focusIndex) {
            // For tabs left of the focused tab move them left to 0.
            addAnimation(set, tab, SCROLL_OFFSET, tab.getScrollOffset(),
                    Math.max(0.0f, tab.getScrollOffset() - mWidth - spacing),
                    TAB_FOCUSED_ANIMATION_DURATION, 0);
        } else if (i > focusIndex) {
            // We also need to animate the X Translation to move them right
            // off the screen.
            float coveringTabPosition = layoutTab.getX();
            float distanceToBorder = LocalizationUtils.isLayoutRtl()
                    ? coveringTabPosition + layoutTab.getScaledContentWidth()
                    : mWidth - coveringTabPosition;
            float clampedDistanceToBorder = MathUtils.clamp(distanceToBorder, 0, mWidth);
            float delay = TAB_FOCUSED_MAX_DELAY * clampedDistanceToBorder / mWidth;
            addAnimation(set, tab, X_IN_STACK_OFFSET, tab.getXInStackOffset(),
                    tab.getXInStackOffset()
                            + (LocalizationUtils.isLayoutRtl() ? -mWidth : mWidth),
                    (TAB_FOCUSED_ANIMATION_DURATION - (long) delay), (long) delay);
        } else {
            // This is the focused tab.  We need to scale it back to
            // 1.0f, move it to the top of the screen, and animate the
            // X Translation so that it looks like it is zooming into the
            // full screen view.  We move the card to the top left and extend it out so
            // it becomes a full card.
            tab.setXOutOfStack(0);
            tab.setYOutOfStack(0.0f);
            layoutTab.setBorderScale(1.f);

            addAnimation(set, tab, SCROLL_OFFSET, tab.getScrollOffset(),
                    StackTab.screenToScroll(0, warpSize), TAB_FOCUSED_ANIMATION_DURATION, 0);
            addAnimation(
                    set, tab, SCALE, tab.getScale(), 1.0f, TAB_FOCUSED_ANIMATION_DURATION, 0);
            addAnimation(set, tab, X_IN_STACK_INFLUENCE, tab.getXInStackInfluence(), 0.0f,
                    TAB_FOCUSED_ANIMATION_DURATION, 0);
            addAnimation(set, tab, Y_IN_STACK_INFLUENCE, tab.getYInStackInfluence(), 0.0f,
                    TAB_FOCUSED_Y_STACK_DURATION, 0);

            addAnimation(set, tab.getLayoutTab(), MAX_CONTENT_HEIGHT,
                    tab.getLayoutTab().getMaxContentHeight(),
                    tab.getLayoutTab().getUnclampedOriginalContentHeight(),
                    TAB_FOCUSED_ANIMATION_DURATION, 0);
            tab.setYOutOfStack(mHeight - mHeightMinusTopControls - mBorderTopHeight);

            if (layoutTab.shouldStall()) {
                addAnimation(set, layoutTab, SATURATION, 1.0f, 0.0f,
                        TAB_FOCUSED_BORDER_ALPHA_DURATION, TAB_FOCUSED_BORDER_ALPHA_DELAY);
            }
            addAnimation(set, tab.getLayoutTab(), TOOLBAR_ALPHA, layoutTab.getToolbarAlpha(),
                    1.f, TAB_FOCUSED_TOOLBAR_ALPHA_DURATION, TAB_FOCUSED_TOOLBAR_ALPHA_DELAY);
            addAnimation(set, tab.getLayoutTab(), TOOLBAR_Y_OFFSET,
                    getToolbarOffsetToLineUpWithBorder(), 0.f,
                    TAB_FOCUSED_TOOLBAR_ALPHA_DURATION, TAB_FOCUSED_TOOLBAR_ALPHA_DELAY);
            addAnimation(set, tab.getLayoutTab(), SIDE_BORDER_SCALE, 1.f, 0.f,
                    TAB_FOCUSED_TOOLBAR_ALPHA_DURATION, TAB_FOCUSED_TOOLBAR_ALPHA_DELAY);
        }
    }

    return set;
}
 
Example 18
Source File: Stack.java    From delion with Apache License 2.0 3 votes vote down vote up
/**
 * Computes the alpha value of the tab based on its discard status.
 *
 * @param amount The discard amount.
 * @param range  The range of the absolute value of discard amount.
 * @return       The alpha value that need to be applied on the tab.
 */
public static float computeDiscardAlpha(float amount, float range) {
    if (Math.abs(amount) < 1.0f) return 1.0f;
    float t = amount / range;
    t = MathUtils.clamp(t, -1.0f, 1.0f);
    return 1.f - Math.abs(t);
}
 
Example 19
Source File: Stack.java    From AndroidChromium with Apache License 2.0 3 votes vote down vote up
/**
 * Computes the alpha value of the tab based on its discard status.
 *
 * @param amount The discard amount.
 * @param range  The range of the absolute value of discard amount.
 * @return       The alpha value that need to be applied on the tab.
 */
public static float computeDiscardAlpha(float amount, float range) {
    if (Math.abs(amount) < 1.0f) return 1.0f;
    float t = amount / range;
    t = MathUtils.clamp(t, -1.0f, 1.0f);
    return 1.f - Math.abs(t);
}
 
Example 20
Source File: ToolbarSwipeLayout.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 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);
}