123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736 |
- #include <QDebug>
- #include <QGLShader>
- #include <QPainter>
- #include <QEvent>
- #include <QTouchEvent>
- #include <QGraphicsSceneMouseEvent>
- #include <QtGui/qdrawutil.h>
- #include <QVarLengthArray>
- #include <QtCore/qmath.h>
- #include <QtCore/qglobal.h>
- #include <QVector2D>
- #include "qparticles.h"
- #include "vertexpositioncolor.h"
- #define KLIMITTOPAGE
- #define KDEFAULTPARTICLES 100
- const QVector2D t1(2.0f, 0.0f);
- const QVector2D t2(0.0f, 2.0f);
- QParticles::QParticles(QDeclarativeItem *parent) :
- QDeclarativeItem(parent), clock(this), m_lastTickTime(0), m_upTime(0), m_particles(0), data(0),
- m_colors(KCOLORS), m_InitShader(false),iColorInit(false), iParticleInit(false), m_particleSize(2.0f),
- m_SquareParticle(true), m_BaseShader(NULL)
- {
- qDebug() << "QParticles::QParticles-> new:" << this;
- setFlag(QGraphicsItem::ItemHasNoContents, false);
- setAcceptedMouseButtons(Qt::LeftButton);
- setAcceptTouchEvents(true);
- setFiltersChildEvents(true);
- generateParticles(KDEFAULTPARTICLES);
- qDebug() << "QParticles::QParticles<-";
- }
- void QParticles::generateColors()
- {
- if(iColorInit)
- {
- return;
- }
- iColorInit = true;
- int cnt = m_colors.count();
- QColor color;
- for(int i=0; i<cnt; ++i)
- {
- color.setHslF((qreal)i / KCOLORS, 1.0, 0.50);
- m_colors[i].setX(color.red()/255.0);
- m_colors[i].setY(color.green()/255.0);
- m_colors[i].setZ(color.blue()/255.0);
- }
- }
- void QParticles::generateParticles( int aNewParticleCount)
- {
- // qDebug() << "->generateParticles";
- m_particles.resize(aNewParticleCount);
- if(m_SquareParticle)
- {
- data.resize(aNewParticleCount*6);
- }
- else
- {
- data.resize(aNewParticleCount*3);
- }
- iParticleInit = false;
- // qDebug() << "<-generateParticles";
- }
- void QParticles::generateParticles(const QRectF & boundingRect)
- {
- // qDebug() << "generateParticles()" << iParticleInit << "particlescount:" << m_particles.count() << "" << &m_particles ;
- if(iParticleInit)
- {
- return;
- }
- iParticleInit = true;
- int cnt = m_particles.count();
- for(int i=0; i<cnt; ++i)
- {
- QVector2D & pos(m_particles[i].Position);
- pos.setX( randInt(0, boundingRect.width()));
- pos.setY( randInt(0, boundingRect.height()));
- }
- }
- //void QParticles::geometryChanged(const QRectF &newGeometry,
- // const QRectF &oldGeometry)
- //{
- // qDebug() << "QParticles::geometryChanged->";
- // qDebug() << "old:" << oldGeometry;
- // qDebug() << "new:" << newGeometry;
- // QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
- // qDebug() << "QParticles::geometryChanged<-";
- //}
- void QParticles::componentComplete()
- {
- qDebug() << "QParticles::componentComplete->";
- QDeclarativeItem::componentComplete();
- qDebug() << boundingRect();
- qDebug("[%f,%f] [%fx%f] opacity:%f Active:%d Visible:%d", x(), y(), width(), height(), opacity(), isActive(), isVisible());
- QBrush m_color(QColor(255, 255, 255, 255), Qt::SolidPattern);
- m_pen = QPen(m_color, 2);
- startRedraw();
- // qDebug() << "QParticles::componentComplete<-";
- }
- bool QParticles::updateParticles(qreal deltaTime, const QRectF & boundingRect, bool dontNull)
- {
- QPointF TL(boundingRect.topLeft());
- QPointF BR(boundingRect.bottomRight());
- int cnt = m_particles.count();
- bool velocity(false);
- QVector2D a;
- for (int i = 0; i < cnt; ++i)
- {
- QParticle & p = m_particles[i];
- a = p.Force * p.InvertMass;
- p.Velocity += a * deltaTime;
- p.Velocity = p.Velocity * (qreal)0.96;
- p.Position += p.Velocity * deltaTime;
- if (p.Position.x() < TL.x())
- {
- p.Velocity.setX(-p.Velocity.x());
- p.Position.setX(TL.x());
- }
- else if ( p.Position.x() > BR.x())
- {
- p.Velocity.setX(-p.Velocity.x());
- p.Position.setX(BR.x());
- }
- if (p.Position.y() < TL.y())
- {
- p.Velocity.setY(-p.Velocity.y());
- p.Position.setY(TL.y());
- }
- else if (p.Position.y() > BR.y())
- {
- p.Velocity.setY(-p.Velocity.y());
- p.Position.setY(BR.y());
- }
- p.Force.setX((qreal)0.0);
- p.Force.setY((qreal)0.0);
- if((m_touchpos.count() == 0) && !p.zeroVelocity(dontNull))
- {
- velocity = true;
- // qDebug() << i << p.Velocity;
- }
- // m_drawParticles[i] = p.Position.toPointF();
- }
- return velocity;
- }
- void QParticles::applyTouchGravity(const QPointF & center)
- {
- int cnt = m_particles.count();
- QVector2D dir;
- QVector2D force;
- float distSq;
- float dist;
- qreal forceSize;
- for (int i = 0; i < cnt; ++i)
- {
- QParticle & p(m_particles[i]);
- dir.setX(center.x() - p.Position.x());
- dir.setY(center.y() - p.Position.y());
- // qreal distSq = (qreal)1.0 / (dir.x() * dir.x() + dir.y() * dir.y());
- // qreal dist = qSqrt(distSq);
- distSq = 1.0f/(dir.x() * dir.x() + dir.y() * dir.y());
- // qreal distSq = (dir.x() * dir.x() + dir.y() * dir.y());
- dist = qSqrt(distSq);
- // qreal dist = Q_rsqrt(distSq);
- dir *= dist;
- // qreal forceSize = (qreal)500.0 * qMin((qreal)1.0, ((qreal)5000.0 * distSq));
- forceSize = 500.0f * qMin(1.0f, (6000.0f * distSq));
- force.setX(dir.x() * forceSize);
- force.setY(dir.y() * forceSize);
- {
- p.Force += force;
- }
- }
- }
- //bool QParticles::sceneEvent(QEvent *event)
- //{
- // bool rv = QDeclarativeItem::sceneEvent(event);
- // if (event->type() == QEvent::UngrabMouse) {
- // setKeepMouseGrab(false);
- // }
- // return rv;
- //}
- //bool QParticles::event(QEvent *event)
- //{
- // if (!isVisible())
- // return QDeclarativeItem::event(event);
- // switch (event->type()) {
- // case QEvent::TouchBegin:
- // case QEvent::TouchUpdate: {
- // QTouchEvent *touch = static_cast<QTouchEvent*>(event);
- // const QList<QTouchEvent::TouchPoint> & touchPoints(touch->touchPoints());
- // {
- // int count = touchPoints.count();
- // qDebug() << count << "----------------------------------";
- // for(int i=0; i<count; ++i)
- // {
- // qDebug("[%d] id[%d][%d,%d] state:%x", i, touchPoints[i].id(), (int)touchPoints[i].pos().x(),
- // (int)touchPoints[i].pos().y(), (int)touchPoints[i].state() );
- // }
- // }
- //// d->touchPoints.clear();
- //// for (int i = 0; i < touch->touchPoints().count(); ++i) {
- //// if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased)) {
- //// d->touchPoints << touch->touchPoints().at(i);
- //// }
- //// }
- //// updatePinch();
- // }
- // return true;
- // case QEvent::TouchEnd:
- // qDebug() << "QEvent::TouchEnd";
- //// d->touchPoints.clear();
- //// updatePinch();
- // break;
- // default:
- // return QDeclarativeItem::event(event);
- // }
- // return QDeclarativeItem::event(event);
- //}
- bool QParticles::sceneEvent(QEvent *event)
- {
- QEvent::Type eventType(event->type());
- switch (eventType)
- {
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
- {
- startRedraw();
- const QList<QTouchEvent::TouchPoint> touchPoints(static_cast<QTouchEvent *>(event)->touchPoints());
- // {
- // int count = touchPoints.count();
- // qDebug() << count << "QEvent::Touch----------------------------------";
- // for(int i=0; i<count; ++i)
- // {
- // qDebug("[%d] id[%d][%d,%d] state:0x%x", i, touchPoints[i].id(), (int)touchPoints[i].pos().x(),
- // (int)touchPoints[i].pos().y(), (int)touchPoints[i].state() );
- // }
- // }
- m_touchpos.clear();
- foreach(const QTouchEvent::TouchPoint touchPoint, touchPoints)
- {
- if( touchPoint.state() != Qt::TouchPointReleased)
- {
- m_touchpos.append(touchPoint.pos());
- }
- }
- if(m_touchpos.count() == 0)
- {
- m_upTime = m_lastTickTime;
- /// qDebug() << "----- empty";
- }
- else
- {
- // qDebug() << "-----" << m_touchpos.count();
- }
- return true;
- }
- #if defined(Q_WS_WIN)
- case QEvent::GraphicsSceneMousePress:
- case QEvent::GraphicsSceneMouseMove:
- {
- startRedraw();
- QGraphicsSceneMouseEvent * MouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
- m_touchpos.clear();
- qDebug() << "QEvent::GraphicsSceneMouseMove";
- // qDebug( "Pos[%f,%f] ScenePos[%f,%f] screenPos[%f,%f]", MouseEvent->pos().x(), MouseEvent->pos().y(),
- // MouseEvent->scenePos().x(), MouseEvent->scenePos().y(), MouseEvent->screenPos().x(), MouseEvent->screenPos().y()
- // );
- m_touchpos.append(MouseEvent->pos());
- // qDebug() << MouseEvent->pos();
- return true;
- }
- case QEvent::GraphicsSceneMouseRelease:
- {
- m_upTime = m_lastTickTime;
- m_touchpos.clear();
- qDebug() << "QEvent::GraphicsSceneMouseRelease ----- empty";
- return true;
- }
- #endif
- default:
- {
- // qDebug() << "eventType:" << eventType;
- }
- }
- return QDeclarativeItem::sceneEvent(event);
- }
- void QParticles::tick(int time)
- {
- if(m_lastTickTime == 0)
- {
- m_lastTickTime = time;
- return;
- }
- int diff = time - m_lastTickTime;
- // qDebug() << "diff:" << diff;
- if(diff < 20)
- {
- return;
- }
- qreal elapsedTimeS = qreal(diff) / qreal(1000.0);
- //qreal elapsedTimeS = 33.0f / 1000.0f;
- // qDebug() << "diff:" << (time - m_lastTickTime);
- //<< "elapsed:" << elapsedTimeMs;
- {
- // touch gravity
- int touchCount = m_touchpos.count();
- for(int i=0; i< touchCount; ++i)
- {
- // qDebug() << "[" << i << "]" << m_touchpos[i];
- applyTouchGravity(m_touchpos[i]);
- }
- // if(touchCount == 0)
- // {
- // qDebug() << "tick touch points empty";
- // }
- }
- int sinceKeyUp = time - m_upTime;
- bool dontnull((sinceKeyUp < 1000) || m_touchpos.count());
- QRectF boundingrect;
- // if(m_DrawOnUI)
- // {
- // boundingrect = topLevelItem()->boundingRect();
- // }
- // else
- {
- boundingrect = boundingRect();
- }
- boundingrect.setHeight(boundingrect.height() - m_particleSize);
- // qDebug() << "OnUi:" << m_DrawOnUI << " boundingrect: " << boundingrect;
- //#ifdef KLIMITTOPAGE
- // boundingrect.translate(scenePos());
- //#endif
- // qDebug() << "boundingrect:" << boundingrect;
- bool velocity = updateParticles(elapsedTimeS, boundingrect, dontnull);
- if(!dontnull && !velocity)
- {
- stopRedraw();
- qDebug() << "stoping";
- }
- update();
- m_lastTickTime = time;
- }
- int QParticles::randInt(int low, int high) const
- {
- // Random number between low and high
- return qrand() % ((high + 1) - low) + low;
- }
- void QParticles::onActivated()
- {
- qDebug() << "QParticles::onActivated->";
- qDebug("[%f,%f] [%fx%f] opacity:%f Active:%d Visible:%d", x(), y(), width(), height(), opacity(), isActive(), isVisible());
- qDebug() << "QParticles::onActivated<-";
- }
- void QParticles::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
- {
- // qDebug() << "paint: opacity:" << painter->opacity() << " active:" << isActive();
- // qDebug() << "m_touchpos" << &m_touchpos << " m_particles:" << &m_particles << "&m_MatrixLoc" << &m_MatrixLoc << "this" << this;
- //<< " matrix:" << painter->matrix();
- qDebug("pos[%f,%f] size[%fx%f] opacity:%f Active:%d Visible:%d scene[%f,%f]", x(), y(),
- width(), height(), opacity(), isActive(), isVisible(), scenePos().x(), scenePos().y());
- //qDebug() << "viewport:" << painter->viewport() << " window:" << painter->window();
- // qDebug() << "wt" << scenePos() << " >> " << painter->worldTransform().map(scenePos());
- // qDebug() << "tr" << scenePos() << " >> " << painter->transform().map(scenePos());
- // qDebug() << "dt" << scenePos() << " >> " << painter->deviceTransform().map(scenePos());
- // qDebug() << "ct" << scenePos() << " >> " << painter->combinedTransform().map(scenePos());
- // return;
- // init
- generateColors();
- if(isActive())
- {
- generateParticles(boundingRect());
- }
- painter->save();
- painter->beginNativePainting();
- InitShaders();
- paintParticles(painter->opacity(), 3.0f);
- painter->endNativePainting();
- painter->restore();
- }
- void QParticles::stopRedraw()
- {
- clock.stop();
- m_lastTickTime = 0;
- m_upTime = 0;
- qDebug() << "stopRedraw";
- }
- void QParticles::startRedraw()
- {
- if(clock.state() == QAbstractAnimation::Running)
- {
- return;
- }
- qDebug() << "startRedraw";
- clock.start();
- m_lastTickTime = 0;
- m_upTime = 0;
- }
- void QParticles::InitShaders()
- {
- if(m_InitShader)
- {
- return;
- }
- qDebug() << "this" << this;
- m_InitShader = true;
- qDebug("currentContext:0x%x", QGLContext::currentContext());
- // m_BaseShader.release();
- // m_BaseShader.bind();
- delete m_BaseShader;
- m_BaseShader = new QGLShaderProgram(QGLContext::currentContext(), this);
- QGLShader* vs = new QGLShader(QGLShader::Vertex, QGLContext::currentContext(), this);
- const char *vssrc =
- "uniform mat4 matrix;\n"
- "attribute vec4 vertex;\n"
- "attribute vec4 color;\n"
- "varying mediump vec4 outColor;\n"
- "void main(void)\n"
- "{\n"
- " outColor = color;\n"
- " gl_Position = matrix * vertex;\n"
- "}\n";
- bool done = vs->compileSourceCode(vssrc);
- Q_ASSERT(done);
- QGLShader *fs = new QGLShader(QGLShader::Fragment, QGLContext::currentContext(), this);
- const char *fssrc =
- "varying mediump vec4 outColor;\n"
- "void main(void)\n"
- "{\n"
- " gl_FragColor = outColor;\n"
- "}\n";
- done = fs->compileSourceCode(fssrc);
- Q_ASSERT(done);
- done = m_BaseShader->addShader(vs);
- if(!done)
- {
- qDebug() << m_BaseShader->log();
- }
- Q_ASSERT(done);
- done = m_BaseShader->addShader(fs);
- if(!done)
- {
- qDebug() << m_BaseShader->log();
- }
- Q_ASSERT(done);
- done = m_BaseShader->link();
- if(!done)
- {
- qDebug() << m_BaseShader->log();
- }
- Q_ASSERT(done);
- m_MatrixLoc = m_BaseShader->uniformLocation("matrix");
- qDebug() << "m_MatrixLoc:" << m_MatrixLoc;
- m_VertexAtribLoc = m_BaseShader->attributeLocation("vertex");
- qDebug() << "m_VertexAtribLoc:" << m_VertexAtribLoc;
- m_ColorAttribLoc = m_BaseShader->attributeLocation("color");
- qDebug() << "m_ColorAttribLoc:" << m_ColorAttribLoc;
- }
- QVector3D QParticles::convertColor(int aColor) const
- {
- return QVector3D(float((aColor & 0xFF0000) >> 16) / 255,
- float((aColor & 0xFF00)>> 8) / 255,
- float(aColor & 0xFF) / 255);
- }
- void QParticles::paintParticles( qreal aOpacity, qreal aParticleSize)
- {
- if(!iParticleInit)
- {
- return;
- }
- // qDebug() << "->paintParticles";
- // return;
- // generate vertices
- // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE );
- // glDisable(GL_CULL_FACE);
- // glEnable(GL_CU);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // alloc buffer
- int count = m_particles.count();
- // generate data
- QVector4D color;
- QVector3D pos0;
- QVector3D pos1;
- QVector3D pos2;
- QVector3D pos3;
- int index;
- for(int i=0; i<count; ++i)
- {
- //qDebug() << m_particles[i].Position;
- //int len = (int(m_particles[i].FastVelocityLength() + 170) % KCOLORS);
- int len = (int)((m_particles[i].Velocity.length() + 170)) % KCOLORS;
- color = m_colors[len];
- color.setW(aOpacity);
- if(m_SquareParticle)
- {
- index = 6*i;
- data[index].Color = color;
- data[index+1].Color = color;
- data[index+2].Color = color;
- data[index+5].Color = color;
- }
- else
- {
- index = 3*i;
- data[index].Color = color;
- data[index+1].Color = color;
- data[index+2].Color = color;
- }
- pos3 = pos2 = pos1 = pos0 = m_particles[i].Position;
- if(m_SquareParticle)
- {
- index = 6*i;
- pos1.setX(pos1.x() + m_particleSize);
- pos2.setX(pos2.x() + m_particleSize);
- pos2.setY(pos2.y() + m_particleSize);
- pos3.setY(pos3.y() + m_particleSize);
- data[index].Position = pos0;
- data[index+1].Position = pos1;
- data[index+2].Position = pos2;
- data[index+3] = data[index];
- data[index+4] = data[index+2];
- data[index+5].Position = pos3;
- }
- else
- {
- index = 3*i;
- data[index].Position = pos0;
- pos0.setX(pos0.x() + m_particleSize);
- data[index+1].Position = pos0;
- pos0.setY(pos0.y() + m_particleSize);
- data[index+2].Position = pos0;
- }
- }
- m_BaseShader->bind();
- QMatrix4x4 modelview;
- {
- QRectF boundingRect = topLevelItem()->boundingRect();
- modelview.ortho( 0.0f,
- boundingRect.width(),
- boundingRect.height(),
- 0.0f,
- -100.0f, 100.0f);
- QMatrix4x4 translate;
- translate.translate(scenePos().x() , scenePos().y(), 0);
- // qDebug() << "boundingRect:" << boundingRect;
- // qDebug() << "scenePos:" << scenePos();
- modelview = modelview * translate ;
- }
- m_BaseShader->setUniformValue(m_MatrixLoc, modelview);
- m_BaseShader->enableAttributeArray(m_VertexAtribLoc);
- m_BaseShader->enableAttributeArray(m_ColorAttribLoc);
- m_BaseShader->setAttributeArray(m_VertexAtribLoc, GL_FLOAT, (void*)&(data[0].Position), 3, sizeof(TVertexPositionColor));
- m_BaseShader->setAttributeArray(m_ColorAttribLoc, GL_FLOAT, (void*)&(data[0].Color), 4, sizeof(TVertexPositionColor));
- if(m_SquareParticle)
- {
- glDrawArrays(GL_TRIANGLES, 0, 2*count);
- }
- else
- {
- glDrawArrays(GL_TRIANGLES, 0, count);
- }
- m_BaseShader->disableAttributeArray(m_VertexAtribLoc);
- m_BaseShader->disableAttributeArray(m_ColorAttribLoc);
- m_BaseShader->release();
- // qDebug() << "<-paintParticles";
- }
- void QParticles::setParticles(int aNewParticlesCount)
- {
- qDebug() << "setParticles:" << aNewParticlesCount;
- qDebug() << "this" << this;
- generateParticles(aNewParticlesCount);
- }
- int QParticles::particles() const
- {
- return m_particles.count();
- }
- void QParticles::setParticleSize(float aParticleSize)
- {
- m_particleSize = aParticleSize;
- }
- float QParticles::particleSize() const
- {
- return m_particleSize;
- }
- void QParticles::appendParticle()
- {
- m_particles.append(QParticle());
- }
- void QParticles::setSquareParticle(bool aSquareParticle)
- {
- m_SquareParticle = aSquareParticle;
- generateParticles(m_particles.count());
- }
- bool QParticles::squareParticle() const
- {
- return m_SquareParticle;
- }
|