Particles: Removed emitters, added more full-featured position affectors
Bug: skia: Change-Id: Ie6485a11bb57fecef470d727dcf3b4fe5dff0b90 Reviewed-on: https://skia-review.googlesource.com/c/195582 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
09ff13c42d
commit
3d76d1bf46
@ -21,7 +21,6 @@ class SkCanvas;
|
||||
class SkFieldVisitor;
|
||||
class SkParticleAffector;
|
||||
class SkParticleDrawable;
|
||||
class SkParticleEmitter;
|
||||
|
||||
class SkParticleEffectParams : public SkRefCnt {
|
||||
public:
|
||||
@ -33,9 +32,6 @@ public:
|
||||
// Drawable (image, sprite sheet, etc.)
|
||||
sk_sp<SkParticleDrawable> fDrawable;
|
||||
|
||||
// Emitter shape & parameters
|
||||
sk_sp<SkParticleEmitter> fEmitter;
|
||||
|
||||
// Rules that configure particles at spawn time
|
||||
SkTArray<sk_sp<SkParticleAffector>> fSpawnAffectors;
|
||||
|
||||
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkParticleEmitter_DEFINED
|
||||
#define SkParticleEmitter_DEFINED
|
||||
|
||||
#include "SkReflected.h"
|
||||
|
||||
struct SkParticlePose;
|
||||
struct SkPoint;
|
||||
class SkRandom;
|
||||
|
||||
class SkParticleEmitter : public SkReflected {
|
||||
public:
|
||||
REFLECTED_ABSTRACT(SkParticleEmitter, SkReflected)
|
||||
|
||||
virtual SkParticlePose emit(SkRandom&) const = 0;
|
||||
|
||||
static void RegisterEmitterTypes();
|
||||
|
||||
static sk_sp<SkParticleEmitter> MakeCircle(SkPoint center, SkScalar radius);
|
||||
static sk_sp<SkParticleEmitter> MakeLine(SkPoint p1, SkPoint p2);
|
||||
static sk_sp<SkParticleEmitter> MakeText(const char* text, SkScalar fontSize);
|
||||
};
|
||||
|
||||
#endif // SkParticleEmitter_DEFINED
|
@ -11,6 +11,5 @@ skia_particle_sources = [
|
||||
"$_src/SkParticleAffector.cpp",
|
||||
"$_src/SkParticleDrawable.cpp",
|
||||
"$_src/SkParticleEffect.cpp",
|
||||
"$_src/SkParticleEmitter.cpp",
|
||||
"$_src/SkReflected.cpp",
|
||||
]
|
||||
|
@ -7,9 +7,15 @@
|
||||
|
||||
#include "SkParticleAffector.h"
|
||||
|
||||
#include "SkContourMeasure.h"
|
||||
#include "SkCurve.h"
|
||||
#include "SkParsePath.h"
|
||||
#include "SkParticleData.h"
|
||||
#include "SkPath.h"
|
||||
#include "SkRandom.h"
|
||||
#include "SkTextUtils.h"
|
||||
|
||||
#include "sk_tool_utils.h"
|
||||
|
||||
constexpr SkFieldVisitor::EnumStringMapping gParticleFrameMapping[] = {
|
||||
{ kWorld_ParticleFrame, "World" },
|
||||
@ -180,6 +186,208 @@ private:
|
||||
int fFrame;
|
||||
};
|
||||
|
||||
class SkPositionInCircleAffector : public SkParticleAffector {
|
||||
public:
|
||||
SkPositionInCircleAffector(const SkCurve& x = 0.0f, const SkCurve& y = 0.0f,
|
||||
const SkCurve& radius = 0.0f, bool setHeading = true)
|
||||
: fX(x)
|
||||
, fY(y)
|
||||
, fRadius(radius)
|
||||
, fSetHeading(setHeading) {}
|
||||
|
||||
REFLECTED(SkPositionInCircleAffector, SkParticleAffector)
|
||||
|
||||
void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
SkVector v;
|
||||
do {
|
||||
v.fX = ps[i].fRandom.nextSScalar1();
|
||||
v.fY = ps[i].fRandom.nextSScalar1();
|
||||
} while (v.dot(v) > 1);
|
||||
|
||||
SkPoint center = { fX.eval(ps[i].fAge, ps[i].fRandom),
|
||||
fY.eval(ps[i].fAge, ps[i].fRandom) };
|
||||
SkScalar radius = fRadius.eval(ps[i].fAge, ps[i].fRandom);
|
||||
ps[i].fPose.fPosition = center + (v * radius);
|
||||
if (fSetHeading) {
|
||||
if (!v.normalize()) {
|
||||
v.set(0, -1);
|
||||
}
|
||||
ps[i].fPose.fHeading = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visitFields(SkFieldVisitor* v) override {
|
||||
SkParticleAffector::visitFields(v);
|
||||
v->visit("SetHeading", fSetHeading);
|
||||
v->visit("X", fX);
|
||||
v->visit("Y", fY);
|
||||
v->visit("Radius", fRadius);
|
||||
}
|
||||
|
||||
private:
|
||||
SkCurve fX;
|
||||
SkCurve fY;
|
||||
SkCurve fRadius;
|
||||
bool fSetHeading;
|
||||
};
|
||||
|
||||
class SkPositionOnPathAffector : public SkParticleAffector {
|
||||
public:
|
||||
SkPositionOnPathAffector(const char* path = "", bool setHeading = true, bool random = true)
|
||||
: fPath(path)
|
||||
, fSetHeading(setHeading)
|
||||
, fRandom(random) {
|
||||
this->rebuild();
|
||||
}
|
||||
|
||||
REFLECTED(SkPositionOnPathAffector, SkParticleAffector)
|
||||
|
||||
void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
|
||||
if (fContours.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
float t = fRandom ? ps[i].fRandom.nextF() : ps[i].fAge;
|
||||
SkScalar len = fTotalLength * t;
|
||||
int idx = 0;
|
||||
while (idx < fContours.count() && len > fContours[idx]->length()) {
|
||||
len -= fContours[idx++]->length();
|
||||
}
|
||||
SkVector localXAxis;
|
||||
if (!fContours[idx]->getPosTan(len, &ps[i].fPose.fPosition, &localXAxis)) {
|
||||
ps[i].fPose.fPosition = { 0, 0 };
|
||||
localXAxis = { 1, 0 };
|
||||
}
|
||||
if (fSetHeading) {
|
||||
ps[i].fPose.fHeading.set(localXAxis.fY, -localXAxis.fX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visitFields(SkFieldVisitor* v) override {
|
||||
SkString oldPath = fPath;
|
||||
|
||||
SkParticleAffector::visitFields(v);
|
||||
v->visit("SetHeading", fSetHeading);
|
||||
v->visit("Random", fRandom);
|
||||
v->visit("Path", fPath);
|
||||
|
||||
if (fPath != oldPath) {
|
||||
this->rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SkString fPath;
|
||||
bool fSetHeading;
|
||||
bool fRandom;
|
||||
|
||||
void rebuild() {
|
||||
SkPath path;
|
||||
if (!SkParsePath::FromSVGString(fPath.c_str(), &path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fTotalLength = 0;
|
||||
fContours.reset();
|
||||
|
||||
SkContourMeasureIter iter(path, false);
|
||||
while (auto contour = iter.next()) {
|
||||
fContours.push_back(contour);
|
||||
fTotalLength += contour->length();
|
||||
}
|
||||
}
|
||||
|
||||
// Cached
|
||||
SkScalar fTotalLength;
|
||||
SkTArray<sk_sp<SkContourMeasure>> fContours;
|
||||
};
|
||||
|
||||
class SkPositionOnTextAffector : public SkParticleAffector {
|
||||
public:
|
||||
SkPositionOnTextAffector(const char* text = "", SkScalar fontSize = 96, bool setHeading = true,
|
||||
bool random = true)
|
||||
: fText(text)
|
||||
, fFontSize(fontSize)
|
||||
, fSetHeading(setHeading)
|
||||
, fRandom(random) {
|
||||
this->rebuild();
|
||||
}
|
||||
|
||||
REFLECTED(SkPositionOnTextAffector, SkParticleAffector)
|
||||
|
||||
void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
|
||||
if (fContours.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Refactor to share code with PositionOnPathAffector
|
||||
for (int i = 0; i < count; ++i) {
|
||||
float t = fRandom ? ps[i].fRandom.nextF() : ps[i].fAge;
|
||||
SkScalar len = fTotalLength * t;
|
||||
int idx = 0;
|
||||
while (idx < fContours.count() && len > fContours[idx]->length()) {
|
||||
len -= fContours[idx++]->length();
|
||||
}
|
||||
SkVector localXAxis;
|
||||
if (!fContours[idx]->getPosTan(len, &ps[i].fPose.fPosition, &localXAxis)) {
|
||||
ps[i].fPose.fPosition = { 0, 0 };
|
||||
localXAxis = { 1, 0 };
|
||||
}
|
||||
if (fSetHeading) {
|
||||
ps[i].fPose.fHeading.set(localXAxis.fY, -localXAxis.fX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visitFields(SkFieldVisitor* v) override {
|
||||
SkString oldText = fText;
|
||||
SkScalar oldSize = fFontSize;
|
||||
|
||||
SkParticleAffector::visitFields(v);
|
||||
v->visit("SetHeading", fSetHeading);
|
||||
v->visit("Random", fRandom);
|
||||
v->visit("Text", fText);
|
||||
v->visit("FontSize", fFontSize);
|
||||
|
||||
if (fText != oldText || fFontSize != oldSize) {
|
||||
this->rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SkString fText;
|
||||
SkScalar fFontSize;
|
||||
bool fSetHeading;
|
||||
bool fRandom;
|
||||
|
||||
void rebuild() {
|
||||
fTotalLength = 0;
|
||||
fContours.reset();
|
||||
|
||||
if (fText.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkFont font(sk_tool_utils::create_portable_typeface());
|
||||
font.setSize(fFontSize);
|
||||
SkPath path;
|
||||
SkTextUtils::GetPath(fText.c_str(), fText.size(), kUTF8_SkTextEncoding, 0, 0, font, &path);
|
||||
SkContourMeasureIter iter(path, false);
|
||||
while (auto contour = iter.next()) {
|
||||
fContours.push_back(contour);
|
||||
fTotalLength += contour->length();
|
||||
}
|
||||
}
|
||||
|
||||
// Cached
|
||||
SkScalar fTotalLength;
|
||||
SkTArray<sk_sp<SkContourMeasure>> fContours;
|
||||
};
|
||||
|
||||
class SkSizeAffector : public SkParticleAffector {
|
||||
public:
|
||||
SkSizeAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
|
||||
@ -250,6 +458,9 @@ void SkParticleAffector::RegisterAffectorTypes() {
|
||||
REGISTER_REFLECTED(SkAngularVelocityAffector);
|
||||
REGISTER_REFLECTED(SkPointForceAffector);
|
||||
REGISTER_REFLECTED(SkOrientationAffector);
|
||||
REGISTER_REFLECTED(SkPositionInCircleAffector);
|
||||
REGISTER_REFLECTED(SkPositionOnPathAffector);
|
||||
REGISTER_REFLECTED(SkPositionOnTextAffector);
|
||||
REGISTER_REFLECTED(SkSizeAffector);
|
||||
REGISTER_REFLECTED(SkFrameAffector);
|
||||
REGISTER_REFLECTED(SkColorAffector);
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "SkPaint.h"
|
||||
#include "SkParticleAffector.h"
|
||||
#include "SkParticleDrawable.h"
|
||||
#include "SkParticleEmitter.h"
|
||||
#include "SkReflected.h"
|
||||
#include "SkRSXform.h"
|
||||
|
||||
@ -25,7 +24,6 @@ void SkParticleEffectParams::visitFields(SkFieldVisitor* v) {
|
||||
v->visit("Life", fLifetime);
|
||||
|
||||
v->visit("Drawable", fDrawable);
|
||||
v->visit("Emitter", fEmitter);
|
||||
|
||||
v->visit("Spawn", fSpawnAffectors);
|
||||
v->visit("Update", fUpdateAffectors);
|
||||
@ -86,7 +84,7 @@ void SkParticleEffect::update(const SkAnimTimer& timer) {
|
||||
int numToSpawn = sk_float_round2int(desired);
|
||||
fSpawnRemainder = desired - numToSpawn;
|
||||
numToSpawn = SkTPin(numToSpawn, 0, fParams->fMaxCount - fCount);
|
||||
if (fParams->fEmitter) {
|
||||
if (numToSpawn) {
|
||||
// This isn't "particle" t, it's effect t.
|
||||
float t = static_cast<float>((now - fSpawnTime) / fParams->fEffectDuration);
|
||||
t = fLooping ? fmodf(t, 1.0f) : SkTPin(t, 0.0f, 1.0f);
|
||||
@ -99,7 +97,9 @@ void SkParticleEffect::update(const SkAnimTimer& timer) {
|
||||
fParticles[fCount].fAge = t;
|
||||
fParticles[fCount].fInvLifetime =
|
||||
sk_ieee_float_divide(1.0f, fParams->fLifetime.eval(t, fRandom));
|
||||
fParticles[fCount].fPose = fParams->fEmitter->emit(fRandom);
|
||||
fParticles[fCount].fPose.fPosition = { 0.0f, 0.0f };
|
||||
fParticles[fCount].fPose.fHeading = { 0.0f, -1.0f };
|
||||
fParticles[fCount].fPose.fScale = 1.0f;
|
||||
fParticles[fCount].fVelocity.fLinear = { 0.0f, 0.0f };
|
||||
fParticles[fCount].fVelocity.fAngular = 0.0f;
|
||||
fParticles[fCount].fColor = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkParticleEmitter.h"
|
||||
|
||||
#include "SkContourMeasure.h"
|
||||
#include "SkParticleData.h"
|
||||
#include "SkRandom.h"
|
||||
#include "SkTextUtils.h"
|
||||
|
||||
#include "sk_tool_utils.h"
|
||||
|
||||
class SkCircleEmitter : public SkParticleEmitter {
|
||||
public:
|
||||
SkCircleEmitter(SkPoint center = { 0.0f, 0.0f }, SkScalar radius = 0.0f)
|
||||
: fCenter(center), fRadius(radius) {}
|
||||
|
||||
REFLECTED(SkCircleEmitter, SkParticleEmitter)
|
||||
|
||||
SkParticlePose emit(SkRandom& random) const override {
|
||||
SkVector v;
|
||||
do {
|
||||
v.fX = random.nextSScalar1();
|
||||
v.fY = random.nextSScalar1();
|
||||
} while (v.distanceToOrigin() > 1);
|
||||
SkParticlePose pose = { fCenter + (v * fRadius), v, 1.0f };
|
||||
if (!pose.fHeading.normalize()) {
|
||||
pose.fHeading.set(0, -1);
|
||||
}
|
||||
return pose;
|
||||
}
|
||||
|
||||
void visitFields(SkFieldVisitor* v) override {
|
||||
v->visit("Center", fCenter);
|
||||
v->visit("Radius", fRadius);
|
||||
}
|
||||
|
||||
private:
|
||||
SkPoint fCenter;
|
||||
SkScalar fRadius;
|
||||
};
|
||||
|
||||
class SkLineEmitter : public SkParticleEmitter {
|
||||
public:
|
||||
SkLineEmitter(SkPoint p1 = { 0.0f, 0.0f }, SkPoint p2 = { 0.0f, 0.0f }) : fP1(p1), fP2(p2) {}
|
||||
|
||||
REFLECTED(SkLineEmitter, SkParticleEmitter)
|
||||
|
||||
SkParticlePose emit(SkRandom& random) const override {
|
||||
SkVector localXAxis = (fP2 - fP1);
|
||||
SkParticlePose pose = { fP1 + (fP2 - fP1) * random.nextUScalar1(),
|
||||
{ localXAxis.fY, -localXAxis.fX },
|
||||
1.0f };
|
||||
if (!pose.fHeading.normalize()) {
|
||||
pose.fHeading.set(0, -1);
|
||||
}
|
||||
return pose;
|
||||
}
|
||||
|
||||
void visitFields(SkFieldVisitor* v) override {
|
||||
v->visit("P1", fP1);
|
||||
v->visit("P2", fP2);
|
||||
}
|
||||
|
||||
private:
|
||||
SkPoint fP1;
|
||||
SkPoint fP2;
|
||||
};
|
||||
|
||||
class SkTextEmitter : public SkParticleEmitter {
|
||||
public:
|
||||
SkTextEmitter(const char* text = "", SkScalar fontSize = 96)
|
||||
: fText(text), fFontSize(fontSize) {
|
||||
this->rebuild();
|
||||
}
|
||||
|
||||
REFLECTED(SkTextEmitter, SkParticleEmitter)
|
||||
|
||||
SkParticlePose emit(SkRandom& random) const override {
|
||||
if (fContours.count() == 0) {
|
||||
return SkParticlePose{ { 0, 0 }, { 0, -1 }, 0.0f };
|
||||
}
|
||||
|
||||
SkScalar len = random.nextRangeScalar(0, fTotalLength);
|
||||
int idx = 0;
|
||||
while (idx < fContours.count() && len > fContours[idx]->length()) {
|
||||
len -= fContours[idx++]->length();
|
||||
}
|
||||
SkParticlePose pose;
|
||||
SkVector localXAxis;
|
||||
if (!fContours[idx]->getPosTan(len, &pose.fPosition, &localXAxis)) {
|
||||
pose.fPosition = { 0, 0 };
|
||||
localXAxis = { 1, 0 };
|
||||
}
|
||||
pose.fHeading = { localXAxis.fY, -localXAxis.fX };
|
||||
pose.fScale = 1.0f;
|
||||
return pose;
|
||||
}
|
||||
|
||||
void visitFields(SkFieldVisitor* v) override {
|
||||
SkString oldText = fText;
|
||||
SkScalar oldSize = fFontSize;
|
||||
|
||||
v->visit("Text", fText);
|
||||
v->visit("FontSize", fFontSize);
|
||||
|
||||
if (fText != oldText || fFontSize != oldSize) {
|
||||
this->rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SkString fText;
|
||||
SkScalar fFontSize;
|
||||
|
||||
void rebuild() {
|
||||
fTotalLength = 0;
|
||||
fContours.reset();
|
||||
|
||||
if (fText.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkFont font(sk_tool_utils::create_portable_typeface());
|
||||
font.setSize(fFontSize);
|
||||
SkPath path;
|
||||
SkTextUtils::GetPath(fText.c_str(), fText.size(), kUTF8_SkTextEncoding, 0, 0, font, &path);
|
||||
fIter.reset(path, false);
|
||||
while (auto contour = fIter.next()) {
|
||||
fContours.push_back(contour);
|
||||
fTotalLength += contour->length();
|
||||
}
|
||||
}
|
||||
|
||||
// Cached
|
||||
SkScalar fTotalLength;
|
||||
SkContourMeasureIter fIter;
|
||||
SkTArray<sk_sp<SkContourMeasure>> fContours;
|
||||
};
|
||||
|
||||
void SkParticleEmitter::RegisterEmitterTypes() {
|
||||
// Register types for serialization
|
||||
REGISTER_REFLECTED(SkParticleEmitter);
|
||||
REGISTER_REFLECTED(SkCircleEmitter);
|
||||
REGISTER_REFLECTED(SkLineEmitter);
|
||||
REGISTER_REFLECTED(SkTextEmitter);
|
||||
}
|
||||
|
||||
sk_sp<SkParticleEmitter> SkParticleEmitter::MakeCircle(SkPoint center, SkScalar radius) {
|
||||
return sk_sp<SkParticleEmitter>(new SkCircleEmitter(center, radius));
|
||||
}
|
||||
|
||||
sk_sp<SkParticleEmitter> SkParticleEmitter::MakeLine(SkPoint p1, SkPoint p2) {
|
||||
return sk_sp<SkParticleEmitter>(new SkLineEmitter(p1, p2));
|
||||
}
|
||||
|
||||
sk_sp<SkParticleEmitter> SkParticleEmitter::MakeText(const char* text, SkScalar fontSize) {
|
||||
return sk_sp<SkParticleEmitter>(new SkTextEmitter(text, fontSize));
|
||||
}
|
@ -18,11 +18,6 @@
|
||||
"Type": "SkCircleDrawable",
|
||||
"Radius": 1
|
||||
},
|
||||
"Emitter": {
|
||||
"Type": "SkTextEmitter",
|
||||
"Text": "SKIA",
|
||||
"FontSize": 96
|
||||
},
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
@ -53,6 +48,13 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type": "SkPositionOnTextAffector",
|
||||
"Enabled": true,
|
||||
"SetHeading": true,
|
||||
"Text": "SKIA",
|
||||
"FontSize": 96
|
||||
}
|
||||
],
|
||||
"Update": [
|
||||
|
@ -20,12 +20,46 @@
|
||||
"Columns": 4,
|
||||
"Rows": 4
|
||||
},
|
||||
"Emitter": {
|
||||
"Type": "SkCircleEmitter",
|
||||
"Center": { "x": 200, "y": 200 },
|
||||
"Radius": 60
|
||||
},
|
||||
"Spawn": [],
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkPositionInCircleAffector",
|
||||
"Enabled": true,
|
||||
"SetHeading": true,
|
||||
"X": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Constant",
|
||||
"Ranged": false,
|
||||
"Bidirectional": false,
|
||||
"A0": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"Y": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Constant",
|
||||
"Ranged": false,
|
||||
"Bidirectional": false,
|
||||
"A0": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"Radius": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Constant",
|
||||
"Ranged": false,
|
||||
"Bidirectional": false,
|
||||
"A0": 60
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"Update": [
|
||||
{
|
||||
"Type": "SkPointForceAffector",
|
||||
|
@ -19,11 +19,6 @@
|
||||
"Columns": 1,
|
||||
"Rows": 1
|
||||
},
|
||||
"Emitter": {
|
||||
"Type": "SkLineEmitter",
|
||||
"P1": { "x": 237, "y": 396 },
|
||||
"P2": { "x": 214, "y": 398 }
|
||||
},
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
|
@ -17,11 +17,6 @@
|
||||
"Type": "SkCircleDrawable",
|
||||
"Radius": 1
|
||||
},
|
||||
"Emitter": {
|
||||
"Type": "SkLineEmitter",
|
||||
"P1": { "x": 61, "y": 34 },
|
||||
"P2": { "x": 606, "y": 32 }
|
||||
},
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
@ -52,6 +47,12 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type": "SkPositionOnPathAffector",
|
||||
"Enabled": true,
|
||||
"SetHeading": false,
|
||||
"Path": "h500"
|
||||
}
|
||||
],
|
||||
"Update": [
|
||||
|
@ -18,11 +18,6 @@
|
||||
"Type": "SkCircleDrawable",
|
||||
"Radius": 2
|
||||
},
|
||||
"Emitter": {
|
||||
"Type": "SkCircleEmitter",
|
||||
"Center": { "x": 0, "y": 0 },
|
||||
"Radius": 0
|
||||
},
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
|
@ -18,12 +18,13 @@
|
||||
"Type": "SkCircleDrawable",
|
||||
"Radius": 2
|
||||
},
|
||||
"Emitter": {
|
||||
"Type": "SkLineEmitter",
|
||||
"P1": { "x": 200, "y": 200 },
|
||||
"P2": { "x": 250, "y": 200 }
|
||||
},
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkPositionOnPathAffector",
|
||||
"Enabled": true,
|
||||
"SetHeading": true,
|
||||
"Path": "h50"
|
||||
},
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
"Enabled": true,
|
||||
|
@ -17,17 +17,51 @@
|
||||
"Type": "SkCircleDrawable",
|
||||
"Radius": 2
|
||||
},
|
||||
"Emitter": {
|
||||
"Type": "SkCircleEmitter",
|
||||
"Center": { "x": 380.8, "y": 273.92 },
|
||||
"Radius": 43
|
||||
},
|
||||
"Spawn": [],
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkPositionInCircleAffector",
|
||||
"Enabled": true,
|
||||
"SetHeading": true,
|
||||
"X": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Constant",
|
||||
"Ranged": false,
|
||||
"Bidirectional": false,
|
||||
"A0": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"Y": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Constant",
|
||||
"Ranged": false,
|
||||
"Bidirectional": false,
|
||||
"A0": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"Radius": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Constant",
|
||||
"Ranged": false,
|
||||
"Bidirectional": false,
|
||||
"A0": 40
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"Update": [
|
||||
{
|
||||
"Type": "SkPointForceAffector",
|
||||
"Enabled": true,
|
||||
"Point": { "x": 375, "y": 273 },
|
||||
"Point": { "x": 0, "y": 0 },
|
||||
"Constant": -10,
|
||||
"InvSquare": 0
|
||||
},
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "SkParticleAffector.h"
|
||||
#include "SkParticleDrawable.h"
|
||||
#include "SkParticleEffect.h"
|
||||
#include "SkParticleEmitter.h"
|
||||
#include "SkParticleSerialization.h"
|
||||
#include "SkReflected.h"
|
||||
|
||||
@ -197,7 +196,6 @@ ParticlesSlide::ParticlesSlide() {
|
||||
REGISTER_REFLECTED(SkReflected);
|
||||
SkParticleAffector::RegisterAffectorTypes();
|
||||
SkParticleDrawable::RegisterDrawableTypes();
|
||||
SkParticleEmitter::RegisterEmitterTypes();
|
||||
fName = "Particles";
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user