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.SplineSet; 20 import androidx.constraintlayout.core.motion.utils.TypedValues; 21 22 import java.util.HashMap; 23 import java.util.HashSet; 24 25 public class MotionKeyAttributes extends MotionKey { 26 static final String NAME = "KeyAttribute"; 27 private static final String TAG = "KeyAttributes"; 28 @SuppressWarnings("unused") private static final boolean DEBUG = false; 29 @SuppressWarnings("unused") private String mTransitionEasing; 30 private int mCurveFit = -1; 31 @SuppressWarnings("unused") private int mVisibility = 0; 32 private float mAlpha = Float.NaN; 33 private float mElevation = Float.NaN; 34 private float mRotation = Float.NaN; 35 private float mRotationX = Float.NaN; 36 private float mRotationY = Float.NaN; 37 private float mPivotX = Float.NaN; 38 private float mPivotY = 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 47 public static final int KEY_TYPE = 1; 48 49 { 50 mType = KEY_TYPE; 51 mCustom = new HashMap<>(); 52 } 53 54 @Override getAttributeNames(HashSet<String> attributes)55 public void getAttributeNames(HashSet<String> attributes) { 56 57 if (!Float.isNaN(mAlpha)) { 58 attributes.add(AttributesType.S_ALPHA); 59 } 60 if (!Float.isNaN(mElevation)) { 61 attributes.add(AttributesType.S_ELEVATION); 62 } 63 if (!Float.isNaN(mRotation)) { 64 attributes.add(AttributesType.S_ROTATION_Z); 65 } 66 if (!Float.isNaN(mRotationX)) { 67 attributes.add(AttributesType.S_ROTATION_X); 68 } 69 if (!Float.isNaN(mRotationY)) { 70 attributes.add(AttributesType.S_ROTATION_Y); 71 } 72 if (!Float.isNaN(mPivotX)) { 73 attributes.add(AttributesType.S_PIVOT_X); 74 } 75 if (!Float.isNaN(mPivotY)) { 76 attributes.add(AttributesType.S_PIVOT_Y); 77 } 78 if (!Float.isNaN(mTranslationX)) { 79 attributes.add(AttributesType.S_TRANSLATION_X); 80 } 81 if (!Float.isNaN(mTranslationY)) { 82 attributes.add(AttributesType.S_TRANSLATION_Y); 83 } 84 if (!Float.isNaN(mTranslationZ)) { 85 attributes.add(AttributesType.S_TRANSLATION_Z); 86 } 87 if (!Float.isNaN(mTransitionPathRotate)) { 88 attributes.add(AttributesType.S_PATH_ROTATE); 89 } 90 if (!Float.isNaN(mScaleX)) { 91 attributes.add(AttributesType.S_SCALE_X); 92 } 93 if (!Float.isNaN(mScaleY)) { 94 attributes.add(AttributesType.S_SCALE_Y); 95 } 96 if (!Float.isNaN(mProgress)) { 97 attributes.add(AttributesType.S_PROGRESS); 98 } 99 if (mCustom.size() > 0) { 100 for (String s : mCustom.keySet()) { 101 attributes.add(TypedValues.S_CUSTOM + "," + s); 102 } 103 } 104 } 105 106 @Override addValues(HashMap<String, SplineSet> splines)107 public void addValues(HashMap<String, SplineSet> splines) { 108 for (String s : splines.keySet()) { 109 SplineSet splineSet = splines.get(s); 110 if (splineSet == null) { 111 continue; 112 } 113 // TODO support custom 114 if (s.startsWith(AttributesType.S_CUSTOM)) { 115 String cKey = s.substring(AttributesType.S_CUSTOM.length() + 1); 116 CustomVariable cValue = mCustom.get(cKey); 117 if (cValue != null) { 118 ((SplineSet.CustomSpline) splineSet).setPoint(mFramePosition, cValue); 119 } 120 continue; 121 } 122 switch (s) { 123 case AttributesType.S_ALPHA: 124 if (!Float.isNaN(mAlpha)) { 125 splineSet.setPoint(mFramePosition, mAlpha); 126 } 127 break; 128 case AttributesType.S_ELEVATION: 129 if (!Float.isNaN(mElevation)) { 130 splineSet.setPoint(mFramePosition, mElevation); 131 } 132 break; 133 case AttributesType.S_ROTATION_Z: 134 if (!Float.isNaN(mRotation)) { 135 splineSet.setPoint(mFramePosition, mRotation); 136 } 137 break; 138 case AttributesType.S_ROTATION_X: 139 if (!Float.isNaN(mRotationX)) { 140 splineSet.setPoint(mFramePosition, mRotationX); 141 } 142 break; 143 case AttributesType.S_ROTATION_Y: 144 if (!Float.isNaN(mRotationY)) { 145 splineSet.setPoint(mFramePosition, mRotationY); 146 } 147 break; 148 case AttributesType.S_PIVOT_X: 149 if (!Float.isNaN(mRotationX)) { 150 splineSet.setPoint(mFramePosition, mPivotX); 151 } 152 break; 153 case AttributesType.S_PIVOT_Y: 154 if (!Float.isNaN(mRotationY)) { 155 splineSet.setPoint(mFramePosition, mPivotY); 156 } 157 break; 158 case AttributesType.S_PATH_ROTATE: 159 if (!Float.isNaN(mTransitionPathRotate)) { 160 splineSet.setPoint(mFramePosition, mTransitionPathRotate); 161 } 162 break; 163 case AttributesType.S_SCALE_X: 164 if (!Float.isNaN(mScaleX)) { 165 splineSet.setPoint(mFramePosition, mScaleX); 166 } 167 break; 168 case AttributesType.S_SCALE_Y: 169 if (!Float.isNaN(mScaleY)) { 170 splineSet.setPoint(mFramePosition, mScaleY); 171 } 172 break; 173 case AttributesType.S_TRANSLATION_X: 174 if (!Float.isNaN(mTranslationX)) { 175 splineSet.setPoint(mFramePosition, mTranslationX); 176 } 177 break; 178 case AttributesType.S_TRANSLATION_Y: 179 if (!Float.isNaN(mTranslationY)) { 180 splineSet.setPoint(mFramePosition, mTranslationY); 181 } 182 break; 183 case AttributesType.S_TRANSLATION_Z: 184 if (!Float.isNaN(mTranslationZ)) { 185 splineSet.setPoint(mFramePosition, mTranslationZ); 186 } 187 break; 188 case AttributesType.S_PROGRESS: 189 if (!Float.isNaN(mProgress)) { 190 splineSet.setPoint(mFramePosition, mProgress); 191 } 192 break; 193 default: 194 System.err.println("not supported by KeyAttributes " + s); 195 } 196 } 197 } 198 199 @Override clone()200 public MotionKey clone() { 201 return null; 202 } 203 204 // @TODO: add description 205 @Override setValue(int type, int value)206 public boolean setValue(int type, int value) { 207 208 switch (type) { 209 case AttributesType.TYPE_VISIBILITY: 210 mVisibility = value; 211 break; 212 case AttributesType.TYPE_CURVE_FIT: 213 mCurveFit = value; 214 break; 215 case TypedValues.TYPE_FRAME_POSITION: 216 mFramePosition = value; 217 break; 218 default: 219 if (!setValue(type, value)) { 220 return super.setValue(type, value); 221 } 222 } 223 return true; 224 } 225 226 // @TODO: add description 227 @Override setValue(int type, float value)228 public boolean setValue(int type, float value) { 229 switch (type) { 230 case AttributesType.TYPE_ALPHA: 231 mAlpha = value; 232 break; 233 case AttributesType.TYPE_TRANSLATION_X: 234 mTranslationX = value; 235 break; 236 case AttributesType.TYPE_TRANSLATION_Y: 237 mTranslationY = value; 238 break; 239 case AttributesType.TYPE_TRANSLATION_Z: 240 mTranslationZ = value; 241 break; 242 case AttributesType.TYPE_ELEVATION: 243 mElevation = value; 244 break; 245 case AttributesType.TYPE_ROTATION_X: 246 mRotationX = value; 247 break; 248 case AttributesType.TYPE_ROTATION_Y: 249 mRotationY = value; 250 break; 251 case AttributesType.TYPE_ROTATION_Z: 252 mRotation = value; 253 break; 254 case AttributesType.TYPE_SCALE_X: 255 mScaleX = value; 256 break; 257 case AttributesType.TYPE_SCALE_Y: 258 mScaleY = value; 259 break; 260 case AttributesType.TYPE_PIVOT_X: 261 mPivotX = value; 262 break; 263 case AttributesType.TYPE_PIVOT_Y: 264 mPivotY = value; 265 break; 266 case AttributesType.TYPE_PROGRESS: 267 mProgress = value; 268 break; 269 case AttributesType.TYPE_PATH_ROTATE: 270 mTransitionPathRotate = value; 271 break; 272 case TypedValues.TYPE_FRAME_POSITION: 273 mTransitionPathRotate = value; 274 break; 275 default: 276 return super.setValue(type, value); 277 } 278 return true; 279 } 280 281 // @TODO: add description 282 @Override setInterpolation(HashMap<String, Integer> interpolation)283 public void setInterpolation(HashMap<String, Integer> interpolation) { 284 if (!Float.isNaN(mAlpha)) { 285 interpolation.put(AttributesType.S_ALPHA, mCurveFit); 286 } 287 if (!Float.isNaN(mElevation)) { 288 interpolation.put(AttributesType.S_ELEVATION, mCurveFit); 289 } 290 if (!Float.isNaN(mRotation)) { 291 interpolation.put(AttributesType.S_ROTATION_Z, mCurveFit); 292 } 293 if (!Float.isNaN(mRotationX)) { 294 interpolation.put(AttributesType.S_ROTATION_X, mCurveFit); 295 } 296 if (!Float.isNaN(mRotationY)) { 297 interpolation.put(AttributesType.S_ROTATION_Y, mCurveFit); 298 } 299 if (!Float.isNaN(mPivotX)) { 300 interpolation.put(AttributesType.S_PIVOT_X, mCurveFit); 301 } 302 if (!Float.isNaN(mPivotY)) { 303 interpolation.put(AttributesType.S_PIVOT_Y, mCurveFit); 304 } 305 if (!Float.isNaN(mTranslationX)) { 306 interpolation.put(AttributesType.S_TRANSLATION_X, mCurveFit); 307 } 308 if (!Float.isNaN(mTranslationY)) { 309 interpolation.put(AttributesType.S_TRANSLATION_Y, mCurveFit); 310 } 311 if (!Float.isNaN(mTranslationZ)) { 312 interpolation.put(AttributesType.S_TRANSLATION_Z, mCurveFit); 313 } 314 if (!Float.isNaN(mTransitionPathRotate)) { 315 interpolation.put(AttributesType.S_PATH_ROTATE, mCurveFit); 316 } 317 if (!Float.isNaN(mScaleX)) { 318 interpolation.put(AttributesType.S_SCALE_X, mCurveFit); 319 } 320 if (!Float.isNaN(mScaleY)) { 321 interpolation.put(AttributesType.S_SCALE_Y, mCurveFit); 322 } 323 if (!Float.isNaN(mProgress)) { 324 interpolation.put(AttributesType.S_PROGRESS, mCurveFit); 325 } 326 if (mCustom.size() > 0) { 327 for (String s : mCustom.keySet()) { 328 interpolation.put(AttributesType.S_CUSTOM + "," + s, mCurveFit); 329 } 330 } 331 } 332 333 // @TODO: add description 334 @Override setValue(int type, String value)335 public boolean setValue(int type, String value) { 336 switch (type) { 337 case AttributesType.TYPE_EASING: 338 mTransitionEasing = value; 339 break; 340 341 case TypedValues.TYPE_TARGET: 342 mTargetString = value; 343 break; 344 default: 345 return super.setValue(type, value); 346 } 347 return true; 348 } 349 350 @Override getId(String name)351 public int getId(String name) { 352 return AttributesType.getId(name); 353 } 354 getCurveFit()355 public int getCurveFit() { 356 return mCurveFit; 357 } 358 359 // @TODO: add description printAttributes()360 public void printAttributes() { 361 HashSet<String> nameSet = new HashSet<>(); 362 getAttributeNames(nameSet); 363 364 System.out.println(" ------------- " + mFramePosition + " -------------"); 365 String[] names = nameSet.toArray(new String[0]); 366 for (int i = 0; i < names.length; i++) { 367 int id = AttributesType.getId(names[i]); 368 System.out.println(names[i] + ":" + getFloatValue(id)); 369 } 370 } 371 getFloatValue(int id)372 private float getFloatValue(int id) { 373 switch (id) { 374 case AttributesType.TYPE_ALPHA: 375 return mAlpha; 376 case AttributesType.TYPE_TRANSLATION_X: 377 return mTranslationX; 378 case AttributesType.TYPE_TRANSLATION_Y: 379 return mTranslationY; 380 case AttributesType.TYPE_TRANSLATION_Z: 381 return mTranslationZ; 382 case AttributesType.TYPE_ELEVATION: 383 return mElevation; 384 case AttributesType.TYPE_ROTATION_X: 385 return mRotationX; 386 case AttributesType.TYPE_ROTATION_Y: 387 return mRotationY; 388 case AttributesType.TYPE_ROTATION_Z: 389 return mRotation; 390 case AttributesType.TYPE_SCALE_X: 391 return mScaleX; 392 case AttributesType.TYPE_SCALE_Y: 393 return mScaleY; 394 case AttributesType.TYPE_PIVOT_X: 395 return mPivotX; 396 case AttributesType.TYPE_PIVOT_Y: 397 return mPivotY; 398 case AttributesType.TYPE_PROGRESS: 399 return mProgress; 400 case AttributesType.TYPE_PATH_ROTATE: 401 return mTransitionPathRotate; 402 case TypedValues.TYPE_FRAME_POSITION: 403 return mFramePosition; 404 default: 405 return Float.NaN; 406 } 407 } 408 } 409