Affector Augmentation
authorAlan Alpert <alan.alpert@nokia.com>
Tue, 3 May 2011 00:23:21 +0000 (10:23 +1000)
committerAlan Alpert <alan.alpert@nokia.com>
Tue, 3 May 2011 00:24:30 +0000 (10:24 +1000)
Affectors gained shape and signal properties, and the affected(x,y)
signal (turned on by the signal property, a theorized performance
improvement).

examples/declarative/particles/allsmiles/smilefactory.qml
src/imports/particles/followemitter.cpp
src/imports/particles/maskextruder.cpp
src/imports/particles/maskextruder.h
src/imports/particles/particleaffector.cpp
src/imports/particles/particleaffector.h
src/imports/particles/particlesystem.cpp

index 1b43adb..47becb5 100644 (file)
@@ -51,6 +51,7 @@ Rectangle{
         particles: ["goingLeft", "goingRight"]
         image: "content/singlesmile.png"
         rotation: 90
+        rotationSpeed: 90
         autoRotation: true
     }
     DeformableParticle{
index 825b9ea..9e1ec7b 100644 (file)
@@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE
 
 FollowEmitter::FollowEmitter(QSGItem *parent) :
     ParticleEmitter(parent)
+  , m_particlesPerParticlePerSecond(0)
   , m_lastTimeStamp(0)
   , m_emitterXVariation(0)
   , m_emitterYVariation(0)
@@ -66,7 +67,7 @@ void FollowEmitter::recalcParticlesPerSecond(){
         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);
index 16c64e0..2683010 100644 (file)
@@ -63,7 +63,8 @@ QPointF MaskExtruder::extrude(const QRectF &r)
 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)
@@ -76,14 +77,14 @@ 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);
         }
     }
index ba63db7..6aaa79a 100644 (file)
@@ -43,6 +43,7 @@
 #define MASKEXTRUDER_H
 #include "particleextruder.h"
 #include <QUrl>
+#include <QImage>
 
 QT_BEGIN_HEADER
 
@@ -85,6 +86,7 @@ private:
     void ensureInitialized(const QRectF &r);
     int m_lastWidth;
     int m_lastHeight;
+    QImage m_img;
     QList<QPointF> m_mask;//TODO: More memory efficient datastructures
 };
 
index 0d7bab5..73564a9 100644 (file)
@@ -43,7 +43,8 @@
 #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()));
@@ -82,11 +83,16 @@ void ParticleAffector::affectSystem(qreal dt)
         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());
                 }
             }
         }
index 1acb405..3a92263 100644 (file)
@@ -44,6 +44,7 @@
 
 #include <QObject>
 #include "particlesystem.h"
+#include "particleextruder.h"
 
 QT_BEGIN_HEADER
 
@@ -59,6 +60,8 @@ class ParticleAffector : public QSGItem
     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);
@@ -84,6 +87,16 @@ public:
         return m_onceOff;
     }
 
+    ParticleExtruder* shape() const
+    {
+        return m_shape;
+    }
+
+    bool signal() const
+    {
+        return m_signal;
+    }
+
 signals:
 
     void systemChanged(ParticleSystem* arg);
@@ -94,6 +107,11 @@ signals:
 
     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)
 {
@@ -129,6 +147,22 @@ void setOnceOff(bool 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);
@@ -146,6 +180,10 @@ private:
 
     bool m_onceOff;
 
+    ParticleExtruder* m_shape;
+
+    bool m_signal;
+
 private slots:
     void updateOffsets();
 };
index 571d33c..854d512 100644 (file)
@@ -186,6 +186,7 @@ void ParticleSystem::initializeSystem()
     m_timestamp.start();
     m_initialized = true;
     emit systemInitialized();
+    qDebug() << "System Initialized. Size:" << m_particle_count;
 }
 
 void ParticleSystem::reset()
@@ -210,6 +211,7 @@ 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;