blob: 1b2daefa0e4c444c6fc82b627125f84db23c5f8c [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 SkParticleData_DEFINED
9#define SkParticleData_DEFINED
10
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#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 Osman7c979f52019-02-12 13:27:51 -050016
17/*
18 * Various structs used to communicate particle information among emitters, affectors, etc.
19 */
20
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050021enum 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
27static constexpr SkFieldVisitor::EnumStringMapping gParticleFrameMapping[] = {
28 { kWorld_ParticleFrame, "World" },
29 { kLocal_ParticleFrame, "Local" },
30 { kVelocity_ParticleFrame, "Velocity" },
31};
32
Brian Osman7c979f52019-02-12 13:27:51 -050033struct 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
47struct SkParticleVelocity {
48 SkVector fLinear;
49 SkScalar fAngular;
50};
51
Brian Osman125daa42019-02-20 12:25:20 -050052struct SkParticleState {
Brian Osmand8e1ee92019-02-20 14:33:49 -050053 float fAge; // Normalized age [0, 1]
54 float fInvLifetime; // 1 / Lifetime
Brian Osman7c979f52019-02-12 13:27:51 -050055 SkParticlePose fPose;
56 SkParticleVelocity fVelocity;
Brian Osman125daa42019-02-20 12:25:20 -050057 SkColor4f fColor;
Brian Osmand8e1ee92019-02-20 14:33:49 -050058 SkScalar fFrame; // Parameter to drawable for animated sprites, etc.
Brian Osmane5d532e2019-02-26 14:58:40 -050059 SkRandom fRandom;
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050060
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 Osman7c979f52019-02-12 13:27:51 -050077};
78
79struct SkParticleUpdateParams {
Brian Osman7c979f52019-02-12 13:27:51 -050080 float fDeltaTime;
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050081 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 */
91struct 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
135private:
136 float getSourceValue(const SkParticleUpdateParams& params, SkParticleState& ps) const;
Brian Osman7c979f52019-02-12 13:27:51 -0500137};
138
139#endif // SkParticleData_DEFINED