From 7b28a7eebeb8cbe5d356fc9b24651a36d73ab1ad Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Fri, 10 Jun 2011 16:07:33 +1000 Subject: [PATCH] Add delegate property to ItemParticle Also add burst(n,x,y) to ParticleEmitter, and a demo that uses both. --- .../declarative/particles/custom/blurparticles.qml | 40 ++++++++ .../particles/custom/content/particle.png | Bin 0 -> 861 bytes .../declarative/particles/custom/fireworks.qml | 101 ++++++++++++++++++++ src/declarative/particles/qsgitemparticle.cpp | 78 ++++++++++----- src/declarative/particles/qsgitemparticle_p.h | 23 ++++- src/declarative/particles/qsgmodelparticle.cpp | 2 + src/declarative/particles/qsgparticleemitter.cpp | 7 ++ src/declarative/particles/qsgparticleemitter_p.h | 1 + 8 files changed, 224 insertions(+), 28 deletions(-) create mode 100644 examples/declarative/particles/custom/content/particle.png create mode 100644 examples/declarative/particles/custom/fireworks.qml diff --git a/examples/declarative/particles/custom/blurparticles.qml b/examples/declarative/particles/custom/blurparticles.qml index 8a3e9ad..15da9ba 100644 --- a/examples/declarative/particles/custom/blurparticles.qml +++ b/examples/declarative/particles/custom/blurparticles.qml @@ -1,3 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + import QtQuick 2.0 import QtQuick.Particles 2.0 diff --git a/examples/declarative/particles/custom/content/particle.png b/examples/declarative/particles/custom/content/particle.png new file mode 100644 index 0000000000000000000000000000000000000000..5c83896d22cdc3c352ff8db97b0b1f2cd2b27125 GIT binary patch literal 861 zcmV-j1ETziP)+uAJ)4!|9fhtYq5Mes-Q6Cx`#|iAbtLlW1enS0*|y zF-AG6Gn?YQHEL+EwV9p=GaO)E)yZ7P#iXw|#tVf#fLG>e0M8MG5RhWevjLdwSw8|D zuhsAfhEd!df^ArA-nL0W%try}N6#(n2}a&~HjZ3K1|mYlq5;_jfW`*`(KwJuF^0aF zr|o?q9tcN*0bGIM4C4r3BJqHu(7x$~T@X|zFe7+8*#8m!?`2AGwkkTtGl1Oy=)z}^ za?OjA&6)WL6h>fq1P)}{8Ug2Y{)hlFC`Rwu^8|a|n->6P9tZ))^CJcdb95FnFqIco-dA~TBvoZEtK3xiQ00Nnht$!z>dj77iw^4%*jqDp zZD1CAt~vjv$|vGRaP<8{tX^>mj-pqPqBoYlt$tiP2UO4awgu8L>g9a^HftXLG|wl< z_dubRj^6csCNE_t0!@Bc=vDb2Gx}h141K;yv1t6N z@~vY~yv9W(!@+w;iAO4L4;GiR<^30@7ZB=z zn!ZBk!aAnfmthA}fMheB+Tv7T@{3nr@9t&K{~=@$rCk7(@3;zVH! zvloHbj!dUC%TCG`;L#&_FJ$XtpU+m~XD1CuI zc@2l1<)Sa-o^Ue7qb+KR6O3Nz=1lO&iqE=DX=|0Rn@J7;KJ%G;oE1#M-Frdf!wD`X z?0tf5l1|YPARrR`(9I|SiAL&X!V~vHCYyK{k|O{Dgl?cqi8vhSmEQ8??O1QAM}TM# nN5v_UffYd2w;a8m{}o^W-^qmk*A=;y00000NkvXXu0mjf5*>;S literal 0 HcmV?d00001 diff --git a/examples/declarative/particles/custom/fireworks.qml b/examples/declarative/particles/custom/fireworks.qml new file mode 100644 index 0000000..edd4acc --- /dev/null +++ b/examples/declarative/particles/custom/fireworks.qml @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Particles 2.0 + +Rectangle{ + width: 360 + height: 600 + color: "black" + ParticleSystem{ + id: otherSys + anchors.fill: parent + Emitter{ + id: emitter + emitting: false + emitRate: 100 + lifeSpan: 1000 + emitCap: 1000 + speed: AngledDirection{angleVariation:180; magnitudeVariation: 60} + } + + ImageParticle{ + source: "content/particle.png" + } + } + Component{ + id: firework + Item{ + id: container + width: 48 + height: 48 + Image{ + width: 48 + height: 48 + id: img + source: "content/particle.png" + } + Timer{ + interval: 1000 + 4000*Math.random() + running: true + repeat: false + onTriggered: { + img.visible = false; + emitter.burst(100, container.x+24, container.y+24); + } + } + } + } + ParticleSystem{ + anchors.fill: parent + Emitter{ + width: parent.width + y: parent.height + emitRate: 2 + lifeSpan: 6000 + speed: PointDirection{y:-100} + } + ItemParticle{ + delegate: firework + } + } +} + diff --git a/src/declarative/particles/qsgitemparticle.cpp b/src/declarative/particles/qsgitemparticle.cpp index 819c823..498dd90 100644 --- a/src/declarative/particles/qsgitemparticle.cpp +++ b/src/declarative/particles/qsgitemparticle.cpp @@ -42,14 +42,22 @@ #include "qsgitemparticle_p.h" #include #include +#include +#include #include QT_BEGIN_NAMESPACE QSGItemParticle::QSGItemParticle(QSGItem *parent) : - QSGParticlePainter(parent), m_fade(true) + QSGParticlePainter(parent), m_fade(true), m_delegate(0) { setFlag(QSGItem::ItemHasContents); + QTimer* manageDelegates = new QTimer(this);//TODO: don't leak + connect(manageDelegates, SIGNAL(timeout()), + this, SLOT(tick())); + manageDelegates->setInterval(16); + manageDelegates->setSingleShot(false); + manageDelegates->start(); } @@ -79,33 +87,54 @@ void QSGItemParticle::give(QSGItem *item) void QSGItemParticle::load(QSGParticleData* d) { - if(m_pendingItems.isEmpty()) - return; int pos = particleTypeIndex(d); - if(m_items[pos]){ - if(m_stasis.contains(m_items[pos])) - qWarning() << "Current model particles prefers overwrite:false"; - //remove old item from the particle that is dying to make room for this one - m_items[pos]->setOpacity(0.); + m_data[pos] = d; + m_loadables << pos; +} + +void QSGItemParticle::tick() +{ + foreach(QSGItem* item, m_deletables){ + if(m_fade) + item->setOpacity(0.); QSGItemParticleAttached* mpa; - if((mpa = qobject_cast(qmlAttachedPropertiesObject(m_items[pos], false)))) + if((mpa = qobject_cast(qmlAttachedPropertiesObject(item)))) mpa->detach();//reparent as well? - m_items[pos] = 0; - m_data[pos] = 0; + //TODO: Delete iff we created it m_activeCount--; + m_deletables.removeAll(item); } - m_items[pos] = m_pendingItems.front(); - m_pendingItems.pop_front(); - m_items[pos]->setX(d->curX() - m_items[pos]->width()/2); - m_items[pos]->setY(d->curY() - m_items[pos]->height()/2); - QSGItemParticleAttached* mpa = qobject_cast(qmlAttachedPropertiesObject(m_items[pos])); - if(mpa){ - mpa->m_mp = this; - mpa->attach(); + + foreach(int pos, m_loadables){ + if(m_stasis.contains(m_items[pos])) + qWarning() << "Current model particles prefers overwrite:false"; + //remove old item from the particle that is dying to make room for this one + if(m_items[pos]){ + m_deletables << m_items[pos]; + m_activeCount--; + } + m_items[pos] = 0; + if(!m_pendingItems.isEmpty()){ + m_items[pos] = m_pendingItems.front(); + m_pendingItems.pop_front(); + }else if(m_delegate){ + m_items[pos] = qobject_cast(m_delegate->create(qmlContext(this))); + } + if(m_items[pos]){ + m_items[pos]->setX(m_data[pos]->curX() - m_items[pos]->width()/2);//TODO: adjust for system? + m_items[pos]->setY(m_data[pos]->curY() - m_items[pos]->height()/2); + QSGItemParticleAttached* mpa = qobject_cast(qmlAttachedPropertiesObject(m_items[pos])); + if(mpa){ + mpa->m_mp = this; + mpa->attach(); + } + m_items[pos]->setParentItem(this); + if(m_fade) + m_items[pos]->setOpacity(0.); + m_activeCount++; + } + m_loadables.removeAll(pos); } - m_items[pos]->setParentItem(this); - m_data[pos] = d; - m_activeCount++; } void QSGItemParticle::reload(QSGParticleData* d) @@ -173,10 +202,7 @@ void QSGItemParticle::prepareNextFrame() continue; } if(t >= 1.0){//Usually happens from load - item->setOpacity(0.); - QSGItemParticleAttached* mpa; - if((mpa = qobject_cast(qmlAttachedPropertiesObject(m_items[i])))) - mpa->detach();//reparent as well? + m_deletables << item; m_items[i] = 0; m_data[i] = 0; m_activeCount--; diff --git a/src/declarative/particles/qsgitemparticle_p.h b/src/declarative/particles/qsgitemparticle_p.h index fa3516b..3b7db51 100644 --- a/src/declarative/particles/qsgitemparticle_p.h +++ b/src/declarative/particles/qsgitemparticle_p.h @@ -55,8 +55,8 @@ class QSGItemParticleAttached; class QSGItemParticle : public QSGParticlePainter { Q_OBJECT - Q_PROPERTY(bool fade READ fade WRITE setFade NOTIFY fadeChanged) + Q_PROPERTY(QDeclarativeComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) public: explicit QSGItemParticle(QSGItem *parent = 0); @@ -69,9 +69,16 @@ public: virtual int count(); static QSGItemParticleAttached *qmlAttachedProperties(QObject *object); + QDeclarativeComponent* delegate() const + { + return m_delegate; + } + signals: void fadeChanged(); + void delegateChanged(QDeclarativeComponent* arg); + public slots: //TODO: Add a follow mode, where moving the delegate causes the logical particle to go with it? void freeze(QSGItem* item); @@ -80,11 +87,22 @@ public slots: void give(QSGItem* item);//give from modelparticle void setFade(bool arg){if(arg == m_fade) return; m_fade = arg; emit fadeChanged();} + void setDelegate(QDeclarativeComponent* arg) + { + if (m_delegate != arg) { + m_delegate = arg; + emit delegateChanged(arg); + } + } + protected: virtual void reset(); void prepareNextFrame(); +private slots: + void tick(); private: - QList > m_deletables; + QList m_deletables; + QList< int > m_loadables; int m_particleCount; bool m_fade; @@ -96,6 +114,7 @@ private: QSet m_stasis; qreal m_lastT; int m_activeCount; + QDeclarativeComponent* m_delegate; }; class QSGItemParticleAttached : public QObject diff --git a/src/declarative/particles/qsgmodelparticle.cpp b/src/declarative/particles/qsgmodelparticle.cpp index 704b9a2..b0b4fa4 100644 --- a/src/declarative/particles/qsgmodelparticle.cpp +++ b/src/declarative/particles/qsgmodelparticle.cpp @@ -177,6 +177,7 @@ void QSGModelParticle::processPending() foreach(QSGItem* item, m_deletables){ item->setOpacity(0.); m_model->release(item); + m_deletables.removeAll(item); } foreach(int pos, m_requests){ @@ -189,6 +190,7 @@ void QSGModelParticle::processPending() mpa->attach(); } m_items[pos]->setParentItem(this); + m_requests.removeAll(pos); } } diff --git a/src/declarative/particles/qsgparticleemitter.cpp b/src/declarative/particles/qsgparticleemitter.cpp index 20f3c6b..143338f 100644 --- a/src/declarative/particles/qsgparticleemitter.cpp +++ b/src/declarative/particles/qsgparticleemitter.cpp @@ -121,6 +121,13 @@ void QSGParticleEmitter::burst(int num) m_burstQueue << qMakePair(num, QPointF(x(), y())); } +void QSGParticleEmitter::burst(int num, qreal x, qreal y) +{ + if(!particleCount()) + qWarning() << "burst called on an emitter with a particle count of zero"; + m_burstQueue << qMakePair(num, QPointF(x, y)); +} + void QSGParticleEmitter::setMaxParticleCount(int arg) { if (m_maxParticleCount != arg) { diff --git a/src/declarative/particles/qsgparticleemitter_p.h b/src/declarative/particles/qsgparticleemitter_p.h index 9fafd9d..65aca0c 100644 --- a/src/declarative/particles/qsgparticleemitter_p.h +++ b/src/declarative/particles/qsgparticleemitter_p.h @@ -142,6 +142,7 @@ signals: public slots: void pulse(qreal seconds); void burst(int num); + void burst(int num, qreal x, qreal y); void setEmitting(bool arg); -- 1.7.2.5