blob: 3d7454e66417a719bb3a92f8c5e211448cee52de [file] [log] [blame]
Brian Osman7c979f52019-02-12 13:27:51 -05001/*
2* Copyright 2019 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#ifndef SkParticleEffect_DEFINED
9#define SkParticleEffect_DEFINED
10
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkRefCnt.h"
Brian Osmanfe491632019-07-25 15:14:50 -040012#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/private/SkTArray.h"
Brian Osmanfe491632019-07-25 15:14:50 -040014#include "include/private/SkTemplates.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "include/utils/SkRandom.h"
Brian Osmanfe491632019-07-25 15:14:50 -040016#include "modules/particles/include/SkParticleData.h"
Brian Osmanfe491632019-07-25 15:14:50 -040017
18#include <memory>
Brian Osman7c979f52019-02-12 13:27:51 -050019
Brian Osman7c979f52019-02-12 13:27:51 -050020class SkCanvas;
Brian Osman2aa85df2019-08-30 10:59:47 -040021class SkFieldVisitor;
22class SkParticleBinding;
Brian Osman543d2e22019-02-15 14:29:38 -050023class SkParticleDrawable;
Brian Osmanfe491632019-07-25 15:14:50 -040024class SkParticleExternalValue;
25
26namespace SkSL {
27 struct ByteCode;
Brian Osmanfe491632019-07-25 15:14:50 -040028}
29
Brian Osman7c979f52019-02-12 13:27:51 -050030class SkParticleEffectParams : public SkRefCnt {
31public:
Brian Osmanfe491632019-07-25 15:14:50 -040032 SkParticleEffectParams();
33
Brian Osman3da607e2019-07-26 15:11:46 -040034 int fMaxCount; // Maximum number of particles per instance of the effect
35 float fEffectDuration; // How long does the effect last after being played, in seconds?
36 float fRate; // How many particles are emitted per second?
Brian Osman7c979f52019-02-12 13:27:51 -050037
Brian Osman3da607e2019-07-26 15:11:46 -040038 // What is drawn for each particle? (Image, shape, sprite sheet, etc.)
39 // See SkParticleDrawable::Make*
Brian Osman543d2e22019-02-15 14:29:38 -050040 sk_sp<SkParticleDrawable> fDrawable;
Brian Osman7c979f52019-02-12 13:27:51 -050041
Brian Osman3da607e2019-07-26 15:11:46 -040042 // Particle behavior is driven by two SkSL functions defined in the fCode string.
43 // Both functions get a mutable Particle struct:
44 //
45 // struct Particle {
46 // float age;
47 // float lifetime;
48 // float2 pos = { 0, 0 }; // Local position, relative to the effect.
49 // float2 dir = { 0, -1 }; // Heading. Should be a normalized vector.
50 // float scale = 1; // Size, normalized relative to the drawable's native size
51 // float2 vel = { 0, 0 }; // Linear velocity, in (units / second)
52 // float spin = 0; // Angular velocity, in (radians / second)
53 // float4 color = { 1, 1, 1, 1 }; // RGBA color
54 // float frame = 0; // Normalized sprite index for multi-frame drawables
55 // };
56 //
57 // In addition, both functions have access to a global variable named 'rand'. Every read of
58 // 'rand' returns a random floating point value in [0, 1). The random generator is stored
59 // per-particle, and the state is rewound after each update, so calls to 'rand' will return
60 // consistent values from one update to the next.
61 //
62 // Finally, there are two global uniform values available. The first is 'dt', a floating point
63 // number of seconds that have elapsed since the last update. The second is 'effectAge', which
64 // is the normalized age of the effect (not particle). For looping effects, this will wrap
65 // back to zero when the effect's age exceeds its duration.
66 //
67 // 'void spawn(inout Particle p)' is called once for each particle when it is first created,
68 // to set initial values. At a minimum, this should set 'lifetime' to the number of seconds
69 // that the particle will exist. Other parameters have defaults shown above.
70 //
71 // 'void update(inout Particle p)' is called for each particle on every call to the running
72 // SkParticleEffect's update() method. It can animate any of the particle's values. Note that
73 // the 'lifetime' field has a different meaning in 'update', and should not be used or changed.
Brian Osmane59acb72019-07-25 16:58:46 -040074 SkString fCode;
Brian Osmanfe491632019-07-25 15:14:50 -040075
Brian Osman3da607e2019-07-26 15:11:46 -040076 // External objects accessible by the effect's SkSL code. Each binding is a name and particular
77 // kind of object. See SkParticleBinding::Make* for details.
Brian Osmanfe491632019-07-25 15:14:50 -040078 SkTArray<sk_sp<SkParticleBinding>> fBindings;
Brian Osman7c979f52019-02-12 13:27:51 -050079
80 void visitFields(SkFieldVisitor* v);
Brian Osmanfe491632019-07-25 15:14:50 -040081
82private:
83 friend class SkParticleEffect;
84
85 // Cached
Brian Osmane59acb72019-07-25 16:58:46 -040086 std::unique_ptr<SkSL::ByteCode> fByteCode;
87 SkTArray<std::unique_ptr<SkParticleExternalValue>> fExternalValues;
Brian Osmanfe491632019-07-25 15:14:50 -040088
89 void rebuild();
Brian Osman7c979f52019-02-12 13:27:51 -050090};
91
92class SkParticleEffect : public SkRefCnt {
93public:
Brian Osman5c1f8eb2019-02-14 14:49:55 -050094 SkParticleEffect(sk_sp<SkParticleEffectParams> params, const SkRandom& random);
Brian Osman7c979f52019-02-12 13:27:51 -050095
Kevin Lubick269fe892019-03-06 09:32:55 -050096 void start(double now, bool looping = false);
Kevin Lubick269fe892019-03-06 09:32:55 -050097 void update(double now);
Brian Osman7c979f52019-02-12 13:27:51 -050098 void draw(SkCanvas* canvas);
99
Brian Osmanb77d5022019-03-06 11:08:48 -0500100 bool isAlive() const { return fSpawnTime >= 0; }
101 int getCount() const { return fCount; }
Brian Osman7c979f52019-02-12 13:27:51 -0500102
Brian Osman2aa85df2019-08-30 10:59:47 -0400103 static void RegisterParticleTypes();
104
Brian Osman7c979f52019-02-12 13:27:51 -0500105private:
106 void setCapacity(int capacity);
107
Brian Osman7c979f52019-02-12 13:27:51 -0500108 sk_sp<SkParticleEffectParams> fParams;
Brian Osman7c979f52019-02-12 13:27:51 -0500109
Brian Osman5c1f8eb2019-02-14 14:49:55 -0500110 SkRandom fRandom;
111
112 bool fLooping;
113 double fSpawnTime;
114
Brian Osman7c979f52019-02-12 13:27:51 -0500115 int fCount;
116 double fLastTime;
117 float fSpawnRemainder;
118
Brian Osmanfe491632019-07-25 15:14:50 -0400119 SkParticles fParticles;
120 SkAutoTMalloc<SkRandom> fStableRandoms;
Brian Osman7c979f52019-02-12 13:27:51 -0500121
122 // Cached
123 int fCapacity;
124};
125
126#endif // SkParticleEffect_DEFINED