Brian Osman | 7c979f5 | 2019-02-12 13:27:51 -0500 | [diff] [blame] | 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 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 11 | #include "include/core/SkColor.h" |
| 12 | #include "include/core/SkPoint.h" |
| 13 | #include "include/core/SkRSXform.h" |
| 14 | #include "include/utils/SkRandom.h" |
| 15 | #include "modules/particles/include/SkReflected.h" |
Brian Osman | 7c979f5 | 2019-02-12 13:27:51 -0500 | [diff] [blame] | 16 | |
| 17 | /* |
| 18 | * Various structs used to communicate particle information among emitters, affectors, etc. |
| 19 | */ |
| 20 | |
Brian Osman | bdcdf1a | 2019-03-04 10:55:22 -0500 | [diff] [blame] | 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 | |
Brian Osman | 7c979f5 | 2019-02-12 13:27:51 -0500 | [diff] [blame] | 33 | struct SkParticlePose { |
| 34 | SkPoint fPosition; |
| 35 | SkVector fHeading; |
| 36 | SkScalar fScale; |
| 37 | |
| 38 | 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 | |
Brian Osman | 125daa4 | 2019-02-20 12:25:20 -0500 | [diff] [blame] | 52 | struct SkParticleState { |
Brian Osman | d8e1ee9 | 2019-02-20 14:33:49 -0500 | [diff] [blame] | 53 | float fAge; // Normalized age [0, 1] |
| 54 | float fInvLifetime; // 1 / Lifetime |
Brian Osman | 7c979f5 | 2019-02-12 13:27:51 -0500 | [diff] [blame] | 55 | SkParticlePose fPose; |
| 56 | SkParticleVelocity fVelocity; |
Brian Osman | 125daa4 | 2019-02-20 12:25:20 -0500 | [diff] [blame] | 57 | SkColor4f fColor; |
Brian Osman | d8e1ee9 | 2019-02-20 14:33:49 -0500 | [diff] [blame] | 58 | SkScalar fFrame; // Parameter to drawable for animated sprites, etc. |
Brian Osman | e5d532e | 2019-02-26 14:58:40 -0500 | [diff] [blame] | 59 | SkRandom fRandom; |
Brian Osman | bdcdf1a | 2019-03-04 10:55:22 -0500 | [diff] [blame] | 60 | |
| 61 | 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 | } |
Brian Osman | 7c979f5 | 2019-02-12 13:27:51 -0500 | [diff] [blame] | 77 | }; |
| 78 | |
| 79 | struct SkParticleUpdateParams { |
Brian Osman | 7c979f5 | 2019-02-12 13:27:51 -0500 | [diff] [blame] | 80 | float fDeltaTime; |
Brian Osman | bdcdf1a | 2019-03-04 10:55:22 -0500 | [diff] [blame] | 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; |
Brian Osman | 7c979f5 | 2019-02-12 13:27:51 -0500 | [diff] [blame] | 137 | }; |
| 138 | |
| 139 | #endif // SkParticleData_DEFINED |