blob: 655fa2989e788e84f8a74ac84ae6e5d348eb9eec [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
18#include "sk_tool_utils.h"
Brian Osman7c979f52019-02-12 13:27:51 -050019
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050020void SkParticleAffector::apply(const SkParticleUpdateParams& params,
21 SkParticleState ps[], int count) {
Brian Osman1b20cd82019-02-25 14:15:02 -050022 if (fEnabled) {
Brian Osman14a67a32019-02-25 14:30:44 -050023 this->onApply(params, ps, count);
Brian Osman1b20cd82019-02-25 14:15:02 -050024 }
25}
26
27void SkParticleAffector::visitFields(SkFieldVisitor* v) {
28 v->visit("Enabled", fEnabled);
29}
30
Brian Osman8b6283f2019-02-14 16:55:21 -050031class SkLinearVelocityAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -050032public:
Brian Osman8b6283f2019-02-14 16:55:21 -050033 SkLinearVelocityAffector(const SkCurve& angle = 0.0f,
34 const SkCurve& strength = 0.0f,
Brian Osmand5c57fe2019-02-22 11:48:18 -050035 bool force = true,
Brian Osman0c486812019-02-26 10:02:15 -050036 SkParticleFrame frame = kWorld_ParticleFrame)
Brian Osman8b6283f2019-02-14 16:55:21 -050037 : fAngle(angle)
38 , fStrength(strength)
Brian Osmand5c57fe2019-02-22 11:48:18 -050039 , fForce(force)
Brian Osman0c486812019-02-26 10:02:15 -050040 , fFrame(frame) {}
Brian Osman7c979f52019-02-12 13:27:51 -050041
Brian Osman8b6283f2019-02-14 16:55:21 -050042 REFLECTED(SkLinearVelocityAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -050043
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050044 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -050045 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050046 float angle = fAngle.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -050047 SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050048 SkVector heading = ps[i].getFrameHeading(static_cast<SkParticleFrame>(fFrame));
Brian Osman14a67a32019-02-25 14:30:44 -050049 SkScalar c = heading.fX * c_local - heading.fY * s_local;
50 SkScalar s = heading.fX * s_local + heading.fY * c_local;
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050051 float strength = fStrength.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -050052 SkVector force = { c * strength, s * strength };
53 if (fForce) {
54 ps[i].fVelocity.fLinear += force * params.fDeltaTime;
55 } else {
56 ps[i].fVelocity.fLinear = force;
57 }
Brian Osman8b6283f2019-02-14 16:55:21 -050058 }
Brian Osman7c979f52019-02-12 13:27:51 -050059 }
60
61 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -050062 SkParticleAffector::visitFields(v);
Brian Osman7c979f52019-02-12 13:27:51 -050063 v->visit("Force", fForce);
Brian Osmane5d532e2019-02-26 14:58:40 -050064 v->visit("Frame", fFrame, gParticleFrameMapping, SK_ARRAY_COUNT(gParticleFrameMapping));
Brian Osman7c979f52019-02-12 13:27:51 -050065 v->visit("Angle", fAngle);
66 v->visit("Strength", fStrength);
Brian Osman7c979f52019-02-12 13:27:51 -050067 }
68
69private:
70 SkCurve fAngle;
71 SkCurve fStrength;
Brian Osman8b6283f2019-02-14 16:55:21 -050072 bool fForce;
Brian Osman0c486812019-02-26 10:02:15 -050073 int fFrame;
74};
75
76class SkAngularVelocityAffector : public SkParticleAffector {
77public:
78 SkAngularVelocityAffector(const SkCurve& strength = 0.0f, bool force = true)
79 : fStrength(strength)
80 , fForce(force) {}
81
82 REFLECTED(SkAngularVelocityAffector, SkParticleAffector)
83
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050084 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman0c486812019-02-26 10:02:15 -050085 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -050086 float strength = fStrength.eval(params, ps[i]);
Brian Osman0c486812019-02-26 10:02:15 -050087 if (fForce) {
88 ps[i].fVelocity.fAngular += strength * params.fDeltaTime;
89 } else {
90 ps[i].fVelocity.fAngular = strength;
91 }
92 }
93 }
94
95 void visitFields(SkFieldVisitor* v) override {
96 SkParticleAffector::visitFields(v);
97 v->visit("Force", fForce);
98 v->visit("Strength", fStrength);
99 }
100
101private:
102 SkCurve fStrength;
103 bool fForce;
Brian Osman7c979f52019-02-12 13:27:51 -0500104};
105
106class SkPointForceAffector : public SkParticleAffector {
107public:
108 SkPointForceAffector(SkPoint point = { 0.0f, 0.0f }, SkScalar constant = 0.0f,
109 SkScalar invSquare = 0.0f)
110 : fPoint(point), fConstant(constant), fInvSquare(invSquare) {}
111
112 REFLECTED(SkPointForceAffector, SkParticleAffector)
113
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500114 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500115 for (int i = 0; i < count; ++i) {
116 SkVector toPoint = fPoint - ps[i].fPose.fPosition;
117 SkScalar lenSquare = toPoint.dot(toPoint);
118 toPoint.normalize();
119 ps[i].fVelocity.fLinear +=
120 toPoint * (fConstant + (fInvSquare / lenSquare)) * params.fDeltaTime;
121 }
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 Osman7c979f52019-02-12 13:27:51 -0500126 v->visit("Point", fPoint);
127 v->visit("Constant", fConstant);
128 v->visit("InvSquare", fInvSquare);
129 }
130
131private:
132 SkPoint fPoint;
133 SkScalar fConstant;
134 SkScalar fInvSquare;
135};
136
Brian Osman0c486812019-02-26 10:02:15 -0500137class SkOrientationAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -0500138public:
Brian Osman0c486812019-02-26 10:02:15 -0500139 SkOrientationAffector(const SkCurve& angle = 0.0f,
140 SkParticleFrame frame = kLocal_ParticleFrame)
141 : fAngle(angle)
142 , fFrame(frame) {}
Brian Osman7c979f52019-02-12 13:27:51 -0500143
Brian Osman0c486812019-02-26 10:02:15 -0500144 REFLECTED(SkOrientationAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -0500145
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500146 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500147 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500148 float angle = fAngle.eval(params, ps[i]);
Brian Osman0c486812019-02-26 10:02:15 -0500149 SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500150 SkVector heading = ps[i].getFrameHeading(static_cast<SkParticleFrame>(fFrame));
Brian Osman0c486812019-02-26 10:02:15 -0500151 ps[i].fPose.fHeading.set(heading.fX * c_local - heading.fY * s_local,
152 heading.fX * s_local + heading.fY * c_local);
Brian Osman7c979f52019-02-12 13:27:51 -0500153 }
Brian Osman7c979f52019-02-12 13:27:51 -0500154 }
155
Brian Osman1b20cd82019-02-25 14:15:02 -0500156 void visitFields(SkFieldVisitor *v) override {
157 SkParticleAffector::visitFields(v);
Brian Osmane5d532e2019-02-26 14:58:40 -0500158 v->visit("Frame", fFrame, gParticleFrameMapping, SK_ARRAY_COUNT(gParticleFrameMapping));
Brian Osman0c486812019-02-26 10:02:15 -0500159 v->visit("Angle", fAngle);
Brian Osman1b20cd82019-02-25 14:15:02 -0500160 }
Brian Osman0c486812019-02-26 10:02:15 -0500161
162private:
163 SkCurve fAngle;
164 int fFrame;
Brian Osman7c979f52019-02-12 13:27:51 -0500165};
166
Brian Osman3d76d1b2019-02-28 15:48:05 -0500167class SkPositionInCircleAffector : public SkParticleAffector {
168public:
169 SkPositionInCircleAffector(const SkCurve& x = 0.0f, const SkCurve& y = 0.0f,
170 const SkCurve& radius = 0.0f, bool setHeading = true)
171 : fX(x)
172 , fY(y)
173 , fRadius(radius)
174 , fSetHeading(setHeading) {}
175
176 REFLECTED(SkPositionInCircleAffector, SkParticleAffector)
177
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500178 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500179 for (int i = 0; i < count; ++i) {
180 SkVector v;
181 do {
182 v.fX = ps[i].fRandom.nextSScalar1();
183 v.fY = ps[i].fRandom.nextSScalar1();
184 } while (v.dot(v) > 1);
185
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500186 SkPoint center = { fX.eval(params, ps[i]), fY.eval(params, ps[i]) };
187 SkScalar radius = fRadius.eval(params, ps[i]);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500188 ps[i].fPose.fPosition = center + (v * radius);
189 if (fSetHeading) {
190 if (!v.normalize()) {
191 v.set(0, -1);
192 }
193 ps[i].fPose.fHeading = v;
194 }
195 }
196 }
197
198 void visitFields(SkFieldVisitor* v) override {
199 SkParticleAffector::visitFields(v);
200 v->visit("SetHeading", fSetHeading);
201 v->visit("X", fX);
202 v->visit("Y", fY);
203 v->visit("Radius", fRadius);
204 }
205
206private:
207 SkCurve fX;
208 SkCurve fY;
209 SkCurve fRadius;
210 bool fSetHeading;
211};
212
213class SkPositionOnPathAffector : public SkParticleAffector {
214public:
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500215 SkPositionOnPathAffector(const char* path = "", bool setHeading = true,
216 SkParticleValue input = SkParticleValue())
Brian Osman3d76d1b2019-02-28 15:48:05 -0500217 : fPath(path)
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500218 , fInput(input)
219 , fSetHeading(setHeading) {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500220 this->rebuild();
221 }
222
223 REFLECTED(SkPositionOnPathAffector, SkParticleAffector)
224
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500225 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500226 if (fContours.empty()) {
227 return;
228 }
229
230 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500231 float t = fInput.eval(params, ps[i]);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500232 SkScalar len = fTotalLength * t;
233 int idx = 0;
234 while (idx < fContours.count() && len > fContours[idx]->length()) {
235 len -= fContours[idx++]->length();
236 }
237 SkVector localXAxis;
238 if (!fContours[idx]->getPosTan(len, &ps[i].fPose.fPosition, &localXAxis)) {
239 ps[i].fPose.fPosition = { 0, 0 };
240 localXAxis = { 1, 0 };
241 }
242 if (fSetHeading) {
243 ps[i].fPose.fHeading.set(localXAxis.fY, -localXAxis.fX);
244 }
245 }
246 }
247
248 void visitFields(SkFieldVisitor* v) override {
249 SkString oldPath = fPath;
250
251 SkParticleAffector::visitFields(v);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500252 v->visit("Input", fInput);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500253 v->visit("SetHeading", fSetHeading);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500254 v->visit("Path", fPath);
255
256 if (fPath != oldPath) {
257 this->rebuild();
258 }
259 }
260
261private:
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500262 SkString fPath;
263 SkParticleValue fInput;
264 bool fSetHeading;
Brian Osman3d76d1b2019-02-28 15:48:05 -0500265
266 void rebuild() {
267 SkPath path;
268 if (!SkParsePath::FromSVGString(fPath.c_str(), &path)) {
269 return;
270 }
271
272 fTotalLength = 0;
273 fContours.reset();
274
275 SkContourMeasureIter iter(path, false);
276 while (auto contour = iter.next()) {
277 fContours.push_back(contour);
278 fTotalLength += contour->length();
279 }
280 }
281
282 // Cached
283 SkScalar fTotalLength;
284 SkTArray<sk_sp<SkContourMeasure>> fContours;
285};
286
287class SkPositionOnTextAffector : public SkParticleAffector {
288public:
289 SkPositionOnTextAffector(const char* text = "", SkScalar fontSize = 96, bool setHeading = true,
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500290 SkParticleValue input = SkParticleValue())
Brian Osman3d76d1b2019-02-28 15:48:05 -0500291 : fText(text)
292 , fFontSize(fontSize)
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500293 , fInput(input)
294 , fSetHeading(setHeading) {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500295 this->rebuild();
296 }
297
298 REFLECTED(SkPositionOnTextAffector, SkParticleAffector)
299
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500300 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman3d76d1b2019-02-28 15:48:05 -0500301 if (fContours.empty()) {
302 return;
303 }
304
305 // TODO: Refactor to share code with PositionOnPathAffector
306 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500307 float t = fInput.eval(params, ps[i]);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500308 SkScalar len = fTotalLength * t;
309 int idx = 0;
310 while (idx < fContours.count() && len > fContours[idx]->length()) {
311 len -= fContours[idx++]->length();
312 }
313 SkVector localXAxis;
314 if (!fContours[idx]->getPosTan(len, &ps[i].fPose.fPosition, &localXAxis)) {
315 ps[i].fPose.fPosition = { 0, 0 };
316 localXAxis = { 1, 0 };
317 }
318 if (fSetHeading) {
319 ps[i].fPose.fHeading.set(localXAxis.fY, -localXAxis.fX);
320 }
321 }
322 }
323
324 void visitFields(SkFieldVisitor* v) override {
325 SkString oldText = fText;
326 SkScalar oldSize = fFontSize;
327
328 SkParticleAffector::visitFields(v);
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500329 v->visit("Input", fInput);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500330 v->visit("SetHeading", fSetHeading);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500331 v->visit("Text", fText);
332 v->visit("FontSize", fFontSize);
333
334 if (fText != oldText || fFontSize != oldSize) {
335 this->rebuild();
336 }
337 }
338
339private:
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500340 SkString fText;
341 SkScalar fFontSize;
342 SkParticleValue fInput;
343 bool fSetHeading;
Brian Osman3d76d1b2019-02-28 15:48:05 -0500344
345 void rebuild() {
346 fTotalLength = 0;
347 fContours.reset();
348
349 if (fText.isEmpty()) {
350 return;
351 }
352
353 SkFont font(sk_tool_utils::create_portable_typeface());
354 font.setSize(fFontSize);
355 SkPath path;
356 SkTextUtils::GetPath(fText.c_str(), fText.size(), kUTF8_SkTextEncoding, 0, 0, font, &path);
357 SkContourMeasureIter iter(path, false);
358 while (auto contour = iter.next()) {
359 fContours.push_back(contour);
360 fTotalLength += contour->length();
361 }
362 }
363
364 // Cached
365 SkScalar fTotalLength;
366 SkTArray<sk_sp<SkContourMeasure>> fContours;
367};
368
Brian Osman8b6283f2019-02-14 16:55:21 -0500369class SkSizeAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -0500370public:
Brian Osman8b6283f2019-02-14 16:55:21 -0500371 SkSizeAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
Brian Osman7c979f52019-02-12 13:27:51 -0500372
Brian Osman8b6283f2019-02-14 16:55:21 -0500373 REFLECTED(SkSizeAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -0500374
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500375 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500376 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500377 ps[i].fPose.fScale = fCurve.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -0500378 }
Brian Osman7c979f52019-02-12 13:27:51 -0500379 }
380
381 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500382 SkParticleAffector::visitFields(v);
Brian Osman8b6283f2019-02-14 16:55:21 -0500383 v->visit("Curve", fCurve);
Brian Osman7c979f52019-02-12 13:27:51 -0500384 }
385
386private:
Brian Osman8b6283f2019-02-14 16:55:21 -0500387 SkCurve fCurve;
Brian Osman7c979f52019-02-12 13:27:51 -0500388};
389
Brian Osman125daa42019-02-20 12:25:20 -0500390class SkFrameAffector : public SkParticleAffector {
391public:
392 SkFrameAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
393
394 REFLECTED(SkFrameAffector, SkParticleAffector)
395
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500396 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500397 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500398 ps[i].fFrame = fCurve.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -0500399 }
Brian Osman125daa42019-02-20 12:25:20 -0500400 }
401
402 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500403 SkParticleAffector::visitFields(v);
Brian Osman125daa42019-02-20 12:25:20 -0500404 v->visit("Curve", fCurve);
405 }
406
407private:
408 SkCurve fCurve;
409};
410
411class SkColorAffector : public SkParticleAffector {
412public:
413 SkColorAffector(const SkColorCurve& curve = SkColor4f{ 1.0f, 1.0f, 1.0f, 1.0f })
414 : fCurve(curve) {}
415
416 REFLECTED(SkColorAffector, SkParticleAffector)
417
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500418 void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
Brian Osman14a67a32019-02-25 14:30:44 -0500419 for (int i = 0; i < count; ++i) {
Brian Osmanbdcdf1a2019-03-04 10:55:22 -0500420 ps[i].fColor = fCurve.eval(params, ps[i]);
Brian Osman14a67a32019-02-25 14:30:44 -0500421 }
Brian Osman125daa42019-02-20 12:25:20 -0500422 }
423
424 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500425 SkParticleAffector::visitFields(v);
Brian Osman125daa42019-02-20 12:25:20 -0500426 v->visit("Curve", fCurve);
427 }
428
429private:
430 SkColorCurve fCurve;
431};
432
Brian Osman7c979f52019-02-12 13:27:51 -0500433void SkParticleAffector::RegisterAffectorTypes() {
434 REGISTER_REFLECTED(SkParticleAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500435 REGISTER_REFLECTED(SkLinearVelocityAffector);
Brian Osman0c486812019-02-26 10:02:15 -0500436 REGISTER_REFLECTED(SkAngularVelocityAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500437 REGISTER_REFLECTED(SkPointForceAffector);
Brian Osman0c486812019-02-26 10:02:15 -0500438 REGISTER_REFLECTED(SkOrientationAffector);
Brian Osman3d76d1b2019-02-28 15:48:05 -0500439 REGISTER_REFLECTED(SkPositionInCircleAffector);
440 REGISTER_REFLECTED(SkPositionOnPathAffector);
441 REGISTER_REFLECTED(SkPositionOnTextAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500442 REGISTER_REFLECTED(SkSizeAffector);
Brian Osman125daa42019-02-20 12:25:20 -0500443 REGISTER_REFLECTED(SkFrameAffector);
444 REGISTER_REFLECTED(SkColorAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500445}
446
Brian Osman8b6283f2019-02-14 16:55:21 -0500447sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,
448 const SkCurve& strength,
Brian Osmand5c57fe2019-02-22 11:48:18 -0500449 bool force,
Brian Osman0c486812019-02-26 10:02:15 -0500450 SkParticleFrame frame) {
451 return sk_sp<SkParticleAffector>(new SkLinearVelocityAffector(angle, strength, force, frame));
452}
453
454sk_sp<SkParticleAffector> SkParticleAffector::MakeAngularVelocity(const SkCurve& strength,
455 bool force) {
456 return sk_sp<SkParticleAffector>(new SkAngularVelocityAffector(strength, force));
Brian Osman7c979f52019-02-12 13:27:51 -0500457}
458
Brian Osman8b6283f2019-02-14 16:55:21 -0500459sk_sp<SkParticleAffector> SkParticleAffector::MakePointForce(SkPoint point, SkScalar constant,
460 SkScalar invSquare) {
Brian Osman7c979f52019-02-12 13:27:51 -0500461 return sk_sp<SkParticleAffector>(new SkPointForceAffector(point, constant, invSquare));
462}
463
Brian Osman0c486812019-02-26 10:02:15 -0500464sk_sp<SkParticleAffector> SkParticleAffector::MakeOrientation(const SkCurve& angle,
465 SkParticleFrame frame) {
466 return sk_sp<SkParticleAffector>(new SkOrientationAffector(angle, frame));
Brian Osman7c979f52019-02-12 13:27:51 -0500467}
Brian Osman8b6283f2019-02-14 16:55:21 -0500468
Brian Osman125daa42019-02-20 12:25:20 -0500469sk_sp<SkParticleAffector> SkParticleAffector::MakeSize(const SkCurve& curve) {
Brian Osman8b6283f2019-02-14 16:55:21 -0500470 return sk_sp<SkParticleAffector>(new SkSizeAffector(curve));
471}
Brian Osman125daa42019-02-20 12:25:20 -0500472
473sk_sp<SkParticleAffector> SkParticleAffector::MakeFrame(const SkCurve& curve) {
474 return sk_sp<SkParticleAffector>(new SkFrameAffector(curve));
475}
476
477sk_sp<SkParticleAffector> SkParticleAffector::MakeColor(const SkColorCurve& curve) {
478 return sk_sp<SkParticleAffector>(new SkColorAffector(curve));
479}