From 2213b80dd964f09ed087b4b284490af7b7e4e82a Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Tue, 3 Jan 2023 13:07:11 -0800 Subject: [PATCH] [Impeller Scene] Use std::chrono for animation durations (#38606) --- ci/licenses_golden/licenses_flutter | 2 ++ impeller/base/BUILD.gn | 1 + impeller/base/timing.h | 15 +++++++++ impeller/scene/animation/animation.cc | 2 +- impeller/scene/animation/animation.h | 5 +-- impeller/scene/animation/animation_clip.cc | 32 +++++++++++-------- impeller/scene/animation/animation_clip.h | 8 ++--- impeller/scene/animation/animation_player.cc | 7 ++-- impeller/scene/animation/animation_player.h | 3 +- impeller/scene/animation/property_resolver.cc | 24 +++++++------- impeller/scene/animation/property_resolver.h | 15 +++++---- 11 files changed, 71 insertions(+), 43 deletions(-) create mode 100644 impeller/base/timing.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 46fb0600187b2..34c5ab34c30d1 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -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 @@ -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 diff --git a/impeller/base/BUILD.gn b/impeller/base/BUILD.gn index 4edd4e1a154f9..1083b79a80b2d 100644 --- a/impeller/base/BUILD.gn +++ b/impeller/base/BUILD.gn @@ -20,6 +20,7 @@ impeller_component("base") { "thread.h", "thread_safety.cc", "thread_safety.h", + "timing.h", "validation.cc", "validation.h", "version.cc", diff --git a/impeller/base/timing.h b/impeller/base/timing.h new file mode 100644 index 0000000000000..b60104337e861 --- /dev/null +++ b/impeller/base/timing.h @@ -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 + +namespace impeller { + +using SecondsF = std::chrono::duration; +using Clock = std::chrono::high_resolution_clock; +using TimePoint = std::chrono::time_point; + +} // namespace impeller diff --git a/impeller/scene/animation/animation.cc b/impeller/scene/animation/animation.cc index b8e4b557e2939..536a3a41595f7 100644 --- a/impeller/scene/animation/animation.cc +++ b/impeller/scene/animation/animation.cc @@ -117,7 +117,7 @@ const std::vector& Animation::GetChannels() const { return channels_; } -Scalar Animation::GetEndTime() const { +SecondsF Animation::GetEndTime() const { return end_time_; } diff --git a/impeller/scene/animation/animation.h b/impeller/scene/animation/animation.h index 3f4799fbd6d36..9eebbfbc49f87 100644 --- a/impeller/scene/animation/animation.h +++ b/impeller/scene/animation/animation.h @@ -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" @@ -60,14 +61,14 @@ class Animation final { const std::vector& GetChannels() const; - Scalar GetEndTime() const; + SecondsF GetEndTime() const; private: Animation(); std::string name_; std::vector channels_; - Scalar end_time_ = 0; + SecondsF end_time_; FML_DISALLOW_COPY_AND_ASSIGN(Animation); }; diff --git a/impeller/scene/animation/animation_clip.cc b/impeller/scene/animation/animation_clip.cc index eabfffbe54377..10019e8f52bd1 100644 --- a/impeller/scene/animation/animation_clip.cc +++ b/impeller/scene/animation/animation_clip.cc @@ -43,7 +43,7 @@ void AnimationClip::Pause() { void AnimationClip::Stop() { SetPlaying(false); - Seek(0); + Seek(SecondsF::zero()); } bool AnimationClip::GetLoop() const { @@ -70,16 +70,16 @@ 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_; @@ -87,22 +87,26 @@ void AnimationClip::Advance(Scalar 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())); } } diff --git a/impeller/scene/animation/animation_clip.h b/impeller/scene/animation/animation_clip.h index 1bd18935fdc10..cf584ae64620a 100644 --- a/impeller/scene/animation/animation_clip.h +++ b/impeller/scene/animation/animation_clip.h @@ -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; @@ -73,7 +73,7 @@ class AnimationClip final { std::shared_ptr animation_; std::vector bindings_; - Scalar playback_time_ = 0; + SecondsF playback_time_; Scalar playback_time_scale_ = 1; // Seconds multiplier, can be negative. Scalar weight_ = 1; bool playing_ = false; diff --git a/impeller/scene/animation/animation_player.cc b/impeller/scene/animation/animation_player.cc index 15d4dc9e7c57d..d2e9c353e03e1 100644 --- a/impeller/scene/animation/animation_player.cc +++ b/impeller/scene/animation/animation_player.cc @@ -7,6 +7,7 @@ #include #include "flutter/fml/time/time_point.h" +#include "impeller/base/timing.h" #include "impeller/scene/node.h" namespace impeller { @@ -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(); diff --git a/impeller/scene/animation/animation_player.h b/impeller/scene/animation/animation_player.h index 808b76e57b910..76b8d853a7bb1 100644 --- a/impeller/scene/animation/animation_player.h +++ b/impeller/scene/animation/animation_player.h @@ -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" @@ -42,7 +43,7 @@ class AnimationPlayer final { std::vector clips_; - std::optional previous_time_; + std::optional previous_time_; FML_DISALLOW_COPY_AND_ASSIGN(AnimationPlayer); }; diff --git a/impeller/scene/animation/property_resolver.cc b/impeller/scene/animation/property_resolver.cc index 6407f1d8a60b4..d4f5e3c7da830 100644 --- a/impeller/scene/animation/property_resolver.cc +++ b/impeller/scene/animation/property_resolver.cc @@ -51,27 +51,27 @@ 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; @@ -79,7 +79,7 @@ TranslationTimelineResolver::TranslationTimelineResolver() = default; TranslationTimelineResolver::~TranslationTimelineResolver() = default; void TranslationTimelineResolver::Apply(Node& target, - Scalar time, + SecondsF time, Scalar weight) { if (values_.empty()) { return; @@ -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; } @@ -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; } diff --git a/impeller/scene/animation/property_resolver.h b/impeller/scene/animation/property_resolver.h index 3e5bde2bb15ac..e0cd1888a857a 100644 --- a/impeller/scene/animation/property_resolver.h +++ b/impeller/scene/animation/property_resolver.h @@ -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" @@ -38,14 +39,14 @@ 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 { @@ -53,7 +54,7 @@ class TimelineResolver : public PropertyResolver { virtual ~TimelineResolver(); // |Resolver| - Scalar GetEndTime(); + SecondsF GetEndTime(); protected: struct TimelineKey { @@ -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 times_; }; @@ -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(); @@ -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(); @@ -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();