particles: ["goingLeft", "goingRight"]
image: "content/singlesmile.png"
rotation: 90
+ rotationSpeed: 90
autoRotation: true
}
DeformableParticle{
FollowEmitter::FollowEmitter(QSGItem *parent) :
ParticleEmitter(parent)
+ , m_particlesPerParticlePerSecond(0)
, m_lastTimeStamp(0)
, m_emitterXVariation(0)
, m_emitterYVariation(0)
return;
m_followCount = m_system->m_groupData[m_system->m_groupIds[m_follow]]->size;
if(!m_followCount){
- setParticlesPerSecond(1000);//XXX: Fix this horrendous hack, needed so they aren't turned off from start
+ setParticlesPerSecond(1000);//XXX: Fix this horrendous hack, needed so they aren't turned off from start (causes crashes - test that when gone you don't crash with 0 PPPS)
}else{
setParticlesPerSecond(m_particlesPerParticlePerSecond * m_followCount);
m_lastEmission.resize(m_followCount);
bool MaskExtruder::contains(const QRectF &bounds, const QPointF &point)
{
ensureInitialized(bounds);//###Current usage patterns WILL lead to different bounds/r calls. Separate list?
- return m_mask.contains(QPointF(point.toPoint() - bounds.topLeft().toPoint()));
+ QPoint p = point.toPoint() - bounds.topLeft().toPoint();
+ return m_img.rect().contains(p) && (bool)m_img.pixelIndex(p);
}
void MaskExtruder::ensureInitialized(const QRectF &r)
m_mask.clear();
if(m_source.isEmpty())
return;
-
- QImage img(m_source.toLocalFile());
- img = img.createAlphaMask();
- img = img.convertToFormat(QImage::Format_Mono);//Else LSB, but I think that's easier
- img = img.scaled(r.size().toSize());//TODO: Do they need aspect ratio stuff? Or tiling?
+ qDebug() << "Rebuild required";
+ m_img = QImage(m_source.toLocalFile());
+ m_img = m_img.createAlphaMask();
+ m_img = m_img.convertToFormat(QImage::Format_Mono);//Else LSB, but I think that's easier
+ m_img = m_img.scaled(r.size().toSize());//TODO: Do they need aspect ratio stuff? Or tiling?
for(int i=0; i<r.width(); i++){
for(int j=0; j<r.height(); j++){
- if(img.pixelIndex(i,j))//Direct bit manipulation is presumably more efficient
+ if(m_img.pixelIndex(i,j))//Direct bit manipulation is presumably more efficient
m_mask << QPointF(i,j);
}
}
#define MASKEXTRUDER_H
#include "particleextruder.h"
#include <QUrl>
+#include <QImage>
QT_BEGIN_HEADER
void ensureInitialized(const QRectF &r);
int m_lastWidth;
int m_lastHeight;
+ QImage m_img;
QList<QPointF> m_mask;//TODO: More memory efficient datastructures
};
#include <QDebug>
QT_BEGIN_NAMESPACE
ParticleAffector::ParticleAffector(QSGItem *parent) :
- QSGItem(parent), m_needsReset(false), m_system(0), m_active(true), m_updateIntSet(false)
+ QSGItem(parent), m_needsReset(false), m_system(0), m_active(true)
+ , m_updateIntSet(false), m_shape(new ParticleExtruder(this)), m_signal(false)
{
connect(this, SIGNAL(systemChanged(ParticleSystem*)),
this, SLOT(updateOffsets()));
if(!d || (m_onceOff && m_onceOffed.contains(d->systemIndex)))
continue;
if(m_groups.isEmpty() || m_groups.contains(d->group)){
- if(width() == 0 || height() == 0 || QRectF(m_offset.x(), m_offset.y(), width(), height()).contains(d->curX(), d->curY())){
+ //Need to have previous location for affected. if signal || shape might be faster?
+ QPointF curPos = QPointF(d->curX(), d->curY());
+ if(width() == 0 || height() == 0
+ || m_shape->contains(QRectF(m_offset.x(), m_offset.y(), width(), height()),curPos)){
if(affectParticle(d, dt)){
m_system->m_needsReset << d;
if(m_onceOff)
m_onceOffed << d->systemIndex;
+ if(m_signal)
+ emit affected(curPos.x(), curPos.y());
}
}
}
#include <QObject>
#include "particlesystem.h"
+#include "particleextruder.h"
QT_BEGIN_HEADER
Q_PROPERTY(QStringList particles READ particles WRITE setParticles NOTIFY particlesChanged)
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
Q_PROPERTY(bool onceOff READ onceOff WRITE setOnceOff NOTIFY onceOffChanged)
+ Q_PROPERTY(ParticleExtruder* shape READ shape WRITE setShape NOTIFY shapeChanged)
+ Q_PROPERTY(bool signal READ signal WRITE setSignal NOTIFY signalChanged)
public:
explicit ParticleAffector(QSGItem *parent = 0);
return m_onceOff;
}
+ ParticleExtruder* shape() const
+ {
+ return m_shape;
+ }
+
+ bool signal() const
+ {
+ return m_signal;
+ }
+
signals:
void systemChanged(ParticleSystem* arg);
void onceOffChanged(bool arg);
+ void shapeChanged(ParticleExtruder* arg);
+
+ void affected(qreal x, qreal y);//###Idx too?
+ void signalChanged(bool arg);
+
public slots:
void setSystem(ParticleSystem* arg)
{
}
}
+void setShape(ParticleExtruder* arg)
+{
+ if (m_shape != arg) {
+ m_shape = arg;
+ emit shapeChanged(arg);
+ }
+}
+
+void setSignal(bool arg)
+{
+ if (m_signal != arg) {
+ m_signal = arg;
+ emit signalChanged(arg);
+ }
+}
+
protected:
friend class ParticleSystem;
virtual bool affectParticle(ParticleData *d, qreal dt);
bool m_onceOff;
+ ParticleExtruder* m_shape;
+
+ bool m_signal;
+
private slots:
void updateOffsets();
};
m_timestamp.start();
m_initialized = true;
emit systemInitialized();
+ qDebug() << "System Initialized. Size:" << m_particle_count;
}
void ParticleSystem::reset()
ParticleData* ParticleSystem::newDatum(int groupId)
{
Q_ASSERT(groupId < m_groupData.count());//XXX shouldn't really be an assert
+ Q_ASSERT(m_groupData[groupId]->size);
int nextIdx = m_groupData[groupId]->start + m_groupData[groupId]->nextIdx++;
if( m_groupData[groupId]->nextIdx >= m_groupData[groupId]->size)
m_groupData[groupId]->nextIdx = 0;