mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-02-16 12:05:38 +00:00
Added theme support and proper application integration for LottieComponent.
This commit is contained in:
parent
0c31124cd2
commit
b16ea29088
|
@ -893,6 +893,7 @@ void FileData::launchGame(Window* window)
|
|||
window->queueInfoPopup("ERROR: MISSING EMULATOR CONFIGURATION FOR '" + emulatorEntry + "'",
|
||||
6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
return;
|
||||
}
|
||||
else if (binaryPath.empty()) {
|
||||
|
@ -903,6 +904,7 @@ void FileData::launchGame(Window* window)
|
|||
window->queueInfoPopup("ERROR: COULDN'T FIND EMULATOR, HAS IT BEEN PROPERLY INSTALLED?",
|
||||
6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
@ -951,6 +953,7 @@ void FileData::launchGame(Window* window)
|
|||
Utils::String::toUpper(Utils::FileSystem::getFileName(coreFile)) + "'",
|
||||
6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
@ -970,6 +973,7 @@ void FileData::launchGame(Window* window)
|
|||
|
||||
window->queueInfoPopup("ERROR: INVALID ENTRY IN SYSTEMS CONFIGURATION FILE", 6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -983,6 +987,7 @@ void FileData::launchGame(Window* window)
|
|||
|
||||
window->queueInfoPopup("ERROR: MISSING CORE CONFIGURATION FOR '" + coreEntry + "'", 6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1053,6 +1058,7 @@ void FileData::launchGame(Window* window)
|
|||
|
||||
window->queueInfoPopup("ERROR: INVALID ENTRY IN SYSTEMS CONFIGURATION FILE", 6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1070,6 +1076,7 @@ void FileData::launchGame(Window* window)
|
|||
Utils::String::toUpper(coreName.substr(0, coreName.size()) + "'"),
|
||||
6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1114,6 +1121,7 @@ void FileData::launchGame(Window* window)
|
|||
Utils::String::toUpper(std::to_string(returnValue) + ")"),
|
||||
6000);
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
}
|
||||
else {
|
||||
// Stop showing the game launch notification.
|
||||
|
@ -1146,8 +1154,10 @@ void FileData::launchGame(Window* window)
|
|||
|
||||
// Unless we're running in the background while the game is launched, re-enable the text
|
||||
// scrolling that was disabled in ViewController.
|
||||
if (!runInBackground)
|
||||
if (!runInBackground) {
|
||||
window->setAllowTextScrolling(true);
|
||||
window->setAllowFileAnimation(true);
|
||||
}
|
||||
|
||||
// Update number of times the game has been launched.
|
||||
FileData* gameToUpdate = getSourceFileData();
|
||||
|
|
|
@ -676,8 +676,10 @@ void ViewController::launch(FileData* game)
|
|||
if (mCurrentView)
|
||||
mCurrentView->onPauseVideo();
|
||||
|
||||
// Disable text scrolling. It will be enabled again in FileData upon returning from the game.
|
||||
// Disable text scrolling and stop any Lottie animations. These will be enabled again in
|
||||
// FileData upon returning from the game.
|
||||
mWindow->setAllowTextScrolling(false);
|
||||
mWindow->setAllowFileAnimation(false);
|
||||
|
||||
stopAnimation(1); // Make sure the fade in isn't still playing.
|
||||
mWindow->stopInfoPopup(); // Make sure we disable any existing info popup.
|
||||
|
@ -839,6 +841,7 @@ bool ViewController::input(InputConfig* config, Input input)
|
|||
// screensaver start on schedule.
|
||||
if (mWindow->getGameLaunchedState()) {
|
||||
mWindow->setAllowTextScrolling(true);
|
||||
mWindow->setAllowFileAnimation(true);
|
||||
mWindow->unsetLaunchedGame();
|
||||
// Filter out the "a" button so the game is not restarted if there was such a button press
|
||||
// queued when leaving the game.
|
||||
|
|
|
@ -518,6 +518,10 @@ void DetailedGameListView::update(int deltaTime)
|
|||
|
||||
void DetailedGameListView::onShow()
|
||||
{
|
||||
// Reset any Lottie animations.
|
||||
for (auto extra : mThemeExtras)
|
||||
extra->resetFileAnimation();
|
||||
|
||||
mLastUpdated = nullptr;
|
||||
GuiComponent::onShow();
|
||||
updateInfoPanel();
|
||||
|
|
|
@ -288,6 +288,10 @@ void GridGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
|||
|
||||
void GridGameListView::onShow()
|
||||
{
|
||||
// Reset any Lottie animations.
|
||||
for (auto extra : mThemeExtras)
|
||||
extra->resetFileAnimation();
|
||||
|
||||
GuiComponent::onShow();
|
||||
updateInfoPanel();
|
||||
}
|
||||
|
|
|
@ -551,6 +551,10 @@ void VideoGameListView::update(int deltaTime)
|
|||
|
||||
void VideoGameListView::onShow()
|
||||
{
|
||||
// Reset any Lottie animations.
|
||||
for (auto extra : mThemeExtras)
|
||||
extra->resetFileAnimation();
|
||||
|
||||
mLastUpdated = nullptr;
|
||||
GuiComponent::onShow();
|
||||
updateInfoPanel();
|
||||
|
|
|
@ -203,6 +203,8 @@ public:
|
|||
virtual void onPauseVideo();
|
||||
virtual void onUnpauseVideo();
|
||||
virtual bool isVideoPaused() { return false; }
|
||||
// For Lottie animations.
|
||||
virtual void resetFileAnimation(){};
|
||||
|
||||
virtual void onScreensaverActivate();
|
||||
virtual void onScreensaverDeactivate();
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "Platform.h"
|
||||
#include "Settings.h"
|
||||
#include "components/ImageComponent.h"
|
||||
#include "components/LottieComponent.h"
|
||||
#include "components/TextComponent.h"
|
||||
#include "utils/FileSystemUtil.h"
|
||||
#include "utils/StringUtil.h"
|
||||
|
@ -146,6 +147,19 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> The
|
|||
{"unfilledPath", PATH},
|
||||
{"visible", BOOLEAN},
|
||||
{"zIndex", FLOAT}}},
|
||||
{"animation",
|
||||
{{"pos", NORMALIZED_PAIR},
|
||||
{"size", NORMALIZED_PAIR},
|
||||
{"origin", NORMALIZED_PAIR},
|
||||
{"rotation", FLOAT},
|
||||
{"rotationOrigin", NORMALIZED_PAIR},
|
||||
{"path", PATH},
|
||||
{"speed", FLOAT},
|
||||
{"direction", STRING},
|
||||
{"keepAspectRatio", BOOLEAN},
|
||||
{"delay", FLOAT},
|
||||
{"visible", BOOLEAN},
|
||||
{"zIndex", FLOAT}}},
|
||||
{"badges",
|
||||
{{"pos", NORMALIZED_PAIR},
|
||||
{"size", NORMALIZED_PAIR},
|
||||
|
@ -650,6 +664,8 @@ std::vector<GuiComponent*> ThemeData::makeExtras(const std::shared_ptr<ThemeData
|
|||
comp = new ImageComponent(window);
|
||||
else if (t == "text")
|
||||
comp = new TextComponent(window);
|
||||
else if (t == "animation")
|
||||
comp = new LottieComponent(window);
|
||||
|
||||
if (comp) {
|
||||
comp->setDefaultZIndex(10.0f);
|
||||
|
|
|
@ -42,6 +42,7 @@ Window::Window() noexcept
|
|||
, mRenderLaunchScreen(false)
|
||||
, mGameLaunchedState(false)
|
||||
, mAllowTextScrolling(true)
|
||||
, mAllowFileAnimation(true)
|
||||
, mCachedBackground(false)
|
||||
, mInvalidatedCachedBackground(false)
|
||||
, mVideoPlayerCount(0)
|
||||
|
@ -732,6 +733,7 @@ void Window::startScreensaver()
|
|||
(*it)->onScreensaverActivate();
|
||||
|
||||
setAllowTextScrolling(false);
|
||||
setAllowFileAnimation(false);
|
||||
mScreensaver->startScreensaver(true);
|
||||
mRenderScreensaver = true;
|
||||
}
|
||||
|
@ -743,6 +745,7 @@ bool Window::stopScreensaver()
|
|||
mScreensaver->stopScreensaver();
|
||||
mRenderScreensaver = false;
|
||||
setAllowTextScrolling(true);
|
||||
setAllowFileAnimation(true);
|
||||
|
||||
// Tell the GUI components the screensaver has stopped.
|
||||
for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); ++it) {
|
||||
|
@ -769,6 +772,8 @@ void Window::startMediaViewer(FileData* game)
|
|||
if (mMediaViewer) {
|
||||
if (mMediaViewer->startMediaViewer(game)) {
|
||||
setAllowTextScrolling(false);
|
||||
setAllowFileAnimation(false);
|
||||
|
||||
mRenderMediaViewer = true;
|
||||
}
|
||||
}
|
||||
|
@ -779,6 +784,7 @@ void Window::stopMediaViewer()
|
|||
if (mMediaViewer) {
|
||||
mMediaViewer->stopMediaViewer();
|
||||
setAllowTextScrolling(true);
|
||||
setAllowFileAnimation(true);
|
||||
}
|
||||
|
||||
mRenderMediaViewer = false;
|
||||
|
|
|
@ -139,9 +139,13 @@ public:
|
|||
void invalidateCachedBackground();
|
||||
|
||||
bool getGameLaunchedState() { return mGameLaunchedState; }
|
||||
void setAllowTextScrolling(bool setting) { mAllowTextScrolling = setting; }
|
||||
void setAllowTextScrolling(bool value) { mAllowTextScrolling = value; }
|
||||
bool getAllowTextScrolling() { return mAllowTextScrolling; }
|
||||
|
||||
// For Lottie animations.
|
||||
void setAllowFileAnimation(bool value) { mAllowFileAnimation = value; }
|
||||
bool getAllowFileAnimation() { return mAllowFileAnimation; }
|
||||
|
||||
void setChangedThemeSet() { mChangedThemeSet = true; }
|
||||
bool getChangedThemeSet() { return mChangedThemeSet; }
|
||||
|
||||
|
@ -191,6 +195,7 @@ private:
|
|||
bool mRenderLaunchScreen;
|
||||
bool mGameLaunchedState;
|
||||
bool mAllowTextScrolling;
|
||||
bool mAllowFileAnimation;
|
||||
bool mCachedBackground;
|
||||
bool mInvalidatedCachedBackground;
|
||||
|
||||
|
|
|
@ -6,9 +6,12 @@
|
|||
// Component to play Lottie animations using the rlottie library.
|
||||
//
|
||||
|
||||
#define DEBUG_ANIMATION true
|
||||
|
||||
#include "components/LottieComponent.h"
|
||||
|
||||
#include "Log.h"
|
||||
#include "ThemeData.h"
|
||||
#include "Window.h"
|
||||
#include "resources/ResourceManager.h"
|
||||
#include "utils/FileSystemUtil.h"
|
||||
|
@ -29,6 +32,8 @@ LottieComponent::LottieComponent(Window* window)
|
|||
, mTargetPacing{0}
|
||||
, mTimeAccumulator{0}
|
||||
, mHoldFrame{false}
|
||||
, mDroppedFrames{0}
|
||||
, mSpeedModifier{1.0f}
|
||||
, mKeepAspectRatio{true}
|
||||
{
|
||||
// Get an empty texture for rendering the animation.
|
||||
|
@ -54,8 +59,8 @@ LottieComponent::LottieComponent(Window* window)
|
|||
setOrigin(0.5f, 0.5f);
|
||||
setSize(Renderer::getScreenWidth() * 0.2f, Renderer::getScreenHeight() * 0.2f);
|
||||
setPosition(Renderer::getScreenWidth() * 0.3f, Renderer::getScreenHeight() * 0.3f);
|
||||
setDefaultZIndex(30.0f);
|
||||
setZIndex(30.0f);
|
||||
setDefaultZIndex(10.0f);
|
||||
setZIndex(10.0f);
|
||||
}
|
||||
|
||||
LottieComponent::~LottieComponent()
|
||||
|
@ -100,8 +105,37 @@ void LottieComponent::setAnimation(const std::string& path)
|
|||
return;
|
||||
}
|
||||
|
||||
size_t width = static_cast<size_t>(mSize.x);
|
||||
size_t height = static_cast<size_t>(mSize.y);
|
||||
if (!mKeepAspectRatio && (mSize.x == 0.0f || mSize.y == 0.0f)) {
|
||||
LOG(LogWarning) << "LottieComponent: Width or height auto sizing is incompatible with "
|
||||
"disabling of <keepAspectRatio> so ignoring this setting";
|
||||
}
|
||||
|
||||
size_t width{0};
|
||||
size_t height{0};
|
||||
|
||||
if (mSize.x == 0.0f || mSize.y == 0.0f) {
|
||||
size_t viewportWidth{0};
|
||||
size_t viewportHeight{0};
|
||||
|
||||
mAnimation->size(viewportWidth, viewportHeight);
|
||||
double sizeRatio = static_cast<double>(viewportWidth) / static_cast<double>(viewportHeight);
|
||||
|
||||
if (mSize.x == 0) {
|
||||
width = static_cast<size_t>(static_cast<double>(mSize.y) * sizeRatio);
|
||||
height = static_cast<size_t>(mSize.y);
|
||||
}
|
||||
else {
|
||||
width = static_cast<size_t>(mSize.x);
|
||||
height = static_cast<size_t>(static_cast<double>(mSize.x) / sizeRatio);
|
||||
}
|
||||
}
|
||||
else {
|
||||
width = static_cast<size_t>(mSize.x);
|
||||
height = static_cast<size_t>(mSize.y);
|
||||
}
|
||||
|
||||
mSize.x = static_cast<float>(width);
|
||||
mSize.y = static_cast<float>(height);
|
||||
|
||||
mPictureRGBA.resize(width * height * 4);
|
||||
mSurface = std::make_unique<rlottie::Surface>(reinterpret_cast<uint32_t*>(&mPictureRGBA[0]),
|
||||
|
@ -122,12 +156,29 @@ void LottieComponent::setAnimation(const std::string& path)
|
|||
mTotalFrames = mAnimation->totalFrame();
|
||||
mFrameRate = mAnimation->frameRate();
|
||||
mFrameSize = width * height * 4;
|
||||
mTargetPacing = static_cast<int>((1000.0 / mFrameRate) / static_cast<double>(mSpeedModifier));
|
||||
|
||||
mTargetPacing = static_cast<int>(1000.0 / mFrameRate);
|
||||
|
||||
LOG(LogDebug) << "Total number of frames: " << mTotalFrames;
|
||||
LOG(LogDebug) << "Frame rate: " << mFrameRate;
|
||||
LOG(LogDebug) << "Duration: " << duration;
|
||||
if (DEBUG_ANIMATION) {
|
||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Rasterized width: " << mSize.x;
|
||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Rasterized height: " << mSize.y;
|
||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Total number of frames: "
|
||||
<< mTotalFrames;
|
||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Frame rate: " << mFrameRate;
|
||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Speed modifier: " << mSpeedModifier;
|
||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Target duration: "
|
||||
<< duration / mSpeedModifier * 1000.0 << " ms";
|
||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Frame size: " << mFrameSize << " bytes ("
|
||||
<< std::fixed << std::setprecision(1)
|
||||
<< static_cast<double>(mFrameSize) / 1024.0 / 1024.0 << " MiB)";
|
||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Animation size: "
|
||||
<< mFrameSize * mTotalFrames << " bytes (" << std::fixed
|
||||
<< std::setprecision(1)
|
||||
<< static_cast<double>(mFrameSize * mTotalFrames) / 1024.0 / 1024.0
|
||||
<< " MiB)";
|
||||
LOG(LogDebug) << "LottieComponent::setAnimation(): Per file maximum cache size: "
|
||||
<< mMaxCacheSize << " bytes (" << std::fixed << std::setprecision(1)
|
||||
<< static_cast<double>(mMaxCacheSize) / 1024.0 / 1024.0 << " MiB)";
|
||||
}
|
||||
}
|
||||
|
||||
void LottieComponent::onSizeChanged()
|
||||
|
@ -142,8 +193,46 @@ void LottieComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
|||
const std::string& element,
|
||||
unsigned int properties)
|
||||
{
|
||||
// using namespace ThemeFlags;
|
||||
using namespace ThemeFlags;
|
||||
|
||||
const ThemeData::ThemeElement* elem{theme->getElement(view, element, "animation")};
|
||||
|
||||
if (elem->has("size")) {
|
||||
glm::vec2 size = elem->get<glm::vec2>("size");
|
||||
if (size.x == 0.0f && size.y == 0.0f) {
|
||||
LOG(LogWarning) << "LottieComponent: Invalid theme configuration, <size> set to \""
|
||||
<< size.x << " " << size.y << "\"";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (elem->has("speed")) {
|
||||
const float speed{elem->get<float>("speed")};
|
||||
if (speed < 0.2f || speed > 3.0f) {
|
||||
LOG(LogWarning) << "LottieComponent: Invalid theme configuration, <speed> set to \""
|
||||
<< std::fixed << std::setprecision(1) << speed << "\"";
|
||||
}
|
||||
else {
|
||||
mSpeedModifier = speed;
|
||||
}
|
||||
}
|
||||
|
||||
if (elem->has("keepAspectRatio")) {
|
||||
mKeepAspectRatio = elem->get<bool>("keepAspectRatio");
|
||||
}
|
||||
|
||||
GuiComponent::applyTheme(theme, view, element, properties);
|
||||
|
||||
if (elem->has("path")) {
|
||||
std::string path{elem->get<std::string>("path")};
|
||||
if (path != "") {
|
||||
setAnimation(path);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG(LogWarning) << "LottieComponent: Invalid theme configuration, <path> not set";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void LottieComponent::update(int deltaTime)
|
||||
|
@ -151,7 +240,23 @@ void LottieComponent::update(int deltaTime)
|
|||
if (mAnimation == nullptr)
|
||||
return;
|
||||
|
||||
if (mTimeAccumulator < mTargetPacing) {
|
||||
if (mWindow->getAllowFileAnimation()) {
|
||||
mPause = false;
|
||||
}
|
||||
else {
|
||||
mPause = true;
|
||||
mTimeAccumulator = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// If the time accumulator value is really high something must have happened such as the
|
||||
// application having been suspended. Reset it to zero in this case as it would otherwise
|
||||
// never recover.
|
||||
if (mTimeAccumulator > deltaTime * 200)
|
||||
mTimeAccumulator = 0;
|
||||
|
||||
// Keep animation speed from going too quickly.
|
||||
if (mTimeAccumulator + deltaTime < mTargetPacing) {
|
||||
mHoldFrame = true;
|
||||
mTimeAccumulator += deltaTime;
|
||||
}
|
||||
|
@ -159,6 +264,18 @@ void LottieComponent::update(int deltaTime)
|
|||
mHoldFrame = false;
|
||||
mTimeAccumulator = mTimeAccumulator - mTargetPacing + deltaTime;
|
||||
}
|
||||
|
||||
// Rudimentary frame skipping logic, not entirely accurate but probably good enough.
|
||||
while (mTimeAccumulator - deltaTime > mTargetPacing) {
|
||||
if (DEBUG_ANIMATION && 0) {
|
||||
LOG(LogDebug)
|
||||
<< "LottieComponent::update(): Skipped frame, mTimeAccumulator / mTargetPacing: "
|
||||
<< mTimeAccumulator - deltaTime << " / " << mTargetPacing;
|
||||
}
|
||||
++mFrameNum;
|
||||
++mDroppedFrames;
|
||||
mTimeAccumulator -= mTargetPacing;
|
||||
}
|
||||
}
|
||||
|
||||
void LottieComponent::render(const glm::mat4& parentTrans)
|
||||
|
@ -171,57 +288,79 @@ void LottieComponent::render(const glm::mat4& parentTrans)
|
|||
|
||||
glm::mat4 trans{parentTrans * getTransform()};
|
||||
|
||||
if (mFrameNum >= mTotalFrames)
|
||||
mFrameNum = 0;
|
||||
|
||||
if (mFrameNum == 0)
|
||||
mAnimationStartTime = std::chrono::system_clock::now();
|
||||
|
||||
bool renderNextFrame = false;
|
||||
|
||||
if (mFuture.valid()) {
|
||||
if (mFuture.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready) {
|
||||
mFuture.get();
|
||||
|
||||
// Cache frame if caching is enabled and we're not exceeding either the per-file
|
||||
// max cache size or the total cache size. Note that this is completely unrelated
|
||||
// to the texture caching used for images.
|
||||
if (mCacheFrames && mFrameCache.find(mFrameNum) == mFrameCache.end()) {
|
||||
size_t newCacheSize = mCacheSize + mFrameSize;
|
||||
if (newCacheSize < mMaxCacheSize &&
|
||||
mTotalFrameCache + mFrameSize < mMaxTotalFrameCache) {
|
||||
mFrameCache[mFrameNum] = mPictureRGBA;
|
||||
mCacheSize += mFrameSize;
|
||||
mTotalFrameCache += mFrameSize;
|
||||
}
|
||||
}
|
||||
|
||||
mTexture->initFromPixels(&mPictureRGBA.at(0), static_cast<size_t>(mSize.x),
|
||||
static_cast<size_t>(mSize.y));
|
||||
|
||||
++mFrameNum;
|
||||
|
||||
if (mFrameNum == mTotalFrames)
|
||||
renderNextFrame = false;
|
||||
else
|
||||
renderNextFrame = true;
|
||||
}
|
||||
// This is necessary as there may otherwise be no texture to render when paused.
|
||||
if (mPause && mTexture->getSize().x == 0.0f) {
|
||||
mTexture->initFromPixels(&mPictureRGBA.at(0), static_cast<size_t>(mSize.x),
|
||||
static_cast<size_t>(mSize.y));
|
||||
}
|
||||
else {
|
||||
if (mFrameCache.find(mFrameNum) != mFrameCache.end()) {
|
||||
if (!mHoldFrame) {
|
||||
mTexture->initFromPixels(&mFrameCache[mFrameNum][0], static_cast<size_t>(mSize.x),
|
||||
|
||||
// Don't render any new frames if paused or if a menu is open.
|
||||
if (!mPause && mWindow->getGuiStackSize() < 2) {
|
||||
if (mFrameNum >= mTotalFrames) {
|
||||
if (DEBUG_ANIMATION) {
|
||||
LOG(LogError) << "Dropped frames: " << mDroppedFrames;
|
||||
LOG(LogDebug) << "LottieComponent::render(): Actual duration: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now() - mAnimationStartTime)
|
||||
.count()
|
||||
<< " ms";
|
||||
}
|
||||
mTimeAccumulator = 0;
|
||||
mFrameNum = 0;
|
||||
mDroppedFrames = 0;
|
||||
}
|
||||
|
||||
if (DEBUG_ANIMATION) {
|
||||
if (mFrameNum == 0)
|
||||
mAnimationStartTime = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
bool renderNextFrame = false;
|
||||
|
||||
if (mFuture.valid()) {
|
||||
if (mFuture.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready) {
|
||||
mFuture.get();
|
||||
// Cache frame if caching is enabled and we're not exceeding either the per-file
|
||||
// max cache size or the total cache size. Note that this is completely unrelated
|
||||
// to the texture caching used for images.
|
||||
if (mCacheFrames && mFrameCache.find(mFrameNum) == mFrameCache.end()) {
|
||||
size_t newCacheSize = mCacheSize + mFrameSize;
|
||||
if (newCacheSize < mMaxCacheSize &&
|
||||
mTotalFrameCache + mFrameSize < mMaxTotalFrameCache) {
|
||||
mFrameCache[mFrameNum] = mPictureRGBA;
|
||||
mCacheSize += mFrameSize;
|
||||
mTotalFrameCache += mFrameSize;
|
||||
}
|
||||
}
|
||||
|
||||
mTexture->initFromPixels(&mPictureRGBA.at(0), static_cast<size_t>(mSize.x),
|
||||
static_cast<size_t>(mSize.y));
|
||||
|
||||
++mFrameNum;
|
||||
|
||||
if (mFrameNum == mTotalFrames)
|
||||
renderNextFrame = false;
|
||||
else
|
||||
renderNextFrame = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
renderNextFrame = true;
|
||||
if (mFrameCache.find(mFrameNum) != mFrameCache.end()) {
|
||||
if (!mHoldFrame) {
|
||||
mTexture->initFromPixels(&mFrameCache[mFrameNum][0],
|
||||
static_cast<size_t>(mSize.x),
|
||||
static_cast<size_t>(mSize.y));
|
||||
++mFrameNum;
|
||||
}
|
||||
}
|
||||
else {
|
||||
renderNextFrame = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (renderNextFrame && !mHoldFrame)
|
||||
mFuture = mAnimation->render(mFrameNum, *mSurface, mKeepAspectRatio);
|
||||
if (renderNextFrame && !mHoldFrame)
|
||||
mFuture = mAnimation->render(mFrameNum, *mSurface, mKeepAspectRatio);
|
||||
}
|
||||
|
||||
Renderer::setMatrix(trans);
|
||||
|
||||
|
@ -252,13 +391,4 @@ void LottieComponent::render(const glm::mat4& parentTrans)
|
|||
// Render it.
|
||||
Renderer::drawTriangleStrips(&vertices[0], 4, trans);
|
||||
}
|
||||
|
||||
if (!mHoldFrame && mFrameNum == mTotalFrames - 1) {
|
||||
mAnimationEndTime = std::chrono::system_clock::now();
|
||||
LOG(LogDebug) << "LottieComponent::render(): Animation duration: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(mAnimationEndTime -
|
||||
mAnimationStartTime)
|
||||
.count()
|
||||
<< " ms";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,12 @@ public:
|
|||
mMaxCacheSize = static_cast<size_t>(glm::clamp(value, 0, 1024) * 1024 * 1024);
|
||||
}
|
||||
|
||||
void resetFileAnimation() override
|
||||
{
|
||||
mTimeAccumulator = 0;
|
||||
mFrameNum = 0;
|
||||
}
|
||||
|
||||
void onSizeChanged() override;
|
||||
|
||||
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||
|
@ -66,12 +72,14 @@ private:
|
|||
int mTargetPacing;
|
||||
int mTimeAccumulator;
|
||||
bool mHoldFrame;
|
||||
int mDroppedFrames;
|
||||
|
||||
bool mPause;
|
||||
|
||||
float mSpeedModifier;
|
||||
bool mKeepAspectRatio;
|
||||
|
||||
// TEMPORARY.
|
||||
std::chrono::time_point<std::chrono::system_clock> mAnimationStartTime;
|
||||
std::chrono::time_point<std::chrono::system_clock> mAnimationEndTime;
|
||||
};
|
||||
|
||||
#endif // ES_CORE_COMPONENTS_LOTTIE_COMPONENT_H
|
||||
|
|
Loading…
Reference in a new issue