Skip to content

Commit 2f63302

Browse files
committed
Add Lottie resource importer using ThorVG
Add lottie importer for `.lot` and `.lottie` to import lottie as CompressedTexture2D, and support dropping it as AnimatedSprite2D in 2d editor.
1 parent a210fe6 commit 2f63302

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+29190
-1
lines changed

editor/doc_tools.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "core/string/translation_server.h"
4141
#include "editor/editor_settings.h"
4242
#include "editor/export/editor_export_platform.h"
43+
#include "editor/import/resource_importer_texture.h"
4344
#include "scene/resources/theme.h"
4445
#include "scene/theme/theme_db.h"
4546

@@ -464,6 +465,34 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
464465
} else if (name == "ProjectSettings") {
465466
ProjectSettings::get_singleton()->get_property_list(&properties);
466467
own_properties = properties;
468+
} else if (name == "ResourceImporterLottie") {
469+
import_option = true;
470+
471+
List<ResourceImporter::ImportOption> texture_options;
472+
ResourceImporter *texture_importer = memnew(ResourceImporterTexture);
473+
texture_importer->get_import_options("", &texture_options);
474+
475+
ResourceImporter *resimp = Object::cast_to<ResourceImporter>(ClassDB::instantiate(name));
476+
List<ResourceImporter::ImportOption> options;
477+
resimp->get_import_options("", &options);
478+
for (const ResourceImporter::ImportOption &option : options) {
479+
const PropertyInfo &prop = option.option;
480+
bool own_property = true;
481+
for (const ResourceImporter::ImportOption &texture_option : texture_options) {
482+
if (texture_option.option.name == prop.name) {
483+
own_property = false;
484+
break;
485+
}
486+
}
487+
if (!own_property) {
488+
continue;
489+
}
490+
properties.push_back(prop);
491+
import_options_default[prop.name] = option.default_value;
492+
}
493+
own_properties = properties;
494+
memdelete(resimp);
495+
memdelete(texture_importer);
467496
} else if (ClassDB::is_parent_class(name, "ResourceImporter") && name != "EditorImportPlugin" && ClassDB::can_instantiate(name)) {
468497
import_option = true;
469498
ResourceImporter *resimp = Object::cast_to<ResourceImporter>(ClassDB::instantiate(name));

editor/plugins/canvas_item_editor_plugin.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#include "core/config/project_settings.h"
3434
#include "core/input/input.h"
35+
#include "core/io/resource_importer.h"
3536
#include "core/os/keyboard.h"
3637
#include "editor/debugger/editor_debugger_node.h"
3738
#include "editor/editor_main_screen.h"
@@ -48,6 +49,7 @@
4849
#include "editor/scene_tree_dock.h"
4950
#include "editor/themes/editor_scale.h"
5051
#include "editor/themes/editor_theme_manager.h"
52+
#include "scene/2d/animated_sprite_2d.h"
5153
#include "scene/2d/audio_stream_player_2d.h"
5254
#include "scene/2d/physics/touch_screen_button.h"
5355
#include "scene/2d/polygon_2d.h"
@@ -62,6 +64,7 @@
6264
#include "scene/gui/view_panner.h"
6365
#include "scene/main/canvas_layer.h"
6466
#include "scene/main/window.h"
67+
#include "scene/resources/atlas_texture.h"
6568
#include "scene/resources/packed_scene.h"
6669
#include "scene/resources/style_box_texture.h"
6770

@@ -5942,6 +5945,24 @@ void CanvasItemEditorViewport::_create_texture_node(Node *p_parent, Node *p_chil
59425945
Vector2(0, texture_size.height)
59435946
};
59445947
undo_redo->add_do_property(p_child, "polygon", list);
5948+
} else if (Object::cast_to<AnimatedSprite2D>(p_child)) {
5949+
// Currently this metadata is only set by ResourceImporterLottie.
5950+
Dictionary meta = ResourceFormatImporter::get_singleton()->get_resource_metadata(p_path);
5951+
Ref<SpriteFrames> frames;
5952+
frames.instantiate();
5953+
frames->set_animation_speed(SceneStringName(default_), meta.get("fps", 5));
5954+
Size2i sprite_size = meta["sprite_size"];
5955+
for (int i = 0; i < (int)meta["frame_count"]; i++) {
5956+
int x = i % (int)meta["columns"] * sprite_size.width;
5957+
int y = i / (int)meta["columns"] * sprite_size.height;
5958+
Ref<AtlasTexture> atlas_texture;
5959+
atlas_texture.instantiate();
5960+
atlas_texture->set_atlas(texture);
5961+
atlas_texture->set_region(Rect2(x, y, sprite_size.width, sprite_size.height));
5962+
frames->add_frame(SceneStringName(default_), atlas_texture);
5963+
}
5964+
undo_redo->add_do_property(p_child, SceneStringName(autoplay), SceneStringName(default_));
5965+
undo_redo->add_do_property(p_child, "sprite_frames", frames);
59455966
}
59465967

