1 /* 2 * Copyright 2021 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "gm/gm.h" 9 10 #if !defined(SK_BUILD_FOR_GOOGLE3) // Google3 doesn't build particles module 11 12 #include "include/core/SkCanvas.h" 13 #include "include/core/SkColor.h" 14 #include "modules/particles/include/SkParticleEffect.h" 15 #include "modules/particles/include/SkParticleSerialization.h" 16 #include "modules/skresources/include/SkResources.h" 17 #include "src/sksl/codegen/SkSLVMCodeGenerator.h" 18 #include "tools/Resources.h" 19 20 struct UniformValue { 21 const char* fName; 22 std::vector<float> fData; 23 }; 24 25 class ParticlesGM : public skiagm::GM { 26 public: ParticlesGM(const char * name,double startTime,SkISize size,SkPoint origin,std::vector<UniformValue> uniforms={})27 ParticlesGM(const char* name, 28 double startTime, 29 SkISize size, 30 SkPoint origin, 31 std::vector<UniformValue> uniforms = {}) 32 : GM(SK_ColorBLACK) 33 , fName(name) 34 , fStartTime(startTime) 35 , fSize(size) 36 , fOrigin(origin) 37 , fUniforms(std::move(uniforms)) {} 38 onShortName()39 SkString onShortName() override { return SkStringPrintf("particles_%s", fName); } onISize()40 SkISize onISize() override { return fSize; } 41 onOnceBeforeDraw()42 void onOnceBeforeDraw() override { 43 SkParticleEffect::RegisterParticleTypes(); 44 45 auto jsonData = GetResourceAsData(SkStringPrintf("particles/%s.json", fName).c_str()); 46 skjson::DOM dom(static_cast<const char*>(jsonData->data()), jsonData->size()); 47 SkFromJsonVisitor fromJson(dom.root()); 48 49 auto resourceProvider = skresources::FileResourceProvider::Make(GetResourcePath()); 50 auto effectParams = sk_make_sp<SkParticleEffectParams>(); 51 effectParams->visitFields(&fromJson); 52 effectParams->prepare(resourceProvider.get()); 53 54 fEffect = sk_make_sp<SkParticleEffect>(effectParams); 55 for (const auto& val : fUniforms) { 56 SkAssertResult(fEffect->setUniform(val.fName, val.fData.data(), val.fData.size())); 57 } 58 59 fEffect->start(/*now=*/0.0, /*looping=*/true); 60 61 // Fast-forward (in 30 fps time-slices) to the requested time 62 for (double time = 0; time < fStartTime; time += 1.0 / 30) { 63 fEffect->update(/*now=*/std::min(time, fStartTime)); 64 } 65 } 66 onAnimate(double nanos)67 bool onAnimate(double nanos) override { 68 if (fEffect) { 69 fEffect->update(fStartTime + (nanos * 1E-9)); 70 } 71 return true; 72 } 73 onDraw(SkCanvas * canvas)74 void onDraw(SkCanvas* canvas) override { 75 canvas->save(); 76 canvas->translate(fOrigin.fX, fOrigin.fY); 77 fEffect->draw(canvas); 78 canvas->restore(); 79 } 80 81 protected: 82 const char* fName; 83 const double fStartTime; 84 const SkISize fSize; 85 const SkPoint fOrigin; 86 sk_sp<SkParticleEffect> fEffect; 87 std::vector<UniformValue> fUniforms; 88 }; 89 90 DEF_GM(return new ParticlesGM("confetti", 1.0, {400, 400}, {200, 200});) 91 DEF_GM(return new ParticlesGM("cube", 1.0, {400, 400}, {200, 200});) 92 DEF_GM(return new ParticlesGM("curves", 4.0, {100, 200}, { 50, 190});) 93 DEF_GM(return new ParticlesGM("mandrill", 1.0, {250, 250}, { 25, 25});) 94 DEF_GM(return new ParticlesGM("spiral", 2.0, {250, 250}, {125, 125});) 95 DEF_GM(return new ParticlesGM("sprite_frame", 1.0, {200, 200}, {100, 100});) 96 DEF_GM(return new ParticlesGM("text", 1.0, {250, 110}, { 10, 100});) 97 DEF_GM(return new ParticlesGM("uniforms", 2.0, {250, 250}, {125, 125}, 98 {{"rate", {2.0f}}, 99 {"spin", {4.0f}}, 100 {"color", {0.25f, 0.75f, 0.75f}}});) 101 102 #endif // SK_BUILD_FOR_GOOGLE3 103