blob: 6a10cf8f48fc3455e2082bab077d3d804b74c9cd [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
20#include "RenderNode.h"
21
22namespace android {
23namespace uirenderer {
24
25using namespace std;
26
27static void unref(BaseRenderNodeAnimator* animator) {
28 animator->decStrong(0);
29}
30
31AnimatorManager::AnimatorManager(RenderNode& parent)
32 : mParent(parent) {
33}
34
35AnimatorManager::~AnimatorManager() {
36 for_each(mNewAnimators.begin(), mNewAnimators.end(), unref);
37 for_each(mAnimators.begin(), mAnimators.end(), unref);
38}
39
40void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
41 animator->incStrong(0);
42 animator->onAttached(&mParent);
43 mNewAnimators.push_back(animator.get());
44}
45
46template<typename T>
47static void move_all(T& source, T& dest) {
48 dest.reserve(source.size() + dest.size());
49 for (typename T::iterator it = source.begin(); it != source.end(); it++) {
50 dest.push_back(*it);
51 }
52 source.clear();
53}
54
55void AnimatorManager::pushStaging(TreeInfo& info) {
56 if (mNewAnimators.size()) {
57 // Since this is a straight move, we don't need to inc/dec the ref count
58 move_all(mNewAnimators, mAnimators);
59 }
60 for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
61 (*it)->pushStaging(&mParent, info);
62 }
63}
64
65class AnimateFunctor {
66public:
67 AnimateFunctor(RenderNode& target, TreeInfo& info)
68 : mTarget(target), mInfo(info) {}
69
70 bool operator() (BaseRenderNodeAnimator* animator) {
71 bool remove = animator->animate(&mTarget, mInfo);
72 if (remove) {
73 animator->decStrong(0);
74 }
75 return remove;
76 }
77private:
78 RenderNode& mTarget;
79 TreeInfo& mInfo;
80};
81
82void AnimatorManager::animate(TreeInfo& info) {
83 if (!mAnimators.size()) return;
84
85 // TODO: Can we target this better? For now treat it like any other staging
86 // property push and just damage self before and after animators are run
87
88 mParent.damageSelf(info);
89 info.damageAccumulator->popTransform();
90
91 AnimateFunctor functor(mParent, info);
92 std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
93 newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
94 mAnimators.erase(newEnd, mAnimators.end());
95
96 mParent.mProperties.updateMatrix();
97 info.damageAccumulator->pushTransform(&mParent);
98 mParent.damageSelf(info);
99}
100
101} /* namespace uirenderer */
102} /* namespace android */