1987ee64612e2510004fdf08536746c87234d01c1Paul Rohde/* 2987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * Copyright (C) 2014 The Android Open Source Project 3987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * 4987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * Licensed under the Apache License, Version 2.0 (the "License"); 5987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * you may not use this file except in compliance with the License. 6987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * You may obtain a copy of the License at 7987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * 8987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * http://www.apache.org/licenses/LICENSE-2.0 9987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * 10987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * Unless required by applicable law or agreed to in writing, software 11987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * distributed under the License is distributed on an "AS IS" BASIS, 12987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * See the License for the specific language governing permissions and 14987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * limitations under the License. 15987ee64612e2510004fdf08536746c87234d01c1Paul Rohde */ 16987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 17987ee64612e2510004fdf08536746c87234d01c1Paul Rohdepackage com.android.camera.ui.motion; 18987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 19987ee64612e2510004fdf08536746c87234d01c1Paul Rohdeimport android.graphics.Canvas; 20987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 21987ee64612e2510004fdf08536746c87234d01c1Paul Rohdeimport java.util.ArrayList; 22987ee64612e2510004fdf08536746c87234d01c1Paul Rohdeimport java.util.List; 23987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 24987ee64612e2510004fdf08536746c87234d01c1Paul Rohde/** 25987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * Designed to handle the lifecycle of a view that needs a continuous update / 26987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * redraw cycle that does not have a defined start / end time. 27987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * 28987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * Fixed length animations should NOT use this class. 29987ee64612e2510004fdf08536746c87234d01c1Paul Rohde */ 30987ee64612e2510004fdf08536746c87234d01c1Paul Rohdepublic class DynamicAnimator implements Invalidator { 31987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 32987ee64612e2510004fdf08536746c87234d01c1Paul Rohde public final List<DynamicAnimation> animations = new ArrayList<>(); 33987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 34987ee64612e2510004fdf08536746c87234d01c1Paul Rohde private final Invalidator mInvalidator; 35987ee64612e2510004fdf08536746c87234d01c1Paul Rohde private final AnimationClock mClock; 36987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 37987ee64612e2510004fdf08536746c87234d01c1Paul Rohde private boolean mUpdateRequested = false; 38987ee64612e2510004fdf08536746c87234d01c1Paul Rohde private boolean mIsDrawing = false; 39987ee64612e2510004fdf08536746c87234d01c1Paul Rohde private long mLastDrawTimeMillis = 0; 40987ee64612e2510004fdf08536746c87234d01c1Paul Rohde private long mDrawTimeMillis = 0; 41987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 42987ee64612e2510004fdf08536746c87234d01c1Paul Rohde public DynamicAnimator(Invalidator invalidator, AnimationClock clock) { 43987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mInvalidator = invalidator; 44987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mClock = clock; 45987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 46987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 47987ee64612e2510004fdf08536746c87234d01c1Paul Rohde public void draw(Canvas canvas) { 48987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mIsDrawing = true; 49987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mUpdateRequested = false; 50987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 51987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mDrawTimeMillis = mClock.getTimeMillis(); 52987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 53987ee64612e2510004fdf08536746c87234d01c1Paul Rohde if (mLastDrawTimeMillis <= 0) { 54987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mLastDrawTimeMillis = mDrawTimeMillis; // On the initial draw, dt is zero. 55987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 56987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 57987ee64612e2510004fdf08536746c87234d01c1Paul Rohde long dt = mDrawTimeMillis - mLastDrawTimeMillis; 58987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mLastDrawTimeMillis = mDrawTimeMillis; 59987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 60987ee64612e2510004fdf08536746c87234d01c1Paul Rohde // Run the animation 61987ee64612e2510004fdf08536746c87234d01c1Paul Rohde for (DynamicAnimation renderer : animations) { 62987ee64612e2510004fdf08536746c87234d01c1Paul Rohde if (renderer.isActive()) { 63987ee64612e2510004fdf08536746c87234d01c1Paul Rohde renderer.draw(mDrawTimeMillis, dt, canvas); 64987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 65987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 66987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 67987ee64612e2510004fdf08536746c87234d01c1Paul Rohde // If either the update or the draw methods requested new frames, then 68987ee64612e2510004fdf08536746c87234d01c1Paul Rohde // invalidate the view which should give us another frame to work with. 69987ee64612e2510004fdf08536746c87234d01c1Paul Rohde // Otherwise, stopAt the last update time. 70987ee64612e2510004fdf08536746c87234d01c1Paul Rohde if (mUpdateRequested) { 71987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mInvalidator.invalidate(); 72987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } else { 73987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mLastDrawTimeMillis = -1; 74987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 75987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 76987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mIsDrawing = false; 77987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 78987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 79987ee64612e2510004fdf08536746c87234d01c1Paul Rohde /** 80987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * If a scheduleNewFrame request comes in outside of the animation loop, 81987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * and we didn't schedule a frame after the previous loop (or it's the 82987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * first time we've used this instance), invalidate the view and set the 83987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * last update time to the current time. Theoretically, a few milliseconds 84987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * have elapsed before the view gets updated. 85987ee64612e2510004fdf08536746c87234d01c1Paul Rohde */ 86987ee64612e2510004fdf08536746c87234d01c1Paul Rohde @Override 87987ee64612e2510004fdf08536746c87234d01c1Paul Rohde public void invalidate() { 88987ee64612e2510004fdf08536746c87234d01c1Paul Rohde if (!mIsDrawing && !mUpdateRequested) { 89987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mInvalidator.invalidate(); 90987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mLastDrawTimeMillis = mClock.getTimeMillis(); 91987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 92987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 93987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mUpdateRequested = true; 94987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 95987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 96987ee64612e2510004fdf08536746c87234d01c1Paul Rohde /** 97987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * This will return the "best guess" for the most current animation frame 98987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * time. If the loop is currently drawing, then it will return the time the 99987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * draw began, and if an update is currently requested it will return the 100987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * time that the update was requested at, and if neither of these are true 101987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * it will return the current system clock time. 102987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * 103987ee64612e2510004fdf08536746c87234d01c1Paul Rohde * This method will not trigger a new update. 104987ee64612e2510004fdf08536746c87234d01c1Paul Rohde */ 105987ee64612e2510004fdf08536746c87234d01c1Paul Rohde public long getTimeMillis() { 106987ee64612e2510004fdf08536746c87234d01c1Paul Rohde if (mIsDrawing) { 107987ee64612e2510004fdf08536746c87234d01c1Paul Rohde return mDrawTimeMillis; 108987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 109987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 110987ee64612e2510004fdf08536746c87234d01c1Paul Rohde if (mUpdateRequested) { 111987ee64612e2510004fdf08536746c87234d01c1Paul Rohde return mLastDrawTimeMillis; 112987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 113987ee64612e2510004fdf08536746c87234d01c1Paul Rohde 114987ee64612e2510004fdf08536746c87234d01c1Paul Rohde return mClock.getTimeMillis(); 115987ee64612e2510004fdf08536746c87234d01c1Paul Rohde } 116987ee64612e2510004fdf08536746c87234d01c1Paul Rohde} 117