| Flutter Impeller |

animation_player.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/scene/animation/animation_player.h"
6
7 #include <memory>
8 #include <unordered_map>
9
10 #include "flutter/fml/time/time_point.h"
11 #include "impeller/base/timing.h"
12 #include "impeller/scene/node.h"
13
14 namespace impeller {
15 namespace scene {
16
17 AnimationPlayer::AnimationPlayer() = default;
18 AnimationPlayer::~AnimationPlayer() = default;
19
20 AnimationPlayer::AnimationPlayer(AnimationPlayer&&) = default;
21 AnimationPlayer& AnimationPlayer::operator=(AnimationPlayer&&) = default;
22
23 AnimationClip* AnimationPlayer::AddAnimation(
24 const std::shared_ptr<Animation>& animation,
25 Node* bind_target) {
26 if (!animation) {
27 VALIDATION_LOG << "Cannot add null animation.";
28 return nullptr;
29 }
30
31 AnimationClip clip(animation, bind_target);
32
33 // Record all of the unique default transforms that this AnimationClip
34 // will mutate.
35 for (const auto& binding : clip.bindings_) {
36 auto decomp = binding.node->GetLocalTransform().Decompose();
37 if (!decomp.has_value()) {
38 continue;
39 }
40 target_transforms_.insert(
41 {binding.node, AnimationTransforms{.bind_pose = decomp.value()}});
42 }
43
44 auto result = clips_.insert({animation->GetName(), std::move(clip)});
45 return &result.first->second;
46 }
47
48 AnimationClip* AnimationPlayer::GetClip(const std::string& name) const {
49 auto result = clips_.find(name);
50 if (result == clips_.end()) {
51 return nullptr;
52 }
53 return const_cast<AnimationClip*>(&result->second);
54 }
55
56 void AnimationPlayer::Update() {
57 if (!previous_time_.has_value()) {
58 previous_time_ = Clock::now();
59 }
60 auto new_time = Clock::now();
61 auto delta_time = new_time - previous_time_.value();
62 previous_time_ = new_time;
63
64 // Reset the animated pose state.
65 for (auto& [node, transforms] : target_transforms_) {
66 transforms.animated_pose = transforms.bind_pose;
67 }
68
69 // Compute a weight multiplier for normalizing the animation.
70 Scalar total_weight = 0;
71 for (auto& [_, clip] : clips_) {
72 total_weight += clip.GetWeight();
73 }
74 Scalar weight_multiplier = total_weight > 1 ? 1 / total_weight : 1;
75
76 // Update and apply all clips to the animation pose state.
77 for (auto& [_, clip] : clips_) {
78 clip.Advance(delta_time);
79 clip.ApplyToBindings(target_transforms_, weight_multiplier);
80 }
81
82 // Apply the animated pose to the bound joints.
83 for (auto& [node, transforms] : target_transforms_) {
84 node->SetLocalTransform(Matrix(transforms.animated_pose));
85 }
86 }
87
88 } // namespace scene
89 } // namespace impeller
timing.h
impeller::scene::AnimationTransforms
Definition: animation_transforms.h:12
impeller::scene::AnimationPlayer::AddAnimation
AnimationClip * AddAnimation(const std::shared_ptr< Animation > &animation, Node *bind_target)
Definition: animation_player.cc:23
impeller::Scalar
float Scalar
Definition: scalar.h:15
impeller::scene::AnimationPlayer::Update
void Update()
Advanced all clips and updates animated properties in the scene.
Definition: animation_player.cc:56
impeller::scene::AnimationTransforms::bind_pose
MatrixDecomposition bind_pose
Definition: animation_transforms.h:13
impeller::scene::AnimationPlayer::~AnimationPlayer
~AnimationPlayer()
animation_player.h
impeller::scene::AnimationClip
Definition: animation_clip.h:21
node.h
impeller::scene::AnimationPlayer::AnimationPlayer
AnimationPlayer()
impeller::scene::AnimationPlayer::GetClip
AnimationClip * GetClip(const std::string &name) const
Definition: animation_player.cc:48
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::scene::Node
Definition: node.h:29
impeller::scene::AnimationPlayer::operator=
AnimationPlayer & operator=(AnimationPlayer &&)
impeller
Definition: aiks_context.cc:10
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:36