blob: a43a308efdb75facc8fd83f191ff5f9021ebe055 [file] [log] [blame]
// 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.
#include "impeller/scene/animation/property_resolver.h"
#include <algorithm>
#include <iterator>
#include <memory>
#include "impeller/geometry/matrix_decomposition.h"
#include "impeller/geometry/point.h"
#include "impeller/scene/node.h"
namespace impeller {
namespace scene {
std::unique_ptr<TranslationTimelineResolver>
PropertyResolver::MakeTranslationTimeline(std::vector<Scalar> times,
std::vector<Vector3> values) {
FML_DCHECK(times.size() == values.size());
auto result = std::unique_ptr<TranslationTimelineResolver>(
new TranslationTimelineResolver());
result->times_ = std::move(times);
result->values_ = std::move(values);
return result;
}
std::unique_ptr<RotationTimelineResolver>
PropertyResolver::MakeRotationTimeline(std::vector<Scalar> times,
std::vector<Quaternion> values) {
FML_DCHECK(times.size() == values.size());
auto result =
std::unique_ptr<RotationTimelineResolver>(new RotationTimelineResolver());
result->times_ = std::move(times);
result->values_ = std::move(values);
return result;
}
std::unique_ptr<ScaleTimelineResolver> PropertyResolver::MakeScaleTimeline(
std::vector<Scalar> times,
std::vector<Vector3> values) {
FML_DCHECK(times.size() == values.size());
auto result =
std::unique_ptr<ScaleTimelineResolver>(new ScaleTimelineResolver());
result->times_ = std::move(times);
result->values_ = std::move(values);
return result;
}
PropertyResolver::~PropertyResolver() = default;
TimelineResolver::~TimelineResolver() = default;
SecondsF TimelineResolver::GetEndTime() {
if (times_.empty()) {
return SecondsF::zero();
}
return SecondsF(times_.back());
}
TimelineResolver::TimelineKey TimelineResolver::GetTimelineKey(SecondsF time) {
if (times_.size() <= 1 || time.count() <= times_.front()) {
return {.index = 0, .lerp = 1};
}
if (time.count() >= times_.back()) {
return {.index = times_.size() - 1, .lerp = 1};
}
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.count() - previous_time) / (next_time - previous_time)};
}
TranslationTimelineResolver::TranslationTimelineResolver() = default;
TranslationTimelineResolver::~TranslationTimelineResolver() = default;
void TranslationTimelineResolver::Apply(AnimationTransforms& target,
SecondsF time,
Scalar weight) {
if (values_.empty()) {
return;
}
auto key = GetTimelineKey(time);
auto value = values_[key.index];
if (key.lerp < 1) {
value = values_[key.index - 1].Lerp(value, key.lerp);
}
target.animated_pose.translation +=
(value - target.bind_pose.translation) * weight;
}
RotationTimelineResolver::RotationTimelineResolver() = default;
RotationTimelineResolver::~RotationTimelineResolver() = default;
void RotationTimelineResolver::Apply(AnimationTransforms& target,
SecondsF time,
Scalar weight) {
if (values_.empty()) {
return;
}
auto key = GetTimelineKey(time);
auto value = values_[key.index];
if (key.lerp < 1) {
value = values_[key.index - 1].Slerp(value, key.lerp);
}
target.animated_pose.rotation =
target.animated_pose.rotation *
Quaternion().Slerp(target.bind_pose.rotation.Invert() * value, weight);
}
ScaleTimelineResolver::ScaleTimelineResolver() = default;
ScaleTimelineResolver::~ScaleTimelineResolver() = default;
void ScaleTimelineResolver::Apply(AnimationTransforms& target,
SecondsF time,
Scalar weight) {
if (values_.empty()) {
return;
}
auto key = GetTimelineKey(time);
auto value = values_[key.index];
if (key.lerp < 1) {
value = values_[key.index - 1].Lerp(value, key.lerp);
}
target.animated_pose.scale *=
Vector3(1, 1, 1).Lerp(value / target.bind_pose.scale, weight);
}
} // namespace scene
} // namespace impeller