59475968
// Compute the global position
@@ -6347,6 +6368,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(CanvasItemEditor *p_canvas_it
63476368
texture_node_types.push_back("GPUParticles2D");
63486369
texture_node_types.push_back("Polygon2D");
63496370
texture_node_types.push_back("TouchScreenButton");
6371+
texture_node_types.push_back("AnimatedSprite2D");
63506372
// Control
63516373
texture_node_types.push_back("TextureRect");
63526374
texture_node_types.push_back("TextureButton");

modules/svg/SCsub

+25-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ thirdparty_sources = [
5959
"src/renderer/sw_engine/tvgSwStroke.cpp",
6060
]
6161

62+
if env.editor_build:
63+
thirdparty_sources += [
64+
"src/renderer/tvgAnimation.cpp",
65+
# Lottie loader
66+
"src/loaders/lottie/tvgLottieAnimation.cpp",
67+
"src/loaders/lottie/tvgLottieBuilder.cpp",
68+
# "src/loaders/lottie/tvgLottieExpressions.cpp",
69+
"src/loaders/lottie/tvgLottieInterpolator.cpp",
70+
"src/loaders/lottie/tvgLottieLoader.cpp",
71+
"src/loaders/lottie/tvgLottieModel.cpp",
72+
"src/loaders/lottie/tvgLottieModifier.cpp",
73+
"src/loaders/lottie/tvgLottieParser.cpp",
74+
"src/loaders/lottie/tvgLottieParserHandler.cpp",
75+
]
76+
6277
if env["module_webp_enabled"]:
6378
thirdparty_sources += ["src/loaders/external_webp/tvgWebpLoader.cpp"]
6479
env_svg.Append(CPPDEFINES=["THORVG_WEBP_LOADER_SUPPORT"])
@@ -72,6 +87,9 @@ env_svg.Append(CPPDEFINES=["TVG_STATIC"])
7287
# Explicit support for embedded images in svg.
7388
env_svg.Append(CPPDEFINES=["THORVG_FILE_IO_SUPPORT"])
7489

90+
if env.editor_build:
91+
env_svg.Append(CPPDEFINES=["THORVG_LOTTIE_LOADER_SUPPORT", "LOTTIE_ENABLED"])
92+
7593
env_thirdparty = env_svg.Clone()
7694
env_thirdparty.disable_warnings()
7795
env_thirdparty.Prepend(
@@ -85,6 +103,9 @@ env_thirdparty.Prepend(
85103
thirdparty_dir + "src/loaders/jpg",
86104
]
87105
)
106+
107+
if env.editor_build:
108+
env_thirdparty.Prepend(CPPPATH=[thirdparty_dir + "src/loaders/lottie"])
88109
if env["builtin_libpng"]:
89110
env_thirdparty.Prepend(CPPEXTPATH=["#thirdparty/libpng"])
90111
if env["module_webp_enabled"]:
@@ -99,7 +120,10 @@ env.modules_sources += thirdparty_obj
99120

100121
module_obj = []
101122

102-
env_svg.add_source_files(module_obj, "*.cpp")
123+
env_svg.add_source_files(module_obj, ["register_types.cpp", "image_loader_svg.cpp"])
124+
if env.editor_build:
125+
env_svg.add_source_files(module_obj, "editor/*.cpp")
126+
103127
env.modules_sources += module_obj
104128

105129
# Needed to force rebuilding the module files when the thirdparty library is updated.

modules/svg/config.py

+10
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,13 @@ def can_build(env, platform):
44

55
def configure(env):
66
pass
7+
8+
9+
def get_doc_classes():
10+
return [
11+
"ResourceImporterLottie",
12+
]
13+
14+
15+
def get_doc_path():
16+
return "doc_classes"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<class name="ResourceImporterLottie" inherits="ResourceImporterTexture" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
3+
<brief_description>
4+
Import a Lottie animation as a sprite sheet.
5+
</brief_description>
6+
<description>
7+
This imports a Lottie animation to a [CompressedTexture2D] with support for Lottie JSON and limited support for dotLottie (Only reads the first animation within dotLottie and ignores other resources).
8+
[b]Note:[/b] This importer only recognizes files with [code].lot[/code] (Lottie JSON) or [code].lottie[/code] (dotLottie) extension. You have to rename Lottie JSON files extension to [code].lot[/code] to import them.
9+
</description>
10+
<tutorials>
11+
</tutorials>
12+
<members>
13+
<member name="lottie/begin" type="float" setter="" getter="" default="0">
14+
The start of the Lottie animation in the range [code]0.0[/code] to [code]1.0[/code].
15+
</member>
16+
<member name="lottie/columns" type="int" setter="" getter="" default="0">
17+
The number of columns of the sprite sheet. If it is [code]0[/code], the number of columns will be automatically calculated to be close to the number of rows.
18+
</member>
19+
<member name="lottie/end" type="float" setter="" getter="" default="1">
20+
The end of the Lottie animation in the range [code]0.0[/code] to [code]1.0[/code]. This value will be clamped to be at least [member lottie/begin].
21+
</member>
22+
<member name="lottie/fps" type="float" setter="" getter="" default="30">
23+
The frame rate Lottie animation should be rendered at. Higher values result in a larger image.
24+
</member>
25+
<member name="lottie/scale" type="float" setter="" getter="" default="1">
26+
The scale the Lottie animation should be rendered at, with [code]1.0[/code] being the original size. Higher values result in a larger image.
27+
</member>
28+
<member name="lottie/size_limit" type="int" setter="" getter="" default="2048">
29+
If set to a value greater than [code]0[/code], the size of the imported Lottie texture is limited on import to a value smaller than or equal to the value specified here.
30+
[b]Note:[/b] Importing large Lottie textures in editor is slow. This setting ensures import speed and ignores [member lottie/scale].
31+
</member>
32+
</members>
33+
</class>

0 commit comments

Comments
 (0)