1 /* 2 * Copyright (C) 2021 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 androidx.constraintlayout.core.motion.key; 17 18 import androidx.constraintlayout.core.motion.CustomVariable; 19 import androidx.constraintlayout.core.motion.utils.Oscillator; 20 import androidx.constraintlayout.core.motion.utils.SplineSet; 21 import androidx.constraintlayout.core.motion.utils.TimeCycleSplineSet; 22 import androidx.constraintlayout.core.motion.utils.TypedValues; 23 import androidx.constraintlayout.core.motion.utils.Utils; 24 25 import java.util.HashMap; 26 import java.util.HashSet; 27 28 public class MotionKeyTimeCycle extends MotionKey { 29 static final String NAME = "KeyTimeCycle"; 30 private static final String TAG = NAME; 31 32 private String mTransitionEasing; 33 private int mCurveFit = -1; 34 private float mAlpha = Float.NaN; 35 private float mElevation = Float.NaN; 36 private float mRotation = Float.NaN; 37 private float mRotationX = Float.NaN; 38 private float mRotationY = Float.NaN; 39 private float mTransitionPathRotate = Float.NaN; 40 private float mScaleX = Float.NaN; 41 private float mScaleY = Float.NaN; 42 private float mTranslationX = Float.NaN; 43 private float mTranslationY = Float.NaN; 44 private float mTranslationZ = Float.NaN; 45 private float mProgress = Float.NaN; 46 private int mWaveShape = 0; 47 48 // TODO add support of custom wave shapes in KeyTimeCycle 49 @SuppressWarnings("unused") private String mCustomWaveShape = null; 50 private float mWavePeriod = Float.NaN; 51 private float mWaveOffset = 0; 52 public static final int KEY_TYPE = 3; 53 54 { 55 mType = KEY_TYPE; 56 mCustom = new HashMap<>(); 57 } 58 59 // @TODO: add description addTimeValues(HashMap<String, TimeCycleSplineSet> splines)60 public void addTimeValues(HashMap<String, TimeCycleSplineSet> splines) { 61 for (String s : splines.keySet()) { 62 TimeCycleSplineSet splineSet = splines.get(s); 63 if (splineSet == null) { 64 continue; 65 } 66 if (s.startsWith(CUSTOM)) { 67 String cKey = s.substring(CUSTOM.length() + 1); 68 CustomVariable cValue = mCustom.get(cKey); 69 if (cValue != null) { 70 ((TimeCycleSplineSet.CustomVarSet) splineSet) 71 .setPoint(mFramePosition, cValue, mWavePeriod, mWaveShape, mWaveOffset); 72 } 73 continue; 74 } 75 switch (s) { 76 case AttributesType.S_ALPHA: 77 if (!Float.isNaN(mAlpha)) { 78 splineSet.setPoint(mFramePosition, 79 mAlpha, mWavePeriod, mWaveShape, mWaveOffset); 80 } 81 break; 82 83 case AttributesType.S_ROTATION_X: 84 if (!Float.isNaN(mRotationX)) { 85 splineSet.setPoint(mFramePosition, 86 mRotationX, mWavePeriod, mWaveShape, mWaveOffset); 87 } 88 break; 89 case AttributesType.S_ROTATION_Y: 90 if (!Float.isNaN(mRotationY)) { 91 splineSet.setPoint(mFramePosition, 92 mRotationY, mWavePeriod, mWaveShape, mWaveOffset); 93 } 94 break; 95 case AttributesType.S_ROTATION_Z: 96 if (!Float.isNaN(mRotation)) { 97 splineSet.setPoint(mFramePosition, 98 mRotation, mWavePeriod, mWaveShape, mWaveOffset); 99 } 100 break; 101 case AttributesType.S_PATH_ROTATE: 102 if (!Float.isNaN(mTransitionPathRotate)) { 103 splineSet.setPoint(mFramePosition, 104 mTransitionPathRotate, mWavePeriod, mWaveShape, mWaveOffset); 105 } 106 break; 107 108 case AttributesType.S_SCALE_X: 109 if (!Float.isNaN(mScaleX)) { 110 splineSet.setPoint(mFramePosition, 111 mScaleX, mWavePeriod, mWaveShape, mWaveOffset); 112 } 113 break; 114 case AttributesType.S_SCALE_Y: 115 if (!Float.isNaN(mScaleY)) { 116 splineSet.setPoint(mFramePosition, 117 mScaleY, mWavePeriod, mWaveShape, mWaveOffset); 118 } 119 break; 120 case AttributesType.S_TRANSLATION_X: 121 if (!Float.isNaN(mTranslationX)) { 122 splineSet.setPoint(mFramePosition, 123 mTranslationX, mWavePeriod, mWaveShape, mWaveOffset); 124 } 125 break; 126 case AttributesType.S_TRANSLATION_Y: 127 if (!Float.isNaN(mTranslationY)) { 128 splineSet.setPoint(mFramePosition, 129 mTranslationY, mWavePeriod, mWaveShape, mWaveOffset); 130 } 131 break; 132 case AttributesType.S_TRANSLATION_Z: 133 if (!Float.isNaN(mTranslationZ)) { 134 splineSet.setPoint(mFramePosition, 135 mTranslationZ, mWavePeriod, mWaveShape, mWaveOffset); 136 } 137 break; 138 case AttributesType.S_ELEVATION: 139 if (!Float.isNaN(mTranslationZ)) { 140 splineSet.setPoint(mFramePosition, 141 mTranslationZ, mWavePeriod, mWaveShape, mWaveOffset); 142 } 143 break; 144 case AttributesType.S_PROGRESS: 145 if (!Float.isNaN(mProgress)) { 146 splineSet.setPoint(mFramePosition, 147 mProgress, mWavePeriod, mWaveShape, mWaveOffset); 148 } 149 break; 150 default: 151 Utils.loge("KeyTimeCycles", "UNKNOWN addValues \"" + s + "\""); 152 } 153 } 154 } 155 156 @Override addValues(HashMap<String, SplineSet> splines)157 public void addValues(HashMap<String, SplineSet> splines) { 158 } 159 160 // @TODO: add description 161 @Override setValue(int type, int value)162 public boolean setValue(int type, int value) { 163 164 switch (type) { 165 case TypedValues.TYPE_FRAME_POSITION: 166 mFramePosition = value; 167 break; 168 case CycleType.TYPE_WAVE_SHAPE: 169 mWaveShape = value; 170 break; 171 default: 172 return super.setValue(type, value); 173 } 174 return true; 175 } 176 177 // @TODO: add description 178 @Override setValue(int type, float value)179 public boolean setValue(int type, float value) { 180 switch (type) { 181 case CycleType.TYPE_ALPHA: 182 mAlpha = value; 183 break; 184 case CycleType.TYPE_CURVE_FIT: 185 mCurveFit = toInt(value); 186 break; 187 case CycleType.TYPE_ELEVATION: 188 mElevation = toFloat(value); 189 break; 190 case CycleType.TYPE_PROGRESS: 191 mProgress = toFloat(value); 192 break; 193 case CycleType.TYPE_ROTATION_Z: 194 mRotation = toFloat(value); 195 break; 196 case CycleType.TYPE_ROTATION_X: 197 mRotationX = toFloat(value); 198 break; 199 case CycleType.TYPE_ROTATION_Y: 200 mRotationY = toFloat(value); 201 break; 202 case CycleType.TYPE_SCALE_X: 203 mScaleX = toFloat(value); 204 break; 205 case CycleType.TYPE_SCALE_Y: 206 mScaleY = toFloat(value); 207 break; 208 case CycleType.TYPE_PATH_ROTATE: 209 mTransitionPathRotate = toFloat(value); 210 break; 211 case CycleType.TYPE_TRANSLATION_X: 212 mTranslationX = toFloat(value); 213 break; 214 case CycleType.TYPE_TRANSLATION_Y: 215 mTranslationY = toFloat(value); 216 break; 217 case CycleType.TYPE_TRANSLATION_Z: 218 mTranslationZ = toFloat(value); 219 break; 220 case CycleType.TYPE_WAVE_PERIOD: 221 mWavePeriod = toFloat(value); 222 break; 223 case CycleType.TYPE_WAVE_OFFSET: 224 mWaveOffset = toFloat(value); 225 break; 226 default: 227 return super.setValue(type, value); 228 } 229 return true; 230 } 231 232 // @TODO: add description 233 @Override setValue(int type, String value)234 public boolean setValue(int type, String value) { 235 switch (type) { 236 case CycleType.TYPE_WAVE_SHAPE: 237 mWaveShape = Oscillator.CUSTOM; 238 mCustomWaveShape = value; 239 break; 240 case CycleType.TYPE_EASING: 241 mTransitionEasing = value; 242 break; 243 default: 244 return super.setValue(type, value); 245 } 246 return true; 247 } 248 249 // @TODO: add description 250 @Override setValue(int type, boolean value)251 public boolean setValue(int type, boolean value) { 252 return super.setValue(type, value); 253 } 254 255 // @TODO: add description 256 @Override copy(MotionKey src)257 public MotionKeyTimeCycle copy(MotionKey src) { 258 super.copy(src); 259 MotionKeyTimeCycle k = (MotionKeyTimeCycle) src; 260 mTransitionEasing = k.mTransitionEasing; 261 mCurveFit = k.mCurveFit; 262 mWaveShape = k.mWaveShape; 263 mWavePeriod = k.mWavePeriod; 264 mWaveOffset = k.mWaveOffset; 265 mProgress = k.mProgress; 266 mAlpha = k.mAlpha; 267 mElevation = k.mElevation; 268 mRotation = k.mRotation; 269 mTransitionPathRotate = k.mTransitionPathRotate; 270 mRotationX = k.mRotationX; 271 mRotationY = k.mRotationY; 272 mScaleX = k.mScaleX; 273 mScaleY = k.mScaleY; 274 mTranslationX = k.mTranslationX; 275 mTranslationY = k.mTranslationY; 276 mTranslationZ = k.mTranslationZ; 277 return this; 278 } 279 280 @Override getAttributeNames(HashSet<String> attributes)281 public void getAttributeNames(HashSet<String> attributes) { 282 if (!Float.isNaN(mAlpha)) { 283 attributes.add(CycleType.S_ALPHA); 284 } 285 if (!Float.isNaN(mElevation)) { 286 attributes.add(CycleType.S_ELEVATION); 287 } 288 if (!Float.isNaN(mRotation)) { 289 attributes.add(CycleType.S_ROTATION_Z); 290 } 291 if (!Float.isNaN(mRotationX)) { 292 attributes.add(CycleType.S_ROTATION_X); 293 } 294 if (!Float.isNaN(mRotationY)) { 295 attributes.add(CycleType.S_ROTATION_Y); 296 } 297 if (!Float.isNaN(mScaleX)) { 298 attributes.add(CycleType.S_SCALE_X); 299 } 300 if (!Float.isNaN(mScaleY)) { 301 attributes.add(CycleType.S_SCALE_Y); 302 } 303 if (!Float.isNaN(mTransitionPathRotate)) { 304 attributes.add(CycleType.S_PATH_ROTATE); 305 } 306 if (!Float.isNaN(mTranslationX)) { 307 attributes.add(CycleType.S_TRANSLATION_X); 308 } 309 if (!Float.isNaN(mTranslationY)) { 310 attributes.add(CycleType.S_TRANSLATION_Y); 311 } 312 if (!Float.isNaN(mTranslationZ)) { 313 attributes.add(CycleType.S_TRANSLATION_Z); 314 } 315 if (mCustom.size() > 0) { 316 for (String s : mCustom.keySet()) { 317 attributes.add(TypedValues.S_CUSTOM + "," + s); 318 } 319 } 320 } 321 322 // @TODO: add description 323 @Override clone()324 public MotionKey clone() { 325 return new MotionKeyTimeCycle().copy(this); 326 } 327 328 @Override getId(String name)329 public int getId(String name) { 330 return CycleType.getId(name); 331 } 332 } 333