Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 53e8ee4a authored by Mike Schneider's avatar Mike Schneider Committed by Android (Google) Code Review
Browse files

Merge "Rename gesture `distance` to `dragOffset` #MotionMechanics" into main

parents 198165ff 24aaa52d
Loading
Loading
Loading
Loading
+30 −29
Original line number Diff line number Diff line
@@ -52,16 +52,16 @@ interface GestureContext {
    /**
     * The gesture distance of the current gesture, in pixels.
     *
     * Used solely for the [GestureDistance] [Guarantee]. Can be hard-coded to a static value if
     * Used solely for the [GestureDragDelta] [Guarantee]. Can be hard-coded to a static value if
     * this type of [Guarantee] is not used.
     */
    val distance: Float
    val dragOffset: Float
}

/** [GestureContext] implementation for manually set values. */
class ProvidedGestureContext(direction: InputDirection, distance: Float) : GestureContext {
class ProvidedGestureContext(direction: InputDirection, dragOffset: Float) : GestureContext {
    override var direction by mutableStateOf(direction)
    override var distance by mutableFloatStateOf(distance)
    override var dragOffset by mutableFloatStateOf(dragOffset)
}

/**
@@ -70,13 +70,13 @@ class ProvidedGestureContext(direction: InputDirection, distance: Float) : Gestu
 * The direction is determined from the gesture input, where going further than
 * [directionChangeSlop] in the opposite direction toggles the direction.
 *
 * @param initialDistance The initial [distance] of the [GestureContext]
 * @param initialDragOffset The initial [dragOffset] of the [GestureContext]
 * @param initialDirection The initial [direction] of the [GestureContext]
 * @param directionChangeSlop the amount [distance] must be moved in the opposite direction for the
 *   [direction] to flip.
 * @param directionChangeSlop the amount [dragOffset] must be moved in the opposite direction for
 *   the [direction] to flip.
 */
class DistanceGestureContext(
    initialDistance: Float,
    initialDragOffset: Float,
    initialDirection: InputDirection,
    directionChangeSlop: Float,
) : GestureContext {
@@ -89,37 +89,38 @@ class DistanceGestureContext(
    override var direction by mutableStateOf(initialDirection)
        private set

    private var furthestDistance by mutableFloatStateOf(initialDistance)
    private var _distance by mutableFloatStateOf(initialDistance)
    private var furthestDragOffset by mutableFloatStateOf(initialDragOffset)

    override var distance: Float
        get() = _distance
    private var _dragOffset by mutableFloatStateOf(initialDragOffset)

    override var dragOffset: Float
        get() = _dragOffset
        /**
         * Updates the [distance].
         * Updates the [dragOffset].
         *
         * This flips the [direction], if the [value] is further than [directionChangeSlop] away
         * from the furthest recorded value regarding to the current [direction].
         */
        set(value) {
            _distance = value
            _dragOffset = value
            this.direction =
                when (direction) {
                    InputDirection.Max -> {
                        if (furthestDistance - value > directionChangeSlop) {
                            furthestDistance = value
                        if (furthestDragOffset - value > directionChangeSlop) {
                            furthestDragOffset = value
                            InputDirection.Min
                        } else {
                            furthestDistance = max(value, furthestDistance)
                            furthestDragOffset = max(value, furthestDragOffset)
                            InputDirection.Max
                        }
                    }

                    InputDirection.Min -> {
                        if (value - furthestDistance > directionChangeSlop) {
                            furthestDistance = value
                        if (value - furthestDragOffset > directionChangeSlop) {
                            furthestDragOffset = value
                            InputDirection.Max
                        } else {
                            furthestDistance = min(value, furthestDistance)
                            furthestDragOffset = min(value, furthestDragOffset)
                            InputDirection.Min
                        }
                    }
@@ -143,14 +144,14 @@ class DistanceGestureContext(

            when (direction) {
                InputDirection.Max -> {
                    if (furthestDistance - distance > directionChangeSlop) {
                        furthestDistance = distance
                    if (furthestDragOffset - dragOffset > directionChangeSlop) {
                        furthestDragOffset = dragOffset
                        direction = InputDirection.Min
                    }
                }
                InputDirection.Min -> {
                    if (distance - furthestDistance > directionChangeSlop) {
                        furthestDistance = value
                    if (dragOffset - furthestDragOffset > directionChangeSlop) {
                        furthestDragOffset = value
                        direction = InputDirection.Max
                    }
                }
@@ -158,14 +159,14 @@ class DistanceGestureContext(
        }

    /**
     * Sets [distance] and [direction] to the specified values.
     * Sets [dragOffset] and [direction] to the specified values.
     *
     * This also resets memoized [furthestDistance], which is used to determine the direction
     * This also resets memoized [furthestDragOffset], which is used to determine the direction
     * change.
     */
    fun reset(distance: Float, direction: InputDirection) {
        this.distance = distance
    fun reset(dragOffset: Float, direction: InputDirection) {
        this.dragOffset = dragOffset
        this.direction = direction
        this.furthestDistance = distance
        this.furthestDragOffset = dragOffset
    }
}
+22 −22
Original line number Diff line number Diff line
@@ -175,7 +175,7 @@ class MotionValue(
                        var result = spec.hashCode()
                        result = result * 31 + currentInput().hashCode()
                        result = result * 31 + currentDirection.hashCode()
                        result = result * 31 + currentGestureDistance.hashCode()
                        result = result * 31 + currentGestureDragOffset.hashCode()

                        // Track whether the spring needs animation frames to finish
                        // In fact, whether the spring is settling is the only relevant bit to
@@ -222,7 +222,7 @@ class MotionValue(
                // Capture the last frames input.
                lastFrameTimeNanos = currentAnimationTimeNanos
                lastInput = currentInput()
                lastGestureDistance = currentGestureDistance
                lastGestureDragOffset = currentGestureDragOffset
                // Not capturing currentDirection and spec explicitly, they are included in
                // lastSegment

@@ -236,7 +236,7 @@ class MotionValue(
                        FrameData(
                            lastInput,
                            currentDirection,
                            lastGestureDistance,
                            lastGestureDragOffset,
                            lastFrameTimeNanos,
                            lastSpringState,
                            lastSegment,
@@ -354,8 +354,8 @@ class MotionValue(
    /** The [currentInput] of the last frame */
    private var lastInput by mutableFloatStateOf(currentInput())

    /** The [currentGestureDistance] input of the last frame. */
    private var lastGestureDistance by mutableFloatStateOf(currentGestureDistance)
    /** The [currentGestureDragOffset] input of the last frame. */
    private var lastGestureDragOffset by mutableFloatStateOf(currentGestureDragOffset)

    // ---- Declarative Update ---------------------------------------------------------------------

@@ -373,9 +373,9 @@ class MotionValue(
    private inline val currentDirection: InputDirection
        get() = gestureContext.direction

    /** [gestureContext]'s [GestureContext.distance], exists solely for consistent naming. */
    private inline val currentGestureDistance: Float
        get() = gestureContext.distance
    /** [gestureContext]'s [GestureContext.dragOffset], exists solely for consistent naming. */
    private inline val currentGestureDragOffset: Float
        get() = gestureContext.dragOffset

    /**
     * The current segment, which defines the [Mapping] function used to transform the input to the
@@ -536,7 +536,7 @@ class MotionValue(
                    GuaranteeState.withStartValue(
                        when (entryBreakpoint.guarantee) {
                            is Guarantee.InputDelta -> currentInput()
                            is Guarantee.GestureDistance -> gestureContext.distance
                            is Guarantee.GestureDragDelta -> gestureContext.dragOffset
                            is Guarantee.None -> return@derivedStateOf GuaranteeState.Inactive
                        }
                    )
@@ -548,16 +548,16 @@ class MotionValue(
                    GuaranteeState.withStartValue(
                        when (entryBreakpoint.guarantee) {
                            is Guarantee.InputDelta -> entryBreakpoint.position
                            is Guarantee.GestureDistance -> {
                                // Guess the [GestureDistance] origin - since the gesture distance
                            is Guarantee.GestureDragDelta -> {
                                // Guess the GestureDragDelta origin - since the gesture dragOffset
                                // is sampled, interpolate it according to when the breakpoint was
                                // crossed in the last frame.
                                val fractionalBreakpointPos =
                                    lastFrameFractionOfPosition(entryBreakpoint.position)

                                lerp(
                                    lastGestureDistance,
                                    gestureContext.distance,
                                    lastGestureDragOffset,
                                    gestureContext.dragOffset,
                                    fractionalBreakpointPos,
                                )
                            }
@@ -573,7 +573,7 @@ class MotionValue(
        guaranteeOriginState.withCurrentValue(
            when (entryBreakpoint.guarantee) {
                is Guarantee.InputDelta -> currentInput()
                is Guarantee.GestureDistance -> gestureContext.distance
                is Guarantee.GestureDragDelta -> gestureContext.dragOffset
                is Guarantee.None -> return@derivedStateOf GuaranteeState.Inactive
            },
            currentSegment.direction,
@@ -689,10 +689,10 @@ class MotionValue(
                            val guaranteeValueAtNextBreakpoint =
                                when (lastBreakpoint.guarantee) {
                                    is Guarantee.InputDelta -> nextBreakpoint.position
                                    is Guarantee.GestureDistance ->
                                    is Guarantee.GestureDragDelta ->
                                        lerp(
                                            lastGestureDistance,
                                            gestureContext.distance,
                                            lastGestureDragOffset,
                                            gestureContext.dragOffset,
                                            nextBreakpointFrameFraction,
                                        )

@@ -734,11 +734,11 @@ class MotionValue(
                                is Guarantee.InputDelta ->
                                    GuaranteeState.withStartValue(nextBreakpoint.position)

                                is Guarantee.GestureDistance ->
                                is Guarantee.GestureDragDelta ->
                                    GuaranteeState.withStartValue(
                                        lerp(
                                            lastGestureDistance,
                                            gestureContext.distance,
                                            lastGestureDragOffset,
                                            gestureContext.dragOffset,
                                            nextBreakpointFrameFraction,
                                        )
                                    )
@@ -827,7 +827,7 @@ class MotionValue(
                    FrameData(
                        lastInput,
                        lastSegment.direction,
                        lastGestureDistance,
                        lastGestureDragOffset,
                        lastFrameTimeNanos,
                        lastSpringState,
                        lastSegment,
@@ -898,7 +898,7 @@ internal value class GuaranteeState(val packedValue: Long) {
            when (val guarantee = breakpoint.guarantee) {
                is Guarantee.None -> return breakpoint.spring
                is Guarantee.InputDelta -> guarantee.delta
                is Guarantee.GestureDistance -> guarantee.distance
                is Guarantee.GestureDragDelta -> guarantee.delta
            }

        val springTighteningFraction = maxDelta / denominator
+1 −1
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ data class FrameData
internal constructor(
    val input: Float,
    val gestureDirection: InputDirection,
    val gestureDistance: Float,
    val gestureDragOffset: Float,
    val frameTimeNanos: Long,
    val springState: SpringState,
    private val segment: SegmentData,
+2 −2
Original line number Diff line number Diff line
@@ -38,8 +38,8 @@ sealed class Guarantee {
    data class InputDelta(val delta: Float) : Guarantee()

    /**
     * Guarantees to complete the animation before the gesture is [distance] away from the gesture
     * Guarantees to complete the animation before the gesture is [delta] away from the gesture
     * position captured when the breakpoint was crossed.
     */
    data class GestureDistance(val distance: Float) : Guarantee()
    data class GestureDragDelta(val delta: Float) : Guarantee()
}
+7 −0
Original line number Diff line number Diff line
@@ -107,6 +107,13 @@ fun interface Mapping {
        }
    }

    data class Tanh(val scaling: Float, val tilt: Float, val offset: Float = 0f) : Mapping {

        override fun map(input: Float): Float {
            return scaling * kotlin.math.tanh((input + offset) / (scaling * tilt))
        }
    }

    companion object {
        val Zero = Fixed(0f)
        val One = Fixed(1f)
Loading