blob: 80094ff2396657d577fdb9a2ee0ef2b4687df6f0 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "modules/particles/include/SkParticleAffector.h"
Brian Osman7c979f52019-02-12 13:27:51 -05009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkContourMeasure.h"
11#include "include/core/SkPath.h"
12#include "include/utils/SkParsePath.h"
13#include "include/utils/SkRandom.h"
14#include "include/utils/SkTextUtils.h"
15#include "modules/particles/include/SkCurve.h"
16#include "modules/particles/include/SkParticleData.h"
Brian Osman3d76d1b2019-02-28 15:48:05 -050017
Brian Osman7c979f52019-02-12 13:27:51 -050018
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050019void SkParticleAffector::apply(const SkParticleUpdateParams& params,
20 SkParticleState ps[], int count) {
Brian Osman1b20cd82019-02-25 14:15:02 -050021 if (fEnabled) {
Brian Osman14a67a32019-02-25 14:30:44 -050022 this->onApply(params, ps, count);
Brian Osman1b20cd82019-02-25 14:15:02 -050023 }
24}
25
26void SkParticleAffector::visitFields(SkFieldVisitor* v) {
27 v->visit("Enabled", fEnabled);
28}
29
Brian Osman8b6283f2019-02-14 16:55:21 -050030class SkLinearVelocityAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -050031public:
Brian Osman8b6283f2019-02-14 16:55:21 -050032 SkLinearVelocityAffector(const SkCurve& angle = 0.0f,
33 const SkCurve& strength = 0.0f,
Brian Osmand5c57fe2019-02-22 11:48:18 -050034 bool force = true,
Brian Osman0c486812019-02-26 10:02:15 -050035 SkParticleFrame frame = kWorld_ParticleFrame)
Brian Osman8b6283f2019-02-14 16:55:21 -050036 : fAngle(angle)
37 , fStrength(strength)
Brian Osmand5c57fe2019-02-22 11:48:18 -050038 , fForce(force)
Brian Osman0c486812019-02-26 10:02:15 -050039 , fFrame(frame) {}
Brian Osman7c979f52019-02-12 13:27:51 -050040
Brian Osman8b6283f2019-02-14 16:55:21 -050041 REFLECTED(SkLinearVelocityAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -050042
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050043 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -050044 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050045 float angle = fAngle.eval(params, ps[i]);
Brian Osman4428f2c2019-04-02 10:59:28 -040046 SkScalar rad = SkDegreesToRadians(angle);
47 SkScalar s_local = SkScalarSin(rad),
48 c_local = SkScalarCos(rad);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050049 SkVector heading = ps[i].getFrameHeading(static_cast<SkParticleFrame>(fFrame));
Brian Osman14a67a32019-02-25 14:30:44 -050050 SkScalar c = heading.fX * c_local - heading.fY * s_local;
51 SkScalar s = heading.fX * s_local + heading.fY * c_local;
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050052 float strength = fStrength.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -050053 SkVector force = { c * strength, s * strength };
54 if (fForce) {
55 ps[i].fVelocity.fLinear += force * params.fDeltaTime;
56 } else {
57 ps[i].fVelocity.fLinear = force;
58 }
Brian Osman8b6283f2019-02-14 16:55:21 -050059 }
Brian Osman7c979f52019-02-12 13:27:51 -050060 }
61
62 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -050063 SkParticleAffector::visitFields(v);
Brian Osman7c979f52019-02-12 13:27:51 -050064 v->visit("Force", fForce);
Brian Osmane5d532e2019-02-26 14:58:40 -050065 v->visit("Frame", fFrame, gParticleFrameMapping, SK_ARRAY_COUNT(gParticleFrameMapping));
Brian Osman7c979f52019-02-12 13:27:51 -050066 v->visit("Angle", fAngle);
67 v->visit("Strength", fStrength);
Brian Osman7c979f52019-02-12 13:27:51 -050068 }
69
70private:
71 SkCurve fAngle;
72 SkCurve fStrength;
Brian Osman8b6283f2019-02-14 16:55:21 -050073 bool fForce;
Brian Osman0c486812019-02-26 10:02:15 -050074 int fFrame;
75};
76
77class SkAngularVelocityAffector : public SkParticleAffector {
78public:
79 SkAngularVelocityAffector(const SkCurve& strength = 0.0f, bool force = true)
80 : fStrength(strength)
81 , fForce(force) {}
82
83 REFLECTED(SkAngularVelocityAffector, SkParticleAffector)
84
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050085 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman0c486812019-02-26 10:02:15 -050086 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050087 float strength = fStrength.eval(params, ps[i]);
Brian Osman0c486812019-02-26 10:02:15 -050088 if (fForce) {
89 ps[i].fVelocity.fAngular += strength * params.fDeltaTime;
90 } else {
91 ps[i].fVelocity.fAngular = strength;
92 }
93 }
94 }
95
96 void visitFields(SkFieldVisitor* v) override {
97 SkParticleAffector::visitFields(v);
98 v->visit("Force", fForce);
99 v->visit("Strength", fStrength);
100 }
101
102private:
103 SkCurve fStrength;
104 bool fForce;
Brian Osman7c979f52019-02-12 13:27:51 -0500105};
106
107class SkPointForceAffector : public SkParticleAffector {
108public:
109 SkPointForceAffector(SkPoint point = { 0.0f, 0.0f }, SkScalar constant = 0.0f,
110 SkScalar invSquare = 0.0f)
111 : fPoint(point), fConstant(constant), fInvSquare(invSquare) {}
112
113 REFLECTED(SkPointForceAffector, SkParticleAffector)
114
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500115 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500116 for (int i = 0; i < count; ++i) {
117 SkVector toPoint = fPoint - ps[i].fPose.fPosition;
118 SkScalar lenSquare = toPoint.dot(toPoint);
119 toPoint.normalize();
120 ps[i].fVelocity.fLinear +=
121 toPoint * (fConstant + (fInvSquare / lenSquare)) * params.fDeltaTime;
122 }
Brian Osman7c979f52019-02-12 13:27:51 -0500123 }
124
125 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500126 SkParticleAffector::visitFields(v);
Brian Osman7c979f52019-02-12 13:27:51 -0500127 v->visit("Point", fPoint);
128 v->visit("Constant", fConstant);
129 v->visit("InvSquare", fInvSquare);
130 }
131
132private:
133 SkPoint fPoint;
134 SkScalar fConstant;
135 SkScalar fInvSquare;
136};
137
Brian Osman0c486812019-02-26 10:02:15 -0500138class SkOrientationAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -0500139public:
Brian Osman0c486812019-02-26 10:02:15 -0500140 SkOrientationAffector(const SkCurve& angle = 0.0f,
141 SkParticleFrame frame = kLocal_ParticleFrame)
142 : fAngle(angle)
143 , fFrame(frame) {}
Brian Osman7c979f52019-02-12 13:27:51 -0500144
Brian Osman0c486812019-02-26 10:02:15 -0500145 REFLECTED(SkOrientationAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -0500146
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500147 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500148 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500149 float angle = fAngle.eval(params, ps[i]);
Brian Osman4428f2c2019-04-02 10:59:28 -0400150 SkScalar rad = SkDegreesToRadians(angle);
151 SkScalar s_local = SkScalarSin(rad),
152 c_local = SkScalarCos(rad);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500153 SkVector heading = ps[i].getFrameHeading(static_cast<SkParticleFrame>(fFrame));
Brian Osman0c486812019-02-26 10:02:15 -0500154 ps[i].fPose.fHeading.set(heading.fX * c_local - heading.fY * s_local,
155 heading.fX * s_local + heading.fY * c_local);
Brian Osman7c979f52019-02-12 13:27:51 -0500156 }
Brian Osman7c979f52019-02-12 13:27:51 -0500157 }
158
Brian Osman1b20cd82019-02-25 14:15:02 -0500159 void visitFields(SkFieldVisitor *v) override {
160 SkParticleAffector::visitFields(v);
Brian Osmane5d532e2019-02-26 14:58:40 -0500161 v->visit("Frame", fFrame, gParticleFrameMapping, SK_ARRAY_COUNT(gParticleFrameMapping));
Brian Osman0c486812019-02-26 10:02:15 -0500162 v->visit("Angle", fAngle);
Brian Osman1b20cd82019-02-25 14:15:02 -0500163 }
Brian Osman0c486812019-02-26 10:02:15 -0500164
165private:
166 SkCurve fAngle;
167 int fFrame;
Brian Osman7c979f52019-02-12 13:27:51 -0500168};
169
Brian Osman3d76d1b2019-02-28 15:48:05 -0500170class SkPositionInCircleAffector : public SkParticleAffector {
171public:
172 SkPositionInCircleAffector(const SkCurve& x = 0.0f, const SkCurve& y = 0.0f,
173 const SkCurve& radius = 0.0f, bool setHeading = true)
174 : fX(x)
175 , fY(y)
176 , fRadius(radius)
177 , fSetHeading(setHeading) {}
178
179 REFLECTED(SkPositionInCircleAffector, SkParticleAffector)
180
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500181 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500182 for (int i = 0; i < count; ++i) {
183 SkVector v;
184 do {
185 v.fX = ps[i].fRandom.nextSScalar1();
186 v.fY = ps[i].fRandom.nextSScalar1();
187 } while (v.dot(v) > 1);
188
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500189 SkPoint center = { fX.eval(params, ps[i]), fY.eval(params, ps[i]) };
190 SkScalar radius = fRadius.eval(params, ps[i]);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500191 ps[i].fPose.fPosition = center + (v * radius);
192 if (fSetHeading) {
193 if (!v.normalize()) {
194 v.set(0, -1);
195 }
196 ps[i].fPose.fHeading = v;
197 }
198 }
199 }
200
201 void visitFields(SkFieldVisitor* v) override {
202 SkParticleAffector::visitFields(v);
203 v->visit("SetHeading", fSetHeading);
204 v->visit("X", fX);
205 v->visit("Y", fY);
206 v->visit("Radius", fRadius);
207 }
208
209private:
210 SkCurve fX;
211 SkCurve fY;
212 SkCurve fRadius;
213 bool fSetHeading;
214};
215
216class SkPositionOnPathAffector : public SkParticleAffector {
217public:
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500218 SkPositionOnPathAffector(const char* path = "", bool setHeading = true,
219 SkParticleValue input = SkParticleValue())
Brian Osman3d76d1b2019-02-28 15:48:05 -0500220 : fPath(path)
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500221 , fInput(input)
222 , fSetHeading(setHeading) {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500223 this->rebuild();
224 }
225
226 REFLECTED(SkPositionOnPathAffector, SkParticleAffector)
227
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500228 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500229 if (fContours.empty()) {
230 return;
231 }
232
233 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500234 float t = fInput.eval(params, ps[i]);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500235 SkScalar len = fTotalLength * t;
236 int idx = 0;
237 while (idx < fContours.count() && len > fContours[idx]->length()) {
238 len -= fContours[idx++]->length();
239 }
240 SkVector localXAxis;
241 if (!fContours[idx]->getPosTan(len, &ps[i].fPose.fPosition, &localXAxis)) {
242 ps[i].fPose.fPosition = { 0, 0 };
243 localXAxis = { 1, 0 };
244 }
245 if (fSetHeading) {
246 ps[i].fPose.fHeading.set(localXAxis.fY, -localXAxis.fX);
247 }
248 }
249 }
250
251 void visitFields(SkFieldVisitor* v) override {
252 SkString oldPath = fPath;
253
254 SkParticleAffector::visitFields(v);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500255 v->visit("Input", fInput);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500256 v->visit("SetHeading", fSetHeading);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500257 v->visit("Path", fPath);
258
259 if (fPath != oldPath) {
260 this->rebuild();
261 }
262 }
263
264private:
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500265 SkString fPath;
266 SkParticleValue fInput;
267 bool fSetHeading;
Brian Osman3d76d1b2019-02-28 15:48:05 -0500268
269 void rebuild() {
270 SkPath path;
271 if (!SkParsePath::FromSVGString(fPath.c_str(), &path)) {
272 return;
273 }
274
275 fTotalLength = 0;
276 fContours.reset();
277
278 SkContourMeasureIter iter(path, false);
279 while (auto contour = iter.next()) {
280 fContours.push_back(contour);
281 fTotalLength += contour->length();
282 }
283 }
284
285 // Cached
286 SkScalar fTotalLength;
287 SkTArray<sk_sp<SkContourMeasure>> fContours;
288};
289
290class SkPositionOnTextAffector : public SkParticleAffector {
291public:
292 SkPositionOnTextAffector(const char* text = "", SkScalar fontSize = 96, bool setHeading = true,
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500293 SkParticleValue input = SkParticleValue())
Brian Osman3d76d1b2019-02-28 15:48:05 -0500294 : fText(text)
295 , fFontSize(fontSize)
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500296 , fInput(input)
297 , fSetHeading(setHeading) {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500298 this->rebuild();
299 }
300
301 REFLECTED(SkPositionOnTextAffector, SkParticleAffector)
302
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500303 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500304 if (fContours.empty()) {
305 return;
306 }
307
308 // TODO: Refactor to share code with PositionOnPathAffector
309 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500310 float t = fInput.eval(params, ps[i]);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500311 SkScalar len = fTotalLength * t;
312 int idx = 0;
313 while (idx < fContours.count() && len > fContours[idx]->length()) {
314 len -= fContours[idx++]->length();
315 }
316 SkVector localXAxis;
317 if (!fContours[idx]->getPosTan(len, &ps[i].fPose.fPosition, &localXAxis)) {
318 ps[i].fPose.fPosition = { 0, 0 };
319 localXAxis = { 1, 0 };
320 }
321 if (fSetHeading) {
322 ps[i].fPose.fHeading.set(localXAxis.fY, -localXAxis.fX);
323 }
324 }
325 }
326
327 void visitFields(SkFieldVisitor* v) override {
328 SkString oldText = fText;
329 SkScalar oldSize = fFontSize;
330
331 SkParticleAffector::visitFields(v);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500332 v->visit("Input", fInput);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500333 v->visit("SetHeading", fSetHeading);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500334 v->visit("Text", fText);
335 v->visit("FontSize", fFontSize);
336
337 if (fText != oldText || fFontSize != oldSize) {
338 this->rebuild();
339 }
340 }
341
342private:
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500343 SkString fText;
344 SkScalar fFontSize;
345 SkParticleValue fInput;
346 bool fSetHeading;
Brian Osman3d76d1b2019-02-28 15:48:05 -0500347
348 void rebuild() {
349 fTotalLength = 0;
350 fContours.reset();
351
352 if (fText.isEmpty()) {
353 return;
354 }
355
Kevin Lubick96634842019-03-05 14:09:24 -0500356 // Use the font manager's default font
357 SkFont font(nullptr, fFontSize);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500358 SkPath path;
359 SkTextUtils::GetPath(fText.c_str(), fText.size(), kUTF8_SkTextEncoding, 0, 0, font, &path);
360 SkContourMeasureIter iter(path, false);
361 while (auto contour = iter.next()) {
362 fContours.push_back(contour);
363 fTotalLength += contour->length();
364 }
365 }
366
367 // Cached
368 SkScalar fTotalLength;
369 SkTArray<sk_sp<SkContourMeasure>> fContours;
370};
371
Brian Osman8b6283f2019-02-14 16:55:21 -0500372class SkSizeAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -0500373public:
Brian Osman8b6283f2019-02-14 16:55:21 -0500374 SkSizeAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
Brian Osman7c979f52019-02-12 13:27:51 -0500375
Brian Osman8b6283f2019-02-14 16:55:21 -0500376 REFLECTED(SkSizeAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -0500377
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500378 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500379 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500380 ps[i].fPose.fScale = fCurve.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -0500381 }
Brian Osman7c979f52019-02-12 13:27:51 -0500382 }
383
384 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500385 SkParticleAffector::visitFields(v);
Brian Osman8b6283f2019-02-14 16:55:21 -0500386 v->visit("Curve", fCurve);
Brian Osman7c979f52019-02-12 13:27:51 -0500387 }
388
389private:
Brian Osman8b6283f2019-02-14 16:55:21 -0500390 SkCurve fCurve;
Brian Osman7c979f52019-02-12 13:27:51 -0500391};
392
Brian Osman125daa42019-02-20 12:25:20 -0500393class SkFrameAffector : public SkParticleAffector {
394public:
395 SkFrameAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
396
397 REFLECTED(SkFrameAffector, SkParticleAffector)
398
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500399 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500400 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500401 ps[i].fFrame = fCurve.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -0500402 }
Brian Osman125daa42019-02-20 12:25:20 -0500403 }
404
405 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500406 SkParticleAffector::visitFields(v);
Brian Osman125daa42019-02-20 12:25:20 -0500407 v->visit("Curve", fCurve);
408 }
409
410private:
411 SkCurve fCurve;
412};
413
414class SkColorAffector : public SkParticleAffector {
415public:
416 SkColorAffector(const SkColorCurve& curve = SkColor4f{ 1.0f, 1.0f, 1.0f, 1.0f })
417 : fCurve(curve) {}
418
419 REFLECTED(SkColorAffector, SkParticleAffector)
420
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500421 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500422 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500423 ps[i].fColor = fCurve.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -0500424 }
Brian Osman125daa42019-02-20 12:25:20 -0500425 }
426
427 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500428 SkParticleAffector::visitFields(v);
Brian Osman125daa42019-02-20 12:25:20 -0500429 v->visit("Curve", fCurve);
430 }
431
432private:
433 SkColorCurve fCurve;
434};
435
Brian Osman7c979f52019-02-12 13:27:51 -0500436void SkParticleAffector::RegisterAffectorTypes() {
437 REGISTER_REFLECTED(SkParticleAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500438 REGISTER_REFLECTED(SkLinearVelocityAffector);
Brian Osman0c486812019-02-26 10:02:15 -0500439 REGISTER_REFLECTED(SkAngularVelocityAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500440 REGISTER_REFLECTED(SkPointForceAffector);
Brian Osman0c486812019-02-26 10:02:15 -0500441 REGISTER_REFLECTED(SkOrientationAffector);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500442 REGISTER_REFLECTED(SkPositionInCircleAffector);
443 REGISTER_REFLECTED(SkPositionOnPathAffector);
444 REGISTER_REFLECTED(SkPositionOnTextAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500445 REGISTER_REFLECTED(SkSizeAffector);
Brian Osman125daa42019-02-20 12:25:20 -0500446 REGISTER_REFLECTED(SkFrameAffector);
447 REGISTER_REFLECTED(SkColorAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500448}
449
Brian Osman8b6283f2019-02-14 16:55:21 -0500450sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,
451 const SkCurve& strength,
Brian Osmand5c57fe2019-02-22 11:48:18 -0500452 bool force,
Brian Osman0c486812019-02-26 10:02:15 -0500453 SkParticleFrame frame) {
454 return sk_sp<SkParticleAffector>(new SkLinearVelocityAffector(angle, strength, force, frame));
455}
456
457sk_sp<SkParticleAffector> SkParticleAffector::MakeAngularVelocity(const SkCurve& strength,
458 bool force) {
459 return sk_sp<SkParticleAffector>(new SkAngularVelocityAffector(strength, force));
Brian Osman7c979f52019-02-12 13:27:51 -0500460}
461
Brian Osman8b6283f2019-02-14 16:55:21 -0500462sk_sp<SkParticleAffector> SkParticleAffector::MakePointForce(SkPoint point, SkScalar constant,
463 SkScalar invSquare) {
Brian Osman7c979f52019-02-12 13:27:51 -0500464 return sk_sp<SkParticleAffector>(new SkPointForceAffector(point, constant, invSquare));
465}
466
Brian Osman0c486812019-02-26 10:02:15 -0500467sk_sp<SkParticleAffector> SkParticleAffector::MakeOrientation(const SkCurve& angle,
468 SkParticleFrame frame) {
469 return sk_sp<SkParticleAffector>(new SkOrientationAffector(angle, frame));
Brian Osman7c979f52019-02-12 13:27:51 -0500470}
Brian Osman8b6283f2019-02-14 16:55:21 -0500471
Brian Osman125daa42019-02-20 12:25:20 -0500472sk_sp<SkParticleAffector> SkParticleAffector::MakeSize(const SkCurve& curve) {
Brian Osman8b6283f2019-02-14 16:55:21 -0500473 return sk_sp<SkParticleAffector>(new SkSizeAffector(curve));
474}
Brian Osman125daa42019-02-20 12:25:20 -0500475
476sk_sp<SkParticleAffector> SkParticleAffector::MakeFrame(const SkCurve& curve) {
477 return sk_sp<SkParticleAffector>(new SkFrameAffector(curve));
478}
479
480sk_sp<SkParticleAffector> SkParticleAffector::MakeColor(const SkColorCurve& curve) {
481 return sk_sp<SkParticleAffector>(new SkColorAffector(curve));
482}