blob: b5308f402bbf53bf51738b9e93f5ee61998de8a9 [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 Osman3d76d1b2019-02-28 15:48:05 -050010#include "SkContourMeasure.h"
Brian Osman8b6283f2019-02-14 16:55:21 -050011#include "SkCurve.h"
Brian Osman3d76d1b2019-02-28 15:48:05 -050012#include "SkParsePath.h"
Brian Osman7c979f52019-02-12 13:27:51 -050013#include "SkParticleData.h"
Brian Osman3d76d1b2019-02-28 15:48:05 -050014#include "SkPath.h"
Brian Osman7c979f52019-02-12 13:27:51 -050015#include "SkRandom.h"
Brian Osman3d76d1b2019-02-28 15:48:05 -050016#include "SkTextUtils.h"
17
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 Osman14a67a32019-02-25 14:30:44 -050046 SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050047 SkVector heading = ps[i].getFrameHeading(static_cast<SkParticleFrame>(fFrame));
Brian Osman14a67a32019-02-25 14:30:44 -050048 SkScalar c = heading.fX * c_local - heading.fY * s_local;
49 SkScalar s = heading.fX * s_local + heading.fY * c_local;
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050050 float strength = fStrength.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -050051 SkVector force = { c * strength, s * strength };
52 if (fForce) {
53 ps[i].fVelocity.fLinear += force * params.fDeltaTime;
54 } else {
55 ps[i].fVelocity.fLinear = force;
56 }
Brian Osman8b6283f2019-02-14 16:55:21 -050057 }
Brian Osman7c979f52019-02-12 13:27:51 -050058 }
59
60 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -050061 SkParticleAffector::visitFields(v);
Brian Osman7c979f52019-02-12 13:27:51 -050062 v->visit("Force", fForce);
Brian Osmane5d532e2019-02-26 14:58:40 -050063 v->visit("Frame", fFrame, gParticleFrameMapping, SK_ARRAY_COUNT(gParticleFrameMapping));
Brian Osman7c979f52019-02-12 13:27:51 -050064 v->visit("Angle", fAngle);
65 v->visit("Strength", fStrength);
Brian Osman7c979f52019-02-12 13:27:51 -050066 }
67
68private:
69 SkCurve fAngle;
70 SkCurve fStrength;
Brian Osman8b6283f2019-02-14 16:55:21 -050071 bool fForce;
Brian Osman0c486812019-02-26 10:02:15 -050072 int fFrame;
73};
74
75class SkAngularVelocityAffector : public SkParticleAffector {
76public:
77 SkAngularVelocityAffector(const SkCurve& strength = 0.0f, bool force = true)
78 : fStrength(strength)
79 , fForce(force) {}
80
81 REFLECTED(SkAngularVelocityAffector, SkParticleAffector)
82
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050083 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman0c486812019-02-26 10:02:15 -050084 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050085 float strength = fStrength.eval(params, ps[i]);
Brian Osman0c486812019-02-26 10:02:15 -050086 if (fForce) {
87 ps[i].fVelocity.fAngular += strength * params.fDeltaTime;
88 } else {
89 ps[i].fVelocity.fAngular = strength;
90 }
91 }
92 }
93
94 void visitFields(SkFieldVisitor* v) override {
95 SkParticleAffector::visitFields(v);
96 v->visit("Force", fForce);
97 v->visit("Strength", fStrength);
98 }
99
100private:
101 SkCurve fStrength;
102 bool fForce;
Brian Osman7c979f52019-02-12 13:27:51 -0500103};
104
105class SkPointForceAffector : public SkParticleAffector {
106public:
107 SkPointForceAffector(SkPoint point = { 0.0f, 0.0f }, SkScalar constant = 0.0f,
108 SkScalar invSquare = 0.0f)
109 : fPoint(point), fConstant(constant), fInvSquare(invSquare) {}
110
111 REFLECTED(SkPointForceAffector, SkParticleAffector)
112
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500113 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500114 for (int i = 0; i < count; ++i) {
115 SkVector toPoint = fPoint - ps[i].fPose.fPosition;
116 SkScalar lenSquare = toPoint.dot(toPoint);
117 toPoint.normalize();
118 ps[i].fVelocity.fLinear +=
119 toPoint * (fConstant + (fInvSquare / lenSquare)) * params.fDeltaTime;
120 }
Brian Osman7c979f52019-02-12 13:27:51 -0500121 }
122
123 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500124 SkParticleAffector::visitFields(v);
Brian Osman7c979f52019-02-12 13:27:51 -0500125 v->visit("Point", fPoint);
126 v->visit("Constant", fConstant);
127 v->visit("InvSquare", fInvSquare);
128 }
129
130private:
131 SkPoint fPoint;
132 SkScalar fConstant;
133 SkScalar fInvSquare;
134};
135
Brian Osman0c486812019-02-26 10:02:15 -0500136class SkOrientationAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -0500137public:
Brian Osman0c486812019-02-26 10:02:15 -0500138 SkOrientationAffector(const SkCurve& angle = 0.0f,
139 SkParticleFrame frame = kLocal_ParticleFrame)
140 : fAngle(angle)
141 , fFrame(frame) {}
Brian Osman7c979f52019-02-12 13:27:51 -0500142
Brian Osman0c486812019-02-26 10:02:15 -0500143 REFLECTED(SkOrientationAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -0500144
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500145 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500146 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500147 float angle = fAngle.eval(params, ps[i]);
Brian Osman0c486812019-02-26 10:02:15 -0500148 SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500149 SkVector heading = ps[i].getFrameHeading(static_cast<SkParticleFrame>(fFrame));
Brian Osman0c486812019-02-26 10:02:15 -0500150 ps[i].fPose.fHeading.set(heading.fX * c_local - heading.fY * s_local,
151 heading.fX * s_local + heading.fY * c_local);
Brian Osman7c979f52019-02-12 13:27:51 -0500152 }
Brian Osman7c979f52019-02-12 13:27:51 -0500153 }
154
Brian Osman1b20cd82019-02-25 14:15:02 -0500155 void visitFields(SkFieldVisitor *v) override {
156 SkParticleAffector::visitFields(v);
Brian Osmane5d532e2019-02-26 14:58:40 -0500157 v->visit("Frame", fFrame, gParticleFrameMapping, SK_ARRAY_COUNT(gParticleFrameMapping));
Brian Osman0c486812019-02-26 10:02:15 -0500158 v->visit("Angle", fAngle);
Brian Osman1b20cd82019-02-25 14:15:02 -0500159 }
Brian Osman0c486812019-02-26 10:02:15 -0500160
161private:
162 SkCurve fAngle;
163 int fFrame;
Brian Osman7c979f52019-02-12 13:27:51 -0500164};
165
Brian Osman3d76d1b2019-02-28 15:48:05 -0500166class SkPositionInCircleAffector : public SkParticleAffector {
167public:
168 SkPositionInCircleAffector(const SkCurve& x = 0.0f, const SkCurve& y = 0.0f,
169 const SkCurve& radius = 0.0f, bool setHeading = true)
170 : fX(x)
171 , fY(y)
172 , fRadius(radius)
173 , fSetHeading(setHeading) {}
174
175 REFLECTED(SkPositionInCircleAffector, SkParticleAffector)
176
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500177 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500178 for (int i = 0; i < count; ++i) {
179 SkVector v;
180 do {
181 v.fX = ps[i].fRandom.nextSScalar1();
182 v.fY = ps[i].fRandom.nextSScalar1();
183 } while (v.dot(v) > 1);
184
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500185 SkPoint center = { fX.eval(params, ps[i]), fY.eval(params, ps[i]) };
186 SkScalar radius = fRadius.eval(params, ps[i]);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500187 ps[i].fPose.fPosition = center + (v * radius);
188 if (fSetHeading) {
189 if (!v.normalize()) {
190 v.set(0, -1);
191 }
192 ps[i].fPose.fHeading = v;
193 }
194 }
195 }
196
197 void visitFields(SkFieldVisitor* v) override {
198 SkParticleAffector::visitFields(v);
199 v->visit("SetHeading", fSetHeading);
200 v->visit("X", fX);
201 v->visit("Y", fY);
202 v->visit("Radius", fRadius);
203 }
204
205private:
206 SkCurve fX;
207 SkCurve fY;
208 SkCurve fRadius;
209 bool fSetHeading;
210};
211
212class SkPositionOnPathAffector : public SkParticleAffector {
213public:
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500214 SkPositionOnPathAffector(const char* path = "", bool setHeading = true,
215 SkParticleValue input = SkParticleValue())
Brian Osman3d76d1b2019-02-28 15:48:05 -0500216 : fPath(path)
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500217 , fInput(input)
218 , fSetHeading(setHeading) {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500219 this->rebuild();
220 }
221
222 REFLECTED(SkPositionOnPathAffector, SkParticleAffector)
223
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500224 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500225 if (fContours.empty()) {
226 return;
227 }
228
229 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500230 float t = fInput.eval(params, ps[i]);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500231 SkScalar len = fTotalLength * t;
232 int idx = 0;
233 while (idx < fContours.count() && len > fContours[idx]->length()) {
234 len -= fContours[idx++]->length();
235 }
236 SkVector localXAxis;
237 if (!fContours[idx]->getPosTan(len, &ps[i].fPose.fPosition, &localXAxis)) {
238 ps[i].fPose.fPosition = { 0, 0 };
239 localXAxis = { 1, 0 };
240 }
241 if (fSetHeading) {
242 ps[i].fPose.fHeading.set(localXAxis.fY, -localXAxis.fX);
243 }
244 }
245 }
246
247 void visitFields(SkFieldVisitor* v) override {
248 SkString oldPath = fPath;
249
250 SkParticleAffector::visitFields(v);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500251 v->visit("Input", fInput);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500252 v->visit("SetHeading", fSetHeading);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500253 v->visit("Path", fPath);
254
255 if (fPath != oldPath) {
256 this->rebuild();
257 }
258 }
259
260private:
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500261 SkString fPath;
262 SkParticleValue fInput;
263 bool fSetHeading;
Brian Osman3d76d1b2019-02-28 15:48:05 -0500264
265 void rebuild() {
266 SkPath path;
267 if (!SkParsePath::FromSVGString(fPath.c_str(), &path)) {
268 return;
269 }
270
271 fTotalLength = 0;
272 fContours.reset();
273
274 SkContourMeasureIter iter(path, false);
275 while (auto contour = iter.next()) {
276 fContours.push_back(contour);
277 fTotalLength += contour->length();
278 }
279 }
280
281 // Cached
282 SkScalar fTotalLength;
283 SkTArray<sk_sp<SkContourMeasure>> fContours;
284};
285
286class SkPositionOnTextAffector : public SkParticleAffector {
287public:
288 SkPositionOnTextAffector(const char* text = "", SkScalar fontSize = 96, bool setHeading = true,
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500289 SkParticleValue input = SkParticleValue())
Brian Osman3d76d1b2019-02-28 15:48:05 -0500290 : fText(text)
291 , fFontSize(fontSize)
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500292 , fInput(input)
293 , fSetHeading(setHeading) {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500294 this->rebuild();
295 }
296
297 REFLECTED(SkPositionOnTextAffector, SkParticleAffector)
298
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500299 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500300 if (fContours.empty()) {
301 return;
302 }
303
304 // TODO: Refactor to share code with PositionOnPathAffector
305 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500306 float t = fInput.eval(params, ps[i]);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500307 SkScalar len = fTotalLength * t;
308 int idx = 0;
309 while (idx < fContours.count() && len > fContours[idx]->length()) {
310 len -= fContours[idx++]->length();
311 }
312 SkVector localXAxis;
313 if (!fContours[idx]->getPosTan(len, &ps[i].fPose.fPosition, &localXAxis)) {
314 ps[i].fPose.fPosition = { 0, 0 };
315 localXAxis = { 1, 0 };
316 }
317 if (fSetHeading) {
318 ps[i].fPose.fHeading.set(localXAxis.fY, -localXAxis.fX);
319 }
320 }
321 }
322
323 void visitFields(SkFieldVisitor* v) override {
324 SkString oldText = fText;
325 SkScalar oldSize = fFontSize;
326
327 SkParticleAffector::visitFields(v);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500328 v->visit("Input", fInput);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500329 v->visit("SetHeading", fSetHeading);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500330 v->visit("Text", fText);
331 v->visit("FontSize", fFontSize);
332
333 if (fText != oldText || fFontSize != oldSize) {
334 this->rebuild();
335 }
336 }
337
338private:
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500339 SkString fText;
340 SkScalar fFontSize;
341 SkParticleValue fInput;
342 bool fSetHeading;
Brian Osman3d76d1b2019-02-28 15:48:05 -0500343
344 void rebuild() {
345 fTotalLength = 0;
346 fContours.reset();
347
348 if (fText.isEmpty()) {
349 return;
350 }
351
Kevin Lubick96634842019-03-05 14:09:24 -0500352 // Use the font manager's default font
353 SkFont font(nullptr, fFontSize);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500354 SkPath path;
355 SkTextUtils::GetPath(fText.c_str(), fText.size(), kUTF8_SkTextEncoding, 0, 0, font, &path);
356 SkContourMeasureIter iter(path, false);
357 while (auto contour = iter.next()) {
358 fContours.push_back(contour);
359 fTotalLength += contour->length();
360 }
361 }
362
363 // Cached
364 SkScalar fTotalLength;
365 SkTArray<sk_sp<SkContourMeasure>> fContours;
366};
367
Brian Osman8b6283f2019-02-14 16:55:21 -0500368class SkSizeAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -0500369public:
Brian Osman8b6283f2019-02-14 16:55:21 -0500370 SkSizeAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
Brian Osman7c979f52019-02-12 13:27:51 -0500371
Brian Osman8b6283f2019-02-14 16:55:21 -0500372 REFLECTED(SkSizeAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -0500373
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500374 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500375 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500376 ps[i].fPose.fScale = fCurve.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -0500377 }
Brian Osman7c979f52019-02-12 13:27:51 -0500378 }
379
380 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500381 SkParticleAffector::visitFields(v);
Brian Osman8b6283f2019-02-14 16:55:21 -0500382 v->visit("Curve", fCurve);
Brian Osman7c979f52019-02-12 13:27:51 -0500383 }
384
385private:
Brian Osman8b6283f2019-02-14 16:55:21 -0500386 SkCurve fCurve;
Brian Osman7c979f52019-02-12 13:27:51 -0500387};
388
Brian Osman125daa42019-02-20 12:25:20 -0500389class SkFrameAffector : public SkParticleAffector {
390public:
391 SkFrameAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
392
393 REFLECTED(SkFrameAffector, SkParticleAffector)
394
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500395 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500396 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500397 ps[i].fFrame = fCurve.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -0500398 }
Brian Osman125daa42019-02-20 12:25:20 -0500399 }
400
401 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500402 SkParticleAffector::visitFields(v);
Brian Osman125daa42019-02-20 12:25:20 -0500403 v->visit("Curve", fCurve);
404 }
405
406private:
407 SkCurve fCurve;
408};
409
410class SkColorAffector : public SkParticleAffector {
411public:
412 SkColorAffector(const SkColorCurve& curve = SkColor4f{ 1.0f, 1.0f, 1.0f, 1.0f })
413 : fCurve(curve) {}
414
415 REFLECTED(SkColorAffector, SkParticleAffector)
416
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500417 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500418 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500419 ps[i].fColor = fCurve.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -0500420 }
Brian Osman125daa42019-02-20 12:25:20 -0500421 }
422
423 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500424 SkParticleAffector::visitFields(v);
Brian Osman125daa42019-02-20 12:25:20 -0500425 v->visit("Curve", fCurve);
426 }
427
428private:
429 SkColorCurve fCurve;
430};
431
Brian Osman7c979f52019-02-12 13:27:51 -0500432void SkParticleAffector::RegisterAffectorTypes() {
433 REGISTER_REFLECTED(SkParticleAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500434 REGISTER_REFLECTED(SkLinearVelocityAffector);
Brian Osman0c486812019-02-26 10:02:15 -0500435 REGISTER_REFLECTED(SkAngularVelocityAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500436 REGISTER_REFLECTED(SkPointForceAffector);
Brian Osman0c486812019-02-26 10:02:15 -0500437 REGISTER_REFLECTED(SkOrientationAffector);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500438 REGISTER_REFLECTED(SkPositionInCircleAffector);
439 REGISTER_REFLECTED(SkPositionOnPathAffector);
440 REGISTER_REFLECTED(SkPositionOnTextAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500441 REGISTER_REFLECTED(SkSizeAffector);
Brian Osman125daa42019-02-20 12:25:20 -0500442 REGISTER_REFLECTED(SkFrameAffector);
443 REGISTER_REFLECTED(SkColorAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500444}
445
Brian Osman8b6283f2019-02-14 16:55:21 -0500446sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,
447 const SkCurve& strength,
Brian Osmand5c57fe2019-02-22 11:48:18 -0500448 bool force,
Brian Osman0c486812019-02-26 10:02:15 -0500449 SkParticleFrame frame) {
450 return sk_sp<SkParticleAffector>(new SkLinearVelocityAffector(angle, strength, force, frame));
451}
452
453sk_sp<SkParticleAffector> SkParticleAffector::MakeAngularVelocity(const SkCurve& strength,
454 bool force) {
455 return sk_sp<SkParticleAffector>(new SkAngularVelocityAffector(strength, force));
Brian Osman7c979f52019-02-12 13:27:51 -0500456}
457
Brian Osman8b6283f2019-02-14 16:55:21 -0500458sk_sp<SkParticleAffector> SkParticleAffector::MakePointForce(SkPoint point, SkScalar constant,
459 SkScalar invSquare) {
Brian Osman7c979f52019-02-12 13:27:51 -0500460 return sk_sp<SkParticleAffector>(new SkPointForceAffector(point, constant, invSquare));
461}
462
Brian Osman0c486812019-02-26 10:02:15 -0500463sk_sp<SkParticleAffector> SkParticleAffector::MakeOrientation(const SkCurve& angle,
464 SkParticleFrame frame) {
465 return sk_sp<SkParticleAffector>(new SkOrientationAffector(angle, frame));
Brian Osman7c979f52019-02-12 13:27:51 -0500466}
Brian Osman8b6283f2019-02-14 16:55:21 -0500467
Brian Osman125daa42019-02-20 12:25:20 -0500468sk_sp<SkParticleAffector> SkParticleAffector::MakeSize(const SkCurve& curve) {
Brian Osman8b6283f2019-02-14 16:55:21 -0500469 return sk_sp<SkParticleAffector>(new SkSizeAffector(curve));
470}
Brian Osman125daa42019-02-20 12:25:20 -0500471
472sk_sp<SkParticleAffector> SkParticleAffector::MakeFrame(const SkCurve& curve) {
473 return sk_sp<SkParticleAffector>(new SkFrameAffector(curve));
474}
475
476sk_sp<SkParticleAffector> SkParticleAffector::MakeColor(const SkColorCurve& curve) {
477 return sk_sp<SkParticleAffector>(new SkColorAffector(curve));
478}