Skip to content

Commit

Permalink
[Impeller Scene] Use std::chrono for animation durations (flutter#38606)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdero authored Jan 3, 2023
1 parent c0b3f8f commit 2213b80
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 43 deletions.
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,7 @@ ORIGIN: ../../../flutter/impeller/base/thread.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/base/thread.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/base/thread_safety.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/base/thread_safety.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/base/timing.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/base/validation.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/base/validation.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/base/version.cc + ../../../flutter/LICENSE
Expand Down Expand Up @@ -3614,6 +3615,7 @@ FILE: ../../../flutter/impeller/base/thread.cc
FILE: ../../../flutter/impeller/base/thread.h
FILE: ../../../flutter/impeller/base/thread_safety.cc
FILE: ../../../flutter/impeller/base/thread_safety.h
FILE: ../../../flutter/impeller/base/timing.h
FILE: ../../../flutter/impeller/base/validation.cc
FILE: ../../../flutter/impeller/base/validation.h
FILE: ../../../flutter/impeller/base/version.cc
Expand Down
1 change: 1 addition & 0 deletions impeller/base/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ impeller_component("base") {
"thread.h",
"thread_safety.cc",
"thread_safety.h",
"timing.h",
"validation.cc",
"validation.h",
"version.cc",
Expand Down
15 changes: 15 additions & 0 deletions impeller/base/timing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include <chrono>

namespace impeller {

using SecondsF = std::chrono::duration<float>;
using Clock = std::chrono::high_resolution_clock;
using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;

} // namespace impeller
2 changes: 1 addition & 1 deletion impeller/scene/animation/animation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const std::vector<Animation::Channel>& Animation::GetChannels() const {
return channels_;
}

Scalar Animation::GetEndTime() const {
SecondsF Animation::GetEndTime() const {
return end_time_;
}

Expand Down
5 changes: 3 additions & 2 deletions impeller/scene/animation/animation.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "flutter/fml/hash_combine.h"
#include "flutter/fml/macros.h"
#include "impeller/base/timing.h"
#include "impeller/geometry/quaternion.h"
#include "impeller/geometry/scalar.h"
#include "impeller/geometry/vector.h"
Expand Down Expand Up @@ -60,14 +61,14 @@ class Animation final {

const std::vector<Channel>& GetChannels() const;

Scalar GetEndTime() const;
SecondsF GetEndTime() const;

private:
Animation();

std::string name_;
std::vector<Channel> channels_;
Scalar end_time_ = 0;
SecondsF end_time_;

FML_DISALLOW_COPY_AND_ASSIGN(Animation);
};
Expand Down
32 changes: 18 additions & 14 deletions impeller/scene/animation/animation_clip.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void AnimationClip::Pause() {

void AnimationClip::Stop() {
SetPlaying(false);
Seek(0);
Seek(SecondsF::zero());
}

bool AnimationClip::GetLoop() const {
Expand All @@ -70,39 +70,43 @@ void AnimationClip::SetWeight(Scalar weight) {
weight_ = weight;
}

Scalar AnimationClip::GetPlaybackTime() const {
SecondsF AnimationClip::GetPlaybackTime() const {
return playback_time_;
}

void AnimationClip::Seek(Scalar time) {
playback_time_ = std::clamp(time, 0.0f, animation_->GetEndTime());
void AnimationClip::Seek(SecondsF time) {
playback_time_ = std::clamp(time, SecondsF::zero(), animation_->GetEndTime());
}

void AnimationClip::Advance(Scalar delta_time) {
if (!playing_ || delta_time <= 0) {
void AnimationClip::Advance(SecondsF delta_time) {
if (!playing_ || delta_time <= SecondsF::zero()) {
return;
}
delta_time *= playback_time_scale_;
playback_time_ += delta_time;

/// Handle looping behavior.

Scalar end_time = animation_->GetEndTime();
if (end_time == 0) {
playback_time_ = 0;
auto end_time = animation_->GetEndTime();
if (end_time == SecondsF::zero()) {
playback_time_ = SecondsF::zero();
return;
}
if (!loop_ && (playback_time_ < 0 || playback_time_ > end_time)) {
if (!loop_ &&
(playback_time_ < SecondsF::zero() || playback_time_ > end_time)) {
// If looping is disabled, clamp to the end (or beginning, if playing in
// reverse) and pause.
Pause();
playback_time_ = std::clamp(playback_time_, 0.0f, end_time);
playback_time_ = std::clamp(playback_time_, SecondsF::zero(), end_time);
} else if (/* loop && */ playback_time_ > end_time) {
// If looping is enabled and we ran off the end, loop to the beginning.
playback_time_ = std::fmod(std::abs(playback_time_), end_time);
} else if (/* loop && */ playback_time_ < 0) {
playback_time_ =
SecondsF(std::fmod(std::abs(playback_time_.count()), end_time.count()));
} else if (/* loop && */ playback_time_ < SecondsF::zero()) {
// If looping is enabled and we ran off the beginning, loop to the end.
playback_time_ = end_time - std::fmod(std::abs(playback_time_), end_time);
playback_time_ =
end_time -
SecondsF(std::fmod(std::abs(playback_time_.count()), end_time.count()));
}
}

Expand Down
8 changes: 4 additions & 4 deletions impeller/scene/animation/animation_clip.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ class AnimationClip final {
void SetWeight(Scalar weight);

/// @brief Get the current playback time of the animation.
Scalar GetPlaybackTime() const;
SecondsF GetPlaybackTime() const;

/// @brief Move the animation to the specified time. The given `time` is
/// clamped to the animation's playback range.
void Seek(Scalar time);
void Seek(SecondsF time);

/// @brief Advance the animation by `delta_time` seconds. Negative
/// `delta_time` values do nothing.
void Advance(Scalar delta_time);
void Advance(SecondsF delta_time);

/// @brief Applies the animation to all binded properties in the scene.
void ApplyToBindings() const;
Expand All @@ -73,7 +73,7 @@ class AnimationClip final {
std::shared_ptr<Animation> animation_;
std::vector<ChannelBinding> bindings_;

Scalar playback_time_ = 0;
SecondsF playback_time_;
Scalar playback_time_scale_ = 1; // Seconds multiplier, can be negative.
Scalar weight_ = 1;
bool playing_ = false;
Expand Down
7 changes: 4 additions & 3 deletions impeller/scene/animation/animation_player.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <memory>

#include "flutter/fml/time/time_point.h"
#include "impeller/base/timing.h"
#include "impeller/scene/node.h"

namespace impeller {
Expand Down Expand Up @@ -36,10 +37,10 @@ AnimationClip& AnimationPlayer::AddAnimation(

void AnimationPlayer::Update() {
if (!previous_time_.has_value()) {
previous_time_ = fml::TimePoint::Now().ToEpochDelta();
previous_time_ = Clock::now();
}
auto new_time = fml::TimePoint::Now().ToEpochDelta();
Scalar delta_time = (new_time - previous_time_.value()).ToSecondsF();
auto new_time = Clock::now();
auto delta_time = new_time - previous_time_.value();
previous_time_ = new_time;

Reset();
Expand Down
3 changes: 2 additions & 1 deletion impeller/scene/animation/animation_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "flutter/fml/hash_combine.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/time/time_delta.h"
#include "impeller/base/timing.h"
#include "impeller/geometry/matrix.h"
#include "impeller/scene/animation/animation_clip.h"

Expand Down Expand Up @@ -42,7 +43,7 @@ class AnimationPlayer final {

std::vector<AnimationClip> clips_;

std::optional<fml::TimeDelta> previous_time_;
std::optional<TimePoint> previous_time_;

FML_DISALLOW_COPY_AND_ASSIGN(AnimationPlayer);
};
Expand Down
24 changes: 13 additions & 11 deletions impeller/scene/animation/property_resolver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,35 +51,35 @@ PropertyResolver::~PropertyResolver() = default;

TimelineResolver::~TimelineResolver() = default;

Scalar TimelineResolver::GetEndTime() {
SecondsF TimelineResolver::GetEndTime() {
if (times_.empty()) {
return 0;
return SecondsF::zero();
}
return times_.back();
return SecondsF(times_.back());
}

TimelineResolver::TimelineKey TimelineResolver::GetTimelineKey(Scalar time) {
if (times_.size() <= 1 || time <= times_.front()) {
TimelineResolver::TimelineKey TimelineResolver::GetTimelineKey(SecondsF time) {
if (times_.size() <= 1 || time.count() <= times_.front()) {
return {.index = 0, .lerp = 1};
}
if (time >= times_.back()) {
if (time.count() >= times_.back()) {
return {.index = times_.size() - 1, .lerp = 1};
}
auto it = std::lower_bound(times_.begin(), times_.end(), time);
auto it = std::lower_bound(times_.begin(), times_.end(), time.count());
size_t index = std::distance(times_.begin(), it);

Scalar previous_time = *(it - 1);
Scalar next_time = *it;
return {.index = index,
.lerp = (time - previous_time) / (next_time - previous_time)};
.lerp = (time.count() - previous_time) / (next_time - previous_time)};
}

TranslationTimelineResolver::TranslationTimelineResolver() = default;

TranslationTimelineResolver::~TranslationTimelineResolver() = default;

void TranslationTimelineResolver::Apply(Node& target,
Scalar time,
SecondsF time,
Scalar weight) {
if (values_.empty()) {
return;
Expand All @@ -97,7 +97,9 @@ RotationTimelineResolver::RotationTimelineResolver() = default;

RotationTimelineResolver::~RotationTimelineResolver() = default;

void RotationTimelineResolver::Apply(Node& target, Scalar time, Scalar weight) {
void RotationTimelineResolver::Apply(Node& target,
SecondsF time,
Scalar weight) {
if (values_.empty()) {
return;
}
Expand All @@ -114,7 +116,7 @@ ScaleTimelineResolver::ScaleTimelineResolver() = default;

ScaleTimelineResolver::~ScaleTimelineResolver() = default;

void ScaleTimelineResolver::Apply(Node& target, Scalar time, Scalar weight) {
void ScaleTimelineResolver::Apply(Node& target, SecondsF time, Scalar weight) {
if (values_.empty()) {
return;
}
Expand Down
15 changes: 8 additions & 7 deletions impeller/scene/animation/property_resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "flutter/fml/hash_combine.h"
#include "flutter/fml/macros.h"
#include "impeller/base/timing.h"
#include "impeller/geometry/quaternion.h"
#include "impeller/geometry/scalar.h"
#include "impeller/geometry/vector.h"
Expand Down Expand Up @@ -38,22 +39,22 @@ class PropertyResolver {

virtual ~PropertyResolver();

virtual Scalar GetEndTime() = 0;
virtual SecondsF GetEndTime() = 0;

/// @brief Resolve and apply the property value to a target node. This
/// operation is additive; a given node property may be amended by
/// many different PropertyResolvers prior to rendering. For example,
/// an AnimationPlayer may blend multiple Animations together by
/// applying several AnimationClips.
virtual void Apply(Node& target, Scalar time, Scalar weight) = 0;
virtual void Apply(Node& target, SecondsF time, Scalar weight) = 0;
};

class TimelineResolver : public PropertyResolver {
public:
virtual ~TimelineResolver();

// |Resolver|
Scalar GetEndTime();
SecondsF GetEndTime();

protected:
struct TimelineKey {
Expand All @@ -63,7 +64,7 @@ class TimelineResolver : public PropertyResolver {
/// and `timeline_index`. The range of this value should always be `0>N>=1`.
Scalar lerp = 1;
};
TimelineKey GetTimelineKey(Scalar time);
TimelineKey GetTimelineKey(SecondsF time);

std::vector<Scalar> times_;
};
Expand All @@ -73,7 +74,7 @@ class TranslationTimelineResolver final : public TimelineResolver {
~TranslationTimelineResolver();

// |Resolver|
void Apply(Node& target, Scalar time, Scalar weight) override;
void Apply(Node& target, SecondsF time, Scalar weight) override;

private:
TranslationTimelineResolver();
Expand All @@ -90,7 +91,7 @@ class RotationTimelineResolver final : public TimelineResolver {
~RotationTimelineResolver();

// |Resolver|
void Apply(Node& target, Scalar time, Scalar weight) override;
void Apply(Node& target, SecondsF time, Scalar weight) override;

private:
RotationTimelineResolver();
Expand All @@ -107,7 +108,7 @@ class ScaleTimelineResolver final : public TimelineResolver {
~ScaleTimelineResolver();

// |Resolver|
void Apply(Node& target, Scalar time, Scalar weight) override;
void Apply(Node& target, SecondsF time, Scalar weight) override;

private:
ScaleTimelineResolver();
Expand Down

0 comments on commit 2213b80

Please sign in to comment.