Merge changes I9dc1de92,I254138ca into sc-dev
* changes: Slow down sparkles and make them more sparse Fix issue where ripple would move
This commit is contained in:
@@ -38,8 +38,7 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public final class RippleAnimationSession {
|
||||
private static final String TAG = "RippleAnimationSession";
|
||||
private static final int ENTER_ANIM_DURATION = 300;
|
||||
private static final int SLIDE_ANIM_DURATION = 450;
|
||||
private static final int ENTER_ANIM_DURATION = 450;
|
||||
private static final int EXIT_ANIM_DURATION = 300;
|
||||
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
|
||||
private static final TimeInterpolator PATH_INTERPOLATOR =
|
||||
@@ -50,26 +49,21 @@ public final class RippleAnimationSession {
|
||||
private Runnable mOnUpdate;
|
||||
private long mStartTime;
|
||||
private boolean mForceSoftware;
|
||||
private final float mWidth, mHeight;
|
||||
private final ValueAnimator mSparkle = ValueAnimator.ofFloat(0, 1);
|
||||
private final ArraySet<Animator> mActiveAnimations = new ArraySet<>(3);
|
||||
|
||||
RippleAnimationSession(@NonNull AnimationProperties<Float, Paint> properties,
|
||||
boolean forceSoftware, float width, float height) {
|
||||
boolean forceSoftware) {
|
||||
mProperties = properties;
|
||||
mForceSoftware = forceSoftware;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
mSparkle.addUpdateListener(anim -> {
|
||||
final long now = AnimationUtils.currentAnimationTimeMillis();
|
||||
final long elapsed = now - mStartTime - ENTER_ANIM_DURATION;
|
||||
final float phase = (float) elapsed / 1000f;
|
||||
mProperties.getShader().setSecondsOffset(phase);
|
||||
final float phase = (float) elapsed / 30000f;
|
||||
mProperties.getShader().setNoisePhase(phase);
|
||||
notifyUpdate();
|
||||
});
|
||||
mSparkle.setDuration(ENTER_ANIM_DURATION);
|
||||
mSparkle.setStartDelay(ENTER_ANIM_DURATION);
|
||||
mSparkle.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
mSparkle.setRepeatCount(ValueAnimator.INFINITE);
|
||||
}
|
||||
@@ -85,7 +79,6 @@ public final class RippleAnimationSession {
|
||||
}
|
||||
|
||||
@NonNull RippleAnimationSession exit(Canvas canvas) {
|
||||
mSparkle.end();
|
||||
if (isHwAccelerated(canvas)) exitHardware((RecordingCanvas) canvas);
|
||||
else exitSoftware();
|
||||
return this;
|
||||
@@ -93,7 +86,6 @@ public final class RippleAnimationSession {
|
||||
|
||||
private void onAnimationEnd(Animator anim) {
|
||||
notifyUpdate();
|
||||
mActiveAnimations.remove(anim);
|
||||
}
|
||||
|
||||
@NonNull RippleAnimationSession setOnSessionEnd(
|
||||
@@ -123,18 +115,18 @@ public final class RippleAnimationSession {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
mSparkle.end();
|
||||
Consumer<RippleAnimationSession> onEnd = mOnSessionEnd;
|
||||
if (onEnd != null) onEnd.accept(RippleAnimationSession.this);
|
||||
}
|
||||
});
|
||||
expand.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
expand.start();
|
||||
mActiveAnimations.add(expand);
|
||||
}
|
||||
|
||||
private long computeDelay() {
|
||||
final long timePassed = AnimationUtils.currentAnimationTimeMillis() - mStartTime;
|
||||
return Math.max((long) SLIDE_ANIM_DURATION - timePassed, 0);
|
||||
return Math.max((long) ENTER_ANIM_DURATION - timePassed, 0);
|
||||
}
|
||||
|
||||
private void notifyUpdate() {
|
||||
@@ -157,6 +149,7 @@ public final class RippleAnimationSession {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
mSparkle.end();
|
||||
Consumer<RippleAnimationSession> onEnd = mOnSessionEnd;
|
||||
if (onEnd != null) onEnd.accept(RippleAnimationSession.this);
|
||||
}
|
||||
@@ -167,7 +160,6 @@ public final class RippleAnimationSession {
|
||||
long delay = computeDelay();
|
||||
exit.setStartDelay(delay);
|
||||
exit.start();
|
||||
mActiveAnimations.add(exit);
|
||||
}
|
||||
|
||||
private void enterHardware(RecordingCanvas canvas) {
|
||||
@@ -175,54 +167,27 @@ public final class RippleAnimationSession {
|
||||
props = getCanvasProperties();
|
||||
RenderNodeAnimator expand =
|
||||
new RenderNodeAnimator(props.getProgress(), .5f);
|
||||
RenderNodeAnimator slideX =
|
||||
new RenderNodeAnimator(props.getX(), mWidth / 2);
|
||||
RenderNodeAnimator slideY =
|
||||
new RenderNodeAnimator(props.getY(), mHeight / 2);
|
||||
expand.setTarget(canvas);
|
||||
slideX.setTarget(canvas);
|
||||
slideY.setTarget(canvas);
|
||||
startAnimation(expand, slideX, slideY);
|
||||
startAnimation(expand);
|
||||
}
|
||||
|
||||
private void startAnimation(Animator expand,
|
||||
Animator slideX, Animator slideY) {
|
||||
expand.setDuration(SLIDE_ANIM_DURATION);
|
||||
slideX.setDuration(SLIDE_ANIM_DURATION);
|
||||
slideY.setDuration(SLIDE_ANIM_DURATION);
|
||||
slideX.addListener(new AnimatorListener(this));
|
||||
private void startAnimation(Animator expand) {
|
||||
expand.setDuration(ENTER_ANIM_DURATION);
|
||||
expand.addListener(new AnimatorListener(this));
|
||||
expand.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
slideX.setInterpolator(PATH_INTERPOLATOR);
|
||||
slideY.setInterpolator(PATH_INTERPOLATOR);
|
||||
expand.start();
|
||||
slideX.start();
|
||||
slideY.start();
|
||||
if (!mSparkle.isRunning()) {
|
||||
mSparkle.start();
|
||||
mActiveAnimations.add(mSparkle);
|
||||
}
|
||||
mActiveAnimations.add(expand);
|
||||
mActiveAnimations.add(slideX);
|
||||
mActiveAnimations.add(slideY);
|
||||
}
|
||||
|
||||
private void enterSoftware() {
|
||||
ValueAnimator expand = ValueAnimator.ofFloat(0f, 0.5f);
|
||||
ValueAnimator slideX = ValueAnimator.ofFloat(
|
||||
mProperties.getX(), mWidth / 2);
|
||||
ValueAnimator slideY = ValueAnimator.ofFloat(
|
||||
mProperties.getY(), mHeight / 2);
|
||||
expand.addUpdateListener(updatedAnimation -> {
|
||||
notifyUpdate();
|
||||
mProperties.getShader().setProgress((Float) expand.getAnimatedValue());
|
||||
});
|
||||
slideX.addUpdateListener(anim -> {
|
||||
float x = (float) slideX.getAnimatedValue();
|
||||
float y = (float) slideY.getAnimatedValue();
|
||||
mProperties.setOrigin(x, y);
|
||||
mProperties.getShader().setOrigin(x, y);
|
||||
});
|
||||
startAnimation(expand, slideX, slideY);
|
||||
startAnimation(expand);
|
||||
}
|
||||
|
||||
@NonNull AnimationProperties<Float, Paint> getProperties() {
|
||||
|
||||
@@ -842,7 +842,7 @@ public class RippleDrawable extends LayerDrawable {
|
||||
if (shouldAnimate && mRunningAnimations.size() <= MAX_RIPPLES) {
|
||||
RippleAnimationSession.AnimationProperties<Float, Paint> properties =
|
||||
createAnimationProperties(x, y, w, h);
|
||||
mRunningAnimations.add(new RippleAnimationSession(properties, !useCanvasProps, w, h)
|
||||
mRunningAnimations.add(new RippleAnimationSession(properties, !useCanvasProps)
|
||||
.setOnAnimationUpdated(() -> invalidateSelf(false))
|
||||
.setOnSessionEnd(session -> {
|
||||
mRunningAnimations.remove(session);
|
||||
@@ -912,14 +912,14 @@ public class RippleDrawable extends LayerDrawable {
|
||||
? mState.mColor.getColorForState(getState(), Color.BLACK)
|
||||
: mMaskColorFilter.getColor();
|
||||
shader.setColor(color);
|
||||
shader.setOrigin(x, y);
|
||||
shader.setOrigin(w / 2, y / 2);
|
||||
shader.setTouch(x, y);
|
||||
shader.setResolution(w, h);
|
||||
shader.setSecondsOffset(0);
|
||||
shader.setNoisePhase(0);
|
||||
shader.setRadius(radius);
|
||||
shader.setProgress(.0f);
|
||||
properties = new RippleAnimationSession.AnimationProperties<>(
|
||||
x, y, radius, p, 0f,
|
||||
shader);
|
||||
w / 2, h / 2, radius, p, 0f, shader);
|
||||
if (mMaskShader == null) {
|
||||
shader.setShader(null);
|
||||
} else {
|
||||
|
||||
@@ -23,11 +23,12 @@ import android.graphics.Shader;
|
||||
|
||||
final class RippleShader extends RuntimeShader {
|
||||
private static final String SHADER_UNIFORMS = "uniform vec2 in_origin;\n"
|
||||
+ "uniform vec2 in_touch;\n"
|
||||
+ "uniform float in_progress;\n"
|
||||
+ "uniform float in_maxRadius;\n"
|
||||
+ "uniform vec2 in_resolution;\n"
|
||||
+ "uniform float in_hasMask;\n"
|
||||
+ "uniform float in_secondsOffset;\n"
|
||||
+ "uniform float in_noisePhase;\n"
|
||||
+ "uniform vec4 in_color;\n"
|
||||
+ "uniform shader in_shader;\n";
|
||||
private static final String SHADER_LIB =
|
||||
@@ -48,7 +49,7 @@ final class RippleShader extends RuntimeShader {
|
||||
+ " float s = 0.0;\n"
|
||||
+ " for (float i = 0; i < 4; i += 1) {\n"
|
||||
+ " float l = i * 0.25;\n"
|
||||
+ " float h = l + 0.025;\n"
|
||||
+ " float h = l + 0.005;\n"
|
||||
+ " float o = abs(sin(0.1 * PI * (t + i)));\n"
|
||||
+ " s += threshold(n + o, l, h);\n"
|
||||
+ " }\n"
|
||||
@@ -79,12 +80,12 @@ final class RippleShader extends RuntimeShader {
|
||||
+ " float fadeIn = subProgress(0., 0.175, in_progress);\n"
|
||||
+ " float fadeOutNoise = subProgress(0.375, 1., in_progress);\n"
|
||||
+ " float fadeOutRipple = subProgress(0.375, 0.75, in_progress);\n"
|
||||
+ " float ring = getRingMask(p, in_origin, in_maxRadius, fadeIn);\n"
|
||||
+ " vec2 center = mix(in_touch, in_origin, fadeIn);\n"
|
||||
+ " float ring = getRingMask(p, center, in_maxRadius, fadeIn);\n"
|
||||
+ " float alpha = min(fadeIn, 1. - fadeOutNoise);\n"
|
||||
+ " float sparkle = sparkles(p, in_progress * 0.25 + in_secondsOffset)\n"
|
||||
+ " * ring * alpha;\n"
|
||||
+ " float fade = min(fadeIn, 1.-fadeOutRipple);\n"
|
||||
+ " vec4 circle = in_color * (softCircle(p, in_origin, in_maxRadius "
|
||||
+ " float sparkle = sparkles(p, in_noisePhase) * ring * alpha;\n"
|
||||
+ " float fade = min(fadeIn, 1. - fadeOutRipple);\n"
|
||||
+ " vec4 circle = in_color * (softCircle(p, center, in_maxRadius "
|
||||
+ " * fadeIn, 0.2) * fade);\n"
|
||||
+ " float mask = in_hasMask == 1. ? sample(in_shader).a > 0. ? 1. : 0. : 1.;\n"
|
||||
+ " return mix(circle, vec4(sparkle), sparkle) * mask;\n"
|
||||
@@ -109,14 +110,18 @@ final class RippleShader extends RuntimeShader {
|
||||
/**
|
||||
* Continuous offset used as noise phase.
|
||||
*/
|
||||
public void setSecondsOffset(float t) {
|
||||
setUniform("in_secondsOffset", t);
|
||||
public void setNoisePhase(float t) {
|
||||
setUniform("in_noisePhase", t);
|
||||
}
|
||||
|
||||
public void setOrigin(float x, float y) {
|
||||
setUniform("in_origin", new float[] {x, y});
|
||||
}
|
||||
|
||||
public void setTouch(float x, float y) {
|
||||
setUniform("in_touch", new float[] {x, y});
|
||||
}
|
||||
|
||||
public void setProgress(float progress) {
|
||||
setUniform("in_progress", progress);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user