Skip to content

Commit

Permalink
fix for unexpected triggered events
Browse files Browse the repository at this point in the history
fixes #7226
This PR fixes reports of events when animations are playing backward.
It considers both the timeline speed and the state machine state speed to determine direction.
It also handles not reporting an event twice if it comes from a "ping pong" loop.
It also adds a small performance improvement, skipping the binary search if possible.

Diffs=
265c00985 fix for unexpected triggered events (#7227)

Co-authored-by: hernan <[email protected]>
  • Loading branch information
bodymovin and bodymovin committed May 22, 2024
1 parent 35f22ae commit 7867298
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8a538c243fcc5b72159388a7e63669f1e6998dda
265c009852e86492deb69277ad18aa2c394c93e5
2 changes: 1 addition & 1 deletion include/rive/animation/keyed_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class KeyedObject : public KeyedObjectBase
void reportKeyedCallbacks(KeyedCallbackReporter* reporter,
float secondsFrom,
float secondsTo,
int secondsFromExactOffset) const;
bool isAtStartFrame) const;
void apply(Artboard* coreContext, float time, float mix);

StatusCode import(ImportStack& importStack) override;
Expand Down
2 changes: 1 addition & 1 deletion include/rive/animation/keyed_property.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class KeyedProperty : public KeyedPropertyBase
uint32_t objectId,
float secondsFrom,
float secondsTo,
int secondsFromExactOffset) const;
bool isAtStartFrame) const;

/// Apply interpolating key frames.
void apply(Core* object, float time, float mix);
Expand Down
5 changes: 4 additions & 1 deletion include/rive/animation/linear_animation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class LinearAnimation : public LinearAnimationBase

/// Returns the start time/ end time of the animation in seconds, considering speed
float startTime() const;
float startTime(float multiplier) const;
float endTime() const;

/// Convert a global clock to local seconds (takes into consideration
Expand All @@ -49,7 +50,9 @@ class LinearAnimation : public LinearAnimationBase

void reportKeyedCallbacks(KeyedCallbackReporter* reporter,
float secondsFrom,
float secondsTo) const;
float secondsTo,
float speedDirection,
bool fromPong) const;
};
} // namespace rive

Expand Down
1 change: 1 addition & 0 deletions include/rive/animation/linear_animation_instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class LinearAnimationInstance : public Scene
private:
const LinearAnimation* m_animation = nullptr;
float m_time;
float m_speedDirection;
float m_totalTime;
float m_lastTotalTime;
float m_spilledTime;
Expand Down
4 changes: 2 additions & 2 deletions src/animation/keyed_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ StatusCode KeyedObject::onAddedClean(CoreContext* context)
void KeyedObject::reportKeyedCallbacks(KeyedCallbackReporter* reporter,
float secondsFrom,
float secondsTo,
int secondsFromExactOffset) const
bool isAtStartFrame) const
{
for (const std::unique_ptr<KeyedProperty>& property : m_keyedProperties)
{
Expand All @@ -64,7 +64,7 @@ void KeyedObject::reportKeyedCallbacks(KeyedCallbackReporter* reporter,
objectId(),
secondsFrom,
secondsTo,
secondsFromExactOffset);
isAtStartFrame);
}
}

Expand Down
37 changes: 31 additions & 6 deletions src/animation/keyed_property.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@ void KeyedProperty::addKeyFrame(std::unique_ptr<KeyFrame> keyframe)

int KeyedProperty::closestFrameIndex(float seconds, int exactOffset) const
{
int idx = 0;
int mid = 0;
float closestSeconds = 0;
int start = 0;
auto numKeyFrames = static_cast<int>(m_keyFrames.size());
int end = numKeyFrames - 1;

// If it's the last keyframe, we skip the binary search
if (seconds > m_keyFrames[end]->seconds())
{
return end + 1;
}

while (start <= end)
{
mid = (start + end) >> 1;
Expand All @@ -41,19 +46,39 @@ int KeyedProperty::closestFrameIndex(float seconds, int exactOffset) const
{
return mid + exactOffset;
}
idx = start;
}
return idx;
return start;
}

void KeyedProperty::reportKeyedCallbacks(KeyedCallbackReporter* reporter,
uint32_t objectId,
float secondsFrom,
float secondsTo,
int secondsFromExactOffset) const
bool isAtStartFrame) const
{
int idx = closestFrameIndex(secondsFrom, secondsFromExactOffset);
int idxTo = closestFrameIndex(secondsTo, 1);
if (secondsFrom == secondsTo)
{
return;
}
bool isForward = secondsFrom <= secondsTo;
int fromExactOffset = 0;
int toExactOffset = isForward ? 1 : 0;
if (isForward)
{
if (!isAtStartFrame)
{
fromExactOffset = 1;
}
}
else
{
if (isAtStartFrame)
{
fromExactOffset = 1;
}
}
int idx = closestFrameIndex(secondsFrom, fromExactOffset);
int idxTo = closestFrameIndex(secondsTo, toExactOffset);

if (idxTo < idx)
{
Expand Down
22 changes: 14 additions & 8 deletions src/animation/linear_animation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ float LinearAnimation::endSeconds() const
}

float LinearAnimation::startTime() const { return (speed() >= 0) ? startSeconds() : endSeconds(); }
float LinearAnimation::startTime(float multiplier) const
{
return ((speed() * multiplier) >= 0) ? startSeconds() : endSeconds();
}
float LinearAnimation::endTime() const { return (speed() >= 0) ? endSeconds() : startSeconds(); }
float LinearAnimation::durationSeconds() const { return std::abs(endSeconds() - startSeconds()); }

Expand Down Expand Up @@ -119,16 +123,18 @@ float LinearAnimation::globalToLocalSeconds(float seconds) const

void LinearAnimation::reportKeyedCallbacks(KeyedCallbackReporter* reporter,
float secondsFrom,
float secondsTo) const
float secondsTo,
float speedDirection,
bool fromPong) const
{
int secondsFromExactOffset =
startTime() == secondsFrom &&
(speed() >= 0 ? secondsFrom < secondsTo : secondsFrom < secondsTo)
? 0
: 1;
float startingTime = startTime(speedDirection);
bool isAtStartFrame = startingTime == secondsFrom;

for (const auto& object : m_KeyedObjects)
if (!isAtStartFrame || !fromPong)
{
object->reportKeyedCallbacks(reporter, secondsFrom, secondsTo, secondsFromExactOffset);
for (const auto& object : m_KeyedObjects)
{
object->reportKeyedCallbacks(reporter, secondsFrom, secondsTo, isAtStartFrame);
}
}
}
20 changes: 16 additions & 4 deletions src/animation/linear_animation_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ LinearAnimationInstance::LinearAnimationInstance(const LinearAnimation* animatio
Scene(instance),
m_animation((assert(animation != nullptr), animation)),
m_time((speedMultiplier >= 0) ? animation->startTime() : animation->endTime()),
m_speedDirection((speedMultiplier >= 0) ? 1 : -1),
m_totalTime(0.0f),
m_lastTotalTime(0.0f),
m_spilledTime(0.0f),
Expand All @@ -23,6 +24,7 @@ LinearAnimationInstance::LinearAnimationInstance(LinearAnimationInstance const&
Scene(lhs),
m_animation(lhs.m_animation),
m_time(lhs.m_time),
m_speedDirection(lhs.m_speedDirection),
m_totalTime(lhs.m_totalTime),
m_lastTotalTime(lhs.m_lastTotalTime),
m_spilledTime(lhs.m_spilledTime),
Expand Down Expand Up @@ -64,7 +66,7 @@ bool LinearAnimationInstance::advance(float elapsedSeconds, KeyedCallbackReporte
m_time += deltaSeconds;
if (reporter != nullptr)
{
animation.reportKeyedCallbacks(reporter, lastTime, m_time);
animation.reportKeyedCallbacks(reporter, lastTime, m_time, m_speedDirection, false);
}

int fps = animation.fps();
Expand Down Expand Up @@ -107,7 +109,7 @@ bool LinearAnimationInstance::advance(float elapsedSeconds, KeyedCallbackReporte
didLoop = true;
if (reporter != nullptr)
{
animation.reportKeyedCallbacks(reporter, 0.0f, m_time);
animation.reportKeyedCallbacks(reporter, 0.0f, m_time, m_speedDirection, false);
}
}
else if (direction == -1 && frames <= start)
Expand All @@ -119,11 +121,16 @@ bool LinearAnimationInstance::advance(float elapsedSeconds, KeyedCallbackReporte
didLoop = true;
if (reporter != nullptr)
{
animation.reportKeyedCallbacks(reporter, end / (float)fps, m_time);
animation.reportKeyedCallbacks(reporter,
end / (float)fps,
m_time,
m_speedDirection,
false);
}
}
break;
case Loop::pingPong:
bool fromPong = true;
while (true)
{
if (direction == 1 && frames >= end)
Expand Down Expand Up @@ -153,8 +160,13 @@ bool LinearAnimationInstance::advance(float elapsedSeconds, KeyedCallbackReporte
didLoop = true;
if (reporter != nullptr)
{
animation.reportKeyedCallbacks(reporter, lastTime, m_time);
animation.reportKeyedCallbacks(reporter,
lastTime,
m_time,
m_speedDirection,
fromPong);
}
fromPong = !fromPong;
}
break;
}
Expand Down

0 comments on commit 7867298

Please sign in to comment.