blob: 3832d426150a2bc28d65d09ba854fecf532896c6 [file] [log] [blame]
John Reck68bfe0a2014-06-24 15:34:58 -07001/*
2 * Copyright (C) 2014 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#include "AnimatorManager.h"
17
18#include <algorithm>
19
John Reck119907c2014-08-14 09:02:01 -070020#include "AnimationContext.h"
John Reck68bfe0a2014-06-24 15:34:58 -070021#include "RenderNode.h"
22
23namespace android {
24namespace uirenderer {
25
26using namespace std;
27
28static void unref(BaseRenderNodeAnimator* animator) {
John Reck8d8af3c2014-07-01 15:23:45 -070029 animator->detach();
John Reck68bfe0a2014-06-24 15:34:58 -070030 animator->decStrong(0);
31}
32
33AnimatorManager::AnimatorManager(RenderNode& parent)
John Reck119907c2014-08-14 09:02:01 -070034 : mParent(parent)
35 , mAnimationHandle(NULL) {
John Reck68bfe0a2014-06-24 15:34:58 -070036}
37
38AnimatorManager::~AnimatorManager() {
39 for_each(mNewAnimators.begin(), mNewAnimators.end(), unref);
40 for_each(mAnimators.begin(), mAnimators.end(), unref);
41}
42
43void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
44 animator->incStrong(0);
John Reck8d8af3c2014-07-01 15:23:45 -070045 animator->attach(&mParent);
John Reck68bfe0a2014-06-24 15:34:58 -070046 mNewAnimators.push_back(animator.get());
47}
48
John Reck119907c2014-08-14 09:02:01 -070049void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
50 LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
51 mAnimationHandle = handle;
52}
53
John Reck68bfe0a2014-06-24 15:34:58 -070054template<typename T>
55static void move_all(T& source, T& dest) {
56 dest.reserve(source.size() + dest.size());
57 for (typename T::iterator it = source.begin(); it != source.end(); it++) {
58 dest.push_back(*it);
59 }
60 source.clear();
61}
62
John Reck119907c2014-08-14 09:02:01 -070063void AnimatorManager::pushStaging() {
John Reck68bfe0a2014-06-24 15:34:58 -070064 if (mNewAnimators.size()) {
65 // Since this is a straight move, we don't need to inc/dec the ref count
66 move_all(mNewAnimators, mAnimators);
67 }
68 for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
John Reck119907c2014-08-14 09:02:01 -070069 (*it)->pushStaging(mAnimationHandle->context());
John Reck68bfe0a2014-06-24 15:34:58 -070070 }
71}
72
73class AnimateFunctor {
74public:
John Reck119907c2014-08-14 09:02:01 -070075 AnimateFunctor(TreeInfo& info, AnimationContext& context)
76 : dirtyMask(0), mInfo(info), mContext(context) {}
John Reck68bfe0a2014-06-24 15:34:58 -070077
78 bool operator() (BaseRenderNodeAnimator* animator) {
John Recka7c2ea22014-08-08 13:21:00 -070079 dirtyMask |= animator->dirtyMask();
John Reck119907c2014-08-14 09:02:01 -070080 bool remove = animator->animate(mContext);
John Reck68bfe0a2014-06-24 15:34:58 -070081 if (remove) {
82 animator->decStrong(0);
John Reck119907c2014-08-14 09:02:01 -070083 } else {
84 if (animator->isRunning()) {
85 mInfo.out.hasAnimations = true;
86 }
John Reck68bfe0a2014-06-24 15:34:58 -070087 }
88 return remove;
89 }
John Recka7c2ea22014-08-08 13:21:00 -070090
91 uint32_t dirtyMask;
92
John Reck68bfe0a2014-06-24 15:34:58 -070093private:
John Reck68bfe0a2014-06-24 15:34:58 -070094 TreeInfo& mInfo;
John Reck119907c2014-08-14 09:02:01 -070095 AnimationContext& mContext;
John Reck68bfe0a2014-06-24 15:34:58 -070096};
97
John Recka7c2ea22014-08-08 13:21:00 -070098uint32_t AnimatorManager::animate(TreeInfo& info) {
99 if (!mAnimators.size()) return 0;
John Reck68bfe0a2014-06-24 15:34:58 -0700100
101 // TODO: Can we target this better? For now treat it like any other staging
102 // property push and just damage self before and after animators are run
103
104 mParent.damageSelf(info);
105 info.damageAccumulator->popTransform();
106
John Reck119907c2014-08-14 09:02:01 -0700107 uint32_t dirty = animateCommon(info);
John Reck68bfe0a2014-06-24 15:34:58 -0700108
109 mParent.mProperties.updateMatrix();
110 info.damageAccumulator->pushTransform(&mParent);
111 mParent.damageSelf(info);
John Recka7c2ea22014-08-08 13:21:00 -0700112
John Reck119907c2014-08-14 09:02:01 -0700113 return dirty;
114}
115
116void AnimatorManager::animateNoDamage(TreeInfo& info) {
117 if (!mAnimators.size()) return;
118
119 animateCommon(info);
120}
121
122uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
123 AnimateFunctor functor(info, mAnimationHandle->context());
124 std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
125 newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
126 mAnimators.erase(newEnd, mAnimators.end());
127 mAnimationHandle->notifyAnimationsRan();
John Recka7c2ea22014-08-08 13:21:00 -0700128 return functor.dirtyMask;
John Reck68bfe0a2014-06-24 15:34:58 -0700129}
130
John Reck119907c2014-08-14 09:02:01 -0700131class EndAnimatorsFunctor {
132public:
133 EndAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
134
135 void operator() (BaseRenderNodeAnimator* animator) {
136 animator->end();
137 animator->pushStaging(mContext);
138 animator->animate(mContext);
139 animator->decStrong(0);
140 }
141
142private:
143 AnimationContext& mContext;
144};
145
146static void endAnimatorsHard(BaseRenderNodeAnimator* animator) {
147 animator->end();
148 if (animator->listener()) {
149 animator->listener()->onAnimationFinished(animator);
150 }
151 animator->decStrong(0);
152}
153
154void AnimatorManager::endAllAnimators() {
155 if (mNewAnimators.size()) {
156 // Since this is a straight move, we don't need to inc/dec the ref count
157 move_all(mNewAnimators, mAnimators);
158 }
159 // First try gracefully ending them
160 if (mAnimationHandle) {
161 EndAnimatorsFunctor functor(mAnimationHandle->context());
162 for_each(mAnimators.begin(), mAnimators.end(), functor);
163 } else {
164 // We have no context, so bust out the sledgehammer
165 // This works because this state can only happen on the UI thread,
166 // which means we're already on the right thread to invoke listeners
167 for_each(mAnimators.begin(), mAnimators.end(), endAnimatorsHard);
168 }
169 mAnimators.clear();
170}
171
John Reck68bfe0a2014-06-24 15:34:58 -0700172} /* namespace uirenderer */
173} /* namespace android */