blob: 7cdf0cb8ee239bb0f1b9fbc6eeac311023b74d01 [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,
18 bool force = true)
19 : fAngle(angle)
20 , fStrength(strength)
21 , fForce(force) {}
Brian Osman7c979f52019-02-12 13:27:51 -050022
Brian Osman8b6283f2019-02-14 16:55:21 -050023 REFLECTED(SkLinearVelocityAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -050024
Brian Osman125daa42019-02-20 12:25:20 -050025 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
26 float angle = fAngle.eval(params.fParticleT, ps.fStableRandom);
Brian Osman8b6283f2019-02-14 16:55:21 -050027 SkScalar c, s = SkScalarSinCos(SkDegreesToRadians(angle), &c);
Brian Osman125daa42019-02-20 12:25:20 -050028 float strength = fStrength.eval(params.fParticleT, ps.fStableRandom);
Brian Osman8b6283f2019-02-14 16:55:21 -050029 SkVector force = { c * strength, s * strength };
30 if (fForce) {
Brian Osman125daa42019-02-20 12:25:20 -050031 ps.fVelocity.fLinear += force * params.fDeltaTime;
Brian Osman8b6283f2019-02-14 16:55:21 -050032 } else {
Brian Osman125daa42019-02-20 12:25:20 -050033 ps.fVelocity.fLinear = force;
Brian Osman8b6283f2019-02-14 16:55:21 -050034 }
Brian Osman7c979f52019-02-12 13:27:51 -050035 }
36
37 void visitFields(SkFieldVisitor* v) override {
38 v->visit("Force", fForce);
Brian Osman7c979f52019-02-12 13:27:51 -050039 v->visit("Angle", fAngle);
40 v->visit("Strength", fStrength);
Brian Osman7c979f52019-02-12 13:27:51 -050041 }
42
43private:
44 SkCurve fAngle;
45 SkCurve fStrength;
Brian Osman8b6283f2019-02-14 16:55:21 -050046 bool fForce;
Brian Osman7c979f52019-02-12 13:27:51 -050047};
48
49class SkPointForceAffector : public SkParticleAffector {
50public:
51 SkPointForceAffector(SkPoint point = { 0.0f, 0.0f }, SkScalar constant = 0.0f,
52 SkScalar invSquare = 0.0f)
53 : fPoint(point), fConstant(constant), fInvSquare(invSquare) {}
54
55 REFLECTED(SkPointForceAffector, SkParticleAffector)
56
Brian Osman125daa42019-02-20 12:25:20 -050057 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
58 SkVector toPoint = fPoint - ps.fPose.fPosition;
Brian Osman7c979f52019-02-12 13:27:51 -050059 SkScalar lenSquare = toPoint.dot(toPoint);
60 toPoint.normalize();
Brian Osman125daa42019-02-20 12:25:20 -050061 ps.fVelocity.fLinear += toPoint * (fConstant + (fInvSquare/lenSquare)) * params.fDeltaTime;
Brian Osman7c979f52019-02-12 13:27:51 -050062 }
63
64 void visitFields(SkFieldVisitor* v) override {
65 v->visit("Point", fPoint);
66 v->visit("Constant", fConstant);
67 v->visit("InvSquare", fInvSquare);
68 }
69
70private:
71 SkPoint fPoint;
72 SkScalar fConstant;
73 SkScalar fInvSquare;
74};
75
76class SkOrientAlongVelocityAffector : public SkParticleAffector {
77public:
78 SkOrientAlongVelocityAffector() {}
79
80 REFLECTED(SkOrientAlongVelocityAffector, SkParticleAffector)
81
Brian Osman125daa42019-02-20 12:25:20 -050082 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
83 SkVector heading = ps.fVelocity.fLinear;
Brian Osman7c979f52019-02-12 13:27:51 -050084 if (!heading.normalize()) {
85 heading.set(0, -1);
86 }
Brian Osman125daa42019-02-20 12:25:20 -050087 ps.fPose.fHeading = heading;
Brian Osman7c979f52019-02-12 13:27:51 -050088 }
89
90 void visitFields(SkFieldVisitor*) override {}
91};
92
Brian Osman8b6283f2019-02-14 16:55:21 -050093class SkSizeAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -050094public:
Brian Osman8b6283f2019-02-14 16:55:21 -050095 SkSizeAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
Brian Osman7c979f52019-02-12 13:27:51 -050096
Brian Osman8b6283f2019-02-14 16:55:21 -050097 REFLECTED(SkSizeAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -050098
Brian Osman125daa42019-02-20 12:25:20 -050099 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
100 ps.fPose.fScale = fCurve.eval(params.fParticleT, ps.fStableRandom);
Brian Osman7c979f52019-02-12 13:27:51 -0500101 }
102
103 void visitFields(SkFieldVisitor* v) override {
Brian Osman8b6283f2019-02-14 16:55:21 -0500104 v->visit("Curve", fCurve);
Brian Osman7c979f52019-02-12 13:27:51 -0500105 }
106
107private:
Brian Osman8b6283f2019-02-14 16:55:21 -0500108 SkCurve fCurve;
Brian Osman7c979f52019-02-12 13:27:51 -0500109};
110
Brian Osman125daa42019-02-20 12:25:20 -0500111class SkFrameAffector : public SkParticleAffector {
112public:
113 SkFrameAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
114
115 REFLECTED(SkFrameAffector, SkParticleAffector)
116
117 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
118 ps.fFrame = fCurve.eval(params.fParticleT, ps.fStableRandom);
119 }
120
121 void visitFields(SkFieldVisitor* v) override {
122 v->visit("Curve", fCurve);
123 }
124
125private:
126 SkCurve fCurve;
127};
128
129class SkColorAffector : public SkParticleAffector {
130public:
131 SkColorAffector(const SkColorCurve& curve = SkColor4f{ 1.0f, 1.0f, 1.0f, 1.0f })
132 : fCurve(curve) {}
133
134 REFLECTED(SkColorAffector, SkParticleAffector)
135
136 void apply(SkParticleUpdateParams& params, SkParticleState& ps) override {
137 ps.fColor = fCurve.eval(params.fParticleT, ps.fStableRandom);
138 }
139
140 void visitFields(SkFieldVisitor* v) override {
141 v->visit("Curve", fCurve);
142 }
143
144private:
145 SkColorCurve fCurve;
146};
147
Brian Osman7c979f52019-02-12 13:27:51 -0500148void SkParticleAffector::RegisterAffectorTypes() {
149 REGISTER_REFLECTED(SkParticleAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500150 REGISTER_REFLECTED(SkLinearVelocityAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500151 REGISTER_REFLECTED(SkPointForceAffector);
152 REGISTER_REFLECTED(SkOrientAlongVelocityAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500153 REGISTER_REFLECTED(SkSizeAffector);
Brian Osman125daa42019-02-20 12:25:20 -0500154 REGISTER_REFLECTED(SkFrameAffector);
155 REGISTER_REFLECTED(SkColorAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500156}
157
Brian Osman8b6283f2019-02-14 16:55:21 -0500158sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,
159 const SkCurve& strength,
160 bool force) {
161 return sk_sp<SkParticleAffector>(new SkLinearVelocityAffector(angle, strength, force));
Brian Osman7c979f52019-02-12 13:27:51 -0500162}
163
Brian Osman8b6283f2019-02-14 16:55:21 -0500164sk_sp<SkParticleAffector> SkParticleAffector::MakePointForce(SkPoint point, SkScalar constant,
165 SkScalar invSquare) {
Brian Osman7c979f52019-02-12 13:27:51 -0500166 return sk_sp<SkParticleAffector>(new SkPointForceAffector(point, constant, invSquare));
167}
168
Brian Osman8b6283f2019-02-14 16:55:21 -0500169sk_sp<SkParticleAffector> SkParticleAffector::MakeOrientAlongVelocity() {
Brian Osman7c979f52019-02-12 13:27:51 -0500170 return sk_sp<SkParticleAffector>(new SkOrientAlongVelocityAffector());
171}
Brian Osman8b6283f2019-02-14 16:55:21 -0500172
Brian Osman125daa42019-02-20 12:25:20 -0500173sk_sp<SkParticleAffector> SkParticleAffector::MakeSize(const SkCurve& curve) {
Brian Osman8b6283f2019-02-14 16:55:21 -0500174 return sk_sp<SkParticleAffector>(new SkSizeAffector(curve));
175}
Brian Osman125daa42019-02-20 12:25:20 -0500176
177sk_sp<SkParticleAffector> SkParticleAffector::MakeFrame(const SkCurve& curve) {
178 return sk_sp<SkParticleAffector>(new SkFrameAffector(curve));
179}
180
181sk_sp<SkParticleAffector> SkParticleAffector::MakeColor(const SkColorCurve& curve) {
182 return sk_sp<SkParticleAffector>(new SkColorAffector(curve));
183}