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