summaryrefslogtreecommitdiff
path: root/packages/SystemUI/src
diff options
context:
space:
mode:
author Yein Jo <yeinj@google.com> 2022-12-03 02:01:52 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2022-12-03 02:01:52 +0000
commitdf36fccf2c4f7a308477fd6950d515cf7d02c228 (patch)
tree3b2fcc4d073a6cd31d9a9b824f1b03e03805b74c /packages/SystemUI/src
parente4a1f6ce34a4278fc36076b1667355b48f34e6d8 (diff)
parentf3cb22c0cb64fda17b3037698b9e39acce4ca16b (diff)
Merge "Move surface effects package to AnimationLib." into tm-qpr-dev am: 31c7f600e1 am: f3cb22c0cb
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20587929 Change-Id: I48ee3d81934b4031e378fe79042748c8eebb276b Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'packages/SystemUI/src')
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt47
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt81
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt74
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt240
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt173
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt116
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt148
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt67
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt30
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt121
-rw-r--r--packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt123
12 files changed, 0 insertions, 1252 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt
deleted file mode 100644
index 93e78acc63fd..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.surfaceeffects.ripple
-
-import androidx.annotation.VisibleForTesting
-
-/** Controller that handles playing [RippleAnimation]. */
-class MultiRippleController(private val multipleRippleView: MultiRippleView) {
-
- companion object {
- /** Max number of ripple animations at a time. */
- @VisibleForTesting const val MAX_RIPPLE_NUMBER = 10
- }
-
- /** Updates all the ripple colors during the animation. */
- fun updateColor(color: Int) {
- multipleRippleView.ripples.forEach { anim -> anim.updateColor(color) }
- }
-
- fun play(rippleAnimation: RippleAnimation) {
- if (multipleRippleView.ripples.size >= MAX_RIPPLE_NUMBER) {
- return
- }
-
- multipleRippleView.ripples.add(rippleAnimation)
-
- // Remove ripple once the animation is done
- rippleAnimation.play { multipleRippleView.ripples.remove(rippleAnimation) }
-
- // Trigger drawing
- multipleRippleView.invalidate()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
deleted file mode 100644
index f558fee776e6..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.surfaceeffects.ripple
-
-import android.content.Context
-import android.graphics.Canvas
-import android.graphics.Paint
-import android.util.AttributeSet
-import android.util.Log
-import android.view.View
-
-/**
- * A view that allows multiple ripples to play.
- *
- * Use [MultiRippleController] to play ripple animations.
- */
-class MultiRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
-
- internal val ripples = ArrayList<RippleAnimation>()
- private val listeners = ArrayList<RipplesFinishedListener>()
- private val ripplePaint = Paint()
- private var isWarningLogged = false
-
- companion object {
- private const val TAG = "MultiRippleView"
-
- interface RipplesFinishedListener {
- /** Triggered when all the ripples finish running. */
- fun onRipplesFinish()
- }
- }
-
- fun addRipplesFinishedListener(listener: RipplesFinishedListener) {
- listeners.add(listener)
- }
-
- override fun onDraw(canvas: Canvas?) {
- if (canvas == null || !canvas.isHardwareAccelerated) {
- // Drawing with the ripple shader requires hardware acceleration, so skip
- // if it's unsupported.
- if (!isWarningLogged) {
- // Only log once to not spam.
- Log.w(
- TAG,
- "Can't draw ripple shader. $canvas does not support hardware acceleration."
- )
- isWarningLogged = true
- }
- return
- }
-
- var shouldInvalidate = false
-
- ripples.forEach { anim ->
- ripplePaint.shader = anim.rippleShader
- canvas.drawPaint(ripplePaint)
-
- shouldInvalidate = shouldInvalidate || anim.isPlaying()
- }
-
- if (shouldInvalidate) {
- invalidate()
- } else { // Nothing is playing.
- listeners.forEach { listener -> listener.onRipplesFinish() }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
deleted file mode 100644
index b2f8994ebf51..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.surfaceeffects.ripple
-
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.ValueAnimator
-import androidx.core.graphics.ColorUtils
-
-/** A single ripple animation. */
-class RippleAnimation(private val config: RippleAnimationConfig) {
- internal val rippleShader: RippleShader = RippleShader(config.rippleShape)
- private val animator: ValueAnimator = ValueAnimator.ofFloat(0f, 1f)
-
- init {
- applyConfigToShader()
- }
-
- /** Updates the ripple color during the animation. */
- fun updateColor(color: Int) {
- config.apply { config.color = color }
- applyConfigToShader()
- }
-
- @JvmOverloads
- fun play(onAnimationEnd: Runnable? = null) {
- if (isPlaying()) {
- return // Ignore if ripple effect is already playing
- }
-
- animator.duration = config.duration
- animator.addUpdateListener { updateListener ->
- val now = updateListener.currentPlayTime
- val progress = updateListener.animatedValue as Float
- rippleShader.progress = progress
- rippleShader.distortionStrength = if (config.shouldDistort) 1 - progress else 0f
- rippleShader.time = now.toFloat()
- }
- animator.addListener(
- object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- onAnimationEnd?.run()
- }
- }
- )
- animator.start()
- }
-
- /** Indicates whether the animation is playing. */
- fun isPlaying(): Boolean = animator.isRunning
-
- private fun applyConfigToShader() {
- rippleShader.setCenter(config.centerX, config.centerY)
- rippleShader.setMaxSize(config.maxWidth, config.maxHeight)
- rippleShader.rippleFill = config.shouldFillRipple
- rippleShader.pixelDensity = config.pixelDensity
- rippleShader.color = ColorUtils.setAlphaComponent(config.color, config.opacity)
- rippleShader.sparkleStrength = config.sparkleStrength
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
deleted file mode 100644
index 773ac55130d4..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.android.systemui.surfaceeffects.ripple
-
-import android.graphics.Color
-
-/**
- * A struct that holds the ripple animation configurations.
- *
- * <p>This configuration is designed to play a SINGLE animation. Do not reuse or modify the
- * configuration parameters to play different animations, unless the value has to change within the
- * single animation (e.g. Change color or opacity during the animation). Note that this data class
- * is pulled out to make the [RippleAnimation] constructor succinct.
- */
-data class RippleAnimationConfig(
- val rippleShape: RippleShader.RippleShape = RippleShader.RippleShape.CIRCLE,
- val duration: Long = 0L,
- val centerX: Float = 0f,
- val centerY: Float = 0f,
- val maxWidth: Float = 0f,
- val maxHeight: Float = 0f,
- val pixelDensity: Float = 1f,
- var color: Int = Color.WHITE,
- val opacity: Int = RIPPLE_DEFAULT_ALPHA,
- val shouldFillRipple: Boolean = false,
- val sparkleStrength: Float = RIPPLE_SPARKLE_STRENGTH,
- val shouldDistort: Boolean = true
-) {
- companion object {
- const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
- const val RIPPLE_DEFAULT_COLOR: Int = 0xffffffff.toInt()
- const val RIPPLE_DEFAULT_ALPHA: Int = 115 // full opacity is 255.
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
deleted file mode 100644
index a950d34513ee..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.surfaceeffects.ripple
-
-import android.graphics.PointF
-import android.graphics.RuntimeShader
-import android.util.MathUtils
-import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary
-import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
-
-/**
- * Shader class that renders an expanding ripple effect. The ripple contains three elements:
- *
- * 1. an expanding filled [RippleShape] that appears in the beginning and quickly fades away
- * 2. an expanding ring that appears throughout the effect
- * 3. an expanding ring-shaped area that reveals noise over #2.
- *
- * The ripple shader will be default to the circle shape if not specified.
- *
- * Modeled after frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java.
- */
-class RippleShader internal constructor(rippleShape: RippleShape = RippleShape.CIRCLE) :
- RuntimeShader(buildShader(rippleShape)) {
-
- /** Shapes that the [RippleShader] supports. */
- enum class RippleShape {
- CIRCLE,
- ROUNDED_BOX,
- ELLIPSE
- }
- // language=AGSL
- companion object {
- private const val SHADER_UNIFORMS =
- """
- uniform vec2 in_center;
- uniform vec2 in_size;
- uniform float in_progress;
- uniform float in_cornerRadius;
- uniform float in_thickness;
- uniform float in_time;
- uniform float in_distort_radial;
- uniform float in_distort_xy;
- uniform float in_fadeSparkle;
- uniform float in_fadeFill;
- uniform float in_fadeRing;
- uniform float in_blur;
- uniform float in_pixelDensity;
- layout(color) uniform vec4 in_color;
- uniform float in_sparkle_strength;
- """
-
- private const val SHADER_CIRCLE_MAIN =
- """
- vec4 main(vec2 p) {
- vec2 p_distorted = distort(p, in_time, in_distort_radial, in_distort_xy);
- float radius = in_size.x * 0.5;
- float sparkleRing = soften(circleRing(p_distorted-in_center, radius), in_blur);
- float inside = soften(sdCircle(p_distorted-in_center, radius * 1.2), in_blur);
- float sparkle = sparkles(p - mod(p, in_pixelDensity * 0.8), in_time * 0.00175)
- * (1.-sparkleRing) * in_fadeSparkle;
-
- float rippleInsideAlpha = (1.-inside) * in_fadeFill;
- float rippleRingAlpha = (1.-sparkleRing) * in_fadeRing;
- float rippleAlpha = max(rippleInsideAlpha, rippleRingAlpha) * in_color.a;
- vec4 ripple = vec4(in_color.rgb, 1.0) * rippleAlpha;
- return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength);
- }
- """
-
- private const val SHADER_ROUNDED_BOX_MAIN =
- """
- vec4 main(vec2 p) {
- float sparkleRing = soften(roundedBoxRing(p-in_center, in_size, in_cornerRadius,
- in_thickness), in_blur);
- float inside = soften(sdRoundedBox(p-in_center, in_size * 1.2, in_cornerRadius),
- in_blur);
- float sparkle = sparkles(p - mod(p, in_pixelDensity * 0.8), in_time * 0.00175)
- * (1.-sparkleRing) * in_fadeSparkle;
-
- float rippleInsideAlpha = (1.-inside) * in_fadeFill;
- float rippleRingAlpha = (1.-sparkleRing) * in_fadeRing;
- float rippleAlpha = max(rippleInsideAlpha, rippleRingAlpha) * in_color.a;
- vec4 ripple = vec4(in_color.rgb, 1.0) * rippleAlpha;
- return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength);
- }
- """
-
- private const val SHADER_ELLIPSE_MAIN =
- """
- vec4 main(vec2 p) {
- vec2 p_distorted = distort(p, in_time, in_distort_radial, in_distort_xy);
-
- float sparkleRing = soften(ellipseRing(p_distorted-in_center, in_size), in_blur);
- float inside = soften(sdEllipse(p_distorted-in_center, in_size * 1.2), in_blur);
- float sparkle = sparkles(p - mod(p, in_pixelDensity * 0.8), in_time * 0.00175)
- * (1.-sparkleRing) * in_fadeSparkle;
-
- float rippleInsideAlpha = (1.-inside) * in_fadeFill;
- float rippleRingAlpha = (1.-sparkleRing) * in_fadeRing;
- float rippleAlpha = max(rippleInsideAlpha, rippleRingAlpha) * in_color.a;
- vec4 ripple = vec4(in_color.rgb, 1.0) * rippleAlpha;
- return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength);
- }
- """
-
- private const val CIRCLE_SHADER =
- SHADER_UNIFORMS +
- ShaderUtilLibrary.SHADER_LIB +
- SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
- SdfShaderLibrary.CIRCLE_SDF +
- SHADER_CIRCLE_MAIN
- private const val ROUNDED_BOX_SHADER =
- SHADER_UNIFORMS +
- ShaderUtilLibrary.SHADER_LIB +
- SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
- SdfShaderLibrary.ROUNDED_BOX_SDF +
- SHADER_ROUNDED_BOX_MAIN
- private const val ELLIPSE_SHADER =
- SHADER_UNIFORMS +
- ShaderUtilLibrary.SHADER_LIB +
- SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
- SdfShaderLibrary.ELLIPSE_SDF +
- SHADER_ELLIPSE_MAIN
-
- private fun buildShader(rippleShape: RippleShape): String =
- when (rippleShape) {
- RippleShape.CIRCLE -> CIRCLE_SHADER
- RippleShape.ROUNDED_BOX -> ROUNDED_BOX_SHADER
- RippleShape.ELLIPSE -> ELLIPSE_SHADER
- }
-
- private fun subProgress(start: Float, end: Float, progress: Float): Float {
- val min = Math.min(start, end)
- val max = Math.max(start, end)
- val sub = Math.min(Math.max(progress, min), max)
- return (sub - start) / (end - start)
- }
- }
-
- /** Sets the center position of the ripple. */
- fun setCenter(x: Float, y: Float) {
- setFloatUniform("in_center", x, y)
- }
-
- /** Max width of the ripple. */
- private var maxSize: PointF = PointF()
- fun setMaxSize(width: Float, height: Float) {
- maxSize.x = width
- maxSize.y = height
- }
-
- /** Progress of the ripple. Float value between [0, 1]. */
- var progress: Float = 0.0f
- set(value) {
- field = value
- setFloatUniform("in_progress", value)
- val curvedProg = 1 - (1 - value) * (1 - value) * (1 - value)
-
- setFloatUniform(
- "in_size",
- /* width= */ maxSize.x * curvedProg,
- /* height= */ maxSize.y * curvedProg
- )
- 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))
-
- val fadeIn = subProgress(0f, 0.1f, value)
- val fadeOutNoise = subProgress(0.4f, 1f, value)
- var fadeOutRipple = 0f
- var fadeFill = 0f
- if (!rippleFill) {
- fadeFill = subProgress(0f, 0.6f, value)
- fadeOutRipple = subProgress(0.3f, 1f, value)
- }
- setFloatUniform("in_fadeSparkle", Math.min(fadeIn, 1 - fadeOutNoise))
- setFloatUniform("in_fadeFill", 1 - fadeFill)
- setFloatUniform("in_fadeRing", Math.min(fadeIn, 1 - fadeOutRipple))
- }
-
- /** Play time since the start of the effect. */
- var time: Float = 0.0f
- set(value) {
- field = value
- setFloatUniform("in_time", value)
- }
-
- /** A hex value representing the ripple color, in the format of ARGB */
- var color: Int = 0xffffff
- set(value) {
- field = value
- setColorUniform("in_color", value)
- }
-
- /**
- * Noise sparkle intensity. Expected value between [0, 1]. The sparkle is white, and thus with
- * strength 0 it's transparent, leaving the ripple fully smooth, while with strength 1 it's
- * opaque white and looks the most grainy.
- */
- var sparkleStrength: Float = 0.0f
- set(value) {
- field = value
- setFloatUniform("in_sparkle_strength", value)
- }
-
- /** Distortion strength of the ripple. Expected value between[0, 1]. */
- var distortionStrength: Float = 0.0f
- set(value) {
- field = value
- setFloatUniform("in_distort_radial", 75 * progress * value)
- setFloatUniform("in_distort_xy", 75 * value)
- }
-
- var pixelDensity: Float = 1.0f
- set(value) {
- field = value
- setFloatUniform("in_pixelDensity", value)
- }
-
- /**
- * True if the ripple should stayed filled in as it expands to give a filled-in circle effect.
- * False for a ring effect.
- */
- var rippleFill: Boolean = false
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
deleted file mode 100644
index ae28a8b6dc2e..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.surfaceeffects.ripple
-
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.ValueAnimator
-import android.content.Context
-import android.content.res.Configuration
-import android.graphics.Canvas
-import android.graphics.Paint
-import android.util.AttributeSet
-import android.view.View
-import androidx.core.graphics.ColorUtils
-import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape
-
-/**
- * A generic expanding ripple effect.
- *
- * Set up the shader with a desired [RippleShape] using [setupShader], [setMaxSize] and [setCenter],
- * then call [startRipple] to trigger the ripple expansion.
- */
-open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
-
- private lateinit var rippleShader: RippleShader
- lateinit var rippleShape: RippleShape
- private set
-
- private val ripplePaint = Paint()
- protected val animator: ValueAnimator = ValueAnimator.ofFloat(0f, 1f)
-
- var duration: Long = 1750
-
- private var maxWidth: Float = 0.0f
- private var maxHeight: Float = 0.0f
- fun setMaxSize(maxWidth: Float, maxHeight: Float) {
- this.maxWidth = maxWidth
- this.maxHeight = maxHeight
- rippleShader.setMaxSize(maxWidth, maxHeight)
- }
-
- private var centerX: Float = 0.0f
- private var centerY: Float = 0.0f
- fun setCenter(x: Float, y: Float) {
- this.centerX = x
- this.centerY = y
- rippleShader.setCenter(x, y)
- }
-
- override fun onConfigurationChanged(newConfig: Configuration?) {
- rippleShader.pixelDensity = resources.displayMetrics.density
- super.onConfigurationChanged(newConfig)
- }
-
- override fun onAttachedToWindow() {
- rippleShader.pixelDensity = resources.displayMetrics.density
- super.onAttachedToWindow()
- }
-
- /** Initializes the shader. Must be called before [startRipple]. */
- fun setupShader(rippleShape: RippleShape = RippleShape.CIRCLE) {
- this.rippleShape = rippleShape
- rippleShader = RippleShader(rippleShape)
-
- rippleShader.color = RippleAnimationConfig.RIPPLE_DEFAULT_COLOR
- rippleShader.progress = 0f
- rippleShader.sparkleStrength = RippleAnimationConfig.RIPPLE_SPARKLE_STRENGTH
- rippleShader.pixelDensity = resources.displayMetrics.density
-
- ripplePaint.shader = rippleShader
- }
-
- @JvmOverloads
- fun startRipple(onAnimationEnd: Runnable? = null) {
- if (animator.isRunning) {
- return // Ignore if ripple effect is already playing
- }
- animator.duration = duration
- animator.addUpdateListener { updateListener ->
- val now = updateListener.currentPlayTime
- val progress = updateListener.animatedValue as Float
- rippleShader.progress = progress
- rippleShader.distortionStrength = 1 - progress
- rippleShader.time = now.toFloat()
- invalidate()
- }
- animator.addListener(
- object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- onAnimationEnd?.run()
- }
- }
- )
- animator.start()
- }
-
- /**
- * Set the color to be used for the ripple.
- *
- * The alpha value of the color will be applied to the ripple. The alpha range is [0-255].
- */
- fun setColor(color: Int, alpha: Int = RippleAnimationConfig.RIPPLE_DEFAULT_ALPHA) {
- rippleShader.color = ColorUtils.setAlphaComponent(color, alpha)
- }
-
- /**
- * Set whether the ripple should remain filled as the ripple expands.
- *
- * See [RippleShader.rippleFill].
- */
- fun setRippleFill(rippleFill: Boolean) {
- rippleShader.rippleFill = rippleFill
- }
-
- /** Set the intensity of the sparkles. */
- fun setSparkleStrength(strength: Float) {
- rippleShader.sparkleStrength = strength
- }
-
- /** Indicates whether the ripple animation is playing. */
- fun rippleInProgress(): Boolean = animator.isRunning
-
- override fun onDraw(canvas: Canvas?) {
- if (canvas == null || !canvas.isHardwareAccelerated) {
- // Drawing with the ripple shader requires hardware acceleration, so skip
- // if it's unsupported.
- return
- }
- // 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.
- if (rippleShape == RippleShape.CIRCLE) {
- val maskRadius =
- (1 -
- (1 - rippleShader.progress) *
- (1 - rippleShader.progress) *
- (1 - rippleShader.progress)) * maxWidth
- 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
- canvas.drawRect(
- /* left= */ centerX - maskWidth,
- /* top= */ centerY - maskHeight,
- /* right= */ centerX + maskWidth,
- /* bottom= */ centerY + maskHeight,
- ripplePaint
- )
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
deleted file mode 100644
index 8b2f46648fef..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.surfaceeffects.shaderutil
-
-/** Library class that contains 2D signed distance functions. */
-class SdfShaderLibrary {
- // language=AGSL
- companion object {
- const val CIRCLE_SDF =
- """
- float sdCircle(vec2 p, float r) {
- return (length(p)-r) / r;
- }
-
- float circleRing(vec2 p, float radius) {
- float thicknessHalf = radius * 0.25;
-
- float outerCircle = sdCircle(p, radius + thicknessHalf);
- float innerCircle = sdCircle(p, radius);
-
- return subtract(outerCircle, innerCircle);
- }
- """
-
- const val ROUNDED_BOX_SDF =
- """
- float sdRoundedBox(vec2 p, vec2 size, float cornerRadius) {
- size *= 0.5;
- cornerRadius *= 0.5;
- vec2 d = abs(p)-size+cornerRadius;
-
- float outside = length(max(d, 0.0));
- float inside = min(max(d.x, d.y), 0.0);
-
- return (outside+inside-cornerRadius)/size.y;
- }
-
- float roundedBoxRing(vec2 p, vec2 size, float cornerRadius,
- float borderThickness) {
- float outerRoundBox = sdRoundedBox(p, size, cornerRadius);
- float innerRoundBox = sdRoundedBox(p, size - vec2(borderThickness),
- cornerRadius - borderThickness);
- return subtract(outerRoundBox, innerRoundBox);
- }
- """
-
- // Used non-trigonometry parametrization and Halley's method (iterative) for root finding.
- // This is more expensive than the regular circle SDF, recommend to use the circle SDF if
- // possible.
- const val ELLIPSE_SDF =
- """float sdEllipse(vec2 p, vec2 wh) {
- wh *= 0.5;
-
- // symmetry
- (wh.x > wh.y) ? wh = wh.yx, p = abs(p.yx) : p = abs(p);
-
- vec2 u = wh*p, v = wh*wh;
-
- float U1 = u.y/2.0; float U5 = 4.0*U1;
- float U2 = v.y-v.x; float U6 = 6.0*U1;
- float U3 = u.x-U2; float U7 = 3.0*U3;
- float U4 = u.x+U2;
-
- float t = 0.5;
- for (int i = 0; i < 3; i ++) {
- float F1 = t*(t*t*(U1*t+U3)+U4)-U1;
- float F2 = t*t*(U5*t+U7)+U4;
- float F3 = t*(U6*t+U7);
-
- t += (F1*F2)/(F1*F3-F2*F2);
- }
-
- t = clamp(t, 0.0, 1.0);
-
- float d = distance(p, wh*vec2(1.0-t*t,2.0*t)/(t*t+1.0));
- d /= wh.y;
-
- return (dot(p/wh,p/wh)>1.0) ? d : -d;
- }
-
- float ellipseRing(vec2 p, vec2 wh) {
- vec2 thicknessHalf = wh * 0.25;
-
- float outerEllipse = sdEllipse(p, wh + thicknessHalf);
- float innerEllipse = sdEllipse(p, wh);
-
- return subtract(outerEllipse, innerEllipse);
- }
- """
-
- const val SHADER_SDF_OPERATION_LIB =
- """
- float soften(float d, float blur) {
- float blurHalf = blur * 0.5;
- return smoothstep(-blurHalf, blurHalf, d);
- }
-
- float subtract(float outer, float inner) {
- return max(outer, -inner);
- }
- """
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
deleted file mode 100644
index d78e0c153db8..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.surfaceeffects.shaderutil
-
-/** A common utility functions that are used for computing shaders. */
-class ShaderUtilLibrary {
- // language=AGSL
- companion object {
- const val SHADER_LIB =
- """
- float triangleNoise(vec2 n) {
- n = fract(n * vec2(5.3987, 5.4421));
- n += dot(n.yx, n.xy + vec2(21.5351, 14.3137));
- float xy = n.x * n.y;
- // compute in [0..2[ and remap to [-1.0..1.0[
- return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
- }
-
- const float PI = 3.1415926535897932384626;
-
- float sparkles(vec2 uv, float t) {
- float n = triangleNoise(uv);
- float s = 0.0;
- for (float i = 0; i < 4; i += 1) {
- float l = i * 0.01;
- float h = l + 0.1;
- float o = smoothstep(n - l, h, n);
- o *= abs(sin(PI * o * (t + 0.55 * i)));
- s += o;
- }
- return s;
- }
-
- vec2 distort(vec2 p, float time, float distort_amount_radial,
- float distort_amount_xy) {
- float angle = atan(p.y, p.x);
- return p + vec2(sin(angle * 8 + time * 0.003 + 1.641),
- cos(angle * 5 + 2.14 + time * 0.00412)) * distort_amount_radial
- + vec2(sin(p.x * 0.01 + time * 0.00215 + 0.8123),
- cos(p.y * 0.01 + time * 0.005931)) * distort_amount_xy;
- }
-
- // Return range [-1, 1].
- vec3 hash(vec3 p) {
- p = fract(p * vec3(.3456, .1234, .9876));
- p += dot(p, p.yxz + 43.21);
- p = (p.xxy + p.yxx) * p.zyx;
- return (fract(sin(p) * 4567.1234567) - .5) * 2.;
- }
-
- // Skew factors (non-uniform).
- const float SKEW = 0.3333333; // 1/3
- const float UNSKEW = 0.1666667; // 1/6
-
- // Return range roughly [-1,1].
- // It's because the hash function (that returns a random gradient vector) returns
- // different magnitude of vectors. Noise doesn't have to be in the precise range thus
- // skipped normalize.
- float simplex3d(vec3 p) {
- // Skew the input coordinate, so that we get squashed cubical grid
- vec3 s = floor(p + (p.x + p.y + p.z) * SKEW);
-
- // Unskew back
- vec3 u = s - (s.x + s.y + s.z) * UNSKEW;
-
- // Unskewed coordinate that is relative to p, to compute the noise contribution
- // based on the distance.
- vec3 c0 = p - u;
-
- // We have six simplices (in this case tetrahedron, since we are in 3D) that we
- // could possibly in.
- // Here, we are finding the correct tetrahedron (simplex shape), and traverse its
- // four vertices (c0..3) when computing noise contribution.
- // The way we find them is by comparing c0's x,y,z values.
- // For example in 2D, we can find the triangle (simplex shape in 2D) that we are in
- // by comparing x and y values. i.e. x>y lower, x<y, upper triangle.
- // Same applies in 3D.
- //
- // Below indicates the offsets (or offset directions) when c0=(x0,y0,z0)
- // x0>y0>z0: (1,0,0), (1,1,0), (1,1,1)
- // x0>z0>y0: (1,0,0), (1,0,1), (1,1,1)
- // z0>x0>y0: (0,0,1), (1,0,1), (1,1,1)
- // z0>y0>x0: (0,0,1), (0,1,1), (1,1,1)
- // y0>z0>x0: (0,1,0), (0,1,1), (1,1,1)
- // y0>x0>z0: (0,1,0), (1,1,0), (1,1,1)
- //
- // The rule is:
- // * For offset1, set 1 at the max component, otherwise 0.
- // * For offset2, set 0 at the min component, otherwise 1.
- // * For offset3, set 1 for all.
- //
- // Encode x0-y0, y0-z0, z0-x0 in a vec3
- vec3 en = c0 - c0.yzx;
- // Each represents whether x0>y0, y0>z0, z0>x0
- en = step(vec3(0.), en);
- // en.zxy encodes z0>x0, x0>y0, y0>x0
- vec3 offset1 = en * (1. - en.zxy); // find max
- vec3 offset2 = 1. - en.zxy * (1. - en); // 1-(find min)
- vec3 offset3 = vec3(1.);
-
- vec3 c1 = c0 - offset1 + UNSKEW;
- vec3 c2 = c0 - offset2 + UNSKEW * 2.;
- vec3 c3 = c0 - offset3 + UNSKEW * 3.;
-
- // Kernel summation: dot(max(0, r^2-d^2))^4, noise contribution)
- //
- // First compute d^2, squared distance to the point.
- vec4 w; // w = max(0, r^2 - d^2))
- w.x = dot(c0, c0);
- w.y = dot(c1, c1);
- w.z = dot(c2, c2);
- w.w = dot(c3, c3);
-
- // Noise contribution should decay to zero before they cross the simplex boundary.
- // Usually r^2 is 0.5 or 0.6;
- // 0.5 ensures continuity but 0.6 increases the visual quality for the application
- // where discontinuity isn't noticeable.
- w = max(0.6 - w, 0.);
-
- // Noise contribution from each point.
- vec4 nc;
- nc.x = dot(hash(s), c0);
- nc.y = dot(hash(s + offset1), c1);
- nc.z = dot(hash(s + offset2), c2);
- nc.w = dot(hash(s + offset3), c3);
-
- nc *= w*w*w*w;
-
- // Add all the noise contributions.
- // Should multiply by the possible max contribution to adjust the range in [-1,1].
- return dot(vec4(32.), nc);
- }
- """
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
deleted file mode 100644
index 5ac3aad749fc..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.surfaceeffects.turbulencenoise
-
-import android.graphics.BlendMode
-import android.graphics.Color
-
-/** Turbulence noise animation configuration. */
-data class TurbulenceNoiseAnimationConfig(
- /** The number of grids that is used to generate noise. */
- val gridCount: Float = DEFAULT_NOISE_GRID_COUNT,
-
- /** Multiplier for the noise luma matte. Increase this for brighter effects. */
- val luminosityMultiplier: Float = DEFAULT_LUMINOSITY_MULTIPLIER,
-
- /**
- * Noise move speed variables.
- *
- * Its sign determines the direction; magnitude determines the speed. <ul>
- * ```
- * <li> [noiseMoveSpeedX] positive: right to left; negative: left to right.
- * <li> [noiseMoveSpeedY] positive: bottom to top; negative: top to bottom.
- * <li> [noiseMoveSpeedZ] its sign doesn't matter much, as it moves in Z direction. Use it
- * to add turbulence in place.
- * ```
- * </ul>
- */
- val noiseMoveSpeedX: Float = 0f,
- val noiseMoveSpeedY: Float = 0f,
- val noiseMoveSpeedZ: Float = DEFAULT_NOISE_SPEED_Z,
-
- /** Color of the effect. */
- var color: Int = DEFAULT_COLOR,
- /** Background color of the effect. */
- val backgroundColor: Int = DEFAULT_BACKGROUND_COLOR,
- val opacity: Int = DEFAULT_OPACITY,
- val width: Float = 0f,
- val height: Float = 0f,
- val duration: Float = DEFAULT_NOISE_DURATION_IN_MILLIS,
- val pixelDensity: Float = 1f,
- val blendMode: BlendMode = DEFAULT_BLEND_MODE,
- val onAnimationEnd: Runnable? = null
-) {
- companion object {
- const val DEFAULT_NOISE_DURATION_IN_MILLIS = 7500F
- const val DEFAULT_LUMINOSITY_MULTIPLIER = 1f
- const val DEFAULT_NOISE_GRID_COUNT = 1.2f
- const val DEFAULT_NOISE_SPEED_Z = 0.3f
- const val DEFAULT_OPACITY = 150 // full opacity is 255.
- const val DEFAULT_COLOR = Color.WHITE
- const val DEFAULT_BACKGROUND_COLOR = Color.BLACK
- val DEFAULT_BLEND_MODE = BlendMode.SRC_OVER
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
deleted file mode 100644
index 4c7e5f4c7093..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.surfaceeffects.turbulencenoise
-
-/** A controller that plays [TurbulenceNoiseView]. */
-class TurbulenceNoiseController(private val turbulenceNoiseView: TurbulenceNoiseView) {
- /** Updates the color of the noise. */
- fun updateNoiseColor(color: Int) {
- turbulenceNoiseView.updateColor(color)
- }
-
- // TODO: add cancel and/ or pause once design requirements become clear.
- /** Plays [TurbulenceNoiseView] with the given config. */
- fun play(turbulenceNoiseAnimationConfig: TurbulenceNoiseAnimationConfig) {
- turbulenceNoiseView.play(turbulenceNoiseAnimationConfig)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
deleted file mode 100644
index 19c114d2693c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.surfaceeffects.turbulencenoise
-
-import android.graphics.RuntimeShader
-import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
-import java.lang.Float.max
-
-/** Shader that renders turbulence simplex noise, with no octave. */
-class TurbulenceNoiseShader : RuntimeShader(TURBULENCE_NOISE_SHADER) {
- // language=AGSL
- companion object {
- private const val UNIFORMS =
- """
- uniform float in_gridNum;
- uniform vec3 in_noiseMove;
- uniform vec2 in_size;
- uniform float in_aspectRatio;
- uniform float in_opacity;
- uniform float in_pixelDensity;
- layout(color) uniform vec4 in_color;
- layout(color) uniform vec4 in_backgroundColor;
- """
-
- private const val SHADER_LIB =
- """
- float getLuminosity(vec3 c) {
- return 0.3*c.r + 0.59*c.g + 0.11*c.b;
- }
-
- vec3 maskLuminosity(vec3 dest, float lum) {
- dest.rgb *= vec3(lum);
- // Clip back into the legal range
- dest = clamp(dest, vec3(0.), vec3(1.0));
- return dest;
- }
- """
-
- private const val MAIN_SHADER =
- """
- vec4 main(vec2 p) {
- vec2 uv = p / in_size.xy;
- uv.x *= in_aspectRatio;
-
- vec3 noiseP = vec3(uv + in_noiseMove.xy, in_noiseMove.z) * in_gridNum;
- float luma = simplex3d(noiseP) * in_opacity;
- vec3 mask = maskLuminosity(in_color.rgb, luma);
- vec3 color = in_backgroundColor.rgb + mask * 0.6;
-
- // Add dither with triangle distribution to avoid color banding. Ok to dither in the
- // shader here as we are in gamma space.
- float dither = triangleNoise(p * in_pixelDensity) / 255.;
-
- // The result color should be pre-multiplied, i.e. [R*A, G*A, B*A, A], thus need to
- // multiply rgb with a to get the correct result.
- color = (color + dither.rrr) * in_color.a;
- return vec4(color, in_color.a);
- }
- """
-
- private const val TURBULENCE_NOISE_SHADER =
- ShaderUtilLibrary.SHADER_LIB + UNIFORMS + SHADER_LIB + MAIN_SHADER
- }
-
- /** Sets the number of grid for generating noise. */
- fun setGridCount(gridNumber: Float = 1.0f) {
- setFloatUniform("in_gridNum", gridNumber)
- }
-
- /**
- * Sets the pixel density of the screen.
- *
- * Used it for noise dithering.
- */
- fun setPixelDensity(pixelDensity: Float) {
- setFloatUniform("in_pixelDensity", pixelDensity)
- }
-
- /** Sets the noise color of the effect. */
- fun setColor(color: Int) {
- setColorUniform("in_color", color)
- }
-
- /** Sets the background color of the effect. */
- fun setBackgroundColor(color: Int) {
- setColorUniform("in_backgroundColor", color)
- }
-
- /**
- * Sets the opacity to achieve fade in/ out of the animation.
- *
- * Expected value range is [1, 0].
- */
- fun setOpacity(opacity: Float) {
- setFloatUniform("in_opacity", opacity)
- }
-
- /** Sets the size of the shader. */
- fun setSize(width: Float, height: Float) {
- setFloatUniform("in_size", width, height)
- setFloatUniform("in_aspectRatio", width / max(height, 0.001f))
- }
-
- /** Sets noise move speed in x, y, and z direction. */
- fun setNoiseMove(x: Float, y: Float, z: Float) {
- setFloatUniform("in_noiseMove", x, y, z)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt b/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
deleted file mode 100644
index 8649d5924587..000000000000
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.surfaceeffects.turbulencenoise
-
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.ValueAnimator
-import android.content.Context
-import android.graphics.Canvas
-import android.graphics.Paint
-import android.util.AttributeSet
-import android.view.View
-import androidx.annotation.VisibleForTesting
-import androidx.core.graphics.ColorUtils
-import java.util.Random
-import kotlin.math.sin
-
-/** View that renders turbulence noise effect. */
-class TurbulenceNoiseView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
-
- companion object {
- private const val MS_TO_SEC = 0.001f
- private const val TWO_PI = Math.PI.toFloat() * 2f
- }
-
- @VisibleForTesting val turbulenceNoiseShader = TurbulenceNoiseShader()
- private val paint = Paint().apply { this.shader = turbulenceNoiseShader }
- private val random = Random()
- private val animator: ValueAnimator = ValueAnimator.ofFloat(0f, 1f)
- private var config: TurbulenceNoiseAnimationConfig? = null
-
- val isPlaying: Boolean
- get() = animator.isRunning
-
- init {
- // Only visible during the animation.
- visibility = INVISIBLE
- }
-
- /** Updates the color during the animation. No-op if there's no animation playing. */
- fun updateColor(color: Int) {
- config?.let {
- it.color = color
- applyConfig(it)
- }
- }
-
- override fun onDraw(canvas: Canvas?) {
- if (canvas == null || !canvas.isHardwareAccelerated) {
- // Drawing with the turbulence noise shader requires hardware acceleration, so skip
- // if it's unsupported.
- return
- }
-
- canvas.drawPaint(paint)
- }
-
- internal fun play(config: TurbulenceNoiseAnimationConfig) {
- if (isPlaying) {
- return // Ignore if the animation is playing.
- }
- visibility = VISIBLE
- applyConfig(config)
-
- // Add random offset to avoid same patterned noise.
- val offsetX = random.nextFloat()
- val offsetY = random.nextFloat()
-
- animator.duration = config.duration.toLong()
- animator.addUpdateListener { updateListener ->
- val timeInSec = updateListener.currentPlayTime * MS_TO_SEC
- // Remap [0,1] to [0, 2*PI]
- val progress = TWO_PI * updateListener.animatedValue as Float
-
- turbulenceNoiseShader.setNoiseMove(
- offsetX + timeInSec * config.noiseMoveSpeedX,
- offsetY + timeInSec * config.noiseMoveSpeedY,
- timeInSec * config.noiseMoveSpeedZ
- )
-
- // Fade in and out the noise as the animation progress.
- // TODO: replace it with a better curve
- turbulenceNoiseShader.setOpacity(sin(TWO_PI - progress) * config.luminosityMultiplier)
-
- invalidate()
- }
-
- animator.addListener(
- object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator) {
- visibility = INVISIBLE
- config.onAnimationEnd?.run()
- }
- }
- )
- animator.start()
- }
-
- private fun applyConfig(config: TurbulenceNoiseAnimationConfig) {
- this.config = config
- with(turbulenceNoiseShader) {
- setGridCount(config.gridCount)
- setColor(ColorUtils.setAlphaComponent(config.color, config.opacity))
- setBackgroundColor(config.backgroundColor)
- setSize(config.width, config.height)
- setPixelDensity(config.pixelDensity)
- }
- paint.blendMode = config.blendMode
- }
-}