Completely refactored APIs, added a new demo

This commit is contained in:
Kyant0 committed 2025-07-28 11:58:08 +08:00
1 parent 3df7722ecb
commit c2203e1f04
83 files changed
+2386 -665

No files matched your search

Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,6 +13,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshots.Snapshot
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@@ -21,19 +22,19 @@ import com.kyant.expressa.components.button.Button
import com.kyant.expressa.components.button.ButtonColors
import com.kyant.expressa.components.iconbutton.IconButton
import com.kyant.expressa.components.iconbutton.IconButtonColors
import com.kyant.expressa.m3.LocalColorScheme
import com.kyant.expressa.m3.motion.MotionScheme
import com.kyant.expressa.m3.shape.CornerShape
import com.kyant.expressa.prelude.*
import com.kyant.expressa.ui.Icon
import com.kyant.expressa.ui.Text
import com.kyant.glass.R
import com.kyant.liquidglass.GlassMaterial
import com.kyant.liquidglass.InnerRefraction
import com.kyant.liquidglass.GlassStyle
import com.kyant.liquidglass.LiquidGlassProviderState
import com.kyant.liquidglass.LiquidGlassStyle
import com.kyant.liquidglass.RefractionValue
import com.kyant.liquidglass.liquidGlass
import com.kyant.liquidglass.material.GlassMaterial
import com.kyant.liquidglass.refraction.InnerRefraction
import com.kyant.liquidglass.refraction.RefractionAmount
import com.kyant.liquidglass.refraction.RefractionHeight
@Composable
fun ConfigurationBottomSheet(
@@ -45,22 +46,20 @@ fun ConfigurationBottomSheet(
CompositionLocalProvider(
// LocalLiquidGlassProviderState provides providerState
) {
val isDark = LocalColorScheme.current.isDark
Column(
modifier
// .liquidGlassProvider(providerState)
.liquidGlass(
providerState,
LiquidGlassStyle(
GlassStyle(
shape = CornerShape.extraLarge,
innerRefraction = InnerRefraction(
height = RefractionValue(24.dp),
amount = RefractionValue((-64).dp)
height = RefractionHeight(24.dp),
amount = RefractionAmount((-64).dp)
),
material = GlassMaterial(
blurRadius = 8.dp,
tint = surface.copy(alpha = 0.6f),
whitePoint = if (isDark) -0.25f else 0.25f
brush = SolidColor(surface.copy(alpha = 0.3f))
)
)
)
@@ -90,7 +89,7 @@ fun ConfigurationBottomSheet(
IconButton(
{ state.configurationMode = null },
Modifier.liquidGlass(providerState, LiquidGlassStyle(CornerShape.full)),
Modifier.liquidGlass(providerState, GlassStyle(CornerShape.full)),
colors = IconButtonColors.tonal(
containerColor = primaryContainer.copy(alpha = 0.85f)
)
@@ -143,7 +142,7 @@ fun ConfigurationBottomSheet(
ConfigurationMode.Advanced -> {
Button(
{ state.unsafeMode = !state.unsafeMode },
Modifier.liquidGlass(providerState, LiquidGlassStyle(CornerShape.full)),
Modifier.liquidGlass(providerState, GlassStyle(CornerShape.full)),
colors = ButtonColors.filled(
containerColor = primary.copy(alpha = 0.85f)
)
@@ -152,53 +152,6 @@ fun Preview() {
clip = true
shape = RoundedRectangle(state.cornerRadius.value)
}
.graphicsLayer { // white point & chroma boost
val contrast = state.contrast.value
val whitePoint = state.whitePoint.value
val chromaMultiplier = state.chromaMultiplier.value
if (contrast != 0f || whitePoint != 0f || chromaMultiplier != 1f) {
renderEffect = RenderEffect.createRuntimeShaderEffect(
RuntimeShader(
"""
uniform shader image;
uniform float contrast;
uniform float whitePoint;
uniform float chromaMultiplier;
$colorShaderUtils
half4 saturateColor(half4 color, float amount) {
half3 linearSrgb = toLinearSrgb(color.rgb);
float y = dot(linearSrgb, rgbToY);
half3 gray = half3(y);
half3 adjustedLinearSrgb = mix(gray, linearSrgb, amount);
half3 adjustedSrgb = fromLinearSrgb(adjustedLinearSrgb);
return half4(adjustedSrgb, color.a);
}
half4 main(float2 coord) {
half4 color = image.eval(coord);
color = saturateColor(color, chromaMultiplier);
float3 target = (whitePoint > 0.0) ? float3(1.0) : float3(0.0);
color.rgb = mix(color.rgb, target, abs(whitePoint));
color.rgb = (color.rgb - 0.5) * (1.0 + contrast) + 0.5;
return color;
}"""
).apply {
setFloatUniform("contrast", contrast)
setFloatUniform("whitePoint", whitePoint)
setFloatUniform("chromaMultiplier", chromaMultiplier)
},
"image"
).asComposeRenderEffect()
}
}
.graphicsLayer { // dispersion effect
renderEffect = RenderEffect.createRuntimeShaderEffect(
RuntimeShader(
@@ -411,6 +364,53 @@ fun Preview() {
).asComposeRenderEffect()
}
}
.graphicsLayer { // white point & chroma boost
val contrast = state.contrast.value
val whitePoint = state.whitePoint.value
val chromaMultiplier = state.chromaMultiplier.value
if (contrast != 0f || whitePoint != 0f || chromaMultiplier != 1f) {
renderEffect = RenderEffect.createRuntimeShaderEffect(
RuntimeShader(
"""
uniform shader image;
uniform float contrast;
uniform float whitePoint;
uniform float chromaMultiplier;
$colorShaderUtils
half4 saturateColor(half4 color, float amount) {
half3 linearSrgb = toLinearSrgb(color.rgb);
float y = dot(linearSrgb, rgbToY);
half3 gray = half3(y);
half3 adjustedLinearSrgb = mix(gray, linearSrgb, amount);
half3 adjustedSrgb = fromLinearSrgb(adjustedLinearSrgb);
return half4(adjustedSrgb, color.a);
}
half4 main(float2 coord) {
half4 color = image.eval(coord);
color = saturateColor(color, chromaMultiplier);
float3 target = (whitePoint > 0.0) ? float3(1.0) : float3(0.0);
color.rgb = mix(color.rgb, target, abs(whitePoint));
color.rgb = (color.rgb - 0.5) * (1.0 + contrast) + 0.5;
return color;
}"""
).apply {
setFloatUniform("contrast", contrast)
setFloatUniform("whitePoint", whitePoint)
setFloatUniform("chromaMultiplier", chromaMultiplier)
},
"image"
).asComposeRenderEffect()
}
}
.drawBehind {
clipRect(0f, 0f, rect.width, rect.height) {
translate(-rect.left, -rect.top) {
@@ -16,6 +16,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@@ -27,10 +28,10 @@ import com.kyant.expressa.m3.shape.CornerShape
import com.kyant.expressa.prelude.*
import com.kyant.expressa.ui.Icon
import com.kyant.glass.R
import com.kyant.liquidglass.GlassMaterial
import com.kyant.liquidglass.GlassStyle
import com.kyant.liquidglass.LiquidGlassProviderState
import com.kyant.liquidglass.LiquidGlassStyle
import com.kyant.liquidglass.liquidGlass
import com.kyant.liquidglass.material.GlassMaterial
import kotlinx.coroutines.launch
@Composable
@@ -41,10 +42,12 @@ fun PreviewToolbar(
) {
val scope = rememberCoroutineScope()
val iconButtonLiquidGlassStyle = remember {
LiquidGlassStyle(
val iconButtonGlassStyle = remember {
GlassStyle(
CornerShape.full,
material = GlassMaterial(whitePoint = -0.5f)
material = GlassMaterial(
brush = SolidColor(Color.Black.copy(alpha = 0.3f))
)
)
}
@@ -55,7 +58,7 @@ fun PreviewToolbar(
) {
IconButton(
{ scope.launch { state.reset() } },
Modifier.liquidGlass(providerState, iconButtonLiquidGlassStyle),
Modifier.liquidGlass(providerState, iconButtonGlassStyle),
sizes = IconButtonSizes.medium,
colors = IconButtonColors.tonal(
containerColor = primary.copy(alpha = 0.6f),
@@ -79,14 +82,7 @@ fun PreviewToolbar(
) {
IconButton(
{ state.displayControls = !state.displayControls },
Modifier.liquidGlass(
providerState,
iconButtonLiquidGlassStyle.copy(
material = GlassMaterial(
whitePoint = if (state.displayControls) 0.5f else -0.5f
)
)
),
Modifier.liquidGlass(providerState, iconButtonGlassStyle),
sizes = IconButtonSizes.medium,
colors = IconButtonColors.tonal(
containerColor = Color.Transparent,
@@ -106,7 +102,7 @@ fun PreviewToolbar(
}
IconButton(
{ state.configurationMode = ConfigurationMode.Colors },
Modifier.liquidGlass(providerState, iconButtonLiquidGlassStyle),
Modifier.liquidGlass(providerState, iconButtonGlassStyle),
sizes = IconButtonSizes.medium,
colors = IconButtonColors.tonal(
containerColor = Color.Transparent,
@@ -120,7 +116,7 @@ fun PreviewToolbar(
}
IconButton(
{ state.configurationMode = ConfigurationMode.Advanced },
Modifier.liquidGlass(providerState, iconButtonLiquidGlassStyle),
Modifier.liquidGlass(providerState, iconButtonGlassStyle),
sizes = IconButtonSizes.medium,
colors = IconButtonColors.tonal(
containerColor = Color.Transparent,
@@ -151,7 +147,7 @@ fun PreviewToolbar(
)
)
},
Modifier.liquidGlass(providerState, iconButtonLiquidGlassStyle),
Modifier.liquidGlass(providerState, iconButtonGlassStyle),
sizes = IconButtonSizes.medium,
colors = IconButtonColors.tonal(
containerColor = primary.copy(alpha = 0.6f),
@@ -1,7 +1,6 @@
package com.kyant.glass.playground
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -11,9 +10,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.text.style.TextDecoration
@@ -25,9 +24,10 @@ import com.kyant.expressa.prelude.*
import com.kyant.expressa.ui.LocalTextStyle
import com.kyant.expressa.ui.ProvideTextStyle
import com.kyant.expressa.ui.Text
import com.kyant.liquidglass.GlassStyle
import com.kyant.liquidglass.LiquidGlassProviderState
import com.kyant.liquidglass.LiquidGlassStyle
import com.kyant.liquidglass.liquidGlass
import com.kyant.liquidglass.material.GlassMaterial
@Composable
fun <T : Comparable<T>> SliderChip(
@@ -48,13 +48,15 @@ fun <T : Comparable<T>> SliderChip(
modifier
.liquidGlass(
providerState,
LiquidGlassStyle(CornerShape.extraLarge)
GlassStyle(
CornerShape.full,
material = GlassMaterial(
brush = SolidColor(surfaceBright.copy(alpha = 0.6f))
)
)
)
.clip(CornerShape.full)
.background(surfaceBright.copy(alpha = 0.85f))
.drawBehind {
if (value.isValid) {
// drawRect(containerColor)
drawRect(
if (value.isSafe) sliderColor else unsafeColors.accentContainer,
topLeft =