@@ -77,7 +77,9 @@ public static void setSlowMotion(boolean aSlowMotion) {
77
77
private double initVelocity , friction ;
78
78
private int lastReturnedValue ;
79
79
private int [] previousLastReturnedValue = new int [3 ];
80
+ private long [] previousLastReturnedValueTime = new long [3 ];
80
81
private long currentMotionTime = -1 ;
82
+ private long previousCurrentMotionTime = -1 ;
81
83
private float p0 , p1 , p2 , p3 ;
82
84
83
85
/**
@@ -95,7 +97,8 @@ protected Motion(int sourceValue, int destinationValue, int duration) {
95
97
if (slowMotion ) {
96
98
this .duration *= 50 ;
97
99
}
98
- previousLastReturnedValue [0 ] = -1 ;
100
+ previousLastReturnedValue [0 ] = -1 ;
101
+ previousLastReturnedValueTime [0 ] = -1 ;
99
102
}
100
103
101
104
/**
@@ -105,6 +108,7 @@ public void finish() {
105
108
if (!isFinished ()) {
106
109
startTime = System .currentTimeMillis () - duration ;
107
110
currentMotionTime = -1 ;
111
+ previousCurrentMotionTime = -1 ;
108
112
}
109
113
}
110
114
@@ -120,15 +124,17 @@ protected Motion(int sourceValue, float initVelocity, float friction) {
120
124
this .initVelocity = initVelocity ;
121
125
this .friction = friction ;
122
126
duration = (int ) ((Math .abs (initVelocity )) / friction );
123
- previousLastReturnedValue [0 ] = -1 ;
127
+ previousLastReturnedValue [0 ] = -1 ;
128
+ previousLastReturnedValueTime [0 ] = -1 ;
124
129
}
125
130
126
131
protected Motion (int sourceValue , double initVelocity , double friction ) {
127
132
this .sourceValue = sourceValue ;
128
133
this .initVelocity = initVelocity ;
129
134
this .friction = friction ;
130
135
duration = (int ) ((Math .abs (initVelocity )) / friction );
131
- previousLastReturnedValue [0 ] = -1 ;
136
+ previousLastReturnedValue [0 ] = -1 ;
137
+ previousLastReturnedValueTime [0 ] = -1 ;
132
138
}
133
139
134
140
@@ -265,6 +271,24 @@ public static Motion createDecelerationMotion(int sourceValue, int destinationVa
265
271
deceleration .motionType = DECELERATION ;
266
272
return deceleration ;
267
273
}
274
+
275
+ /**
276
+ * Creates a deceleration motion starting from the current position of another motion.
277
+ *
278
+ * @param motion the number from which we are starting (usually indicating animation start position)
279
+ * @param maxDestinationValue The farthest position to allow motion to go.
280
+ * @param maxDuration The longest that the duration is allowed to proceed for.
281
+ * @return new motion object
282
+ */
283
+ public static Motion createDecelerationMotionFrom (Motion motion , int maxDestinationValue , int maxDuration ) {
284
+ return createDecelerationMotion (
285
+ motion .lastReturnedValue ,
286
+ motion .destinationValue < motion .sourceValue
287
+ ? Math .min (motion .destinationValue , maxDestinationValue )
288
+ : Math .max (motion .destinationValue , maxDestinationValue ),
289
+ (int )Math .min (maxDuration , motion .duration - (System .currentTimeMillis () - motion .startTime ))
290
+ );
291
+ }
268
292
269
293
/**
270
294
* Creates a friction motion starting from source with initial speed and the friction
@@ -319,6 +343,7 @@ public long getCurrentMotionTime() {
319
343
* @param currentMotionTime the time in milliseconds for the motion.
320
344
*/
321
345
public void setCurrentMotionTime (long currentMotionTime ) {
346
+ this .previousCurrentMotionTime = this .currentMotionTime ;
322
347
this .currentMotionTime = currentMotionTime ;
323
348
324
349
// workaround allowing the motion to be restarted when manually setting the current time
@@ -327,6 +352,10 @@ public void setCurrentMotionTime(long currentMotionTime) {
327
352
}
328
353
}
329
354
355
+ public boolean isDecayMotion () {
356
+ return motionType == EXPONENTIAL_DECAY ;
357
+ }
358
+
330
359
/**
331
360
* Sets the start time of the motion
332
361
*
@@ -414,69 +443,6 @@ private int getCubicValue() {
414
443
return current ;
415
444
}
416
445
417
- // private int[] values = new int[1000];
418
- // private int[] times = new int[1000];
419
- // private int vOff;
420
- //
421
- // /**
422
- // * Returns the value for the motion for the current clock time.
423
- // * The value is dependent on the Motion type.
424
- // *
425
- // * @return a value that is relative to the source value
426
- // */
427
- // public int getValue() {
428
- // int v = getValueImpl();
429
- // if(isFinished() && vOff > 0) {
430
- // System.out.println("initVelocity:\t"+initVelocity + "\tfriction:\t" + friction + "\tdestinationValue:\t" + destinationValue + "\tsourceValue:\t" + sourceValue);
431
- // System.out.println("Value\tTime");
432
- // for(int iter = 0 ; iter < vOff ; iter++) {
433
- // System.out.println("" + values[iter] + "\t" + times[iter]);
434
- // }
435
- // vOff = 0;
436
- // } else {
437
- // values[vOff] = v;
438
- // int time = (int) getCurrentMotionTime();
439
- // times[vOff] = time;
440
- //
441
- // vOff++;
442
- // }
443
- //
444
- // return v;
445
- // }
446
- //
447
- // /**
448
- // * Returns the value for the motion for the current clock time.
449
- // * The value is dependent on the Motion type.
450
- // *
451
- // * @return a value that is relative to the source value
452
- // */
453
- // private int getValueImpl() {
454
- // if(currentMotionTime > -1 && startTime > getCurrentMotionTime()) {
455
- // return sourceValue;
456
- // }
457
- // switch(motionType) {
458
- // case SPLINE:
459
- // lastReturnedValue = getSplineValue();
460
- // break;
461
- // case CUBIC:
462
- // lastReturnedValue = getCubicValue();
463
- // break;
464
- // case FRICTION:
465
- // lastReturnedValue = getFriction();
466
- // break;
467
- // case DECELERATION:
468
- // lastReturnedValue = getRubber();
469
- // break;
470
- // case COLOR_LINEAR:
471
- // lastReturnedValue = getColorLinear();
472
- // break;
473
- // default:
474
- // lastReturnedValue = getLinear();
475
- // break;
476
- // }
477
- // return lastReturnedValue;
478
- // }
479
-
480
446
/**
481
447
* Returns the value for the motion for the current clock time.
482
448
* The value is dependent on the Motion type.
@@ -489,8 +455,14 @@ public int getValue() {
489
455
}
490
456
491
457
previousLastReturnedValue [0 ] = previousLastReturnedValue [1 ];
458
+ previousLastReturnedValueTime [0 ] = previousLastReturnedValueTime [1 ];
492
459
previousLastReturnedValue [1 ] = previousLastReturnedValue [2 ];
460
+ previousLastReturnedValueTime [1 ] = previousLastReturnedValueTime [2 ];
493
461
previousLastReturnedValue [2 ] = lastReturnedValue ;
462
+ previousLastReturnedValueTime [2 ] = previousCurrentMotionTime ;
463
+ if (previousCurrentMotionTime < 0 ) {
464
+ previousCurrentMotionTime = getCurrentMotionTime ();
465
+ }
494
466
switch (motionType ) {
495
467
case SPLINE :
496
468
lastReturnedValue = getSplineValue ();
@@ -516,6 +488,55 @@ public int getValue() {
516
488
}
517
489
return lastReturnedValue ;
518
490
}
491
+
492
+ /**
493
+ * Gets an approximation of the current velocity in pixels per millisecond.
494
+ *
495
+ * <p>NOTE: If {@link #countAvailableVelocitySamplingPoints()} <= 1, then this method will always output {@literal 0}.
496
+ * Therefore the output of this method only has meaning if {@link #countAvailableVelocitySamplingPoints()} > {@literal 0}</p>
497
+ *
498
+ * @return Current velocity in pixels per millisecond.
499
+ * @since 8.0
500
+ */
501
+ public double getVelocity () {
502
+ final long localCurrentMotionTime = getCurrentMotionTime ();
503
+ final int lastReturnedValueLocal = lastReturnedValue ;
504
+ double velocity = 0 ;
505
+ boolean firstIteration = true ;
506
+ for (int i =2 ; i >= 0 ; i --) {
507
+ final long t = previousLastReturnedValueTime [i ];
508
+ if (t <= 0 || localCurrentMotionTime == t ) {
509
+ break ;
510
+ }
511
+ final int valueAtT = previousLastReturnedValue [i ];
512
+ final double spotVelocity = (lastReturnedValueLocal - valueAtT ) / (double )(localCurrentMotionTime - t );
513
+ velocity = firstIteration ? spotVelocity : (velocity + spotVelocity )/2.0 ;
514
+ firstIteration = false ;
515
+ }
516
+
517
+ return velocity ;
518
+ }
519
+
520
+ /**
521
+ * Gets the number of sampling points that can be used by {@link #getVelocity()}. A minimum of 2 sampling
522
+ * points are required for the result of {@link #getVelocity()} to have any meaning.
523
+ *
524
+ * @since 8.0
525
+ * @return The number of sampling points that can be used by {@link #getVelocity()}.
526
+ */
527
+ public int countAvailableVelocitySamplingPoints () {
528
+ int count = 1 ;
529
+ final long localCurrentMotionTime = getCurrentMotionTime ();
530
+ for (int i =2 ; i >= 0 ; i --) {
531
+ final long t = previousLastReturnedValueTime [i ];
532
+ if (t <= 0 || localCurrentMotionTime == t ) {
533
+ break ;
534
+ }
535
+ count ++;
536
+ }
537
+
538
+ return count ;
539
+ }
519
540
520
541
private int getLinear () {
521
542
//make sure we reach the destination value.
@@ -600,9 +621,6 @@ private int getFriction() {
600
621
}
601
622
602
623
private int getExponentialDecay () {
603
- //amplitude = initialVelocity * scaleFactor;
604
- //targetPosition = position + amplitude;
605
- //timestamp = Date.now();
606
624
double elapsed = getCurrentMotionTime ();
607
625
double timeConstant = friction ;
608
626
double amplitude = targetPosition - sourceValue ;
@@ -612,9 +630,7 @@ private int getExponentialDecay() {
612
630
} else {
613
631
return Math .max (position , destinationValue );
614
632
}
615
-
616
633
}
617
-
618
634
private int getRubber () {
619
635
if (isFinished ()){
620
636
return destinationValue ;
0 commit comments