blob: eb6fa0f8f28eac68320e9aee8c551eefb5c10362 [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 Osman8b6283f2019-02-14 16:55:21 -050014class SkLinearVelocityAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -050015public:
Brian Osman8b6283f2019-02-14 16:55:21 -050016 SkLinearVelocityAffector(const SkCurve& angle = 0.0f,
17 const SkCurve& strength = 0.0f,
Brian Osmand5c57fe2019-02-22 11:48:18 -050018 bool force = true,
19 bool local = false)
Brian Osman8b6283f2019-02-14 16:55:21 -050020 : fAngle(angle)
21 , fStrength(strength)
Brian Osmand5c57fe2019-02-22 11:48:18 -050022 , fForce(force)
23 , fLocal(local) {}
Brian Osman7c979f52019-02-12 13:27:51 -050024
Brian Osman8b6283f2019-02-14 16:55:21 -050025 REFLECTED(SkLinearVelocityAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -050026
Brian Osman125daa42019-02-20 12:25:20 -050027 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
Brian Osmand8e1ee92019-02-20 14:33:49 -050028 float angle = fAngle.eval(ps.fAge, ps.fStableRandom);
Brian Osmand5c57fe2019-02-22 11:48:18 -050029 SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
30 SkVector heading = fLocal ? ps.fPose.fHeading : SkVector{ 0, -1 };
31 SkScalar c = heading.fX * c_local - heading.fY * s_local;
32 SkScalar s = heading.fX * s_local + heading.fY * c_local;
Brian Osmand8e1ee92019-02-20 14:33:49 -050033 float strength = fStrength.eval(ps.fAge, ps.fStableRandom);
Brian Osman8b6283f2019-02-14 16:55:21 -050034 SkVector force = { c * strength, s * strength };
35 if (fForce) {
Brian Osman125daa42019-02-20 12:25:20 -050036 ps.fVelocity.fLinear += force * params.fDeltaTime;
Brian Osman8b6283f2019-02-14 16:55:21 -050037 } else {
Brian Osman125daa42019-02-20 12:25:20 -050038 ps.fVelocity.fLinear = force;
Brian Osman8b6283f2019-02-14 16:55:21 -050039 }
Brian Osman7c979f52019-02-12 13:27:51 -050040 }
41
42 void visitFields(SkFieldVisitor* v) override {
43 v->visit("Force", fForce);
Brian Osmand5c57fe2019-02-22 11:48:18 -050044 v->visit("Local", fLocal);
Brian Osman7c979f52019-02-12 13:27:51 -050045 v->visit("Angle", fAngle);
46 v->visit("Strength", fStrength);
Brian Osman7c979f52019-02-12 13:27:51 -050047 }
48
49private:
50 SkCurve fAngle;
51 SkCurve fStrength;
Brian Osman8b6283f2019-02-14 16:55:21 -050052 bool fForce;
Brian Osmand5c57fe2019-02-22 11:48:18 -050053 bool fLocal;
Brian Osman7c979f52019-02-12 13:27:51 -050054};
55
56class SkPointForceAffector : public SkParticleAffector {
57public:
58 SkPointForceAffector(SkPoint point = { 0.0f, 0.0f }, SkScalar constant = 0.0f,
59 SkScalar invSquare = 0.0f)
60 : fPoint(point), fConstant(constant), fInvSquare(invSquare) {}
61
62 REFLECTED(SkPointForceAffector, SkParticleAffector)
63
Brian Osman125daa42019-02-20 12:25:20 -050064 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
65 SkVector toPoint = fPoint - ps.fPose.fPosition;
Brian Osman7c979f52019-02-12 13:27:51 -050066 SkScalar lenSquare = toPoint.dot(toPoint);
67 toPoint.normalize();
Brian Osman125daa42019-02-20 12:25:20 -050068 ps.fVelocity.fLinear += toPoint * (fConstant + (fInvSquare/lenSquare)) * params.fDeltaTime;
Brian Osman7c979f52019-02-12 13:27:51 -050069 }
70
71 void visitFields(SkFieldVisitor* v) override {
72 v->visit("Point", fPoint);
73 v->visit("Constant", fConstant);
74 v->visit("InvSquare", fInvSquare);
75 }
76
77private:
78 SkPoint fPoint;
79 SkScalar fConstant;
80 SkScalar fInvSquare;
81};
82
83class SkOrientAlongVelocityAffector : public SkParticleAffector {
84public:
85 SkOrientAlongVelocityAffector() {}
86
87 REFLECTED(SkOrientAlongVelocityAffector, SkParticleAffector)
88
Brian Osman125daa42019-02-20 12:25:20 -050089 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
90 SkVector heading = ps.fVelocity.fLinear;
Brian Osman7c979f52019-02-12 13:27:51 -050091 if (!heading.normalize()) {
92 heading.set(0, -1);
93 }
Brian Osman125daa42019-02-20 12:25:20 -050094 ps.fPose.fHeading = heading;
Brian Osman7c979f52019-02-12 13:27:51 -050095 }
96
97 void visitFields(SkFieldVisitor*) override {}
98};
99
Brian Osman8b6283f2019-02-14 16:55:21 -0500100class SkSizeAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -0500101public:
Brian Osman8b6283f2019-02-14 16:55:21 -0500102 SkSizeAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
Brian Osman7c979f52019-02-12 13:27:51 -0500103
Brian Osman8b6283f2019-02-14 16:55:21 -0500104 REFLECTED(SkSizeAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -0500105
Brian Osman125daa42019-02-20 12:25:20 -0500106 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
Brian Osmand8e1ee92019-02-20 14:33:49 -0500107 ps.fPose.fScale = fCurve.eval(ps.fAge, ps.fStableRandom);
Brian Osman7c979f52019-02-12 13:27:51 -0500108 }
109
110 void visitFields(SkFieldVisitor* v) override {
Brian Osman8b6283f2019-02-14 16:55:21 -0500111 v->visit("Curve", fCurve);
Brian Osman7c979f52019-02-12 13:27:51 -0500112 }
113
114private:
Brian Osman8b6283f2019-02-14 16:55:21 -0500115 SkCurve fCurve;
Brian Osman7c979f52019-02-12 13:27:51 -0500116};
117
Brian Osman125daa42019-02-20 12:25:20 -0500118class SkFrameAffector : public SkParticleAffector {
119public:
120 SkFrameAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
121
122 REFLECTED(SkFrameAffector, SkParticleAffector)
123
124 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
Brian Osmand8e1ee92019-02-20 14:33:49 -0500125 ps.fFrame = fCurve.eval(ps.fAge, ps.fStableRandom);
Brian Osman125daa42019-02-20 12:25:20 -0500126 }
127
128 void visitFields(SkFieldVisitor* v) override {
129 v->visit("Curve", fCurve);
130 }
131
132private:
133 SkCurve fCurve;
134};
135
136class SkColorAffector : public SkParticleAffector {
137public:
138 SkColorAffector(const SkColorCurve& curve = SkColor4f{ 1.0f, 1.0f, 1.0f, 1.0f })
139 : fCurve(curve) {}
140
141 REFLECTED(SkColorAffector, SkParticleAffector)
142
143 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
Brian Osmand8e1ee92019-02-20 14:33:49 -0500144 ps.fColor = fCurve.eval(ps.fAge, ps.fStableRandom);
Brian Osman125daa42019-02-20 12:25:20 -0500145 }
146
147 void visitFields(SkFieldVisitor* v) override {
148 v->visit("Curve", fCurve);
149 }
150
151private:
152 SkColorCurve fCurve;
153};
154
Brian Osman7c979f52019-02-12 13:27:51 -0500155void SkParticleAffector::RegisterAffectorTypes() {
156 REGISTER_REFLECTED(SkParticleAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500157 REGISTER_REFLECTED(SkLinearVelocityAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500158 REGISTER_REFLECTED(SkPointForceAffector);
159 REGISTER_REFLECTED(SkOrientAlongVelocityAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500160 REGISTER_REFLECTED(SkSizeAffector);
Brian Osman125daa42019-02-20 12:25:20 -0500161 REGISTER_REFLECTED(SkFrameAffector);
162 REGISTER_REFLECTED(SkColorAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500163}
164
Brian Osman8b6283f2019-02-14 16:55:21 -0500165sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,
166 const SkCurve& strength,
Brian Osmand5c57fe2019-02-22 11:48:18 -0500167 bool force,
168 bool local) {
169 return sk_sp<SkParticleAffector>(new SkLinearVelocityAffector(angle, strength, force, local));
Brian Osman7c979f52019-02-12 13:27:51 -0500170}
171
Brian Osman8b6283f2019-02-14 16:55:21 -0500172sk_sp<SkParticleAffector> SkParticleAffector::MakePointForce(SkPoint point, SkScalar constant,
173 SkScalar invSquare) {
Brian Osman7c979f52019-02-12 13:27:51 -0500174 return sk_sp<SkParticleAffector>(new SkPointForceAffector(point, constant, invSquare));
175}
176
Brian Osman8b6283f2019-02-14 16:55:21 -0500177sk_sp<SkParticleAffector> SkParticleAffector::MakeOrientAlongVelocity() {
Brian Osman7c979f52019-02-12 13:27:51 -0500178 return sk_sp<SkParticleAffector>(new SkOrientAlongVelocityAffector());
179}
Brian Osman8b6283f2019-02-14 16:55:21 -0500180
Brian Osman125daa42019-02-20 12:25:20 -0500181sk_sp<SkParticleAffector> SkParticleAffector::MakeSize(const SkCurve& curve) {
Brian Osman8b6283f2019-02-14 16:55:21 -0500182 return sk_sp<SkParticleAffector>(new SkSizeAffector(curve));
183}
Brian Osman125daa42019-02-20 12:25:20 -0500184
185sk_sp<SkParticleAffector> SkParticleAffector::MakeFrame(const SkCurve& curve) {
186 return sk_sp<SkParticleAffector>(new SkFrameAffector(curve));
187}
188
189sk_sp<SkParticleAffector> SkParticleAffector::MakeColor(const SkColorCurve& curve) {
190 return sk_sp<SkParticleAffector>(new SkColorAffector(curve));
191}