[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:
parent
6065793294
commit
72f6c42ed8
@ -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",
|
||||
],
|
||||
)
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user