Skip to content

Commit

Permalink
Change to Inherit Texture2D
Browse files Browse the repository at this point in the history
  • Loading branch information
beicause committed May 6, 2024
1 parent 655bdf8 commit d0f179f
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 83 deletions.
51 changes: 51 additions & 0 deletions doc/classes/LottieTexture2D.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="LottieTexture2D" inherits="Texture2D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<methods>
<method name="get_duration">
<return type="float" />
<description>
Returns the duration of the Lottie animation in seconds.
</description>
</method>
<method name="get_total_frame">
<return type="float" />
<description>
Returns the total number of frames in the animation.
</description>
</method>
<method name="load_json" qualifiers="static">
<return type="LottieTexture2D" />
<param index="0" name="p_json" type="JSON" />
<param index="1" name="p_scale" type="float" default="1" />
<description>
Loads Lottie from the json.
</description>
</method>
<method name="load_string" qualifiers="static">
<return type="LottieTexture2D" />
<param index="0" name="p_string" type="String" />
<param index="1" name="p_scale" type="float" default="1" />
<description>
Loads Lottie from the string.
</description>
</method>
</methods>
<members>
<member name="frame" type="float" setter="set_frame" getter="get_frame" default="0.0">
The current frame in the animation.
</member>
<member name="json" type="JSON" setter="set_json" getter="get_json">
The Lottie JSON file.
</member>
<member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="scale" type="float" setter="set_scale" getter="get_scale" default="1.0">
The scaling factor of the Lottie animation. Set it to change the texture size.
</member>
</members>
</class>
151 changes: 88 additions & 63 deletions modules/svg/lottie_sheet.cpp → modules/svg/lottie_texture.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**************************************************************************/
/* lottie_sheet.cpp */
/* lottie_texture.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
Expand Down Expand Up @@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "lottie_sheet.h"
#include "lottie_texture.h"

#include "core/os/memory.h"
#include "core/variant/variant.h"

#include <thorvg.h>

void LottieSheet::_load_data(String p_string, float p_scale) {
void LottieTexture2D::_load_data(String p_string, float p_scale) {
ERR_FAIL_COND_MSG(Math::is_zero_approx(p_scale), "LottieSheet: Can't load Lottie with a scale of 0.");

tvg::Result result = picture->load(p_string.utf8(), p_string.utf8().size(), "lottie", true);
Expand All @@ -45,45 +45,49 @@ void LottieSheet::_load_data(String p_string, float p_scale) {
float fw, fh;
picture->size(&fw, &fh);

uint32_t _width = MAX(1, round(fw * p_scale));
uint32_t _height = MAX(1, round(fh * p_scale));
uint32_t w = MAX(1, round(fw * p_scale));
uint32_t h = MAX(1, round(fh * p_scale));

const uint32_t max_dimension = 16384;
if (_width > max_dimension || _height > max_dimension) {
if (w > max_dimension || h > max_dimension) {
WARN_PRINT(vformat(
String::utf8("LottieSheet: Target canvas dimensions %d×%d (with scale %.2f) exceed the max supported dimensions %d×%d. The target canvas will be scaled down."),
_width, _height, p_scale, max_dimension, max_dimension));
_width = MIN(_width, max_dimension);
_height = MIN(_height, max_dimension);
w, h, p_scale, max_dimension, max_dimension));
w = MIN(w, max_dimension);
h = MIN(h, max_dimension);
}

picture->size(_width, _height);
this->width = _width;
this->height = _height;
image = Image::create_empty(_width, _height, false, Image::FORMAT_RGBA8);
picture->size(w, h);
this->width = w;
this->height = h;
image = Image::create_empty(w, h, false, Image::FORMAT_RGBA8);
// Note: memalloc here, be sure to memfree before any return.
buffer = (uint32_t *)(buffer == nullptr ? memalloc(sizeof(uint32_t) * _width * _height) : memrealloc(buffer, sizeof(uint32_t) * _width * _height));
}
buffer = (uint32_t *)(buffer == nullptr ? memalloc(sizeof(uint32_t) * w * h) : memrealloc(buffer, sizeof(uint32_t) * w * h));

Ref<LottieSheet> LottieSheet::load_json(Ref<JSON> p_json, float p_scale) {
String data = p_json->get_parsed_text();
if (data.is_empty()) {
data = p_json->to_string();
if (texture.is_null()) {
texture = RenderingServer::get_singleton()->texture_2d_create(image);
} else {
RID new_texture = RenderingServer::get_singleton()->texture_2d_create(image);
RenderingServer::get_singleton()->texture_replace(texture, new_texture);
}
Ref<LottieSheet> ret = memnew(LottieSheet);
ret->_load_data(data, p_scale);
ret->json = p_json;
set_frame(frame);
}

Ref<LottieTexture2D> LottieTexture2D::load_json(Ref<JSON> p_json, float p_scale) {
Ref<LottieTexture2D> ret = memnew(LottieTexture2D);
ret->set_json(p_json);
return ret;
}

Ref<LottieSheet> LottieSheet::load_string(String p_string, float p_scale) {
Ref<LottieSheet> ret = memnew(LottieSheet);
Ref<LottieTexture2D> LottieTexture2D::load_string(String p_string, float p_scale) {
Ref<LottieTexture2D> ret = memnew(LottieTexture2D);
ret->_load_data(p_string, p_scale);
ret->json.instantiate();
ret->json->parse(p_string, true);
return ret;
}

void LottieSheet::update_frame(float frame) {
void LottieTexture2D::set_frame(float frame) {

Check failure on line 90 in modules/svg/lottie_texture.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor w/ Mono (target=editor)

declaration of 'frame' shadows a member of 'LottieTexture2D' [-Werror=shadow]

Check failure on line 90 in modules/svg/lottie_texture.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=gold)

declaration of 'frame' shadows a member of 'LottieTexture2D' [-Werror=shadow]

Check failure on line 90 in modules/svg/lottie_texture.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Editor (target=editor, tests=yes)

the following warning is treated as an error

Check warning on line 90 in modules/svg/lottie_texture.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Editor (target=editor, tests=yes)

declaration of 'frame' hides class member

Check failure on line 90 in modules/svg/lottie_texture.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Template w/ Mono (target=template_release)

declaration of 'frame' shadows a member of 'LottieTexture2D' [-Werror=shadow]

Check failure on line 90 in modules/svg/lottie_texture.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Template (target=template_release)

the following warning is treated as an error

Check warning on line 90 in modules/svg/lottie_texture.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Template (target=template_release)

declaration of 'frame' hides class member
tvg::Result res = animation->frame(frame);
if (res == tvg::Result::Success) {
sw_canvas->update(picture);
Expand Down Expand Up @@ -126,60 +130,81 @@ void LottieSheet::update_frame(float frame) {
res = sw_canvas->clear(true);

image->set_data(width, height, false, Image::FORMAT_RGBA8, image_data);
}

Ref<Image> LottieSheet::get_image() { return image; };

Ref<Image> LottieSheet::get_frame_image(float frame) {
update_frame(frame);
return image;
};

Vector2i LottieSheet::get_image_size() {
return Vector2i(width, height);
if (texture.is_null()) {
texture = RenderingServer::get_singleton()->texture_2d_create(image);
} else {
RID new_texture = RenderingServer::get_singleton()->texture_2d_create(image);
RenderingServer::get_singleton()->texture_replace(texture, new_texture);
}
this->frame = frame;
}

float LottieSheet::get_total_frame() { return animation->totalFrame(); };
float LottieTexture2D::get_total_frame() { return animation->totalFrame(); };

float LottieSheet::get_duration() { return animation->duration(); };
float LottieTexture2D::get_duration() { return animation->duration(); };

Ref<JSON> LottieSheet::get_json() { return json; }

void LottieSheet::set_json(Ref<JSON> p_json) {
String data = p_json->get_parsed_text();
if (data.is_empty()) {
data = p_json->to_string();
void LottieTexture2D::set_json(Ref<JSON> p_json) {
String data = p_json.is_valid() ? p_json->get_parsed_text() : "";
if (p_json.is_valid() && data.is_empty()) {
data = JSON::stringify(p_json->get_data());
}
_load_data(data, scale);
json = p_json;
}

float LottieSheet::get_scale() { return scale; };
void LottieSheet::set_scale(float p_scale) {
void LottieTexture2D::set_scale(float p_scale) {
String data = json->get_parsed_text();
if (data.is_empty()) {
data = json->to_string();
data = JSON::stringify(json->get_data());
}
_load_data(data, scale);
scale = p_scale;
};

LottieSheet::~LottieSheet() { memfree(buffer); }

void LottieSheet::_bind_methods() {
ClassDB::bind_static_method("LottieSheet", D_METHOD("load_string", "p_string", "p_scale"), &LottieSheet::load_string, DEFVAL(1));
ClassDB::bind_static_method("LottieSheet", D_METHOD("load_json", "p_json", "p_scale"), &LottieSheet::load_json, DEFVAL(1));
ClassDB::bind_method(D_METHOD("get_json"), &LottieSheet::get_json);
ClassDB::bind_method(D_METHOD("set_json", "p_json"), &LottieSheet::set_json);
ClassDB::bind_method(D_METHOD("get_scale"), &LottieSheet::get_scale);
ClassDB::bind_method(D_METHOD("set_scale", "p_scale"), &LottieSheet::set_scale);
ClassDB::bind_method(D_METHOD("update_frame", "frame"), &LottieSheet::update_frame);
ClassDB::bind_method(D_METHOD("get_image"), &LottieSheet::get_image);
ClassDB::bind_method(D_METHOD("get_frame_image", "frame"), &LottieSheet::get_frame_image);
ClassDB::bind_method(D_METHOD("get_image_size"), &LottieSheet::get_image_size);
ClassDB::bind_method(D_METHOD("get_total_frame"), &LottieSheet::get_total_frame);
ClassDB::bind_method(D_METHOD("get_duration"), &LottieSheet::get_duration);

ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "json"), "set_json", "get_json");
void LottieTexture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const {
if ((width | height) == 0) {
return;
}
RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), texture, false, p_modulate, p_transpose);
}

void LottieTexture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const {
if ((width | height) == 0) {
return;
}
RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose);
}

void LottieTexture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const {
if ((width | height) == 0) {
return;
}
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, p_clip_uv);
}

LottieTexture2D::~LottieTexture2D() {
if (texture.is_valid()) {
RenderingServer::get_singleton()->free(texture);
}
if (buffer) {
memfree(buffer);
}
}

void LottieTexture2D::_bind_methods() {
ClassDB::bind_static_method("LottieTexture2D", D_METHOD("load_string", "p_string", "p_scale"), &LottieTexture2D::load_string, DEFVAL(1));
ClassDB::bind_static_method("LottieTexture2D", D_METHOD("load_json", "p_json", "p_scale"), &LottieTexture2D::load_json, DEFVAL(1));
ClassDB::bind_method(D_METHOD("set_json", "p_json"), &LottieTexture2D::set_json);
ClassDB::bind_method(D_METHOD("get_json"), &LottieTexture2D::get_json);
ClassDB::bind_method(D_METHOD("set_scale", "p_scale"), &LottieTexture2D::set_scale);
ClassDB::bind_method(D_METHOD("get_scale"), &LottieTexture2D::get_scale);
ClassDB::bind_method(D_METHOD("set_frame", "frame"), &LottieTexture2D::set_frame);
ClassDB::bind_method(D_METHOD("get_frame"), &LottieTexture2D::get_frame);
ClassDB::bind_method(D_METHOD("get_total_frame"), &LottieTexture2D::get_total_frame);
ClassDB::bind_method(D_METHOD("get_duration"), &LottieTexture2D::get_duration);

ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "json", PROPERTY_HINT_RESOURCE_TYPE, "JSON"), "set_json", "get_json");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scale"), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frame"), "set_frame", "get_frame");
}
50 changes: 32 additions & 18 deletions modules/svg/lottie_sheet.h → modules/svg/lottie_texture.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**************************************************************************/
/* lottie_sheet.h */
/* lottie_texture.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
Expand Down Expand Up @@ -28,47 +28,61 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef LOTTIE_SHEET_H
#define LOTTIE_SHEET_H
#ifndef LOTTIE_TEXTURE_H
#define LOTTIE_TEXTURE_H

#include "core/io/json.h"
#include "core/io/resource.h"
#include "scene/resources/texture.h"

#include <thorvg.h>

class LottieSheet : public Resource {
GDCLASS(LottieSheet, Resource);
class LottieTexture2D : public Texture2D {
GDCLASS(LottieTexture2D, Texture2D);

std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen();
std::unique_ptr<tvg::Animation> animation = tvg::Animation::gen();
tvg::Picture *picture = animation->picture();
Ref<Image> image;
mutable RID texture;
uint32_t *buffer = nullptr;
Ref<JSON> json = memnew(JSON);
Ref<JSON> json;

float scale;
float scale = 1.0;
uint32_t width, height;
float frame = 0;

void _load_data(String p_string, float p_scale);

protected:
static void _bind_methods();

public:
static Ref<LottieSheet> load_string(String p_string, float p_scale = 1);
static Ref<LottieSheet> load_json(Ref<JSON> p_json, float p_scale = 1);
static Ref<LottieTexture2D> load_string(String p_string, float p_scale = 1);
static Ref<LottieTexture2D> load_json(Ref<JSON> p_json, float p_scale = 1);

Ref<JSON> get_json();
void set_json(Ref<JSON> p_json);
float get_scale();
Ref<JSON> get_json() { return json; };

void set_scale(float p_scale);
void update_frame(float frame);
Ref<Image> get_image();
Ref<Image> get_frame_image(float frame);
Vector2i get_image_size();
float get_scale() { return scale; };

void set_frame(float frame);
float get_frame() { return frame; };

float get_total_frame();
float get_duration();
~LottieSheet();

int get_width() const override { return width; };
int get_height() const override { return height; };
Size2 get_size() const override { return Size2(width, height); };
bool is_pixel_opaque(int p_x, int p_y) const override { return image.is_valid() ? image->get_pixel(p_x, p_y).a > 0.1 : true; };
bool has_alpha() const override { return true; };
void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const override;
void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const override;
void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = true) const override;
Ref<Image> get_image() const override { return image; };

~LottieTexture2D();
};

#endif // LOTTIE_SHEET_H
#endif // LOTTIE_TEXTURE_H
4 changes: 2 additions & 2 deletions modules/svg/register_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include "register_types.h"

#include "image_loader_svg.h"
#include "lottie_sheet.h"
#include "lottie_texture.h"

#include <thorvg.h>

Expand All @@ -56,7 +56,7 @@ void initialize_svg_module(ModuleInitializationLevel p_level) {

image_loader_svg.instantiate();
ImageLoader::add_image_format_loader(image_loader_svg);
ClassDB::register_class<LottieSheet>();
ClassDB::register_class<LottieTexture2D>();
}

void uninitialize_svg_module(ModuleInitializationLevel p_level) {
Expand Down

0 comments on commit d0f179f

Please sign in to comment.