mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 22:25:38 +00:00
Added play direction support to LottieComponent.
Also fixed some bugs and cleaned up the code a bit.
This commit is contained in:
parent
e730d24da0
commit
cd7cfe36ce
|
@ -157,7 +157,6 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> The
|
||||||
{"speed", FLOAT},
|
{"speed", FLOAT},
|
||||||
{"direction", STRING},
|
{"direction", STRING},
|
||||||
{"keepAspectRatio", BOOLEAN},
|
{"keepAspectRatio", BOOLEAN},
|
||||||
{"delay", FLOAT},
|
|
||||||
{"visible", BOOLEAN},
|
{"visible", BOOLEAN},
|
||||||
{"zIndex", FLOAT}}},
|
{"zIndex", FLOAT}}},
|
||||||
{"badges",
|
{"badges",
|
||||||
|
|
|
@ -26,14 +26,17 @@ LottieComponent::LottieComponent(Window* window)
|
||||||
, mFrameSize{0}
|
, mFrameSize{0}
|
||||||
, mAnimation{nullptr}
|
, mAnimation{nullptr}
|
||||||
, mSurface{nullptr}
|
, mSurface{nullptr}
|
||||||
|
, mStartDirection{"normal"}
|
||||||
, mTotalFrames{0}
|
, mTotalFrames{0}
|
||||||
, mFrameNum{0}
|
, mFrameNum{0}
|
||||||
, mFrameRate{0.0}
|
, mFrameRate{0.0}
|
||||||
|
, mSpeedModifier{1.0f}
|
||||||
, mTargetPacing{0}
|
, mTargetPacing{0}
|
||||||
, mTimeAccumulator{0}
|
, mTimeAccumulator{0}
|
||||||
|
, mSkippedFrames{0}
|
||||||
, mHoldFrame{false}
|
, mHoldFrame{false}
|
||||||
, mDroppedFrames{0}
|
, mPause{false}
|
||||||
, mSpeedModifier{1.0f}
|
, mAlternate{false}
|
||||||
, mKeepAspectRatio{true}
|
, mKeepAspectRatio{true}
|
||||||
{
|
{
|
||||||
// Get an empty texture for rendering the animation.
|
// Get an empty texture for rendering the animation.
|
||||||
|
@ -65,8 +68,10 @@ LottieComponent::LottieComponent(Window* window)
|
||||||
|
|
||||||
LottieComponent::~LottieComponent()
|
LottieComponent::~LottieComponent()
|
||||||
{
|
{
|
||||||
|
// This is required as rlottie could otherwise crash on application shutdown.
|
||||||
if (mFuture.valid())
|
if (mFuture.valid())
|
||||||
mFuture.get();
|
mFuture.get();
|
||||||
|
|
||||||
mTotalFrameCache -= mCacheSize;
|
mTotalFrameCache -= mCacheSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,10 +152,6 @@ void LottieComponent::setAnimation(const std::string& path)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the first frame as a type of preload to decrease the chance of seeing a blank
|
|
||||||
// texture when first entering a view that uses this animation.
|
|
||||||
mFuture = mAnimation->render(mFrameNum, *mSurface, mKeepAspectRatio);
|
|
||||||
|
|
||||||
// Some statistics for the file.
|
// Some statistics for the file.
|
||||||
double duration = mAnimation->duration();
|
double duration = mAnimation->duration();
|
||||||
mTotalFrames = mAnimation->totalFrame();
|
mTotalFrames = mAnimation->totalFrame();
|
||||||
|
@ -158,6 +159,11 @@ void LottieComponent::setAnimation(const std::string& path)
|
||||||
mFrameSize = width * height * 4;
|
mFrameSize = width * height * 4;
|
||||||
mTargetPacing = static_cast<int>((1000.0 / mFrameRate) / static_cast<double>(mSpeedModifier));
|
mTargetPacing = static_cast<int>((1000.0 / mFrameRate) / static_cast<double>(mSpeedModifier));
|
||||||
|
|
||||||
|
mDirection = mStartDirection;
|
||||||
|
|
||||||
|
if (mDirection == "reverse")
|
||||||
|
mFrameNum = mTotalFrames - 1;
|
||||||
|
|
||||||
if (DEBUG_ANIMATION) {
|
if (DEBUG_ANIMATION) {
|
||||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Rasterized width: " << mSize.x;
|
LOG(LogDebug) << "LottieComponent::setAnimation(): Rasterized width: " << mSize.x;
|
||||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Rasterized height: " << mSize.y;
|
LOG(LogDebug) << "LottieComponent::setAnimation(): Rasterized height: " << mSize.y;
|
||||||
|
@ -181,6 +187,15 @@ void LottieComponent::setAnimation(const std::string& path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LottieComponent::resetFileAnimation()
|
||||||
|
{
|
||||||
|
mTimeAccumulator = 0;
|
||||||
|
mFrameNum = mStartDirection == "reverse" ? mTotalFrames - 1 : 0;
|
||||||
|
|
||||||
|
if (mAnimation != nullptr)
|
||||||
|
mFuture = mAnimation->render(mFrameNum, *mSurface, mKeepAspectRatio);
|
||||||
|
}
|
||||||
|
|
||||||
void LottieComponent::onSizeChanged()
|
void LottieComponent::onSizeChanged()
|
||||||
{
|
{
|
||||||
// Setting the animation again will completely reinitialize it.
|
// Setting the animation again will completely reinitialize it.
|
||||||
|
@ -221,6 +236,32 @@ void LottieComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
mKeepAspectRatio = elem->get<bool>("keepAspectRatio");
|
mKeepAspectRatio = elem->get<bool>("keepAspectRatio");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (elem->has("direction")) {
|
||||||
|
std::string direction = elem->get<std::string>("direction");
|
||||||
|
if (direction == "normal") {
|
||||||
|
mStartDirection = "normal";
|
||||||
|
mAlternate = false;
|
||||||
|
}
|
||||||
|
else if (direction == "reverse") {
|
||||||
|
mStartDirection = "reverse";
|
||||||
|
mAlternate = false;
|
||||||
|
}
|
||||||
|
else if (direction == "alternate") {
|
||||||
|
mStartDirection = "normal";
|
||||||
|
mAlternate = true;
|
||||||
|
}
|
||||||
|
else if (direction == "alternateReverse") {
|
||||||
|
mStartDirection = "reverse";
|
||||||
|
mAlternate = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG(LogWarning) << "LottieComponent: Invalid theme configuration, <direction> set to \""
|
||||||
|
<< direction << "\"";
|
||||||
|
mStartDirection = "normal";
|
||||||
|
mAlternate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GuiComponent::applyTheme(theme, view, element, properties);
|
GuiComponent::applyTheme(theme, view, element, properties);
|
||||||
|
|
||||||
if (elem->has("path")) {
|
if (elem->has("path")) {
|
||||||
|
@ -255,7 +296,7 @@ void LottieComponent::update(int deltaTime)
|
||||||
if (mTimeAccumulator > deltaTime * 200)
|
if (mTimeAccumulator > deltaTime * 200)
|
||||||
mTimeAccumulator = 0;
|
mTimeAccumulator = 0;
|
||||||
|
|
||||||
// Keep animation speed from going too quickly.
|
// Prevent animation from playing too quickly.
|
||||||
if (mTimeAccumulator + deltaTime < mTargetPacing) {
|
if (mTimeAccumulator + deltaTime < mTargetPacing) {
|
||||||
mHoldFrame = true;
|
mHoldFrame = true;
|
||||||
mTimeAccumulator += deltaTime;
|
mTimeAccumulator += deltaTime;
|
||||||
|
@ -272,8 +313,13 @@ void LottieComponent::update(int deltaTime)
|
||||||
<< "LottieComponent::update(): Skipped frame, mTimeAccumulator / mTargetPacing: "
|
<< "LottieComponent::update(): Skipped frame, mTimeAccumulator / mTargetPacing: "
|
||||||
<< mTimeAccumulator - deltaTime << " / " << mTargetPacing;
|
<< mTimeAccumulator - deltaTime << " / " << mTargetPacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mDirection == "reverse")
|
||||||
|
--mFrameNum;
|
||||||
|
else
|
||||||
++mFrameNum;
|
++mFrameNum;
|
||||||
++mDroppedFrames;
|
|
||||||
|
++mSkippedFrames;
|
||||||
mTimeAccumulator -= mTargetPacing;
|
mTimeAccumulator -= mTargetPacing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,24 +340,48 @@ void LottieComponent::render(const glm::mat4& parentTrans)
|
||||||
static_cast<size_t>(mSize.y));
|
static_cast<size_t>(mSize.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't render any new frames if paused or if a menu is open.
|
bool doRender = true;
|
||||||
if (!mPause && mWindow->getGuiStackSize() < 2) {
|
|
||||||
if (mFrameNum >= mTotalFrames) {
|
// Don't render if a menu is open except if the cached background is getting invalidated.
|
||||||
|
if (mWindow->getGuiStackSize() > 1) {
|
||||||
|
if (mWindow->isInvalidatingCachedBackground())
|
||||||
|
doRender = true;
|
||||||
|
else
|
||||||
|
doRender = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't render any new frames if paused or if a menu is open (unless invalidating background).
|
||||||
|
if (!mPause && doRender) {
|
||||||
|
if ((mDirection == "normal" && mFrameNum >= mTotalFrames) ||
|
||||||
|
(mDirection == "reverse" && mFrameNum > mTotalFrames)) {
|
||||||
if (DEBUG_ANIMATION) {
|
if (DEBUG_ANIMATION) {
|
||||||
LOG(LogError) << "Dropped frames: " << mDroppedFrames;
|
LOG(LogDebug) << "LottieComponent::render(): Skipped frames: " << mSkippedFrames;
|
||||||
LOG(LogDebug) << "LottieComponent::render(): Actual duration: "
|
LOG(LogDebug) << "LottieComponent::render(): Actual duration: "
|
||||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
std::chrono::system_clock::now() - mAnimationStartTime)
|
std::chrono::system_clock::now() - mAnimationStartTime)
|
||||||
.count()
|
.count()
|
||||||
<< " ms";
|
<< " ms";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mAlternate) {
|
||||||
|
if (mDirection == "normal")
|
||||||
|
mDirection = "reverse";
|
||||||
|
else
|
||||||
|
mDirection = "normal";
|
||||||
|
}
|
||||||
|
|
||||||
mTimeAccumulator = 0;
|
mTimeAccumulator = 0;
|
||||||
|
mSkippedFrames = 0;
|
||||||
|
|
||||||
|
if (mDirection == "reverse")
|
||||||
|
mFrameNum = mTotalFrames - 1;
|
||||||
|
else
|
||||||
mFrameNum = 0;
|
mFrameNum = 0;
|
||||||
mDroppedFrames = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG_ANIMATION) {
|
if (DEBUG_ANIMATION) {
|
||||||
if (mFrameNum == 0)
|
if ((mDirection == "normal" && mFrameNum == 0) ||
|
||||||
|
(mDirection == "reverse" && mFrameNum == mTotalFrames - 1))
|
||||||
mAnimationStartTime = std::chrono::system_clock::now();
|
mAnimationStartTime = std::chrono::system_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,6 +406,9 @@ void LottieComponent::render(const glm::mat4& parentTrans)
|
||||||
mTexture->initFromPixels(&mPictureRGBA.at(0), static_cast<size_t>(mSize.x),
|
mTexture->initFromPixels(&mPictureRGBA.at(0), static_cast<size_t>(mSize.x),
|
||||||
static_cast<size_t>(mSize.y));
|
static_cast<size_t>(mSize.y));
|
||||||
|
|
||||||
|
if (mDirection == "reverse")
|
||||||
|
--mFrameNum;
|
||||||
|
else
|
||||||
++mFrameNum;
|
++mFrameNum;
|
||||||
|
|
||||||
if (mFrameNum == mTotalFrames)
|
if (mFrameNum == mTotalFrames)
|
||||||
|
@ -350,6 +423,10 @@ void LottieComponent::render(const glm::mat4& parentTrans)
|
||||||
mTexture->initFromPixels(&mFrameCache[mFrameNum][0],
|
mTexture->initFromPixels(&mFrameCache[mFrameNum][0],
|
||||||
static_cast<size_t>(mSize.x),
|
static_cast<size_t>(mSize.x),
|
||||||
static_cast<size_t>(mSize.y));
|
static_cast<size_t>(mSize.y));
|
||||||
|
|
||||||
|
if (mDirection == "reverse")
|
||||||
|
--mFrameNum;
|
||||||
|
else
|
||||||
++mFrameNum;
|
++mFrameNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,12 +34,7 @@ public:
|
||||||
mMaxCacheSize = static_cast<size_t>(glm::clamp(value, 0, 1024) * 1024 * 1024);
|
mMaxCacheSize = static_cast<size_t>(glm::clamp(value, 0, 1024) * 1024 * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetFileAnimation() override
|
void resetFileAnimation() override;
|
||||||
{
|
|
||||||
mTimeAccumulator = 0;
|
|
||||||
mFrameNum = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onSizeChanged() override;
|
void onSizeChanged() override;
|
||||||
|
|
||||||
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme,
|
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
|
@ -62,24 +57,26 @@ private:
|
||||||
size_t mCacheSize;
|
size_t mCacheSize;
|
||||||
size_t mFrameSize;
|
size_t mFrameSize;
|
||||||
|
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> mAnimationStartTime;
|
||||||
std::unique_ptr<rlottie::Animation> mAnimation;
|
std::unique_ptr<rlottie::Animation> mAnimation;
|
||||||
std::unique_ptr<rlottie::Surface> mSurface;
|
std::unique_ptr<rlottie::Surface> mSurface;
|
||||||
std::future<rlottie::Surface> mFuture;
|
std::future<rlottie::Surface> mFuture;
|
||||||
std::string mPath;
|
std::string mPath;
|
||||||
|
std::string mStartDirection;
|
||||||
|
std::string mDirection;
|
||||||
size_t mTotalFrames;
|
size_t mTotalFrames;
|
||||||
size_t mFrameNum;
|
size_t mFrameNum;
|
||||||
|
|
||||||
double mFrameRate;
|
double mFrameRate;
|
||||||
|
float mSpeedModifier;
|
||||||
int mTargetPacing;
|
int mTargetPacing;
|
||||||
int mTimeAccumulator;
|
int mTimeAccumulator;
|
||||||
|
int mSkippedFrames;
|
||||||
|
|
||||||
bool mHoldFrame;
|
bool mHoldFrame;
|
||||||
int mDroppedFrames;
|
|
||||||
|
|
||||||
bool mPause;
|
bool mPause;
|
||||||
|
bool mAlternate;
|
||||||
float mSpeedModifier;
|
|
||||||
bool mKeepAspectRatio;
|
bool mKeepAspectRatio;
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::system_clock> mAnimationStartTime;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ES_CORE_COMPONENTS_LOTTIE_COMPONENT_H
|
#endif // ES_CORE_COMPONENTS_LOTTIE_COMPONENT_H
|
||||||
|
|
Loading…
Reference in a new issue