[skottie] render particles through transform tracker decorator

Change the way we transform the matrix on render for specific decorations

Change-Id: I3112c38a95cd1473e9e9c5bfff9eac09e20f6016
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/536101
Commit-Queue: Jorge Betancourt <jmbetancourt@google.com>
Reviewed-by: Florin Malita <fmalita@google.com>
This commit is contained in:
Jorge Betancourt 2022-05-03 15:23:16 -04:00 committed by SkCQ
parent 6065793294
commit 72f6c42ed8
2 changed files with 64 additions and 7 deletions

View File

@ -262,11 +262,14 @@ generated_cc_atom(
"//include/private:SkNoncopyable_hdr",
"//include/private:SkTPin_hdr",
"//modules/audioplayer:SkAudioPlayer_hdr",
"//modules/particles/include:SkParticleEffect_hdr",
"//modules/particles/include:SkParticleSerialization_hdr",
"//modules/skottie/include:SkottieProperty_hdr",
"//modules/skottie/include:Skottie_hdr",
"//modules/skottie/utils:SkottieUtils_hdr",
"//modules/skresources/include:SkResources_hdr",
"//src/utils:SkOSPath_hdr",
"//tools:Resources_hdr",
"//tools/timer:TimeUtils_hdr",
],
)

View File

@ -15,11 +15,14 @@
#include "include/private/SkNoncopyable.h"
#include "include/private/SkTPin.h"
#include "modules/audioplayer/SkAudioPlayer.h"
#include "modules/particles/include/SkParticleEffect.h"
#include "modules/particles/include/SkParticleSerialization.h"
#include "modules/skottie/include/Skottie.h"
#include "modules/skottie/include/SkottieProperty.h"
#include "modules/skottie/utils/SkottieUtils.h"
#include "modules/skresources/include/SkResources.h"
#include "src/utils/SkOSPath.h"
#include "tools/Resources.h"
#include "tools/timer/TimeUtils.h"
#include <cmath>
@ -81,7 +84,9 @@ class Decorator : public SkNoncopyable {
public:
virtual ~Decorator() = default;
virtual void render(SkCanvas*) = 0;
// We pass in the Matrix and have the Decorator handle using it independently
// This is so decorators like particle effects can keep position on screen after moving.
virtual void render(SkCanvas*, double, const SkMatrix) = 0;
};
class SimpleMarker final : public Decorator {
@ -90,7 +95,8 @@ public:
static std::unique_ptr<Decorator> Make() { return std::make_unique<SimpleMarker>(); }
void render(SkCanvas* canvas) override {
void render(SkCanvas* canvas, double t, const SkMatrix transform) override {
canvas->concat(transform);
SkPaint p;
p.setAntiAlias(true);
@ -104,11 +110,56 @@ public:
}
};
class ParticleMarker final : public Decorator {
public:
~ParticleMarker() override = default;
static std::unique_ptr<Decorator> MakeConfetti() { return std::make_unique<ParticleMarker>("confetti.json"); }
static std::unique_ptr<Decorator> MakeSine() { return std::make_unique<ParticleMarker>("sinusoidal_emitter.json"); }
explicit ParticleMarker(const char* effect_file) {
SkParticleEffect::RegisterParticleTypes();
auto params = sk_sp<SkParticleEffectParams>();
params.reset(new SkParticleEffectParams());
auto effectJsonPath = SkOSPath::Join(GetResourcePath("particles").c_str(), effect_file);
if (auto fileData = SkData::MakeFromFileName(effectJsonPath.c_str())) {
skjson::DOM dom(static_cast<const char*>(fileData->data()), fileData->size());
SkFromJsonVisitor fromJson(dom.root());
params->visitFields(&fromJson);
// We can pass in a null pointer because the SkCircleDrawable used in confetti.json
// doesn't use the resource provider
params->prepare(nullptr);
} else {
SkDebugf("no particle effect file found at: %s\n", effectJsonPath.c_str());
}
fEffect = sk_make_sp<SkParticleEffect>(params);
}
void render(SkCanvas* canvas, double t, SkMatrix transform) override {
if (!fStarted || t < 0.01) {
fStarted = true;
fEffect->start(t, true, { 0, 0 }, { 0, -1 }, 1, { 0, 0 }, 0,
{ 1, 1, 1, 1 }, 0, 0);
fEffect->setPosition({0,0});
}
SkPoint p = {0,0};
transform.mapPoints(&p, 1);
fEffect->setPosition(p);
fEffect->update(t);
fEffect->draw(canvas);
}
private:
sk_sp<SkParticleEffect> fEffect;
bool fStarted = false;
};
static const struct DecoratorRec {
const char* fName;
std::unique_ptr<Decorator>(*fFactory)();
} kDecorators[] = {
{ "Simple marker", SimpleMarker::Make }
{ "Simple marker", SimpleMarker::Make },
{ "Confetti", ParticleMarker::MakeConfetti },
{ "Sine Wave", ParticleMarker::MakeSine },
};
} // namespace
@ -152,7 +203,7 @@ public:
ImGui::End();
}
void renderTracker(SkCanvas* canvas, const SkSize& win_size, const SkSize& anim_size) const {
void renderTracker(SkCanvas* canvas, double time, const SkSize& win_size, const SkSize& anim_size) const {
if (!fTransformSelect) {
return;
}
@ -170,10 +221,9 @@ public:
SkAutoCanvasRestore acr(canvas, true);
canvas->concat(viewer_matrix);
canvas->concat(m);
SkASSERT(fDecorator);
fDecorator->render(canvas);
fDecorator->render(canvas, time, m);
}
private:
@ -336,7 +386,11 @@ void SkottieSlide::draw(SkCanvas* canvas) {
fFrameTimes[frame_index] = static_cast<float>((SkTime::GetNSecs() - t0) * 1e-6);
}
fTransformTracker->renderTracker(canvas, fWinSize, fAnimation->size());
double fr = 60;
if (fFrameRate != 0) {
fr = fFrameRate;
}
fTransformTracker->renderTracker(canvas, fCurrentFrame/fr, fWinSize, fAnimation->size());
if (fShowAnimationStats) {
draw_stats_box(canvas, fAnimationStats);