1 /* <lambda>null2 * Copyright (C) 2025 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 @file:OptIn(ExperimentalMaterial3ExpressiveApi::class) 18 19 package com.android.mechanics.demo.tuneable 20 21 import androidx.compose.foundation.layout.Column 22 import androidx.compose.foundation.layout.Row 23 import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi 24 import androidx.compose.material3.Text 25 import androidx.compose.runtime.Composable 26 import androidx.compose.runtime.getValue 27 import androidx.compose.runtime.mutableFloatStateOf 28 import androidx.compose.runtime.remember 29 import androidx.compose.runtime.setValue 30 import androidx.compose.ui.Alignment 31 import androidx.compose.ui.Modifier 32 import com.android.mechanics.demo.util.asLabel 33 import com.android.mechanics.spring.SpringParameters 34 import kotlin.math.floor 35 import kotlin.math.log10 36 import kotlin.math.pow 37 import kotlin.math.round 38 import kotlin.math.roundToInt 39 40 @Composable 41 fun SpringParameterSection( 42 label: String, 43 value: SpringParameters, 44 onValueChanged: (SpringParameters) -> Unit, 45 sectionKey: String, 46 modifier: Modifier = Modifier, 47 description: (@Composable () -> Unit)? = null, 48 ) { 49 Section( 50 label = label, 51 summary = { it.asLabel() }, 52 value = value, 53 sectionKey = sectionKey, 54 onValueChanged = onValueChanged, 55 modifier = modifier, 56 ) { springSpec, onSpringSpecChanged -> 57 description?.invoke() 58 59 var damping by remember { mutableFloatStateOf(springSpec.dampingRatio) } 60 var stiffness by remember { mutableFloatStateOf(springSpec.stiffness) } 61 Column { 62 Row(verticalAlignment = Alignment.CenterVertically) { 63 Text("Damping") 64 SliderWithPreview( 65 value = damping, 66 onValueChange = { 67 damping = it 68 onSpringSpecChanged(SpringParameters(stiffness, damping)) 69 }, 70 valueRange = 0.1f..2f, 71 normalize = { round(it * 100) / 100f }, 72 render = { "%.2f".format(it) }, 73 ) 74 } 75 Row(verticalAlignment = Alignment.CenterVertically) { 76 Text("Stiffness") 77 LogarithmicSliderWithPreview( 78 value = stiffness, 79 onValueChange = { 80 stiffness = round(it) 81 onSpringSpecChanged(SpringParameters(stiffness, damping)) 82 }, 83 valueRange = 50f..50000f, 84 normalize = { 85 val digits = floor(log10(it)) 86 val factor = 10f.pow(digits - 1) 87 88 round(round(it / factor) * factor) 89 }, 90 render = { "${it.roundToInt()}" }, 91 ) 92 } 93 } 94 } 95 } 96