mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
lottie/slot: Support expressions overriding
issue: #3168 Co-Authored-By: Hermet Park <hermet@lottiefiles.com>
This commit is contained in:
parent
e235eb8152
commit
0e76ba3e47
3 changed files with 76 additions and 43 deletions
|
@ -919,7 +919,7 @@ struct LottieSlot
|
||||||
void assign(LottieObject* target, bool byDefault);
|
void assign(LottieObject* target, bool byDefault);
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
LottieSlot(char* sid, LottieObject* obj, LottieProperty::Type type) : sid(sid), type(type)
|
LottieSlot(LottieLayer* layer, LottieObject* parent, char* sid, LottieObject* obj, LottieProperty::Type type) : context{layer, parent}, sid(sid), type(type)
|
||||||
{
|
{
|
||||||
pairs.push({obj});
|
pairs.push({obj});
|
||||||
}
|
}
|
||||||
|
@ -931,9 +931,15 @@ struct LottieSlot
|
||||||
ARRAY_FOREACH(pair, pairs) delete(pair->prop);
|
ARRAY_FOREACH(pair, pairs) delete(pair->prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct {
|
||||||
|
LottieLayer* layer;
|
||||||
|
LottieObject* parent;
|
||||||
|
} context;
|
||||||
|
|
||||||
char* sid;
|
char* sid;
|
||||||
Array<Pair> pairs;
|
Array<Pair> pairs;
|
||||||
LottieProperty::Type type;
|
LottieProperty::Type type;
|
||||||
|
|
||||||
bool overridden = false;
|
bool overridden = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -471,7 +471,7 @@ void LottieParser::registerSlot(LottieObject* obj, const char* sid)
|
||||||
(*p)->pairs.push({obj});
|
(*p)->pairs.push({obj});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
comp->slots.push(new LottieSlot(duplicate(sid), obj, type));
|
comp->slots.push(new LottieSlot(context.layer, context.parent, duplicate(sid), obj, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1502,41 +1502,36 @@ bool LottieParser::apply(LottieSlot* slot, bool byDefault)
|
||||||
|
|
||||||
//OPTIMIZE: we can create the property directly, without object
|
//OPTIMIZE: we can create the property directly, without object
|
||||||
LottieObject* obj = nullptr; //slot object
|
LottieObject* obj = nullptr; //slot object
|
||||||
|
context = {slot->context.layer, slot->context.parent};
|
||||||
|
|
||||||
switch (slot->type) {
|
switch (slot->type) {
|
||||||
case LottieProperty::Type::Position: {
|
case LottieProperty::Type::Position: {
|
||||||
obj = new LottieTransform;
|
obj = new LottieTransform;
|
||||||
context.parent = obj;
|
|
||||||
parseSlotProperty<LottieProperty::Type::Position>(static_cast<LottieTransform*>(obj)->position);
|
parseSlotProperty<LottieProperty::Type::Position>(static_cast<LottieTransform*>(obj)->position);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LottieProperty::Type::Point: {
|
case LottieProperty::Type::Point: {
|
||||||
obj = new LottieTransform;
|
obj = new LottieTransform;
|
||||||
context.parent = obj;
|
|
||||||
parseSlotProperty<LottieProperty::Type::Point>(static_cast<LottieTransform*>(obj)->scale);
|
parseSlotProperty<LottieProperty::Type::Point>(static_cast<LottieTransform*>(obj)->scale);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LottieProperty::Type::Float: {
|
case LottieProperty::Type::Float: {
|
||||||
obj = new LottieTransform;
|
obj = new LottieTransform;
|
||||||
context.parent = obj;
|
|
||||||
parseSlotProperty<LottieProperty::Type::Float>(static_cast<LottieTransform*>(obj)->rotation);
|
parseSlotProperty<LottieProperty::Type::Float>(static_cast<LottieTransform*>(obj)->rotation);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LottieProperty::Type::Opacity: {
|
case LottieProperty::Type::Opacity: {
|
||||||
obj = new LottieSolid;
|
obj = new LottieSolid;
|
||||||
context.parent = obj;
|
|
||||||
parseSlotProperty<LottieProperty::Type::Opacity>(static_cast<LottieSolid*>(obj)->opacity);
|
parseSlotProperty<LottieProperty::Type::Opacity>(static_cast<LottieSolid*>(obj)->opacity);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LottieProperty::Type::Color: {
|
case LottieProperty::Type::Color: {
|
||||||
obj = new LottieSolid;
|
obj = new LottieSolid;
|
||||||
context.parent = obj;
|
|
||||||
parseSlotProperty<LottieProperty::Type::Color>(static_cast<LottieSolid*>(obj)->color);
|
parseSlotProperty<LottieProperty::Type::Color>(static_cast<LottieSolid*>(obj)->color);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LottieProperty::Type::ColorStop: {
|
case LottieProperty::Type::ColorStop: {
|
||||||
obj = new LottieGradient;
|
obj = new LottieGradient;
|
||||||
context.parent = obj;
|
|
||||||
while (auto key = nextObjectKey()) {
|
while (auto key = nextObjectKey()) {
|
||||||
if (KEY_AS("p")) parseColorStop(static_cast<LottieGradient*>(obj));
|
if (KEY_AS("p")) parseColorStop(static_cast<LottieGradient*>(obj));
|
||||||
else skip();
|
else skip();
|
||||||
|
@ -1545,7 +1540,6 @@ bool LottieParser::apply(LottieSlot* slot, bool byDefault)
|
||||||
}
|
}
|
||||||
case LottieProperty::Type::TextDoc: {
|
case LottieProperty::Type::TextDoc: {
|
||||||
obj = new LottieText;
|
obj = new LottieText;
|
||||||
context.parent = obj;
|
|
||||||
parseSlotProperty<LottieProperty::Type::TextDoc>(static_cast<LottieText*>(obj)->doc);
|
parseSlotProperty<LottieProperty::Type::TextDoc>(static_cast<LottieText*>(obj)->doc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1554,7 +1548,6 @@ bool LottieParser::apply(LottieSlot* slot, bool byDefault)
|
||||||
if (KEY_AS("p")) obj = parseAsset();
|
if (KEY_AS("p")) obj = parseAsset();
|
||||||
else skip();
|
else skip();
|
||||||
}
|
}
|
||||||
context.parent = obj;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
struct LottieFont;
|
struct LottieFont;
|
||||||
struct LottieLayer;
|
struct LottieLayer;
|
||||||
struct LottieObject;
|
struct LottieObject;
|
||||||
|
struct LottieProperty;
|
||||||
|
|
||||||
|
|
||||||
//default keyframe updates condition (no tweening)
|
//default keyframe updates condition (no tweening)
|
||||||
|
@ -123,23 +124,6 @@ struct LottieVectorFrame
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//Property would have an either keyframes or single value.
|
|
||||||
struct LottieProperty
|
|
||||||
{
|
|
||||||
enum class Type : uint8_t { Point = 0, Float, Opacity, Color, PathSet, ColorStop, Position, TextDoc, Image, Invalid };
|
|
||||||
|
|
||||||
LottieExpression* exp = nullptr;
|
|
||||||
Type type;
|
|
||||||
uint8_t ix; //property index
|
|
||||||
|
|
||||||
//TODO: Apply common bodies?
|
|
||||||
virtual ~LottieProperty() {}
|
|
||||||
virtual uint32_t frameCnt() = 0;
|
|
||||||
virtual uint32_t nearest(float time) = 0;
|
|
||||||
virtual float frameNo(int32_t key) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct LottieExpression
|
struct LottieExpression
|
||||||
{
|
{
|
||||||
enum LoopMode : uint8_t { None = 0, InCycle = 1, InPingPong, InOffset, InContinue, OutCycle, OutPingPong, OutOffset, OutContinue };
|
enum LoopMode : uint8_t { None = 0, InCycle = 1, InPingPong, InOffset, InContinue, OutCycle, OutPingPong, OutOffset, OutContinue };
|
||||||
|
@ -157,6 +141,18 @@ struct LottieExpression
|
||||||
LoopMode mode = None;
|
LoopMode mode = None;
|
||||||
} loop;
|
} loop;
|
||||||
|
|
||||||
|
LottieExpression() {}
|
||||||
|
|
||||||
|
LottieExpression(const LottieExpression* rhs)
|
||||||
|
{
|
||||||
|
code = strdup(rhs->code);
|
||||||
|
comp = rhs->comp;
|
||||||
|
layer = rhs->layer;
|
||||||
|
object = rhs->object;
|
||||||
|
property = rhs->property;
|
||||||
|
disabled = rhs->disabled;
|
||||||
|
}
|
||||||
|
|
||||||
~LottieExpression()
|
~LottieExpression()
|
||||||
{
|
{
|
||||||
tvg::free(code);
|
tvg::free(code);
|
||||||
|
@ -164,6 +160,36 @@ struct LottieExpression
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//Property would have an either keyframes or single value.
|
||||||
|
struct LottieProperty
|
||||||
|
{
|
||||||
|
enum class Type : uint8_t { Point = 0, Float, Opacity, Color, PathSet, ColorStop, Position, TextDoc, Image, Invalid };
|
||||||
|
|
||||||
|
LottieExpression* exp = nullptr;
|
||||||
|
Type type;
|
||||||
|
uint8_t ix; //property index
|
||||||
|
|
||||||
|
//TODO: Apply common bodies?
|
||||||
|
virtual ~LottieProperty() {}
|
||||||
|
virtual uint32_t frameCnt() = 0;
|
||||||
|
virtual uint32_t nearest(float time) = 0;
|
||||||
|
virtual float frameNo(int32_t key) = 0;
|
||||||
|
|
||||||
|
bool copy(LottieProperty* rhs, bool shallow)
|
||||||
|
{
|
||||||
|
if (!rhs->exp) return false;
|
||||||
|
if (shallow) {
|
||||||
|
exp = rhs->exp;
|
||||||
|
rhs->exp = nullptr;
|
||||||
|
} else {
|
||||||
|
exp = new LottieExpression(rhs->exp);
|
||||||
|
}
|
||||||
|
exp->property = this;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void _copy(PathSet* pathset, Array<Point>& out, Matrix* transform)
|
static void _copy(PathSet* pathset, Array<Point>& out, Matrix* transform)
|
||||||
{
|
{
|
||||||
Array<Point> in;
|
Array<Point> in;
|
||||||
|
@ -279,7 +305,7 @@ struct LottieGenericProperty : LottieProperty
|
||||||
|
|
||||||
LottieGenericProperty(const LottieGenericProperty<Frame, Value>& rhs)
|
LottieGenericProperty(const LottieGenericProperty<Frame, Value>& rhs)
|
||||||
{
|
{
|
||||||
copy(rhs);
|
copy(const_cast<LottieGenericProperty<Frame, Value>&>(rhs));
|
||||||
type = rhs.type;
|
type = rhs.type;
|
||||||
ix = rhs.ix;
|
ix = rhs.ix;
|
||||||
}
|
}
|
||||||
|
@ -355,12 +381,14 @@ struct LottieGenericProperty : LottieProperty
|
||||||
return tvg::lerp(operator()(frameNo, exps), operator()(tween.frameNo, exps), tween.progress);
|
return tvg::lerp(operator()(frameNo, exps), operator()(tween.frameNo, exps), tween.progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy(const LottieGenericProperty<Frame, Value, Scalar>& rhs, bool shallow = true)
|
void copy(LottieGenericProperty<Frame, Value, Scalar>& rhs, bool shallow = true)
|
||||||
{
|
{
|
||||||
|
if (LottieProperty::copy(&rhs, shallow)) return;
|
||||||
|
|
||||||
if (rhs.frames) {
|
if (rhs.frames) {
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
frames = rhs.frames;
|
frames = rhs.frames;
|
||||||
const_cast<LottieGenericProperty<Frame, Value, Scalar>&>(rhs).frames = nullptr;
|
rhs.frames = nullptr;
|
||||||
} else {
|
} else {
|
||||||
frames = new Array<Frame>;
|
frames = new Array<Frame>;
|
||||||
*frames = *rhs.frames;
|
*frames = *rhs.frames;
|
||||||
|
@ -593,7 +621,7 @@ struct LottieColorStop : LottieProperty
|
||||||
|
|
||||||
LottieColorStop(const LottieColorStop& rhs)
|
LottieColorStop(const LottieColorStop& rhs)
|
||||||
{
|
{
|
||||||
copy(rhs);
|
copy(const_cast<LottieColorStop&>(rhs));
|
||||||
type = rhs.type;
|
type = rhs.type;
|
||||||
ix = rhs.ix;
|
ix = rhs.ix;
|
||||||
}
|
}
|
||||||
|
@ -741,19 +769,21 @@ struct LottieColorStop : LottieProperty
|
||||||
return tweening(frameNo, fill, tween, exps);
|
return tweening(frameNo, fill, tween, exps);
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy(const LottieColorStop& rhs, bool shallow = true)
|
void copy(LottieColorStop& rhs, bool shallow = true)
|
||||||
{
|
{
|
||||||
|
if (LottieProperty::copy(&rhs, shallow)) return;
|
||||||
|
|
||||||
if (rhs.frames) {
|
if (rhs.frames) {
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
frames = rhs.frames;
|
frames = rhs.frames;
|
||||||
const_cast<LottieColorStop&>(rhs).frames = nullptr;
|
rhs.frames = nullptr;
|
||||||
} else {
|
} else {
|
||||||
frames = new Array<LottieScalarFrame<ColorStop>>;
|
frames = new Array<LottieScalarFrame<ColorStop>>;
|
||||||
*frames = *rhs.frames;
|
*frames = *rhs.frames;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = rhs.value;
|
value = rhs.value;
|
||||||
const_cast<LottieColorStop&>(rhs).value = ColorStop();
|
rhs.value = ColorStop();
|
||||||
}
|
}
|
||||||
populated = rhs.populated;
|
populated = rhs.populated;
|
||||||
count = rhs.count;
|
count = rhs.count;
|
||||||
|
@ -772,7 +802,7 @@ struct LottieTextDoc : LottieProperty
|
||||||
|
|
||||||
LottieTextDoc(const LottieTextDoc& rhs)
|
LottieTextDoc(const LottieTextDoc& rhs)
|
||||||
{
|
{
|
||||||
copy(rhs);
|
copy(const_cast<LottieTextDoc&>(rhs));
|
||||||
type = rhs.type;
|
type = rhs.type;
|
||||||
ix = rhs.ix;
|
ix = rhs.ix;
|
||||||
}
|
}
|
||||||
|
@ -853,20 +883,22 @@ struct LottieTextDoc : LottieProperty
|
||||||
return frame->value;
|
return frame->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy(const LottieTextDoc& rhs, bool shallow = true)
|
void copy(LottieTextDoc& rhs, bool shallow = true)
|
||||||
{
|
{
|
||||||
|
if (LottieProperty::copy(&rhs, shallow)) return;
|
||||||
|
|
||||||
if (rhs.frames) {
|
if (rhs.frames) {
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
frames = rhs.frames;
|
frames = rhs.frames;
|
||||||
const_cast<LottieTextDoc&>(rhs).frames = nullptr;
|
rhs.frames = nullptr;
|
||||||
} else {
|
} else {
|
||||||
frames = new Array<LottieScalarFrame<TextDocument>>;
|
frames = new Array<LottieScalarFrame<TextDocument>>;
|
||||||
*frames = *rhs.frames;
|
*frames = *rhs.frames;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = rhs.value;
|
value = rhs.value;
|
||||||
const_cast<LottieTextDoc&>(rhs).value.text = nullptr;
|
rhs.value.text = nullptr;
|
||||||
const_cast<LottieTextDoc&>(rhs).value.name = nullptr;
|
rhs.value.name = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,7 +921,7 @@ struct LottieBitmap : LottieProperty
|
||||||
|
|
||||||
LottieBitmap(const LottieBitmap& rhs)
|
LottieBitmap(const LottieBitmap& rhs)
|
||||||
{
|
{
|
||||||
copy(rhs);
|
copy(const_cast<LottieBitmap&>(rhs));
|
||||||
type = rhs.type;
|
type = rhs.type;
|
||||||
ix = rhs.ix;
|
ix = rhs.ix;
|
||||||
}
|
}
|
||||||
|
@ -912,8 +944,10 @@ struct LottieBitmap : LottieProperty
|
||||||
uint32_t nearest(float time) override { return 0; }
|
uint32_t nearest(float time) override { return 0; }
|
||||||
float frameNo(int32_t key) override { return 0; }
|
float frameNo(int32_t key) override { return 0; }
|
||||||
|
|
||||||
void copy(const LottieBitmap& rhs, bool shallow = true)
|
void copy(LottieBitmap& rhs, bool shallow = true)
|
||||||
{
|
{
|
||||||
|
if (LottieProperty::copy(&rhs, shallow)) return;
|
||||||
|
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
b64Data = rhs.b64Data;
|
b64Data = rhs.b64Data;
|
||||||
mimeType = rhs.mimeType;
|
mimeType = rhs.mimeType;
|
||||||
|
@ -927,8 +961,8 @@ struct LottieBitmap : LottieProperty
|
||||||
width = rhs.width;
|
width = rhs.width;
|
||||||
height = rhs.height;
|
height = rhs.height;
|
||||||
|
|
||||||
const_cast<LottieBitmap&>(rhs).b64Data = nullptr;
|
rhs.b64Data = nullptr;
|
||||||
const_cast<LottieBitmap&>(rhs).mimeType = nullptr;
|
rhs.mimeType = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue