Added an onFrame callback that only is called when a frame change happens.

This commit is contained in:
Zed A. Shaw 2026-01-21 00:06:39 -05:00
parent ba966aa7bf
commit 992b8f0e0a

View file

@ -52,6 +52,7 @@ struct Transform {
/* Gets the number of times it looped, and returns if it should stop. */ /* Gets the number of times it looped, and returns if it should stop. */
using OnLoopHandler = std::function<bool(Sequence& seq, Transform& tr)>; using OnLoopHandler = std::function<bool(Sequence& seq, Transform& tr)>;
using OnFrameHandler = std::function<void()>;
bool DefaultOnLoop(Sequence& seq, Transform& tr) { bool DefaultOnLoop(Sequence& seq, Transform& tr) {
seq.current = 0; seq.current = 0;
@ -63,6 +64,8 @@ class Animate2 {
Sheet $sheet; Sheet $sheet;
Sequence $sequence; Sequence $sequence;
Transform $transform; Transform $transform;
OnFrameHandler onFrame = nullptr;
std::vector<sf::IntRect> $frame_rects{calc_frames()}; std::vector<sf::IntRect> $frame_rects{calc_frames()};
OnLoopHandler onLoop = DefaultOnLoop; OnLoopHandler onLoop = DefaultOnLoop;
bool playing = false; bool playing = false;
@ -109,10 +112,12 @@ class Animate2 {
dbc::check($sequence.frame_count == $sequence.frames.size(), "frame_count doesn't match frame.size()"); dbc::check($sequence.frame_count == $sequence.frames.size(), "frame_count doesn't match frame.size()");
auto duration = $sequence.durations.at($sequence.current); auto duration = $sequence.durations.at($sequence.current);
bool frame_change = false;
if($sequence.timer.getElapsedTime() >= duration) { if($sequence.timer.getElapsedTime() >= duration) {
$sequence.timer.restart(); $sequence.timer.restart();
$sequence.current++; $sequence.current++;
frame_change = true;
} }
if($sequence.current >= $sequence.frame_count) { if($sequence.current >= $sequence.frame_count) {
@ -120,7 +125,9 @@ class Animate2 {
playing = onLoop($sequence, $transform); playing = onLoop($sequence, $transform);
} }
dbc::check($sequence.current < $sequence.frame_count, "current frame out of frames.size()"); if(frame_change && onFrame != nullptr) onFrame();
dbc::check($sequence.current < $sequence.frame_count, "onLoop fail: current frame out of frames.size()");
} }
void update() { void update() {
@ -240,21 +247,22 @@ TEST_CASE("confirm frame sequencing works", "[animation-new]") {
anim.onLoop = [&](auto& seq, auto& tr) -> bool { anim.onLoop = [&](auto& seq, auto& tr) -> bool {
seq.current = 0; seq.current = 0;
loop_ran = true; loop_ran = true;
REQUIRE(blanket.sprite->getTextureRect() != init_rect); REQUIRE(blanket.sprite->getTextureRect() != init_rect);
return false; return false;
}; };
anim.onFrame = [&](){
anim.apply(*blanket.sprite, {});
};
sf::Vector2f pos{0,0}; sf::Vector2f pos{0,0};
while(anim.playing) { while(anim.playing) {
anim.update(); anim.update();
// NOTE: possibly find a way to only run apply on frame change? // NOTE: possibly find a way to only run apply on frame change?
anim.apply(*blanket.sprite, pos);
} }
// NOTE: might need one final apply call to go to frame 0?
anim.apply(*blanket.sprite, pos);
REQUIRE(loop_ran == true); REQUIRE(loop_ran == true);
REQUIRE(anim.playing == false); REQUIRE(anim.playing == false);