Code: Model Objects
"Model Objects" are the objects used to represent animation data internally, there is basically a 1:1 map between the contents of a Glaxnimate json file and these objects.
Document Nodes
"Document Nodes" are stand alone Model Objects that are part of the document structure.
This includes Assets, Visual Nodes, Containers, etc.
Visual Nodes
"Visual Nodes" are Document Nodes that correspond to a visual element of the animation. These are listed in the Layers View.
How to define a new class
If you are defining a new class, make sure it uses all the code generation machinery.
Follows an example:
Adding code
When you add a new class, the code-generation machinery will automatically integrate the new class with the UI and serialization to/from Glaxnimate json.
You still need to register it in a couple places:
Python interpreter
In src/core/python.cpp
you have to expose classes so they are visible in scripts.
For QObject-derived classes (which include Model Objects) there's code-generation
facilities that expose properties defined by the GLAXNIMATE_*
macros as
well as QObject-related declarations such as Q_PROPERTY
and Q_INVOKABLE
.
Automatic generation supports most but not all types for properties and methods.
It supports basic c++ types (like int
, etc), common Qt types (eg: QString
),
QObject-derived classes, and exposed enums.
Properties or methods using other types, need to be declared manually here.
Example:
PYBIND11_EMBEDDED_MODULE(glaxnimate, glaxnimate_module)
{
// ...
// The template parameters are the class to be declared and its parent
// The function argument is the module you want to define the class into.
register_from_meta<model::MyNewObject, Object>(glaxnimate_module);
// Abstract classes should also be declared,
// otherwise their properties won't be visible from python.
register_from_meta<model::MyNewAbstractClass, Object>(glaxnimate_module);
// If you define enums, you need to list them like this:
register_from_meta<model::MyClassWithEnum, Object>(glaxnimate_module, enums<model::MyClassWithEnum::MyEnum>{});
}
Lottie Import/Export
Lottie serialization is semi-automatic, you need to add your class in
core/io/lottie/lottie_private_common.hpp
.
The variable fields
defines metadata on how to interpret the lottie json fields
and you should add your class and relevant properties in there.
Example:
const QMap<QString, QVector<FieldInfo>> fields = {
// ...
// Use the class name without namespace as key
{"MyNewAbstractClass", {
// maps the Glaxnimate property "myprop" to the json field "mp"
FieldInfo{"mp", "myprop"},
}},
{"MyNewAbstractClass", {
// fields without mappings are ignored without warning when opening files
FieldInfo{"ignored"},
// maps the Glaxnimate property "my_animated" to the json field "ma"
FieldInfo{"ma", "my_animated"},
// fields marked with Custom need to be manually read/written in the lottie code
FieldInfo{"custom", Custom},
}},
{"MyClassWithEnum", {
// If the enum values are the same in lottie you don't have to do much,
// otherwise you need to use Custom
FieldInfo{"type", "type"},
}}
// ...
};
Note that the order of properties is important in some lottie renderers.
Glaxnimate keeps the automatic properties in the order defined into fields
but care needs to be taken when setting Custom
properties.
If you define new shapes that have a corresponding lottie type,
you need to add them to shape_types
which maps Glaxnimate class names (without namespace) to the lottie ty
field
corresponding to the right object.
SVG Import/Export
SVG rendering is done mostly manually so you'd need to add the appropriate code.
New Shape / Layer Checklist
- Define the class, having
ShapeElement
(or the appropriate class) as parent- Add GLAXNIMATE_OBJECT
- Add properties
- Define metadata with GLAXNIMATE_OBJECT_IMPL
- If you want to add menus, inherit from the CRTP Class
StaticOverrides
- Override the relevant methods
- (
static_
)tree_icon
- (
static_
)type_name_human
to_path
- (
- Expose the class to Python
- Add editors (if needed) to
gui/graphics/create_items.cpp
. - Implement Lottie I/O
- Populate
io::lottie::detail::fields
incore/io/lottie/lottie_private_common.hpp
- Add entry to
io::lottie::detail::shape_types
incore/io/lottie/lottie_private_common.hpp
- If it has custom fields, add the relevant code to
lottie_importer.hpp
andlottie_exporter.hpp
- If it isn't supported by TGS, add the required warnings in
- Populate
- Implement SVG Export (
core/io/svg/svg_renderer.cpp
)- Write a conversion function
- If it's a
Shape
, add the condition inwrite_shape_shape
- Otherwise, add the condition in
write_shape
- Implement SVG Import, if there is a standard SVG or Inkscape SVG analogue (
core/io/svg/svg_parser.cpp
)- Write a conversion function
- If adding support for a new element, map the element name to conversion function in
io::svg::SvgParser::Private::shape_parsers
. - Otherwise add the relevant condition in the existing
parseshape_*
function.