blob: 83d5fb08963000a167f0d219ebdda425406bd7f8 [file] [log] [blame]
/*
* 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 SkParticleEffect_DEFINED
#define SkParticleEffect_DEFINED
#include "SkAutoMalloc.h"
#include "SkColor.h"
#include "SkCurve.h"
#include "SkParticleData.h"
#include "SkRandom.h"
#include "SkRect.h"
#include "SkRefCnt.h"
#include "SkString.h"
#include "SkTArray.h"
class SkAnimTimer;
class SkCanvas;
class SkFieldVisitor;
class SkImage;
class SkParticleAffector;
class SkParticleEmitter;
struct SkRSXform;
// TODO: Phase this out, once all properties are driven by the two-lists-of-affectors
struct InitialVelocityParams {
float fAngle = 0.0f;
float fAngleSpread = 0.0f;
SkRangedFloat fStrength = { 0.0f, 0.0f };
bool fBidirectional = false;
SkRangedFloat fSpin = { 0.0f, 0.0f };
bool fBidirectionalSpin = false;
SkParticleVelocity eval(SkRandom& random) const;
void visitFields(SkFieldVisitor* v);
};
class SkParticleEffectParams : public SkRefCnt {
public:
int fMaxCount = 128;
float fRate = 8.0f;
SkRangedFloat fLifetime = { 1.0f, 1.0f };
SkColor4f fStartColor = { 1.0f, 1.0f, 1.0f, 1.0f };
SkColor4f fEndColor = { 1.0f, 1.0f, 1.0f, 1.0f };
SkCurve fSize = 1.0f;
// TODO: Add local vs. world copies of these
// Initial velocity controls
InitialVelocityParams fVelocity;
// Sprite image parameters
// TODO: Move sprite stuff in here, out of effect
SkString fImage;
int fImageCols = 1;
int fImageRows = 1;
// Emitter shape & parameters
sk_sp<SkParticleEmitter> fEmitter;
// Update rules
SkTArray<sk_sp<SkParticleAffector>> fAffectors;
void visitFields(SkFieldVisitor* v);
};
class SkParticleEffect : public SkRefCnt {
public:
SkParticleEffect(sk_sp<SkParticleEffectParams> params);
void update(SkRandom& random, const SkAnimTimer& timer);
void draw(SkCanvas* canvas);
SkParticleEffectParams* getParams() { return fParams.get(); }
private:
void setCapacity(int capacity);
int spriteCount() const { return fParams->fImageCols * fParams->fImageRows; }
SkRect spriteRect(int i) const {
SkASSERT(i >= 0 && i < this->spriteCount());
int row = i / fParams->fImageCols;
int col = i % fParams->fImageCols;
return fImageRect.makeOffset(col * fImageRect.width(), row * fImageRect.height());
}
SkPoint spriteCenter() const {
return { fImageRect.width() * 0.5f, fImageRect.height() * 0.5f };
}
struct Particle {
double fTimeOfBirth;
double fTimeOfDeath;
SkRandom fStableRandom;
// Texture coord rects and colors are stored in parallel arrays for drawAtlas.
SkParticlePoseAndVelocity fPV;
};
sk_sp<SkParticleEffectParams> fParams;
sk_sp<SkImage> fImage;
SkRect fImageRect;
int fCount;
double fLastTime;
float fSpawnRemainder;
SkAutoTMalloc<Particle> fParticles;
SkAutoTMalloc<SkRSXform> fXforms;
SkAutoTMalloc<SkRect> fSpriteRects;
SkAutoTMalloc<SkColor> fColors;
// Cached
int fCapacity;
};
#endif // SkParticleEffect_DEFINED