From abd002e7ba0ab6cc0efb5cd6d7e3cc61f32de580 Mon Sep 17 00:00:00 2001 From: Yein Jo Date: Thu, 26 Jan 2023 18:57:06 +0000 Subject: [PATCH] Split progress into raw and curved in RippleShader. Note that the easing curve has updated to Standard easing. onDraw is also simplified by using the current size of the ripple. Please find recordings in the bug. Bug: 265326983 Test: Manual, adb commands Change-Id: I0ef357465d931e2f5cf46db0517879a05e3faf81 --- .../surfaceeffects/ripple/RippleAnimation.kt | 2 +- .../surfaceeffects/ripple/RippleShader.kt | 38 +++++++++++-------- .../surfaceeffects/ripple/RippleView.kt | 24 +++--------- .../systemui/biometrics/AuthRippleView.kt | 10 ++--- .../receiver/ReceiverChipRippleView.kt | 6 +-- 5 files changed, 37 insertions(+), 43 deletions(-) diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt index 0e3d41c40c972..7897934fa2645 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt @@ -48,7 +48,7 @@ class RippleAnimation(private val config: RippleAnimationConfig) { animator.addUpdateListener { updateListener -> val now = updateListener.currentPlayTime val progress = updateListener.animatedValue as Float - rippleShader.progress = progress + rippleShader.rawProgress = progress rippleShader.distortionStrength = if (config.shouldDistort) 1 - progress else 0f rippleShader.time = now.toFloat() } diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt index 90585109643a5..4322d53bcab93 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt @@ -18,6 +18,7 @@ package com.android.systemui.surfaceeffects.ripple import android.graphics.PointF import android.graphics.RuntimeShader import android.util.MathUtils +import com.android.systemui.animation.Interpolators import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary @@ -47,7 +48,6 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) : """ uniform vec2 in_center; uniform vec2 in_size; - uniform float in_progress; uniform float in_cornerRadius; uniform float in_thickness; uniform float in_time; @@ -162,21 +162,15 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) : maxSize.y = height } - /** Progress of the ripple. Float value between [0, 1]. */ - var progress: Float = 0.0f + /** + * Linear progress of the ripple. Float value between [0, 1]. + * + *

Note that the progress here is expected to be linear without any curve applied. + */ + var rawProgress: Float = 0.0f set(value) { field = value - setFloatUniform("in_progress", value) - val curvedProg = 1 - (1 - value) * (1 - value) * (1 - value) - - currentWidth = maxSize.x * curvedProg - currentHeight = maxSize.y * curvedProg - setFloatUniform("in_size", /* width= */ currentWidth, /* height= */ currentHeight) - setFloatUniform("in_thickness", maxSize.y * curvedProg * 0.5f) - // radius should not exceed width and height values. - setFloatUniform("in_cornerRadius", Math.min(maxSize.x, maxSize.y) * curvedProg) - - setFloatUniform("in_blur", MathUtils.lerp(1.25f, 0.5f, value)) + progress = Interpolators.STANDARD.getInterpolation(value) val fadeIn = subProgress(0f, 0.1f, value) val fadeOutNoise = subProgress(0.4f, 1f, value) @@ -191,6 +185,20 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) : setFloatUniform("in_fadeRing", Math.min(fadeIn, 1 - fadeOutRipple)) } + /** Progress with Standard easing curve applied. */ + private var progress: Float = 0.0f + set(value) { + currentWidth = maxSize.x * value + currentHeight = maxSize.y * value + setFloatUniform("in_size", currentWidth, currentHeight) + + setFloatUniform("in_thickness", maxSize.y * value * 0.5f) + // radius should not exceed width and height values. + setFloatUniform("in_cornerRadius", Math.min(maxSize.x, maxSize.y) * value) + + setFloatUniform("in_blur", MathUtils.lerp(1.25f, 0.5f, value)) + } + /** Play time since the start of the effect. */ var time: Float = 0.0f set(value) { @@ -220,7 +228,7 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) : var distortionStrength: Float = 0.0f set(value) { field = value - setFloatUniform("in_distort_radial", 75 * progress * value) + setFloatUniform("in_distort_radial", 75 * rawProgress * value) setFloatUniform("in_distort_xy", 75 * value) } diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt index b37c734171198..bc4796aff042b 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt @@ -77,7 +77,7 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a rippleShader = RippleShader(rippleShape) rippleShader.color = RippleAnimationConfig.RIPPLE_DEFAULT_COLOR - rippleShader.progress = 0f + rippleShader.rawProgress = 0f rippleShader.sparkleStrength = RippleAnimationConfig.RIPPLE_SPARKLE_STRENGTH rippleShader.pixelDensity = resources.displayMetrics.density @@ -93,7 +93,7 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a animator.addUpdateListener { updateListener -> val now = updateListener.currentPlayTime val progress = updateListener.animatedValue as Float - rippleShader.progress = progress + rippleShader.rawProgress = progress rippleShader.distortionStrength = 1 - progress rippleShader.time = now.toFloat() invalidate() @@ -142,25 +142,13 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a } // To reduce overdraw, we mask the effect to a circle or a rectangle that's bigger than the // active effect area. Values here should be kept in sync with the animation implementation - // in the ripple shader. + // in the ripple shader. (Twice bigger) if (rippleShape == RippleShape.CIRCLE) { - val maskRadius = - (1 - - (1 - rippleShader.progress) * - (1 - rippleShader.progress) * - (1 - rippleShader.progress)) * maxWidth + val maskRadius = rippleShader.currentWidth canvas.drawCircle(centerX, centerY, maskRadius, ripplePaint) } else { - val maskWidth = - (1 - - (1 - rippleShader.progress) * - (1 - rippleShader.progress) * - (1 - rippleShader.progress)) * maxWidth * 2 - val maskHeight = - (1 - - (1 - rippleShader.progress) * - (1 - rippleShader.progress) * - (1 - rippleShader.progress)) * maxHeight * 2 + val maskWidth = rippleShader.currentWidth * 2 + val maskHeight = rippleShader.currentHeight * 2 canvas.drawRect( /* left= */ centerX - maskWidth, /* top= */ centerY - maskHeight, diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt index 4b57d455a1375..ff612af15760d 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt @@ -86,7 +86,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at init { rippleShader.color = 0xffffffff.toInt() // default color - rippleShader.progress = 0f + rippleShader.rawProgress = 0f rippleShader.sparkleStrength = RIPPLE_SPARKLE_STRENGTH ripplePaint.shader = rippleShader @@ -271,7 +271,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at duration = AuthRippleController.RIPPLE_ANIMATION_DURATION addUpdateListener { animator -> val now = animator.currentPlayTime - rippleShader.progress = animator.animatedValue as Float + rippleShader.rawProgress = animator.animatedValue as Float rippleShader.time = now.toFloat() invalidate() @@ -345,7 +345,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at override fun onDraw(canvas: Canvas?) { // To reduce overdraw, we mask the effect to a circle whose radius is big enough to cover // the active effect area. Values here should be kept in sync with the - // animation implementation in the ripple shader. + // animation implementation in the ripple shader. (Twice bigger) if (drawDwell) { val maskRadius = (1 - (1 - dwellShader.progress) * (1 - dwellShader.progress) * (1 - dwellShader.progress)) * dwellRadius * 2f @@ -354,10 +354,8 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at } if (drawRipple) { - val mask = (1 - (1 - rippleShader.progress) * (1 - rippleShader.progress) * - (1 - rippleShader.progress)) * radius * 2f canvas?.drawCircle(origin.x.toFloat(), origin.y.toFloat(), - mask, ripplePaint) + rippleShader.currentWidth, ripplePaint) } } } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt index f8785fcf5de0a..f1acae8e26854 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt @@ -79,9 +79,9 @@ class ReceiverChipRippleView(context: Context?, attrs: AttributeSet?) : RippleVi animator.addUpdateListener { updateListener -> val now = updateListener.currentPlayTime val progress = updateListener.animatedValue as Float - rippleShader.progress = startingPercentage + (progress * (1 - startingPercentage)) - rippleShader.distortionStrength = 1 - rippleShader.progress - rippleShader.pixelDensity = 1 - rippleShader.progress + rippleShader.rawProgress = startingPercentage + (progress * (1 - startingPercentage)) + rippleShader.distortionStrength = 1 - rippleShader.rawProgress + rippleShader.pixelDensity = 1 - rippleShader.rawProgress rippleShader.time = now.toFloat() invalidate() }