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 package com.android.internal.widget.remotecompose.core.operations.layout.animation; 17 18 import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT; 19 20 import android.annotation.NonNull; 21 22 import com.android.internal.widget.remotecompose.core.Operation; 23 import com.android.internal.widget.remotecompose.core.Operations; 24 import com.android.internal.widget.remotecompose.core.RemoteContext; 25 import com.android.internal.widget.remotecompose.core.WireBuffer; 26 import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; 27 import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ModifierOperation; 28 import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; 29 import com.android.internal.widget.remotecompose.core.operations.utilities.easing.Easing; 30 import com.android.internal.widget.remotecompose.core.operations.utilities.easing.GeneralEasing; 31 import com.android.internal.widget.remotecompose.core.serialize.MapSerializer; 32 33 import java.util.List; 34 35 /** Basic component animation spec */ 36 public class AnimationSpec extends Operation implements ModifierOperation { 37 public static final AnimationSpec DEFAULT = new AnimationSpec(); 38 public static final AnimationSpec DISABLED = new AnimationSpec(0); 39 int mAnimationId = -1; 40 float mMotionDuration = 300; 41 int mMotionEasingType = GeneralEasing.CUBIC_STANDARD; 42 float mVisibilityDuration = 300; 43 int mVisibilityEasingType = GeneralEasing.CUBIC_STANDARD; 44 @NonNull ANIMATION mEnterAnimation = ANIMATION.FADE_IN; 45 @NonNull ANIMATION mExitAnimation = ANIMATION.FADE_OUT; 46 AnimationSpec( int animationId, float motionDuration, int motionEasingType, float visibilityDuration, int visibilityEasingType, @NonNull ANIMATION enterAnimation, @NonNull ANIMATION exitAnimation)47 public AnimationSpec( 48 int animationId, 49 float motionDuration, 50 int motionEasingType, 51 float visibilityDuration, 52 int visibilityEasingType, 53 @NonNull ANIMATION enterAnimation, 54 @NonNull ANIMATION exitAnimation) { 55 this.mAnimationId = animationId; 56 this.mMotionDuration = motionDuration; 57 this.mMotionEasingType = motionEasingType; 58 this.mVisibilityDuration = visibilityDuration; 59 this.mVisibilityEasingType = visibilityEasingType; 60 this.mEnterAnimation = enterAnimation; 61 this.mExitAnimation = exitAnimation; 62 } 63 AnimationSpec()64 public AnimationSpec() { 65 this( 66 -1, 67 600, 68 GeneralEasing.CUBIC_STANDARD, 69 500, 70 GeneralEasing.CUBIC_STANDARD, 71 ANIMATION.FADE_IN, 72 ANIMATION.FADE_OUT); 73 } 74 AnimationSpec(int value)75 public AnimationSpec(int value) { 76 this(); 77 mAnimationId = value; 78 } 79 isAnimationEnabled()80 public boolean isAnimationEnabled() { 81 return mAnimationId != 0; 82 } 83 getAnimationId()84 public int getAnimationId() { 85 return mAnimationId; 86 } 87 getMotionDuration()88 public float getMotionDuration() { 89 return mMotionDuration; 90 } 91 getMotionEasingType()92 public int getMotionEasingType() { 93 return mMotionEasingType; 94 } 95 getVisibilityDuration()96 public float getVisibilityDuration() { 97 return mVisibilityDuration; 98 } 99 getVisibilityEasingType()100 public int getVisibilityEasingType() { 101 return mVisibilityEasingType; 102 } 103 104 @NonNull getEnterAnimation()105 public ANIMATION getEnterAnimation() { 106 return mEnterAnimation; 107 } 108 109 @NonNull getExitAnimation()110 public ANIMATION getExitAnimation() { 111 return mExitAnimation; 112 } 113 114 @NonNull 115 @Override toString()116 public String toString() { 117 return "ANIMATION_SPEC (" + mMotionDuration + " ms)"; 118 } 119 120 @Override serializeToString(int indent, @NonNull StringSerializer serializer)121 public void serializeToString(int indent, @NonNull StringSerializer serializer) { 122 serializer.append( 123 indent, 124 "ANIMATION_SPEC = [" 125 + getMotionDuration() 126 + ", " 127 + getMotionEasingType() 128 + ", " 129 + getVisibilityDuration() 130 + ", " 131 + getVisibilityEasingType() 132 + ", " 133 + getEnterAnimation() 134 + ", " 135 + getExitAnimation() 136 + "]"); 137 } 138 139 @Override serialize(MapSerializer serializer)140 public void serialize(MapSerializer serializer) { 141 serializer 142 .addType("AnimationSpec") 143 .add("animationId", mAnimationId) 144 .add("motionDuration", getMotionDuration()) 145 .add("motionEasingType", Easing.getString(getMotionEasingType())) 146 .add("visibilityDuration", getVisibilityDuration()) 147 .add("visibilityEasingType", Easing.getString(getVisibilityEasingType())) 148 .add("enterAnimation", getEnterAnimation()) 149 .add("exitAnimation", getExitAnimation()); 150 } 151 152 public enum ANIMATION { 153 FADE_IN, 154 FADE_OUT, 155 SLIDE_LEFT, 156 SLIDE_RIGHT, 157 SLIDE_TOP, 158 SLIDE_BOTTOM, 159 ROTATE, 160 PARTICLE 161 } 162 163 @Override write(@onNull WireBuffer buffer)164 public void write(@NonNull WireBuffer buffer) { 165 apply( 166 buffer, 167 mAnimationId, 168 mMotionDuration, 169 mMotionEasingType, 170 mVisibilityDuration, 171 mVisibilityEasingType, 172 mEnterAnimation, 173 mExitAnimation); 174 } 175 176 @Override apply(@onNull RemoteContext context)177 public void apply(@NonNull RemoteContext context) { 178 // nothing here 179 } 180 181 @NonNull 182 @Override deepToString(@onNull String indent)183 public String deepToString(@NonNull String indent) { 184 return (indent != null ? indent : "") + toString(); 185 } 186 187 /** 188 * The name of the class 189 * 190 * @return the name 191 */ 192 @NonNull name()193 public static String name() { 194 return "AnimationSpec"; 195 } 196 197 /** 198 * The OP_CODE for this command 199 * 200 * @return the opcode 201 */ id()202 public static int id() { 203 return Operations.ANIMATION_SPEC; 204 } 205 206 /** 207 * Returns an int for the given ANIMATION 208 * 209 * @param animation an ANIMATION enum value 210 * @return a corresponding int value 211 */ animationToInt(@onNull ANIMATION animation)212 public static int animationToInt(@NonNull ANIMATION animation) { 213 return animation.ordinal(); 214 } 215 216 /** 217 * Maps int value to the corresponding ANIMATION enum values 218 * 219 * @param value int value mapped to the enum 220 * @return the corresponding ANIMATION enum value 221 */ 222 @NonNull intToAnimation(int value)223 public static ANIMATION intToAnimation(int value) { 224 switch (value) { 225 case 0: 226 return ANIMATION.FADE_IN; 227 case 1: 228 return ANIMATION.FADE_OUT; 229 case 2: 230 return ANIMATION.SLIDE_LEFT; 231 case 3: 232 return ANIMATION.SLIDE_RIGHT; 233 case 4: 234 return ANIMATION.SLIDE_TOP; 235 case 5: 236 return ANIMATION.SLIDE_BOTTOM; 237 case 6: 238 return ANIMATION.ROTATE; 239 case 7: 240 return ANIMATION.PARTICLE; 241 default: 242 return ANIMATION.FADE_IN; 243 } 244 } 245 246 /** 247 * Write the operation to the buffer 248 * 249 * @param buffer a WireBuffer 250 * @param animationId the animation id 251 * @param motionDuration the duration of the motion animation 252 * @param motionEasingType the type of easing for the motion animation 253 * @param visibilityDuration the duration of the visibility animation 254 * @param visibilityEasingType the type of easing for the visibility animation 255 * @param enterAnimation the type of animation when "entering" (newly visible) 256 * @param exitAnimation the type of animation when "exiting" (newly gone) 257 */ apply( @onNull WireBuffer buffer, int animationId, float motionDuration, int motionEasingType, float visibilityDuration, int visibilityEasingType, @NonNull ANIMATION enterAnimation, @NonNull ANIMATION exitAnimation)258 public static void apply( 259 @NonNull WireBuffer buffer, 260 int animationId, 261 float motionDuration, 262 int motionEasingType, 263 float visibilityDuration, 264 int visibilityEasingType, 265 @NonNull ANIMATION enterAnimation, 266 @NonNull ANIMATION exitAnimation) { 267 buffer.start(Operations.ANIMATION_SPEC); 268 buffer.writeInt(animationId); 269 buffer.writeFloat(motionDuration); 270 buffer.writeInt(motionEasingType); 271 buffer.writeFloat(visibilityDuration); 272 buffer.writeInt(visibilityEasingType); 273 buffer.writeInt(animationToInt(enterAnimation)); 274 buffer.writeInt(animationToInt(exitAnimation)); 275 } 276 277 /** 278 * Read this operation and add it to the list of operations 279 * 280 * @param buffer the buffer to read 281 * @param operations the list of operations that will be added to 282 */ read(@onNull WireBuffer buffer, @NonNull List<Operation> operations)283 public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) { 284 int animationId = buffer.readInt(); 285 float motionDuration = buffer.readFloat(); 286 int motionEasingType = buffer.readInt(); 287 float visibilityDuration = buffer.readFloat(); 288 int visibilityEasingType = buffer.readInt(); 289 ANIMATION enterAnimation = intToAnimation(buffer.readInt()); 290 ANIMATION exitAnimation = intToAnimation(buffer.readInt()); 291 AnimationSpec op = 292 new AnimationSpec( 293 animationId, 294 motionDuration, 295 motionEasingType, 296 visibilityDuration, 297 visibilityEasingType, 298 enterAnimation, 299 exitAnimation); 300 operations.add(op); 301 } 302 303 /** 304 * Populate the documentation with a description of this operation 305 * 306 * @param doc to append the description to. 307 */ documentation(@onNull DocumentationBuilder doc)308 public static void documentation(@NonNull DocumentationBuilder doc) { 309 doc.operation("Layout Operations", id(), name()) 310 .description("define the animation") 311 .field(INT, "animationId", "") 312 .field(INT, "motionDuration", "") 313 .field(INT, "motionEasingType", "") 314 .field(INT, "visibilityDuration", "") 315 .field(INT, "visibilityEasingType", ""); 316 } 317 } 318