• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 SkParticleData_DEFINED
9 #define SkParticleData_DEFINED
10 
11 #include "SkColor.h"
12 #include "SkPoint.h"
13 #include "SkRandom.h"
14 #include "SkReflected.h"
15 #include "SkRSXform.h"
16 
17 /*
18  *  Various structs used to communicate particle information among emitters, affectors, etc.
19  */
20 
21 enum SkParticleFrame {
22     kWorld_ParticleFrame,     // "Up" is { 0, -1 }
23     kLocal_ParticleFrame,     // "Up" is particle's heading
24     kVelocity_ParticleFrame,  // "Up" is particle's direction of travel
25 };
26 
27 static constexpr SkFieldVisitor::EnumStringMapping gParticleFrameMapping[] = {
28     { kWorld_ParticleFrame,    "World" },
29     { kLocal_ParticleFrame,    "Local" },
30     { kVelocity_ParticleFrame, "Velocity" },
31 };
32 
33 struct SkParticlePose {
34     SkPoint  fPosition;
35     SkVector fHeading;
36     SkScalar fScale;
37 
asRSXformSkParticlePose38     SkRSXform asRSXform(SkPoint ofs) const {
39         const float s =  fHeading.fX * fScale;
40         const float c = -fHeading.fY * fScale;
41         return SkRSXform::Make(c, s,
42                                fPosition.fX + -c * ofs.fX +  s * ofs.fY,
43                                fPosition.fY + -s * ofs.fX + -c * ofs.fY);
44     }
45 };
46 
47 struct SkParticleVelocity {
48     SkVector fLinear;
49     SkScalar fAngular;
50 };
51 
52 struct SkParticleState {
53     float              fAge;          // Normalized age [0, 1]
54     float              fInvLifetime;  // 1 / Lifetime
55     SkParticlePose     fPose;
56     SkParticleVelocity fVelocity;
57     SkColor4f          fColor;
58     SkScalar           fFrame;        // Parameter to drawable for animated sprites, etc.
59     SkRandom           fRandom;
60 
getFrameHeadingSkParticleState61     SkVector getFrameHeading(SkParticleFrame frame) const {
62         switch (frame) {
63             case kLocal_ParticleFrame:
64                 return fPose.fHeading;
65             case kVelocity_ParticleFrame: {
66                 SkVector heading = fVelocity.fLinear;
67                 if (!heading.normalize()) {
68                     heading.set(0, -1);
69                 }
70                 return heading;
71             }
72             case kWorld_ParticleFrame:
73             default:
74                 return SkVector{ 0, -1 };
75         }
76     }
77 };
78 
79 struct SkParticleUpdateParams {
80     float fDeltaTime;
81     float fEffectAge;
82     int   fAgeSource;
83 };
84 
85 /**
86  * SkParticleValue selects a specific value to be used when evaluating a curve, position on a path,
87  * or any other affector that needs a scalar float input. An SkParticleValue starts with a source
88  * value taken from the state of the effect or particle. That can be adjusted using a scale and
89  * bias, and then reduced into the desired range (typically [0, 1]) via a chosen tile mode.
90  */
91 struct SkParticleValue {
92     enum Source {
93         // Either the particle or effect age, depending on spawn or update
94         kAge_Source,
95 
96         kRandom_Source,
97         kParticleAge_Source,
98         kEffectAge_Source,
99         kPositionX_Source,
100         kPositionY_Source,
101         kHeadingX_Source,
102         kHeadingY_Source,
103         kScale_Source,
104         kVelocityX_Source,
105         kVelocityY_Source,
106         kRotation_Source,
107         kColorR_Source,
108         kColorG_Source,
109         kColorB_Source,
110         kColorA_Source,
111         kSpriteFrame_Source,
112     };
113 
114     enum TileMode {
115         kClamp_TileMode,
116         kRepeat_TileMode,
117         kMirror_TileMode,
118     };
119 
120     void visitFields(SkFieldVisitor* v);
121     float eval(const SkParticleUpdateParams& params, SkParticleState& ps) const;
122 
123     int   fSource   = kAge_Source;
124     int   fFrame    = kWorld_ParticleFrame;
125     int   fTileMode = kRepeat_TileMode;
126 
127     // We map fLeft -> 0 and fRight -> 1. This is easier to work with and reason about.
128     float fLeft     = 0.0f;
129     float fRight    = 1.0f;
130 
131     // Cached from the above
132     float fScale    = 1.0f;
133     float fBias     = 0.0f;
134 
135 private:
136     float getSourceValue(const SkParticleUpdateParams& params, SkParticleState& ps) const;
137 };
138 
139 #endif // SkParticleData_DEFINED
140