diff --git a/backdrop/src/main/java/com/kyant/backdrop/Shaders.kt b/backdrop/src/main/java/com/kyant/backdrop/Shaders.kt index 6e346c6..12304ae 100644 --- a/backdrop/src/main/java/com/kyant/backdrop/Shaders.kt +++ b/backdrop/src/main/java/com/kyant/backdrop/Shaders.kt @@ -143,7 +143,7 @@ half4 main(float2 coord) { }""" @Language("AGSL") -internal const val DynamicHighlightShaderString = """ +internal const val DefaultHighlightShaderString = """ uniform shader content; uniform float2 size; diff --git a/backdrop/src/main/java/com/kyant/backdrop/highlight/Highlight.kt b/backdrop/src/main/java/com/kyant/backdrop/highlight/Highlight.kt index 1e74c60..baa5da8 100644 --- a/backdrop/src/main/java/com/kyant/backdrop/highlight/Highlight.kt +++ b/backdrop/src/main/java/com/kyant/backdrop/highlight/Highlight.kt @@ -14,7 +14,7 @@ data class Highlight( val width: Dp = 0.5f.dp, val blurRadius: Dp = width / 2f, val alpha: Float = 1f, - val style: HighlightStyle = HighlightStyle.Dynamic.Default + val style: HighlightStyle = HighlightStyle.Default ) { @Deprecated(message = "Use the non-lambda version of style parameter") @@ -38,10 +38,10 @@ data class Highlight( val Default: Highlight = Highlight() @Stable - val AmbientDefault: Highlight = Highlight(style = HighlightStyle.Dynamic(isAmbient = true)) + val Ambient: Highlight = Highlight(style = HighlightStyle.Ambient) @Stable - val SolidDefault: Highlight = Highlight(style = HighlightStyle.Solid) + val Plain: Highlight = Highlight(style = HighlightStyle.Plain) } } diff --git a/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt b/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt index 54dff1f..c8894da 100644 --- a/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt +++ b/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt @@ -12,11 +12,12 @@ import androidx.compose.ui.graphics.RenderEffect import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.asComposeRenderEffect import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.lerp import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.util.fastCoerceAtMost import androidx.compose.ui.util.lerp import com.kyant.backdrop.AmbientHighlightShaderString -import com.kyant.backdrop.DynamicHighlightShaderString +import com.kyant.backdrop.DefaultHighlightShaderString import com.kyant.backdrop.RuntimeShaderCacheScope import kotlin.math.PI @@ -33,12 +34,15 @@ interface HighlightStyle { shaderCache: RuntimeShaderCacheScope ): RenderEffect? - @Immutable + @Deprecated( + message = "Use HighlightStyle.Plain instead", + replaceWith = ReplaceWith("HighlightStyle.Plain") + ) data object Solid : HighlightStyle { - override val color: Color = DefaultHighlightColor + override val color: Color = Color.White.copy(alpha = 0.38f) - override val blendMode: BlendMode = DrawScope.DefaultBlendMode + override val blendMode: BlendMode = BlendMode.Plus @RequiresApi(Build.VERSION_CODES.S) override fun DrawScope.createRenderEffect( @@ -48,16 +52,41 @@ interface HighlightStyle { } @Immutable - data class Dynamic( - val angle: Float = 45f, - @param:FloatRange(from = 0.0) val falloff: Float = 1f, - val isAmbient: Boolean = false + data class Plain( + override val color: Color = Color.White.copy(alpha = 0.38f), + override val blendMode: BlendMode = BlendMode.Plus ) : HighlightStyle { - override val color: Color = DefaultHighlightColor + @RequiresApi(Build.VERSION_CODES.S) + override fun DrawScope.createRenderEffect( + shape: Shape, + shaderCache: RuntimeShaderCacheScope + ): RenderEffect? = null + } - override val blendMode: BlendMode = - if (isAmbient) DrawScope.DefaultBlendMode else BlendMode.Plus + @Deprecated( + message = "Use HighlightStyle.Default instead", + replaceWith = ReplaceWith("HighlightStyle.Default") + ) + data class Dynamic( + override val color: Color = Color.White.copy(alpha = 0.5f), + override val blendMode: BlendMode = BlendMode.Plus, + val angle: Float = 45f, + @param:FloatRange(from = 0.0) val falloff: Float = 1f + ) : HighlightStyle by Default( + color = color, + blendMode = blendMode, + angle = angle, + falloff = falloff + ) + + @Immutable + data class Default( + override val color: Color = Color.White.copy(alpha = 0.5f), + override val blendMode: BlendMode = BlendMode.Plus, + val angle: Float = 45f, + @param:FloatRange(from = 0.0) val falloff: Float = 1f + ) : HighlightStyle { @RequiresApi(Build.VERSION_CODES.S) override fun DrawScope.createRenderEffect( @@ -65,12 +94,7 @@ interface HighlightStyle { shaderCache: RuntimeShaderCacheScope ): RenderEffect? { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - val shader = - if (isAmbient) { - shaderCache.obtainRuntimeShader("Ambient", AmbientHighlightShaderString) - } else { - shaderCache.obtainRuntimeShader("Dynamic", DynamicHighlightShaderString) - } + val shader = shaderCache.obtainRuntimeShader("Dynamic", DefaultHighlightShaderString) shader.apply { setFloatUniform("size", size.width, size.height) setFloatUniform("cornerRadii", getCornerRadii(shape)) @@ -83,25 +107,75 @@ interface HighlightStyle { null } } + } - companion object { + @Immutable + data class Ambient( + override val color: Color = Color.White.copy(alpha = 0.5f), + override val blendMode: BlendMode = DrawScope.DefaultBlendMode + ) : HighlightStyle { - @Stable - val Default: Dynamic = Dynamic() + @RequiresApi(Build.VERSION_CODES.S) + override fun DrawScope.createRenderEffect( + shape: Shape, + shaderCache: RuntimeShaderCacheScope + ): RenderEffect? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + val shader = shaderCache.obtainRuntimeShader("Ambient", AmbientHighlightShaderString) + shader.apply { + setFloatUniform("size", size.width, size.height) + setFloatUniform("cornerRadii", getCornerRadii(shape)) + setFloatUniform("angle", 45f * (PI / 180f).toFloat()) + setFloatUniform("falloff", 1f) + } + android.graphics.RenderEffect.createRuntimeShaderEffect(shader, "content") + .asComposeRenderEffect() + } else { + null + } } } + + companion object { + + @Stable + val Default: Default = Default() + + @Deprecated( + message = "Use HighlightStyle.Default instead", + replaceWith = ReplaceWith("HighlightStyle.Default") + ) + @Stable + val Dynamic: Dynamic = Dynamic() + + @Stable + val Ambient: Ambient = Ambient() + + @Stable + val Plain: Plain = Plain() + } } @Stable fun lerp(start: HighlightStyle, stop: HighlightStyle, fraction: Float): HighlightStyle { - if (start is HighlightStyle.Solid && stop is HighlightStyle.Solid) { - return HighlightStyle.Solid + if (start is HighlightStyle.Plain && stop is HighlightStyle.Plain) { + return HighlightStyle.Plain( + color = lerp(start.color, stop.color, fraction), + blendMode = if (fraction < 0.5f) start.blendMode else stop.blendMode + ) } - if (start is HighlightStyle.Dynamic && stop is HighlightStyle.Dynamic) { - return HighlightStyle.Dynamic( + if (start is HighlightStyle.Default && stop is HighlightStyle.Default) { + return HighlightStyle.Default( + color = lerp(start.color, stop.color, fraction), + blendMode = if (fraction < 0.5f) start.blendMode else stop.blendMode, angle = lerp(start.angle, stop.angle, fraction), - falloff = lerp(start.falloff, stop.falloff, fraction), - isAmbient = if (fraction < 0.5f) start.isAmbient else stop.isAmbient + falloff = lerp(start.falloff, stop.falloff, fraction) + ) + } + if (start is HighlightStyle.Ambient && stop is HighlightStyle.Ambient) { + return HighlightStyle.Ambient( + color = lerp(start.color, stop.color, fraction), + blendMode = if (fraction < 0.5f) start.blendMode else stop.blendMode ) } return if (fraction < 0.5f) start else stop @@ -131,5 +205,3 @@ private fun DrawScope.getCornerRadii(shape: Shape): FloatArray { bottomLeft.fastCoerceAtMost(maxRadius) ) } - -private val DefaultHighlightColor = Color.White.copy(alpha = 0.5f) diff --git a/catalog/release/baselineProfiles/0/catalog-release.dm b/catalog/release/baselineProfiles/0/catalog-release.dm index d977537..0ae7b11 100644 Binary files a/catalog/release/baselineProfiles/0/catalog-release.dm and b/catalog/release/baselineProfiles/0/catalog-release.dm differ diff --git a/catalog/release/baselineProfiles/1/catalog-release.dm b/catalog/release/baselineProfiles/1/catalog-release.dm index ad25bbb..edc2136 100644 Binary files a/catalog/release/baselineProfiles/1/catalog-release.dm and b/catalog/release/baselineProfiles/1/catalog-release.dm differ diff --git a/catalog/release/catalog-release.apk b/catalog/release/catalog-release.apk index b920436..7490d85 100644 Binary files a/catalog/release/catalog-release.apk and b/catalog/release/catalog-release.apk differ diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt index ec3452f..e54d1b1 100644 --- a/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt +++ b/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt @@ -120,7 +120,7 @@ fun LiquidSlider( shape = { ContinuousCapsule }, highlight = { val progress = momentumAnimation.progress - Highlight.AmbientDefault.copy(alpha = progress) + Highlight.Ambient.copy(alpha = progress) }, shadow = { Shadow( diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt index 7a31eaa..7a27cbc 100644 --- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt +++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt @@ -99,7 +99,7 @@ fun AdaptiveLuminanceGlassContent() { .drawBackdrop( backdrop = backdrop, shape = { ContinuousRoundedRectangle(24f.dp) }, - highlight = { Highlight.SolidDefault }, + highlight = { Highlight.Plain }, effects = { val l = (luminanceAnimation.value * 2f - 1f).let { sign(it) * it * it } colorControls( diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt index 777c330..c2d8a71 100644 --- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt +++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt @@ -98,7 +98,7 @@ fun ControlCenterContent() { val glassShape = { itemShape } val glassHighlight = { Highlight( - style = HighlightStyle.Dynamic( + style = HighlightStyle.Default( angle = uiSensor.gravityAngle, falloff = 2f ) diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt index e7a99d8..fae7421 100644 --- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt +++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt @@ -60,7 +60,7 @@ fun DialogContent() { .drawBackdrop( backdrop = backdrop, shape = { ContinuousRoundedRectangle(48f.dp) }, - highlight = { Highlight.SolidDefault }, + highlight = { Highlight.Plain }, effects = { colorControls( brightness = if (isLightTheme) 0.2f else 0f, diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt index c5593ad..4a57596 100644 --- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt +++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt @@ -67,7 +67,7 @@ fun GlassPlaygroundContent() { .drawBackdrop( backdrop = backdrop, shape = { ContinuousRoundedRectangle(256f.dp / 2f * cornerRadiusFrac) }, - highlight = { Highlight.SolidDefault }, + highlight = { Highlight.Plain }, effects = { val minDimension = size.minDimension vibrancy() @@ -130,7 +130,7 @@ fun GlassPlaygroundContent() { .drawBackdrop( backdrop = backdrop, shape = { ContinuousRoundedRectangle(32f.dp) }, - highlight = { Highlight.SolidDefault }, + highlight = { Highlight.Plain }, effects = { vibrancy() blur(4f.dp.toPx())