Loading mechanics/src/com/android/mechanics/MotionValue.kt +15 −32 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.mechanics import androidx.compose.runtime.FloatState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableLongStateOf Loading Loading @@ -153,7 +152,7 @@ class MotionValue( /** The current segment used to compute the output. */ val segmentKey: SegmentKey get() = impl.currentSegment.key get() = impl.currentComputedValues.segment.key /** * Keeps the [MotionValue]'s animated output running. Loading Loading @@ -254,7 +253,7 @@ private class ObservableComputations( initialSpec: MotionSpec = MotionSpec.Empty, override val stableThreshold: Float, override val label: String?, ) : Computations { ) : Computations() { // ---- CurrentFrameInput --------------------------------------------------------------------- Loading Loading @@ -309,26 +308,6 @@ private class ObservableComputations( // ---- Computations --------------------------------------------------------------------------- override val currentSegment by derivedStateOf { computeCurrentSegment() } override val currentGuaranteeState by derivedStateOf { computeCurrentGuaranteeState() } override val currentAnimation by derivedStateOf { computeCurrentAnimation() } private var memoizedSpringState: SpringState = SpringState.AtRest private var memoizedAnimation: DiscontinuityAnimation? = null private var memoizedTimeNanos: Long = Long.MIN_VALUE override val currentSpringState: SpringState get() { val animation = currentAnimation val timeNanos = currentAnimationTimeNanos return if (memoizedAnimation == animation && memoizedTimeNanos == timeNanos) { memoizedSpringState } else { memoizedAnimation = animation memoizedTimeNanos = timeNanos computeCurrentSpringState(animation, timeNanos).also { memoizedSpringState = it } } } suspend fun keepRunning(continueRunning: () -> Boolean) { check(!isActive) { "MotionValue($label) is already running" } isActive = true Loading @@ -336,9 +315,10 @@ private class ObservableComputations( // These `captured*` values will be applied to the `last*` values, at the beginning // of the each new frame. // TODO(b/397837971): Encapsulate the state in a StateRecord. var capturedSegment = currentSegment var capturedGuaranteeState = currentGuaranteeState var capturedAnimation = currentAnimation val initialValues = currentComputedValues var capturedSegment = initialValues.segment var capturedGuaranteeState = initialValues.guarantee var capturedAnimation = initialValues.animation var capturedSpringState = currentSpringState var capturedFrameTimeNanos = currentAnimationTimeNanos var capturedInput = currentInput Loading Loading @@ -393,18 +373,21 @@ private class ObservableComputations( var scheduleNextFrame = false if (!isSameSegmentAndAtRest) { if (capturedSegment != currentSegment) { capturedSegment = currentSegment // Read currentComputedValues only once and update it, if necessary val currentValues = currentComputedValues if (capturedSegment != currentValues.segment) { capturedSegment = currentValues.segment scheduleNextFrame = true } if (capturedGuaranteeState != currentGuaranteeState) { capturedGuaranteeState = currentGuaranteeState if (capturedGuaranteeState != currentValues.guarantee) { capturedGuaranteeState = currentValues.guarantee scheduleNextFrame = true } if (capturedAnimation != currentAnimation) { capturedAnimation = currentAnimation if (capturedAnimation != currentValues.animation) { capturedAnimation = currentValues.animation scheduleNextFrame = true } Loading mechanics/src/com/android/mechanics/impl/Computations.kt +239 −153 File changed.Preview size limit exceeded, changes collapsed. Show changes mechanics/src/com/android/mechanics/view/ViewMotionValue.kt +12 −25 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ class ViewMotionValue( /** The current segment used to compute the output. */ val segmentKey: SegmentKey get() = impl.currentSegment.key get() = impl.currentComputedValues.segment.key val label: String? by impl::label Loading Loading @@ -156,7 +156,7 @@ private class ImperativeComputations( initialSpec: MotionSpec, override val stableThreshold: Float, override val label: String?, ) : Computations, GestureContextUpdateListener { ) : Computations(), GestureContextUpdateListener { init { gestureContext.addUpdateCallback(this) Loading Loading @@ -204,14 +204,6 @@ private class ImperativeComputations( override var directMappedVelocity: Float = 0f var lastDirection: InputDirection = currentDirection // ---- Computations --------------------------------------------------------------------------- override var currentSegment: SegmentData = computeCurrentSegment() override var currentGuaranteeState: GuaranteeState = computeCurrentGuaranteeState() override var currentAnimation: DiscontinuityAnimation = computeCurrentAnimation() override var currentSpringState: SpringState = computeCurrentSpringState(currentAnimation, currentAnimationTimeNanos) // ---- Lifecycle ------------------------------------------------------------------------------ // HACK: Use a ValueAnimator to listen to animation frames without using Choreographer directly. Loading Loading @@ -278,13 +270,8 @@ private class ImperativeComputations( currentAnimationTimeNanos = frameTimeMillis * 1_000_000L if (!isSameSegmentAndAtRest) { currentSegment = computeCurrentSegment() currentGuaranteeState = computeCurrentGuaranteeState() currentAnimation = computeCurrentAnimation() currentSpringState = computeCurrentSpringState(currentAnimation, currentAnimationTimeNanos) } // Read currentComputedValues only once and update it, if necessary val currentValues = currentComputedValues debugInspector?.run { frame = Loading @@ -294,8 +281,8 @@ private class ImperativeComputations( currentGestureDragOffset, currentAnimationTimeNanos, currentSpringState, currentSegment, currentAnimation, currentValues.segment, currentValues.animation, ) } Loading @@ -314,18 +301,18 @@ private class ImperativeComputations( } var isAnimationFinished = isStable if (lastSegment != currentSegment) { lastSegment = currentSegment if (lastSegment != currentValues.segment) { lastSegment = currentValues.segment isAnimationFinished = false } if (lastGuaranteeState != currentGuaranteeState) { lastGuaranteeState = currentGuaranteeState if (lastGuaranteeState != currentValues.guarantee) { lastGuaranteeState = currentValues.guarantee isAnimationFinished = false } if (lastAnimation != currentAnimation) { lastAnimation = currentAnimation if (lastAnimation != currentValues.animation) { lastAnimation = currentValues.animation isAnimationFinished = false } Loading Loading
mechanics/src/com/android/mechanics/MotionValue.kt +15 −32 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.mechanics import androidx.compose.runtime.FloatState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableLongStateOf Loading Loading @@ -153,7 +152,7 @@ class MotionValue( /** The current segment used to compute the output. */ val segmentKey: SegmentKey get() = impl.currentSegment.key get() = impl.currentComputedValues.segment.key /** * Keeps the [MotionValue]'s animated output running. Loading Loading @@ -254,7 +253,7 @@ private class ObservableComputations( initialSpec: MotionSpec = MotionSpec.Empty, override val stableThreshold: Float, override val label: String?, ) : Computations { ) : Computations() { // ---- CurrentFrameInput --------------------------------------------------------------------- Loading Loading @@ -309,26 +308,6 @@ private class ObservableComputations( // ---- Computations --------------------------------------------------------------------------- override val currentSegment by derivedStateOf { computeCurrentSegment() } override val currentGuaranteeState by derivedStateOf { computeCurrentGuaranteeState() } override val currentAnimation by derivedStateOf { computeCurrentAnimation() } private var memoizedSpringState: SpringState = SpringState.AtRest private var memoizedAnimation: DiscontinuityAnimation? = null private var memoizedTimeNanos: Long = Long.MIN_VALUE override val currentSpringState: SpringState get() { val animation = currentAnimation val timeNanos = currentAnimationTimeNanos return if (memoizedAnimation == animation && memoizedTimeNanos == timeNanos) { memoizedSpringState } else { memoizedAnimation = animation memoizedTimeNanos = timeNanos computeCurrentSpringState(animation, timeNanos).also { memoizedSpringState = it } } } suspend fun keepRunning(continueRunning: () -> Boolean) { check(!isActive) { "MotionValue($label) is already running" } isActive = true Loading @@ -336,9 +315,10 @@ private class ObservableComputations( // These `captured*` values will be applied to the `last*` values, at the beginning // of the each new frame. // TODO(b/397837971): Encapsulate the state in a StateRecord. var capturedSegment = currentSegment var capturedGuaranteeState = currentGuaranteeState var capturedAnimation = currentAnimation val initialValues = currentComputedValues var capturedSegment = initialValues.segment var capturedGuaranteeState = initialValues.guarantee var capturedAnimation = initialValues.animation var capturedSpringState = currentSpringState var capturedFrameTimeNanos = currentAnimationTimeNanos var capturedInput = currentInput Loading Loading @@ -393,18 +373,21 @@ private class ObservableComputations( var scheduleNextFrame = false if (!isSameSegmentAndAtRest) { if (capturedSegment != currentSegment) { capturedSegment = currentSegment // Read currentComputedValues only once and update it, if necessary val currentValues = currentComputedValues if (capturedSegment != currentValues.segment) { capturedSegment = currentValues.segment scheduleNextFrame = true } if (capturedGuaranteeState != currentGuaranteeState) { capturedGuaranteeState = currentGuaranteeState if (capturedGuaranteeState != currentValues.guarantee) { capturedGuaranteeState = currentValues.guarantee scheduleNextFrame = true } if (capturedAnimation != currentAnimation) { capturedAnimation = currentAnimation if (capturedAnimation != currentValues.animation) { capturedAnimation = currentValues.animation scheduleNextFrame = true } Loading
mechanics/src/com/android/mechanics/impl/Computations.kt +239 −153 File changed.Preview size limit exceeded, changes collapsed. Show changes
mechanics/src/com/android/mechanics/view/ViewMotionValue.kt +12 −25 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ class ViewMotionValue( /** The current segment used to compute the output. */ val segmentKey: SegmentKey get() = impl.currentSegment.key get() = impl.currentComputedValues.segment.key val label: String? by impl::label Loading Loading @@ -156,7 +156,7 @@ private class ImperativeComputations( initialSpec: MotionSpec, override val stableThreshold: Float, override val label: String?, ) : Computations, GestureContextUpdateListener { ) : Computations(), GestureContextUpdateListener { init { gestureContext.addUpdateCallback(this) Loading Loading @@ -204,14 +204,6 @@ private class ImperativeComputations( override var directMappedVelocity: Float = 0f var lastDirection: InputDirection = currentDirection // ---- Computations --------------------------------------------------------------------------- override var currentSegment: SegmentData = computeCurrentSegment() override var currentGuaranteeState: GuaranteeState = computeCurrentGuaranteeState() override var currentAnimation: DiscontinuityAnimation = computeCurrentAnimation() override var currentSpringState: SpringState = computeCurrentSpringState(currentAnimation, currentAnimationTimeNanos) // ---- Lifecycle ------------------------------------------------------------------------------ // HACK: Use a ValueAnimator to listen to animation frames without using Choreographer directly. Loading Loading @@ -278,13 +270,8 @@ private class ImperativeComputations( currentAnimationTimeNanos = frameTimeMillis * 1_000_000L if (!isSameSegmentAndAtRest) { currentSegment = computeCurrentSegment() currentGuaranteeState = computeCurrentGuaranteeState() currentAnimation = computeCurrentAnimation() currentSpringState = computeCurrentSpringState(currentAnimation, currentAnimationTimeNanos) } // Read currentComputedValues only once and update it, if necessary val currentValues = currentComputedValues debugInspector?.run { frame = Loading @@ -294,8 +281,8 @@ private class ImperativeComputations( currentGestureDragOffset, currentAnimationTimeNanos, currentSpringState, currentSegment, currentAnimation, currentValues.segment, currentValues.animation, ) } Loading @@ -314,18 +301,18 @@ private class ImperativeComputations( } var isAnimationFinished = isStable if (lastSegment != currentSegment) { lastSegment = currentSegment if (lastSegment != currentValues.segment) { lastSegment = currentValues.segment isAnimationFinished = false } if (lastGuaranteeState != currentGuaranteeState) { lastGuaranteeState = currentGuaranteeState if (lastGuaranteeState != currentValues.guarantee) { lastGuaranteeState = currentValues.guarantee isAnimationFinished = false } if (lastAnimation != currentAnimation) { lastAnimation = currentAnimation if (lastAnimation != currentValues.animation) { lastAnimation = currentValues.animation isAnimationFinished = false } Loading