1 /* 2 * 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 package com.android.mechanics.impl 18 19 import androidx.compose.ui.util.fastCoerceAtLeast 20 import androidx.compose.ui.util.packFloats 21 import androidx.compose.ui.util.unpackFloat1 22 import androidx.compose.ui.util.unpackFloat2 23 import com.android.mechanics.spec.Breakpoint 24 import com.android.mechanics.spec.Guarantee 25 import com.android.mechanics.spec.InputDirection 26 import com.android.mechanics.spring.SpringParameters 27 import kotlin.math.max 28 29 /** 30 * Captures the origin of a guarantee, and the maximal distance the input has been away from the 31 * origin at most. 32 */ 33 @JvmInline 34 internal value class GuaranteeState(val packedValue: Long) { 35 private val start: Float 36 get() = unpackFloat1(packedValue) 37 38 private val maxDelta: Float 39 get() = unpackFloat2(packedValue) 40 41 private val isInactive: Boolean 42 get() = this == Inactive 43 withCurrentValuenull44 fun withCurrentValue(value: Float, direction: InputDirection): GuaranteeState { 45 if (isInactive) return Inactive 46 47 val delta = ((value - start) * direction.sign).fastCoerceAtLeast(0f) 48 return GuaranteeState(start, max(delta, maxDelta)) 49 } 50 updatedSpringParametersnull51 fun updatedSpringParameters(breakpoint: Breakpoint): SpringParameters { 52 if (isInactive) return breakpoint.spring 53 54 val denominator = 55 when (val guarantee = breakpoint.guarantee) { 56 is Guarantee.None -> return breakpoint.spring 57 is Guarantee.InputDelta -> guarantee.delta 58 is Guarantee.GestureDragDelta -> guarantee.delta 59 } 60 61 val springTighteningFraction = maxDelta / denominator 62 return com.android.mechanics.spring.lerp( 63 breakpoint.spring, 64 SpringParameters.Snap, 65 springTighteningFraction, 66 ) 67 } 68 69 companion object { 70 val Inactive = GuaranteeState(packFloats(Float.NaN, Float.NaN)) 71 withStartValuenull72 fun withStartValue(start: Float) = GuaranteeState(packFloats(start, 0f)) 73 } 74 } 75 76 internal fun GuaranteeState(start: Float, maxDelta: Float) = 77 GuaranteeState(packFloats(start, maxDelta)) 78