summaryrefslogtreecommitdiffstats
path: root/cc/animation/animation_timeline.cc
blob: 42591d01dcca4501a00bb809587887a8fb13b3c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/animation/animation_timeline.h"

#include <algorithm>

#include "cc/animation/animation_player.h"

namespace cc {

scoped_refptr<AnimationTimeline> AnimationTimeline::Create(int id) {
  return make_scoped_refptr(new AnimationTimeline(id));
}

AnimationTimeline::AnimationTimeline(int id)
    : id_(id), animation_host_(), is_impl_only_(false) {
}

AnimationTimeline::~AnimationTimeline() {
  for (auto& kv : id_to_player_map_)
    kv.second->SetAnimationTimeline(nullptr);
}

scoped_refptr<AnimationTimeline> AnimationTimeline::CreateImplInstance() const {
  scoped_refptr<AnimationTimeline> timeline = AnimationTimeline::Create(id());
  return timeline;
}

void AnimationTimeline::SetAnimationHost(AnimationHost* animation_host) {
  animation_host_ = animation_host;
  for (auto& kv : id_to_player_map_)
    kv.second->SetAnimationHost(animation_host);
}

void AnimationTimeline::AttachPlayer(scoped_refptr<AnimationPlayer> player) {
  DCHECK(player->id());
  player->SetAnimationHost(animation_host_);
  player->SetAnimationTimeline(this);
  id_to_player_map_.insert(std::make_pair(player->id(), std::move(player)));
}

void AnimationTimeline::DetachPlayer(scoped_refptr<AnimationPlayer> player) {
  DCHECK(player->id());
  ErasePlayer(player);
  id_to_player_map_.erase(player->id());
}

AnimationPlayer* AnimationTimeline::GetPlayerById(int player_id) const {
  auto f = id_to_player_map_.find(player_id);
  return f == id_to_player_map_.end() ? nullptr : f->second.get();
}

void AnimationTimeline::ClearPlayers() {
  for (auto& kv : id_to_player_map_)
    ErasePlayer(kv.second);
  id_to_player_map_.clear();
}

void AnimationTimeline::PushPropertiesTo(AnimationTimeline* timeline_impl) {
  PushAttachedPlayersToImplThread(timeline_impl);
  RemoveDetachedPlayersFromImplThread(timeline_impl);
  PushPropertiesToImplThread(timeline_impl);
}

void AnimationTimeline::PushAttachedPlayersToImplThread(
    AnimationTimeline* timeline_impl) const {
  for (auto& kv : id_to_player_map_) {
    auto& player = kv.second;
    AnimationPlayer* player_impl = timeline_impl->GetPlayerById(player->id());
    if (player_impl)
      continue;

    scoped_refptr<AnimationPlayer> to_add = player->CreateImplInstance();
    timeline_impl->AttachPlayer(to_add.get());
  }
}

void AnimationTimeline::RemoveDetachedPlayersFromImplThread(
    AnimationTimeline* timeline_impl) const {
  IdToPlayerMap& players_impl = timeline_impl->id_to_player_map_;

  // Erase all the impl players which |this| doesn't have.
  for (auto it = players_impl.begin(); it != players_impl.end();) {
    if (GetPlayerById(it->second->id())) {
      ++it;
    } else {
      timeline_impl->ErasePlayer(it->second);
      it = players_impl.erase(it);
    }
  }
}

void AnimationTimeline::ErasePlayer(scoped_refptr<AnimationPlayer> player) {
  if (player->element_animations())
    player->DetachLayer();
  player->SetAnimationTimeline(nullptr);
  player->SetAnimationHost(nullptr);
}

void AnimationTimeline::PushPropertiesToImplThread(
    AnimationTimeline* timeline_impl) {
  for (auto& kv : id_to_player_map_) {
    AnimationPlayer* player = kv.second.get();
    AnimationPlayer* player_impl = timeline_impl->GetPlayerById(player->id());
    if (player_impl)
      player->PushPropertiesTo(player_impl);
  }
}

}  // namespace cc