mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
Created proper program structure for LottieComponent.
This commit is contained in:
parent
8d648867e1
commit
3f629b6c1e
|
@ -25,6 +25,7 @@ LottieComponent::LottieComponent(Window* window)
|
||||||
, mTargetPacing{0}
|
, mTargetPacing{0}
|
||||||
, mTimeAccumulator{0}
|
, mTimeAccumulator{0}
|
||||||
, mHoldFrame{false}
|
, mHoldFrame{false}
|
||||||
|
, mKeepAspectRatio{true}
|
||||||
{
|
{
|
||||||
// Get an empty texture for rendering the animation.
|
// Get an empty texture for rendering the animation.
|
||||||
mTexture = TextureResource::get("");
|
mTexture = TextureResource::get("");
|
||||||
|
@ -34,37 +35,45 @@ LottieComponent::LottieComponent(Window* window)
|
||||||
mTexture->setFormat(Renderer::Texture::BGRA);
|
mTexture->setFormat(Renderer::Texture::BGRA);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: Temporary test files.
|
// Set component defaults.
|
||||||
std::string filePath{":/animations/a_mountain.json"};
|
setOrigin(0.5f, 0.5f);
|
||||||
// std::string filePath{":/animations/bell.json"};
|
setSize(Renderer::getScreenWidth() * 0.2f, Renderer::getScreenHeight() * 0.2f);
|
||||||
|
setPosition(Renderer::getScreenWidth() * 0.3f, Renderer::getScreenHeight() * 0.3f);
|
||||||
|
setDefaultZIndex(30.0f);
|
||||||
|
setZIndex(30.0f);
|
||||||
|
}
|
||||||
|
|
||||||
if (filePath.empty()) {
|
void LottieComponent::setAnimation(const std::string& path)
|
||||||
|
{
|
||||||
|
if (mAnimation != nullptr) {
|
||||||
|
if (mFuture.valid())
|
||||||
|
mFuture.get();
|
||||||
|
mSurface.reset();
|
||||||
|
mAnimation.reset();
|
||||||
|
mPictureRGBA.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
mPath = path;
|
||||||
|
|
||||||
|
if (mPath.empty()) {
|
||||||
LOG(LogError) << "Path to Lottie animation is empty";
|
LOG(LogError) << "Path to Lottie animation is empty";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filePath.front() == ':')
|
if (mPath.front() == ':')
|
||||||
filePath = ResourceManager::getInstance().getResourcePath(filePath);
|
mPath = ResourceManager::getInstance().getResourcePath(mPath);
|
||||||
else
|
else
|
||||||
filePath = Utils::FileSystem::expandHomePath(filePath);
|
mPath = Utils::FileSystem::expandHomePath(mPath);
|
||||||
|
|
||||||
if (!(Utils::FileSystem::isRegularFile(filePath) || Utils::FileSystem::isSymlink(filePath))) {
|
if (!(Utils::FileSystem::isRegularFile(mPath) || Utils::FileSystem::isSymlink(mPath))) {
|
||||||
LOG(LogError) << "Couldn't open Lottie animation file \"" << filePath << "\"";
|
LOG(LogError) << "Couldn't open Lottie animation file \"" << mPath << "\"";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Only meant for development, to be replaced with proper theming support.
|
mAnimation = rlottie::Animation::loadFromFile(mPath);
|
||||||
setOrigin(0.5f, 0.5f);
|
|
||||||
setSize(500.0f, 500.0f);
|
|
||||||
setPosition(mSize.x * 0.35f, mSize.y * 0.5f);
|
|
||||||
setDefaultZIndex(70.0f);
|
|
||||||
setZIndex(70.0f);
|
|
||||||
setVisible(true);
|
|
||||||
|
|
||||||
mAnimation = rlottie::Animation::loadFromFile(filePath);
|
|
||||||
|
|
||||||
if (mAnimation == nullptr) {
|
if (mAnimation == nullptr) {
|
||||||
LOG(LogError) << "Couldn't parse Lottie animation file \"" << filePath << "\"";
|
LOG(LogError) << "Couldn't parse Lottie animation file \"" << mPath << "\"";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,13 +81,21 @@ LottieComponent::LottieComponent(Window* window)
|
||||||
size_t height = static_cast<size_t>(mSize.y);
|
size_t height = static_cast<size_t>(mSize.y);
|
||||||
|
|
||||||
mPictureRGBA.resize(width * height * 4);
|
mPictureRGBA.resize(width * height * 4);
|
||||||
|
|
||||||
mSurface = std::make_unique<rlottie::Surface>(reinterpret_cast<uint32_t*>(&mPictureRGBA[0]),
|
mSurface = std::make_unique<rlottie::Surface>(reinterpret_cast<uint32_t*>(&mPictureRGBA[0]),
|
||||||
width, height, width * sizeof(uint32_t));
|
width, height, width * sizeof(uint32_t));
|
||||||
|
|
||||||
// Animation time in seconds.
|
if (mSurface == nullptr) {
|
||||||
double duration = mAnimation->duration();
|
LOG(LogError) << "Couldn't create Lottie surface for file \"" << mPath << "\"";
|
||||||
|
mAnimation.reset();
|
||||||
|
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.
|
||||||
|
double duration = mAnimation->duration();
|
||||||
mTotalFrames = mAnimation->totalFrame();
|
mTotalFrames = mAnimation->totalFrame();
|
||||||
mFrameRate = mAnimation->frameRate();
|
mFrameRate = mAnimation->frameRate();
|
||||||
|
|
||||||
|
@ -89,6 +106,12 @@ LottieComponent::LottieComponent(Window* window)
|
||||||
LOG(LogDebug) << "Duration: " << duration;
|
LOG(LogDebug) << "Duration: " << duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LottieComponent::onSizeChanged()
|
||||||
|
{
|
||||||
|
// Setting the animation again will completely reinitialize it.
|
||||||
|
setAnimation(mPath);
|
||||||
|
}
|
||||||
|
|
||||||
void LottieComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
void LottieComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
const std::string& view,
|
const std::string& view,
|
||||||
const std::string& element,
|
const std::string& element,
|
||||||
|
@ -100,6 +123,9 @@ void LottieComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
|
|
||||||
void LottieComponent::update(int deltaTime)
|
void LottieComponent::update(int deltaTime)
|
||||||
{
|
{
|
||||||
|
if (mAnimation == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
if (mTimeAccumulator < mTargetPacing) {
|
if (mTimeAccumulator < mTargetPacing) {
|
||||||
mHoldFrame = true;
|
mHoldFrame = true;
|
||||||
mTimeAccumulator += deltaTime;
|
mTimeAccumulator += deltaTime;
|
||||||
|
@ -115,6 +141,11 @@ void LottieComponent::render(const glm::mat4& parentTrans)
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (mAnimation == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
glm::mat4 trans{parentTrans * getTransform()};
|
||||||
|
|
||||||
if (mFrameNum >= mTotalFrames)
|
if (mFrameNum >= mTotalFrames)
|
||||||
mFrameNum = 0;
|
mFrameNum = 0;
|
||||||
|
|
||||||
|
@ -135,33 +166,37 @@ void LottieComponent::render(const glm::mat4& parentTrans)
|
||||||
else {
|
else {
|
||||||
renderNextFrame = true;
|
renderNextFrame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderNextFrame && !mHoldFrame)
|
if (renderNextFrame && !mHoldFrame)
|
||||||
mFuture = mAnimation->render(mFrameNum, *mSurface);
|
mFuture = mAnimation->render(mFrameNum, *mSurface, mKeepAspectRatio);
|
||||||
|
|
||||||
|
Renderer::setMatrix(trans);
|
||||||
|
|
||||||
|
if (Settings::getInstance()->getBool("DebugImage"))
|
||||||
|
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033);
|
||||||
|
|
||||||
if (mTexture->getSize().x != 0.0f) {
|
if (mTexture->getSize().x != 0.0f) {
|
||||||
mTexture->bind();
|
mTexture->bind();
|
||||||
|
|
||||||
|
Renderer::Vertex vertices[4];
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
mVertices[0] = {{0.0f, 0.0f }, {0.0f, 0.0f}, 0xFFFFFFFF};
|
vertices[0] = {{0.0f, 0.0f }, {0.0f, 0.0f}, 0xFFFFFFFF};
|
||||||
mVertices[1] = {{0.0f, mSize.y}, {0.0f, 1.0f}, 0xFFFFFFFF};
|
vertices[1] = {{0.0f, mSize.y}, {0.0f, 1.0f}, 0xFFFFFFFF};
|
||||||
mVertices[2] = {{mSize.x, 0.0f }, {1.0f, 0.0f}, 0xFFFFFFFF};
|
vertices[2] = {{mSize.x, 0.0f }, {1.0f, 0.0f}, 0xFFFFFFFF};
|
||||||
mVertices[3] = {{mSize.x, mSize.y}, {1.0f, 1.0f}, 0xFFFFFFFF};
|
vertices[3] = {{mSize.x, mSize.y}, {1.0f, 1.0f}, 0xFFFFFFFF};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
// Round vertices.
|
// Round vertices.
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
mVertices[i].pos = glm::round(mVertices[i].pos);
|
vertices[i].pos = glm::round(vertices[i].pos);
|
||||||
|
|
||||||
#if defined(USE_OPENGL_21)
|
#if defined(USE_OPENGL_21)
|
||||||
// Perform color space conversion from BGRA to RGBA.
|
// Perform color space conversion from BGRA to RGBA.
|
||||||
mVertices[0].shaders = Renderer::SHADER_BGRA_TO_RGBA;
|
vertices[0].shaders = Renderer::SHADER_BGRA_TO_RGBA;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Render it.
|
// Render it.
|
||||||
glm::mat4 trans{parentTrans * getTransform()};
|
Renderer::drawTriangleStrips(&vertices[0], 4, trans);
|
||||||
Renderer::setMatrix(trans);
|
|
||||||
Renderer::drawTriangleStrips(&mVertices[0], 4, trans);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mHoldFrame && mFrameNum == mTotalFrames - 1) {
|
if (!mHoldFrame && mFrameNum == mTotalFrames - 1) {
|
||||||
|
|
|
@ -23,6 +23,11 @@ class LottieComponent : public GuiComponent
|
||||||
public:
|
public:
|
||||||
LottieComponent(Window* window);
|
LottieComponent(Window* window);
|
||||||
|
|
||||||
|
void setAnimation(const std::string& path);
|
||||||
|
void setKeepAspectRatio(bool value) { mKeepAspectRatio = value; }
|
||||||
|
|
||||||
|
void onSizeChanged() override;
|
||||||
|
|
||||||
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme,
|
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
const std::string& view,
|
const std::string& view,
|
||||||
const std::string& element,
|
const std::string& element,
|
||||||
|
@ -35,11 +40,10 @@ private:
|
||||||
std::shared_ptr<TextureResource> mTexture;
|
std::shared_ptr<TextureResource> mTexture;
|
||||||
std::vector<uint8_t> mPictureRGBA;
|
std::vector<uint8_t> mPictureRGBA;
|
||||||
|
|
||||||
Renderer::Vertex mVertices[4];
|
|
||||||
|
|
||||||
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;
|
||||||
size_t mTotalFrames;
|
size_t mTotalFrames;
|
||||||
size_t mFrameNum;
|
size_t mFrameNum;
|
||||||
double mFrameRate;
|
double mFrameRate;
|
||||||
|
@ -47,6 +51,8 @@ private:
|
||||||
int mTimeAccumulator;
|
int mTimeAccumulator;
|
||||||
bool mHoldFrame;
|
bool mHoldFrame;
|
||||||
|
|
||||||
|
bool mKeepAspectRatio;
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::system_clock> mAnimationStartTime;
|
std::chrono::time_point<std::chrono::system_clock> mAnimationStartTime;
|
||||||
std::chrono::time_point<std::chrono::system_clock> mAnimationEndTime;
|
std::chrono::time_point<std::chrono::system_clock> mAnimationEndTime;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue