1 /* 2 * Copyright (C) 2024 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 platform.test.motion.view 18 19 /** 20 * Description of animation sampling strategy. 21 * 22 * @param sampleAt The animation progress fractions at which to capture an animation frame. 23 * @param sampleBefore Samples the frame before the animation is started. 24 * @param sampleAfter Samples the frame after the animation has ended. 25 */ 26 data class AnimationSampling( 27 val sampleAt: List<Float>, 28 val sampleBefore: Boolean = true, 29 val sampleAfter: Boolean = true, 30 ) { 31 32 init { <lambda>null33 check(sampleAt.all { it in 0.0f..1.0f }) <lambda>null34 check(sampleAt.zipWithNext().all { it.first < it.second }) 35 } 36 37 companion object { 38 /** 39 * Creates a [AnimationSampling] to sample an animation exactly [sampleCount] times, evenly 40 * distributed over the animations playtime. 41 * 42 * [sampleAtStart] and [sampleAtEnd] define whether a frame is sampled at progress 0 and 1, 43 * respectively. 44 * 45 * [sampleBefore] and [sampleAfter] define whether to capture a sample before the animation 46 * is started, or after it is finished respectively. This is helpful to capture issues 47 * caused by code triggered at the start or end of the animation. 48 * 49 * [sampleAfter] is `false` by default, since [sampleAtEnd] in most cases equal to 50 * [sampleAfter], as the animation is automatically ended when the playTime of the animation 51 * equals the duration. 52 */ evenlySamplednull53 fun evenlySampled( 54 sampleCount: Int, 55 sampleBefore: Boolean = true, 56 sampleAtStart: Boolean = true, 57 sampleAtEnd: Boolean = true, 58 sampleAfter: Boolean = !sampleAtEnd, 59 ): AnimationSampling { 60 if (sampleAtStart && sampleAtEnd) { 61 require(sampleCount >= 2) 62 } else { 63 require(sampleCount >= 1) 64 } 65 66 val offset = if (sampleAtStart) 0 else 1 67 val divider = 68 when { 69 sampleAtStart xor sampleAtEnd -> sampleCount 70 sampleAtStart and sampleAtEnd -> sampleCount - 1 71 else -> sampleCount + 1 72 } 73 74 return AnimationSampling( 75 List(sampleCount) { (1f / divider) * (it + offset) }, 76 sampleBefore, 77 sampleAfter, 78 ) 79 } 80 } 81 } 82