blob: 74d55e9fc5e744ebcb221bf1104ee4c3792fcb64 [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#include "SkParticleAffector.h"
9
Brian Osman8b6283f2019-02-14 16:55:21 -050010#include "SkCurve.h"
Brian Osman7c979f52019-02-12 13:27:51 -050011#include "SkParticleData.h"
12#include "SkRandom.h"
13
Brian Osman1b20cd82019-02-25 14:15:02 -050014void SkParticleAffector::apply(SkParticleUpdateParams& params, SkParticleState& ps) {
15 if (fEnabled) {
16 this->onApply(params, ps);
17 }
18}
19
20void SkParticleAffector::visitFields(SkFieldVisitor* v) {
21 v->visit("Enabled", fEnabled);
22}
23
Brian Osman8b6283f2019-02-14 16:55:21 -050024class SkLinearVelocityAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -050025public:
Brian Osman8b6283f2019-02-14 16:55:21 -050026 SkLinearVelocityAffector(const SkCurve& angle = 0.0f,
27 const SkCurve& strength = 0.0f,
Brian Osmand5c57fe2019-02-22 11:48:18 -050028 bool force = true,
29 bool local = false)
Brian Osman8b6283f2019-02-14 16:55:21 -050030 : fAngle(angle)
31 , fStrength(strength)
Brian Osmand5c57fe2019-02-22 11:48:18 -050032 , fForce(force)
33 , fLocal(local) {}
Brian Osman7c979f52019-02-12 13:27:51 -050034
Brian Osman8b6283f2019-02-14 16:55:21 -050035 REFLECTED(SkLinearVelocityAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -050036
Brian Osman1b20cd82019-02-25 14:15:02 -050037 void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
Brian Osmand8e1ee92019-02-20 14:33:49 -050038 float angle = fAngle.eval(ps.fAge, ps.fStableRandom);
Brian Osmand5c57fe2019-02-22 11:48:18 -050039 SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
40 SkVector heading = fLocal ? ps.fPose.fHeading : SkVector{ 0, -1 };
41 SkScalar c = heading.fX * c_local - heading.fY * s_local;
42 SkScalar s = heading.fX * s_local + heading.fY * c_local;
Brian Osmand8e1ee92019-02-20 14:33:49 -050043 float strength = fStrength.eval(ps.fAge, ps.fStableRandom);
Brian Osman8b6283f2019-02-14 16:55:21 -050044 SkVector force = { c * strength, s * strength };
45 if (fForce) {
Brian Osman125daa42019-02-20 12:25:20 -050046 ps.fVelocity.fLinear += force * params.fDeltaTime;
Brian Osman8b6283f2019-02-14 16:55:21 -050047 } else {
Brian Osman125daa42019-02-20 12:25:20 -050048 ps.fVelocity.fLinear = force;
Brian Osman8b6283f2019-02-14 16:55:21 -050049 }
Brian Osman7c979f52019-02-12 13:27:51 -050050 }
51
52 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -050053 SkParticleAffector::visitFields(v);
Brian Osman7c979f52019-02-12 13:27:51 -050054 v->visit("Force", fForce);
Brian Osmand5c57fe2019-02-22 11:48:18 -050055 v->visit("Local", fLocal);
Brian Osman7c979f52019-02-12 13:27:51 -050056 v->visit("Angle", fAngle);
57 v->visit("Strength", fStrength);
Brian Osman7c979f52019-02-12 13:27:51 -050058 }
59
60private:
61 SkCurve fAngle;
62 SkCurve fStrength;
Brian Osman8b6283f2019-02-14 16:55:21 -050063 bool fForce;
Brian Osmand5c57fe2019-02-22 11:48:18 -050064 bool fLocal;
Brian Osman7c979f52019-02-12 13:27:51 -050065};
66
67class SkPointForceAffector : public SkParticleAffector {
68public:
69 SkPointForceAffector(SkPoint point = { 0.0f, 0.0f }, SkScalar constant = 0.0f,
70 SkScalar invSquare = 0.0f)
71 : fPoint(point), fConstant(constant), fInvSquare(invSquare) {}
72
73 REFLECTED(SkPointForceAffector, SkParticleAffector)
74
Brian Osman1b20cd82019-02-25 14:15:02 -050075 void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
Brian Osman125daa42019-02-20 12:25:20 -050076 SkVector toPoint = fPoint - ps.fPose.fPosition;
Brian Osman7c979f52019-02-12 13:27:51 -050077 SkScalar lenSquare = toPoint.dot(toPoint);
78 toPoint.normalize();
Brian Osman125daa42019-02-20 12:25:20 -050079 ps.fVelocity.fLinear += toPoint * (fConstant + (fInvSquare/lenSquare)) * params.fDeltaTime;
Brian Osman7c979f52019-02-12 13:27:51 -050080 }
81
82 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -050083 SkParticleAffector::visitFields(v);
Brian Osman7c979f52019-02-12 13:27:51 -050084 v->visit("Point", fPoint);
85 v->visit("Constant", fConstant);
86 v->visit("InvSquare", fInvSquare);
87 }
88
89private:
90 SkPoint fPoint;
91 SkScalar fConstant;
92 SkScalar fInvSquare;
93};
94
95class SkOrientAlongVelocityAffector : public SkParticleAffector {
96public:
97 SkOrientAlongVelocityAffector() {}
98
99 REFLECTED(SkOrientAlongVelocityAffector, SkParticleAffector)
100
Brian Osman1b20cd82019-02-25 14:15:02 -0500101 void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
Brian Osman125daa42019-02-20 12:25:20 -0500102 SkVector heading = ps.fVelocity.fLinear;
Brian Osman7c979f52019-02-12 13:27:51 -0500103 if (!heading.normalize()) {
104 heading.set(0, -1);
105 }
Brian Osman125daa42019-02-20 12:25:20 -0500106 ps.fPose.fHeading = heading;
Brian Osman7c979f52019-02-12 13:27:51 -0500107 }
108
Brian Osman1b20cd82019-02-25 14:15:02 -0500109 void visitFields(SkFieldVisitor *v) override {
110 SkParticleAffector::visitFields(v);
111 }
Brian Osman7c979f52019-02-12 13:27:51 -0500112};
113
Brian Osman8b6283f2019-02-14 16:55:21 -0500114class SkSizeAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -0500115public:
Brian Osman8b6283f2019-02-14 16:55:21 -0500116 SkSizeAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
Brian Osman7c979f52019-02-12 13:27:51 -0500117
Brian Osman8b6283f2019-02-14 16:55:21 -0500118 REFLECTED(SkSizeAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -0500119
Brian Osman1b20cd82019-02-25 14:15:02 -0500120 void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
Brian Osmand8e1ee92019-02-20 14:33:49 -0500121 ps.fPose.fScale = fCurve.eval(ps.fAge, ps.fStableRandom);
Brian Osman7c979f52019-02-12 13:27:51 -0500122 }
123
124 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500125 SkParticleAffector::visitFields(v);
Brian Osman8b6283f2019-02-14 16:55:21 -0500126 v->visit("Curve", fCurve);
Brian Osman7c979f52019-02-12 13:27:51 -0500127 }
128
129private:
Brian Osman8b6283f2019-02-14 16:55:21 -0500130 SkCurve fCurve;
Brian Osman7c979f52019-02-12 13:27:51 -0500131};
132
Brian Osman125daa42019-02-20 12:25:20 -0500133class SkFrameAffector : public SkParticleAffector {
134public:
135 SkFrameAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
136
137 REFLECTED(SkFrameAffector, SkParticleAffector)
138
Brian Osman1b20cd82019-02-25 14:15:02 -0500139 void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
Brian Osmand8e1ee92019-02-20 14:33:49 -0500140 ps.fFrame = fCurve.eval(ps.fAge, ps.fStableRandom);
Brian Osman125daa42019-02-20 12:25:20 -0500141 }
142
143 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500144 SkParticleAffector::visitFields(v);
Brian Osman125daa42019-02-20 12:25:20 -0500145 v->visit("Curve", fCurve);
146 }
147
148private:
149 SkCurve fCurve;
150};
151
152class SkColorAffector : public SkParticleAffector {
153public:
154 SkColorAffector(const SkColorCurve& curve = SkColor4f{ 1.0f, 1.0f, 1.0f, 1.0f })
155 : fCurve(curve) {}
156
157 REFLECTED(SkColorAffector, SkParticleAffector)
158
Brian Osman1b20cd82019-02-25 14:15:02 -0500159 void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
Brian Osmand8e1ee92019-02-20 14:33:49 -0500160 ps.fColor = fCurve.eval(ps.fAge, ps.fStableRandom);
Brian Osman125daa42019-02-20 12:25:20 -0500161 }
162
163 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500164 SkParticleAffector::visitFields(v);
Brian Osman125daa42019-02-20 12:25:20 -0500165 v->visit("Curve", fCurve);
166 }
167
168private:
169 SkColorCurve fCurve;
170};
171
Brian Osman7c979f52019-02-12 13:27:51 -0500172void SkParticleAffector::RegisterAffectorTypes() {
173 REGISTER_REFLECTED(SkParticleAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500174 REGISTER_REFLECTED(SkLinearVelocityAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500175 REGISTER_REFLECTED(SkPointForceAffector);
176 REGISTER_REFLECTED(SkOrientAlongVelocityAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500177 REGISTER_REFLECTED(SkSizeAffector);
Brian Osman125daa42019-02-20 12:25:20 -0500178 REGISTER_REFLECTED(SkFrameAffector);
179 REGISTER_REFLECTED(SkColorAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500180}
181
Brian Osman8b6283f2019-02-14 16:55:21 -0500182sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,
183 const SkCurve& strength,
Brian Osmand5c57fe2019-02-22 11:48:18 -0500184 bool force,
185 bool local) {
186 return sk_sp<SkParticleAffector>(new SkLinearVelocityAffector(angle, strength, force, local));
Brian Osman7c979f52019-02-12 13:27:51 -0500187}
188
Brian Osman8b6283f2019-02-14 16:55:21 -0500189sk_sp<SkParticleAffector> SkParticleAffector::MakePointForce(SkPoint point, SkScalar constant,
190 SkScalar invSquare) {
Brian Osman7c979f52019-02-12 13:27:51 -0500191 return sk_sp<SkParticleAffector>(new SkPointForceAffector(point, constant, invSquare));
192}
193
Brian Osman8b6283f2019-02-14 16:55:21 -0500194sk_sp<SkParticleAffector> SkParticleAffector::MakeOrientAlongVelocity() {
Brian Osman7c979f52019-02-12 13:27:51 -0500195 return sk_sp<SkParticleAffector>(new SkOrientAlongVelocityAffector());
196}
Brian Osman8b6283f2019-02-14 16:55:21 -0500197
Brian Osman125daa42019-02-20 12:25:20 -0500198sk_sp<SkParticleAffector> SkParticleAffector::MakeSize(const SkCurve& curve) {
Brian Osman8b6283f2019-02-14 16:55:21 -0500199 return sk_sp<SkParticleAffector>(new SkSizeAffector(curve));
200}
Brian Osman125daa42019-02-20 12:25:20 -0500201
202sk_sp<SkParticleAffector> SkParticleAffector::MakeFrame(const SkCurve& curve) {
203 return sk_sp<SkParticleAffector>(new SkFrameAffector(curve));
204}
205
206sk_sp<SkParticleAffector> SkParticleAffector::MakeColor(const SkColorCurve& curve) {
207 return sk_sp<SkParticleAffector>(new SkColorAffector(curve));
208}