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.KeyCycleOscillator; 20 import androidx.constraintlayout.core.motion.utils.Oscillator; 21 import androidx.constraintlayout.core.motion.utils.SplineSet; 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 MotionKeyCycle extends MotionKey { 29 private static final String TAG = "KeyCycle"; 30 static final String NAME = "KeyCycle"; 31 public static final String WAVE_PERIOD = "wavePeriod"; 32 public static final String WAVE_OFFSET = "waveOffset"; 33 public static final String WAVE_PHASE = "wavePhase"; 34 public static final String WAVE_SHAPE = "waveShape"; 35 public static final int SHAPE_SIN_WAVE = Oscillator.SIN_WAVE; 36 public static final int SHAPE_SQUARE_WAVE = Oscillator.SQUARE_WAVE; 37 public static final int SHAPE_TRIANGLE_WAVE = Oscillator.TRIANGLE_WAVE; 38 public static final int SHAPE_SAW_WAVE = Oscillator.SAW_WAVE; 39 public static final int SHAPE_REVERSE_SAW_WAVE = Oscillator.REVERSE_SAW_WAVE; 40 public static final int SHAPE_COS_WAVE = Oscillator.COS_WAVE; 41 public static final int SHAPE_BOUNCE = Oscillator.BOUNCE; 42 43 @SuppressWarnings("unused") private String mTransitionEasing = null; 44 @SuppressWarnings("unused") private int mCurveFit = 0; 45 private int mWaveShape = -1; 46 private String mCustomWaveShape = null; 47 private float mWavePeriod = Float.NaN; 48 private float mWaveOffset = 0; 49 private float mWavePhase = 0; 50 private float mProgress = Float.NaN; 51 private float mAlpha = Float.NaN; 52 private float mElevation = Float.NaN; 53 private float mRotation = Float.NaN; 54 private float mTransitionPathRotate = Float.NaN; 55 private float mRotationX = Float.NaN; 56 private float mRotationY = Float.NaN; 57 private float mScaleX = Float.NaN; 58 private float mScaleY = Float.NaN; 59 private float mTranslationX = Float.NaN; 60 private float mTranslationY = Float.NaN; 61 private float mTranslationZ = Float.NaN; 62 public static final int KEY_TYPE = 4; 63 64 { 65 mType = KEY_TYPE; 66 mCustom = new HashMap<>(); 67 } 68 69 @Override getAttributeNames(HashSet<String> attributes)70 public void getAttributeNames(HashSet<String> attributes) { 71 if (!Float.isNaN(mAlpha)) { 72 attributes.add(CycleType.S_ALPHA); 73 } 74 if (!Float.isNaN(mElevation)) { 75 attributes.add(CycleType.S_ELEVATION); 76 } 77 if (!Float.isNaN(mRotation)) { 78 attributes.add(CycleType.S_ROTATION_Z); 79 } 80 if (!Float.isNaN(mRotationX)) { 81 attributes.add(CycleType.S_ROTATION_X); 82 } 83 if (!Float.isNaN(mRotationY)) { 84 attributes.add(CycleType.S_ROTATION_Y); 85 } 86 if (!Float.isNaN(mScaleX)) { 87 attributes.add(CycleType.S_SCALE_X); 88 } 89 if (!Float.isNaN(mScaleY)) { 90 attributes.add(CycleType.S_SCALE_Y); 91 } 92 if (!Float.isNaN(mTransitionPathRotate)) { 93 attributes.add(CycleType.S_PATH_ROTATE); 94 } 95 if (!Float.isNaN(mTranslationX)) { 96 attributes.add(CycleType.S_TRANSLATION_X); 97 } 98 if (!Float.isNaN(mTranslationY)) { 99 attributes.add(CycleType.S_TRANSLATION_Y); 100 } 101 if (!Float.isNaN(mTranslationZ)) { 102 attributes.add(CycleType.S_TRANSLATION_Z); 103 } 104 if (mCustom.size() > 0) { 105 for (String s : mCustom.keySet()) { 106 attributes.add(TypedValues.S_CUSTOM + "," + s); 107 } 108 } 109 } 110 111 @Override addValues(HashMap<String, SplineSet> splines)112 public void addValues(HashMap<String, SplineSet> splines) { 113 114 } 115 116 // @TODO: add description 117 @Override setValue(int type, int value)118 public boolean setValue(int type, int value) { 119 switch (type) { 120 case CycleType.TYPE_CURVE_FIT: 121 mCurveFit = value; 122 return true; 123 case CycleType.TYPE_WAVE_SHAPE: 124 mWaveShape = value; 125 return true; 126 default: 127 boolean ret = setValue(type, (float) value); 128 if (ret) { 129 return true; 130 } 131 return super.setValue(type, value); 132 } 133 } 134 135 // @TODO: add description 136 @Override setValue(int type, String value)137 public boolean setValue(int type, String value) { 138 switch (type) { 139 case CycleType.TYPE_EASING: 140 mTransitionEasing = value; 141 return true; 142 case CycleType.TYPE_CUSTOM_WAVE_SHAPE: 143 mCustomWaveShape = value; 144 return true; 145 default: 146 return super.setValue(type, value); 147 } 148 149 } 150 151 // @TODO: add description 152 @Override setValue(int type, float value)153 public boolean setValue(int type, float value) { 154 switch (type) { 155 case CycleType.TYPE_ALPHA: 156 mAlpha = value; 157 break; 158 case CycleType.TYPE_TRANSLATION_X: 159 mTranslationX = value; 160 break; 161 case CycleType.TYPE_TRANSLATION_Y: 162 mTranslationY = value; 163 break; 164 case CycleType.TYPE_TRANSLATION_Z: 165 mTranslationZ = value; 166 break; 167 case CycleType.TYPE_ELEVATION: 168 mElevation = value; 169 break; 170 case CycleType.TYPE_ROTATION_X: 171 mRotationX = value; 172 break; 173 case CycleType.TYPE_ROTATION_Y: 174 mRotationY = value; 175 break; 176 case CycleType.TYPE_ROTATION_Z: 177 mRotation = value; 178 break; 179 case CycleType.TYPE_SCALE_X: 180 mScaleX = value; 181 break; 182 case CycleType.TYPE_SCALE_Y: 183 mScaleY = value; 184 break; 185 case CycleType.TYPE_PROGRESS: 186 mProgress = value; 187 break; 188 case CycleType.TYPE_PATH_ROTATE: 189 mTransitionPathRotate = value; 190 break; 191 case CycleType.TYPE_WAVE_PERIOD: 192 mWavePeriod = value; 193 break; 194 case CycleType.TYPE_WAVE_OFFSET: 195 mWaveOffset = value; 196 break; 197 case CycleType.TYPE_WAVE_PHASE: 198 mWavePhase = value; 199 break; 200 default: 201 return super.setValue(type, value); 202 } 203 return true; 204 } 205 206 // @TODO: add description getValue(String key)207 public float getValue(String key) { 208 switch (key) { 209 case CycleType.S_ALPHA: 210 return mAlpha; 211 case CycleType.S_ELEVATION: 212 return mElevation; 213 case CycleType.S_ROTATION_Z: 214 return mRotation; 215 case CycleType.S_ROTATION_X: 216 return mRotationX; 217 case CycleType.S_ROTATION_Y: 218 return mRotationY; 219 case CycleType.S_PATH_ROTATE: 220 return mTransitionPathRotate; 221 case CycleType.S_SCALE_X: 222 return mScaleX; 223 case CycleType.S_SCALE_Y: 224 return mScaleY; 225 case CycleType.S_TRANSLATION_X: 226 return mTranslationX; 227 case CycleType.S_TRANSLATION_Y: 228 return mTranslationY; 229 case CycleType.S_TRANSLATION_Z: 230 return mTranslationZ; 231 case CycleType.S_WAVE_OFFSET: 232 return mWaveOffset; 233 case CycleType.S_WAVE_PHASE: 234 return mWavePhase; 235 case CycleType.S_PROGRESS: 236 return mProgress; 237 default: 238 return Float.NaN; 239 } 240 } 241 242 @Override clone()243 public MotionKey clone() { 244 return null; 245 } 246 247 @Override getId(String name)248 public int getId(String name) { 249 switch (name) { 250 case CycleType.S_CURVE_FIT: 251 return CycleType.TYPE_CURVE_FIT; 252 case CycleType.S_VISIBILITY: 253 return CycleType.TYPE_VISIBILITY; 254 case CycleType.S_ALPHA: 255 return CycleType.TYPE_ALPHA; 256 case CycleType.S_TRANSLATION_X: 257 return CycleType.TYPE_TRANSLATION_X; 258 case CycleType.S_TRANSLATION_Y: 259 return CycleType.TYPE_TRANSLATION_Y; 260 case CycleType.S_TRANSLATION_Z: 261 return CycleType.TYPE_TRANSLATION_Z; 262 case CycleType.S_ROTATION_X: 263 return CycleType.TYPE_ROTATION_X; 264 case CycleType.S_ROTATION_Y: 265 return CycleType.TYPE_ROTATION_Y; 266 case CycleType.S_ROTATION_Z: 267 return CycleType.TYPE_ROTATION_Z; 268 case CycleType.S_SCALE_X: 269 return CycleType.TYPE_SCALE_X; 270 case CycleType.S_SCALE_Y: 271 return CycleType.TYPE_SCALE_Y; 272 case CycleType.S_PIVOT_X: 273 return CycleType.TYPE_PIVOT_X; 274 case CycleType.S_PIVOT_Y: 275 return CycleType.TYPE_PIVOT_Y; 276 case CycleType.S_PROGRESS: 277 return CycleType.TYPE_PROGRESS; 278 case CycleType.S_PATH_ROTATE: 279 return CycleType.TYPE_PATH_ROTATE; 280 case CycleType.S_EASING: 281 return CycleType.TYPE_EASING; 282 case CycleType.S_WAVE_PERIOD: 283 return CycleType.TYPE_WAVE_PERIOD; 284 case CycleType.S_WAVE_SHAPE: 285 return CycleType.TYPE_WAVE_SHAPE; 286 case CycleType.S_WAVE_PHASE: 287 return CycleType.TYPE_WAVE_PHASE; 288 case CycleType.S_WAVE_OFFSET: 289 return CycleType.TYPE_WAVE_OFFSET; 290 case CycleType.S_CUSTOM_WAVE_SHAPE: 291 return CycleType.TYPE_CUSTOM_WAVE_SHAPE; 292 293 } 294 return -1; 295 } 296 297 // @TODO: add description addCycleValues(HashMap<String, KeyCycleOscillator> oscSet)298 public void addCycleValues(HashMap<String, KeyCycleOscillator> oscSet) { 299 300 for (String key : oscSet.keySet()) { 301 if (key.startsWith(TypedValues.S_CUSTOM)) { 302 String customKey = key.substring(TypedValues.S_CUSTOM.length() + 1); 303 CustomVariable cValue = mCustom.get(customKey); 304 if (cValue == null || cValue.getType() != Custom.TYPE_FLOAT) { 305 continue; 306 } 307 308 KeyCycleOscillator osc = oscSet.get(key); 309 if (osc == null) { 310 continue; 311 } 312 313 osc.setPoint(mFramePosition, mWaveShape, mCustomWaveShape, -1, mWavePeriod, 314 mWaveOffset, mWavePhase / 360, cValue.getValueToInterpolate(), cValue); 315 continue; 316 } 317 float value = getValue(key); 318 if (Float.isNaN(value)) { 319 continue; 320 } 321 322 KeyCycleOscillator osc = oscSet.get(key); 323 if (osc == null) { 324 continue; 325 } 326 327 osc.setPoint(mFramePosition, mWaveShape, mCustomWaveShape, 328 -1, mWavePeriod, mWaveOffset, mWavePhase / 360, value); 329 } 330 } 331 332 333 // @TODO: add description dump()334 public void dump() { 335 System.out.println("MotionKeyCycle{" 336 + "mWaveShape=" + mWaveShape 337 + ", mWavePeriod=" + mWavePeriod 338 + ", mWaveOffset=" + mWaveOffset 339 + ", mWavePhase=" + mWavePhase 340 + ", mRotation=" + mRotation 341 + '}'); 342 } 343 344 // @TODO: add description printAttributes()345 public void printAttributes() { 346 HashSet<String> nameSet = new HashSet<>(); 347 getAttributeNames(nameSet); 348 349 Utils.log(" ------------- " + mFramePosition + " -------------"); 350 Utils.log("MotionKeyCycle{" 351 + "Shape=" + mWaveShape 352 + ", Period=" + mWavePeriod 353 + ", Offset=" + mWaveOffset 354 + ", Phase=" + mWavePhase 355 + '}'); 356 String[] names = nameSet.toArray(new String[0]); 357 for (int i = 0; i < names.length; i++) { 358 Utils.log(names[i] + ":" + getValue(names[i])); 359 } 360 } 361 362 363 } 364