Refactoring Animator class.

This commit is contained in:
Attila Uygun 2023-05-17 18:34:45 +02:00
parent cda1d750f8
commit be1d562a07
2 changed files with 71 additions and 65 deletions

View File

@ -126,10 +126,10 @@ void Animator::SetMovement(Vector2f direction,
a.movement_last_pos = {0, 0};
}
void Animator::SetRotation(float trget,
void Animator::SetRotation(float target,
float duration,
Interpolator interpolator) {
rotation_target_ = trget;
rotation_target_ = target;
rotation_speed_ = 1.0f / duration;
rotation_interpolator_ = std::move(interpolator);
@ -153,7 +153,7 @@ void Animator::SetFrames(int count,
frame_count_ = count;
frame_speed_ = (float)frames_per_second / (float)count;
for (auto& a : elements_)
a.frame_start_ = a.animatable->GetFrame();
a.frame_start = a.animatable->GetFrame();
frame_interpolator_ = std::move(interpolator);
}
@ -180,66 +180,43 @@ void Animator::Update(float delta_time) {
UpdateAnimTime(delta_time, kFrames, frame_speed_, frame_time_, frame_cb_);
if (play_flags_ & kTimer)
UpdateAnimTime(delta_time, kTimer, timer_speed_, timer_time_, timer_cb_);
did_evaluate_ = false;
}
void Animator::Evaluate(float frame_frac_time) {
did_evaluate_ = true;
Vector2f pos = {0, 0};
if (play_flags_ & kMovement) {
float time = movement_time_ + movement_speed_ * frame_frac_time;
float interpolated_time =
movement_interpolator_ ? movement_interpolator_(time) : time;
pos = base::Lerp({0, 0}, movement_direction_, interpolated_time);
}
float theta = 0;
if (play_flags_ & kRotation) {
float time = rotation_time_ + rotation_speed_ * frame_frac_time;
float interpolated_time =
rotation_interpolator_ ? rotation_interpolator_(time) : time;
theta = base::Lerp(0.0f, rotation_target_, interpolated_time);
}
float blending_itime = 0;
if (play_flags_ & kBlending) {
float time = blending_time_ + blending_speed_ * frame_frac_time;
blending_itime =
blending_interpolator_ ? blending_interpolator_(time) : time;
}
float frame_itime = 0;
if (play_flags_ & kFrames) {
float time = frame_time_ + frame_speed_ * frame_frac_time;
frame_itime = frame_interpolator_ ? frame_interpolator_(time) : time;
}
for (auto& a : elements_) {
if (play_flags_ & kMovement) {
void Animator::Evaluate(float frame_frac) {
if (play_flags_ & kMovement)
EvaluateAnimation<Vector2f, true>(
frame_frac, movement_speed_, movement_time_, movement_interpolator_,
movement_direction_, [](Element& a, Vector2f pos) {
a.animatable->Translate(pos - a.movement_last_pos);
a.movement_last_pos = pos;
}
});
if (play_flags_ & kRotation) {
if (play_flags_ & kRotation)
EvaluateAnimation<float, true>(
frame_frac, rotation_speed_, rotation_time_, rotation_interpolator_,
rotation_target_, [](Element& a, float theta) {
a.animatable->Rotate(theta - a.rotation_last_theta);
a.rotation_last_theta = theta;
}
});
if (play_flags_ & kBlending) {
if (play_flags_ & kBlending)
EvaluateAnimation<float, false>(
frame_frac, blending_speed_, blending_time_, blending_interpolator_, {},
[&](Element& a, float interpolated_time) {
Vector4f blending =
base::Lerp(a.blending_start, blending_target_, blending_itime);
base::Lerp(a.blending_start, blending_target_, interpolated_time);
a.animatable->SetColor(blending);
}
});
if (play_flags_ & kFrames) {
int target = a.frame_start_ + frame_count_;
int frame = base::Lerp(a.frame_start_, target, frame_itime);
if (play_flags_ & kFrames)
EvaluateAnimation<float, false>(
frame_frac, frame_speed_, frame_time_, frame_interpolator_, {},
[&](Element& a, float interpolated_time) {
int target = a.frame_start + frame_count_;
int frame = base::Lerp(a.frame_start, target, interpolated_time);
if (frame < target)
a.animatable->SetFrame(frame);
}
}
});
}
void Animator::UpdateAnimTime(float delta_time,
@ -252,7 +229,7 @@ void Animator::UpdateAnimTime(float delta_time,
if (loop_flags_ & anim) {
anim_time = fmod(anim_time, 1.0f);
} else {
if (!did_evaluate_)
anim_time = 1.0f;
Evaluate(0);
anim_time = 0;
play_flags_ &= ~anim;
@ -269,4 +246,24 @@ void Animator::UpdateAnimTime(float delta_time,
}
}
template <typename T, bool relative>
void Animator::EvaluateAnimation(float frame_frac,
float anim_speed,
float anim_time,
Interpolator& interpolator,
T target,
ResultSetter<T> set_result) {
float time = anim_time + anim_speed * frame_frac;
float interpolated_time = interpolator ? interpolator(time) : time;
if constexpr (relative) {
T result = base::Lerp(T{0}, target, interpolated_time);
for (auto& a : elements_)
set_result(a, result);
} else {
for (auto& a : elements_)
set_result(a, interpolated_time);
}
}
} // namespace eng

View File

@ -40,7 +40,7 @@ class Animator {
float GetTime(int animation);
void SetTime(int animation, float time, bool force_update = false);
// Set callback ro be called once animation ends.
// Set callback to be called once animation ends.
void SetEndCallback(int animation, base::Closure cb);
// Distance is the magnitude of direction vector. Duration is in seconds.
@ -69,7 +69,7 @@ class Animator {
void SetVisible(bool visible);
void Update(float delta_time);
void Evaluate(float frame_frac_time);
void Evaluate(float frame_frac);
bool IsPlaying(int animation) const { return play_flags_ & animation; }
@ -79,7 +79,7 @@ class Animator {
base::Vector2f movement_last_pos = {0, 0};
float rotation_last_theta = 0;
base::Vector4f blending_start = {0, 0, 0, 0};
int frame_start_ = 0;
int frame_start = 0;
};
unsigned int play_flags_ = 0;
@ -120,13 +120,22 @@ class Animator {
base::Closure pending_cb_;
Flags inside_cb_ = kNone;
bool did_evaluate_ = false;
void UpdateAnimTime(float delta_time,
int anim,
float anim_speed,
float& anim_time,
base::Closure& cb);
template <typename T>
using ResultSetter = std::function<void(Element&, T)>;
template <typename T, bool relative>
void EvaluateAnimation(float frame_frac,
float anim_speed,
float anim_time,
Interpolator& interpolator,
T target,
ResultSetter<T> set_result);
};
} // namespace eng