aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2011-06-22 16:10:28 +1000
committerAndrew den Exter <andrew.den-exter@nokia.com>2011-06-22 16:10:28 +1000
commitc06c661ecfb08731729d902a12bcf045c36e5bea (patch)
tree9588e475cafcea9c5c0ddb7dedc1e666a2b31d87
parent6cc53afcd5ae36575e1f59e51640218a0794ac3e (diff)
parent6938289ce3e1e29cc81f0e007390e0b5f6ef1a43 (diff)
Merge branch 'qtquick2' into visuallistmodel
-rw-r--r--examples/declarative/particles/custom/fireworks.qml37
-rw-r--r--examples/declarative/particles/custom/shader.qml84
-rw-r--r--examples/declarative/particles/trails/dynamicemitters.qml8
-rw-r--r--src/declarative/items/qsganchors.cpp1
-rw-r--r--src/declarative/items/qsganimatedimage.cpp1
-rw-r--r--src/declarative/items/qsganimation.cpp1
-rw-r--r--src/declarative/items/qsgborderimage.cpp1
-rw-r--r--src/declarative/items/qsgcanvas.cpp35
-rw-r--r--src/declarative/items/qsgclipnode.cpp1
-rw-r--r--src/declarative/items/qsgcontext2d.cpp15
-rw-r--r--src/declarative/items/qsgevents.cpp1
-rw-r--r--src/declarative/items/qsgflickable.cpp1
-rw-r--r--src/declarative/items/qsgflipable.cpp1
-rw-r--r--src/declarative/items/qsgfocusscope.cpp1
-rw-r--r--src/declarative/items/qsggridview.cpp1
-rw-r--r--src/declarative/items/qsgimage.cpp1
-rw-r--r--src/declarative/items/qsgimagebase.cpp1
-rw-r--r--src/declarative/items/qsgimplicitsizeitem.cpp1
-rw-r--r--src/declarative/items/qsgitem.cpp5
-rw-r--r--src/declarative/items/qsgitem_p.h2
-rw-r--r--src/declarative/items/qsgitemsmodule.cpp1
-rw-r--r--src/declarative/items/qsglistview.cpp1
-rw-r--r--src/declarative/items/qsgloader.cpp1
-rw-r--r--src/declarative/items/qsgmousearea.cpp15
-rw-r--r--src/declarative/items/qsgmousearea_p_p.h3
-rw-r--r--src/declarative/items/qsgpathview.cpp1
-rw-r--r--src/declarative/items/qsgpincharea.cpp1
-rw-r--r--src/declarative/items/qsgpositioners.cpp1
-rw-r--r--src/declarative/items/qsgrectangle.cpp1
-rw-r--r--src/declarative/items/qsgrepeater.cpp1
-rw-r--r--src/declarative/items/qsgscalegrid.cpp1
-rw-r--r--src/declarative/items/qsgshadereffectmesh.cpp5
-rw-r--r--src/declarative/items/qsgshadereffectsource.cpp8
-rw-r--r--src/declarative/items/qsgstateoperations.cpp1
-rw-r--r--src/declarative/items/qsgtext.cpp1
-rw-r--r--src/declarative/items/qsgtextedit.cpp1
-rw-r--r--src/declarative/items/qsgtextinput.cpp1
-rw-r--r--src/declarative/items/qsgtextnode.cpp10
-rw-r--r--src/declarative/items/qsgtranslate.cpp1
-rw-r--r--src/declarative/items/qsgview.cpp1
-rw-r--r--src/declarative/items/qsgvisualitemmodel.cpp1
-rw-r--r--src/declarative/particles/qsgcustomparticle.cpp101
-rw-r--r--src/declarative/particles/qsgcustomparticle_p.h12
-rw-r--r--src/declarative/particles/qsgemitter.cpp21
-rw-r--r--src/declarative/particles/qsgfollowemitter.cpp49
-rw-r--r--src/declarative/particles/qsggravity.cpp4
-rw-r--r--src/declarative/particles/qsgimageparticle.cpp295
-rw-r--r--src/declarative/particles/qsgimageparticle_p.h20
-rw-r--r--src/declarative/particles/qsgitemparticle.cpp75
-rw-r--r--src/declarative/particles/qsgitemparticle_p.h10
-rw-r--r--src/declarative/particles/qsgkill.cpp2
-rw-r--r--src/declarative/particles/qsgmodelparticle.cpp84
-rw-r--r--src/declarative/particles/qsgmodelparticle_p.h10
-rw-r--r--src/declarative/particles/qsgparticleaffector.cpp36
-rw-r--r--src/declarative/particles/qsgparticleaffector_p.h6
-rw-r--r--src/declarative/particles/qsgparticlepainter.cpp77
-rw-r--r--src/declarative/particles/qsgparticlepainter_p.h50
-rw-r--r--src/declarative/particles/qsgparticlesystem.cpp363
-rw-r--r--src/declarative/particles/qsgparticlesystem_p.h79
-rw-r--r--src/declarative/particles/qsgpointattractor.cpp16
-rw-r--r--src/declarative/particles/qsgspritegoal.cpp6
-rw-r--r--src/declarative/particles/qsgturbulence.cpp50
-rw-r--r--src/declarative/particles/qsgwander.cpp8
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest.cpp9
-rw-r--r--src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp141
-rw-r--r--src/declarative/scenegraph/coreapi/qsgdefaultrenderer_p.h32
-rw-r--r--src/declarative/scenegraph/coreapi/qsgmaterial.cpp6
-rw-r--r--src/declarative/scenegraph/coreapi/qsgmatrix4x4stack.cpp380
-rw-r--r--src/declarative/scenegraph/coreapi/qsgmatrix4x4stack.h104
-rw-r--r--src/declarative/scenegraph/coreapi/qsgmatrix4x4stack_p.h73
-rw-r--r--src/declarative/scenegraph/coreapi/qsgnode.cpp175
-rw-r--r--src/declarative/scenegraph/coreapi/qsgnode.h28
-rw-r--r--src/declarative/scenegraph/coreapi/qsgnodeupdater.cpp99
-rw-r--r--src/declarative/scenegraph/coreapi/qsgnodeupdater_p.h20
-rw-r--r--src/declarative/scenegraph/coreapi/qsgrenderer.cpp34
-rw-r--r--src/declarative/scenegraph/coreapi/qsgrenderer_p.h26
-rw-r--r--src/declarative/scenegraph/qsgcontext.cpp9
-rw-r--r--src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp55
-rw-r--r--src/declarative/scenegraph/qsgflashnode.cpp2
-rw-r--r--src/declarative/scenegraph/scenegraph.pri3
-rw-r--r--tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp1
-rw-r--r--tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp3
-rw-r--r--tests/auto/declarative/qdeclarativetranslation/data/idtranslation.qml7
-rw-r--r--tests/auto/declarative/qdeclarativetranslation/data/qml_fr.qmbin0 -> 374 bytes
-rw-r--r--tests/auto/declarative/qdeclarativetranslation/data/qml_fr.ts43
-rw-r--r--tests/auto/declarative/qdeclarativetranslation/data/qmlid_fr.qmbin0 -> 119 bytes
-rw-r--r--tests/auto/declarative/qdeclarativetranslation/data/qmlid_fr.ts13
-rw-r--r--tests/auto/declarative/qdeclarativetranslation/data/translation.qml17
-rw-r--r--tests/auto/declarative/qdeclarativetranslation/qdeclarativetranslation.pro17
-rw-r--r--tests/auto/declarative/qdeclarativetranslation/tst_qdeclarativetranslation.cpp113
-rw-r--r--tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData.qml2
-rw-r--r--tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData_DELETE.expect7
-rw-r--r--tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData_HEAD.expect (renamed from tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData_PUT.expect)0
-rw-r--r--tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp23
-rw-r--r--tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp6
-rw-r--r--tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp22
96 files changed, 1489 insertions, 1611 deletions
diff --git a/examples/declarative/particles/custom/fireworks.qml b/examples/declarative/particles/custom/fireworks.qml
index edd4accfdf..b73a5e234f 100644
--- a/examples/declarative/particles/custom/fireworks.qml
+++ b/examples/declarative/particles/custom/fireworks.qml
@@ -45,22 +45,6 @@ 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{
@@ -79,14 +63,28 @@ Rectangle{
repeat: false
onTriggered: {
img.visible = false;
- emitter.burst(100, container.x+24, container.y+24);
+ emitter.burst(100);
}
}
+ Emitter{
+ anchors.centerIn: parent
+ id: emitter
+ system: syssy
+ particle: "works"
+ emitting: false
+ emitRate: 100
+ lifeSpan: 1000
+ //speed: AngledDirection{angle: 270; angleVariation:60; magnitudeVariation: 60; magnitude: 20}
+ speed: PointDirection{y:-60; yVariation: 80; xVariation: 80}
+ acceleration: PointDirection{y:100; yVariation: 20}
+ }
}
}
ParticleSystem{
anchors.fill: parent
+ id: syssy
Emitter{
+ particle: "fire"
width: parent.width
y: parent.height
emitRate: 2
@@ -94,8 +92,13 @@ Rectangle{
speed: PointDirection{y:-100}
}
ItemParticle{
+ particles: ["fire"]
delegate: firework
}
+ ImageParticle{
+ particles: ["works"]
+ source: "content/particle.png"
+ }
}
}
diff --git a/examples/declarative/particles/custom/shader.qml b/examples/declarative/particles/custom/shader.qml
new file mode 100644
index 0000000000..d83e7864c4
--- /dev/null
+++ b/examples/declarative/particles/custom/shader.qml
@@ -0,0 +1,84 @@
+import QtQuick 2.0
+import QtQuick.Particles 2.0
+
+ParticleSystem{
+ id: root
+ width: 1024
+ height: 768
+ Rectangle{
+ z: -1
+ anchors.fill: parent
+ color: "black"
+ Text{
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ font.pixelSize: 36
+ color: "white"
+ text: "It's all in the fragment shader."
+ }
+ }
+ Emitter{
+ emitRate: 400
+ lifeSpan: 8000
+ size: 24
+ sizeVariation: 16
+ speed: PointDirection{x: root.width/10; y: root.height/10;}
+ //acceleration: AngledDirection{angle:225; magnitude: root.width/36; angleVariation: 45; magnitudeVariation: 80}
+ acceleration: PointDirection{x: -root.width/40; y: -root.height/40; xVariation: -root.width/20; yVariation: -root.width/20}
+ }
+ CustomParticle{
+ //TODO: Someway that you don't have to rewrite the basics for a simple addition
+ vertexShader:"
+ attribute highp vec2 vPos;
+ attribute highp vec2 vTex;
+ attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
+ attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
+ attribute highp float r;
+
+ uniform highp mat4 qt_ModelViewProjectionMatrix;
+ uniform highp float timestamp;
+ uniform lowp float qt_Opacity;
+
+ varying highp vec2 fTex;
+ varying lowp float fFade;
+ varying highp vec2 fPos;
+
+ void main() {
+ fTex = vTex;
+ highp float size = vData.z;
+ highp float endSize = vData.w;
+
+ highp float t = (timestamp - vData.x) / vData.y;
+
+ highp float currentSize = mix(size, endSize, t * t);
+
+ if (t < 0. || t > 1.)
+ currentSize = 0.;
+
+ highp vec2 pos = vPos
+ - currentSize / 2. + currentSize * vTex // adjust size
+ + vVec.xy * t * vData.y // apply speed vector..
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.);
+
+ gl_Position = qt_ModelViewProjectionMatrix * vec4(pos.x, pos.y, 0, 1);
+
+ highp float fadeIn = min(t * 20., 1.);
+ highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+
+ fFade = fadeIn * fadeOut * qt_Opacity;
+ fPos = vec2(pos.x/1024., pos.y/768.);
+ }
+ "
+ fragmentShader: "
+ varying highp vec2 fPos;
+ varying lowp float fFade;
+ varying highp vec2 fTex;
+ void main() {//*2 because this generates dark colors mostly
+ highp vec2 circlePos = fTex*2.0 - vec2(1.0,1.0);
+ highp float dist = length(circlePos);
+ highp float circleFactor = max(min(1.0 - dist, 1.0), 0.0);
+ gl_FragColor = vec4(fPos.x*2.0 - fPos.y, fPos.y*2.0 - fPos.x, fPos.x*fPos.y*2.0, 0.0) * circleFactor * fFade;
+ }"
+
+ }
+}
diff --git a/examples/declarative/particles/trails/dynamicemitters.qml b/examples/declarative/particles/trails/dynamicemitters.qml
index 588474fb43..f338c204db 100644
--- a/examples/declarative/particles/trails/dynamicemitters.qml
+++ b/examples/declarative/particles/trails/dynamicemitters.qml
@@ -81,7 +81,7 @@ Rectangle{
}
system: sys
emitting: true
- emitRate: 64
+ emitRate: 32
lifeSpan: 600
size: 24
endSize: 8
@@ -107,12 +107,12 @@ Rectangle{
MouseArea{
anchors.fill: parent
onClicked:{
- for(var i=0; i<16; i++){
+ for(var i=0; i<8; i++){
var obj = emitterComp.createObject(root);
obj.x = mouse.x
obj.y = mouse.y
- obj.targetX = Math.random() * 640
- obj.targetY = Math.random() * 480
+ obj.targetX = Math.random() * 240 - 120 + obj.x
+ obj.targetY = Math.random() * 240 - 120 + obj.y
obj.life = Math.round(Math.random() * 2400) + 200
obj.go();
}
diff --git a/src/declarative/items/qsganchors.cpp b/src/declarative/items/qsganchors.cpp
index ff9351edbc..b491894532 100644
--- a/src/declarative/items/qsganchors.cpp
+++ b/src/declarative/items/qsganchors.cpp
@@ -1,4 +1,3 @@
-// Commit: 2c7cab4172f1acc86fd49345a2847417e162f2c3
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsganimatedimage.cpp b/src/declarative/items/qsganimatedimage.cpp
index f036042ce2..0d7fb952d4 100644
--- a/src/declarative/items/qsganimatedimage.cpp
+++ b/src/declarative/items/qsganimatedimage.cpp
@@ -1,4 +1,3 @@
-// Commit: af33f9f2e7ec433b81f5c18e3e7395db4a56c5fe
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsganimation.cpp b/src/declarative/items/qsganimation.cpp
index eceff81c7f..a733107a8c 100644
--- a/src/declarative/items/qsganimation.cpp
+++ b/src/declarative/items/qsganimation.cpp
@@ -1,4 +1,3 @@
-// Commit: 91501cc9b542de644cd70098a6bc5ff738cdeb49
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgborderimage.cpp b/src/declarative/items/qsgborderimage.cpp
index 81df0a31e7..a0bb72ea35 100644
--- a/src/declarative/items/qsgborderimage.cpp
+++ b/src/declarative/items/qsgborderimage.cpp
@@ -1,4 +1,3 @@
-// Commit: 462429f5692f810bdd4e04b916db5f9af428d9e4
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp
index fee58b87a8..0500b752c7 100644
--- a/src/declarative/items/qsgcanvas.cpp
+++ b/src/declarative/items/qsgcanvas.cpp
@@ -394,7 +394,7 @@ void QSGCanvasPrivate::renderSceneGraph(const QSize &size)
{
context->renderer()->setDeviceRect(QRect(QPoint(0, 0), size));
context->renderer()->setViewportRect(QRect(QPoint(0, 0), size));
- context->renderer()->setProjectMatrixToDeviceRect();
+ context->renderer()->setProjectionMatrixToDeviceRect();
context->renderNextFrame();
@@ -1759,10 +1759,8 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
}
}
- if (dirty & QSGItemPrivate::ChildrenUpdateMask) {
- while (itemPriv->childContainerNode()->childCount())
- itemPriv->childContainerNode()->removeChildNode(itemPriv->childContainerNode()->childAtIndex(0));
- }
+ if (dirty & QSGItemPrivate::ChildrenUpdateMask)
+ itemPriv->childContainerNode()->removeAllChildNodes();
if (effectRefEffectivelyChanged) {
QSGNode *parent = itemPriv->clipNode;
@@ -1795,15 +1793,12 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
if (dirty & QSGItemPrivate::ChildrenUpdateMask) {
QSGNode *groupNode = itemPriv->groupNode;
- if (groupNode) {
- for (int count = groupNode->childCount(); count; --count)
- groupNode->removeChildNode(groupNode->childAtIndex(0));
- }
+ if (groupNode)
+ groupNode->removeAllChildNodes();
QList<QSGItem *> orderedChildren = itemPriv->paintOrderChildItems();
int ii = 0;
- itemPriv->paintNodeIndex = 0;
for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
QSGItemPrivate *childPrivate = QSGItemPrivate::get(orderedChildren.at(ii));
if (!childPrivate->explicitVisible && !childPrivate->effectRefCount)
@@ -1812,8 +1807,8 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
- itemPriv->paintNodeIndex++;
}
+ itemPriv->beforePaintNode = itemPriv->groupNode ? itemPriv->groupNode->lastChild() : 0;
if (itemPriv->paintNode)
itemPriv->childContainerNode()->appendChildNode(itemPriv->paintNode);
@@ -1869,10 +1864,10 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
itemPriv->paintNode->parent() == itemPriv->childContainerNode());
if (itemPriv->paintNode && itemPriv->paintNode->parent() == 0) {
- if (itemPriv->childContainerNode()->childCount() == itemPriv->paintNodeIndex)
- itemPriv->childContainerNode()->appendChildNode(itemPriv->paintNode);
- else
- itemPriv->childContainerNode()->insertChildNodeBefore(itemPriv->paintNode, itemPriv->childContainerNode()->childAtIndex(itemPriv->paintNodeIndex));
+ if (itemPriv->beforePaintNode)
+ itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, itemPriv->beforePaintNode);
+ else
+ itemPriv->childContainerNode()->prependChildNode(itemPriv->paintNode);
}
} else if (itemPriv->paintNode) {
delete itemPriv->paintNode;
@@ -1908,8 +1903,8 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 1);
Q_ASSERT(child->parent() == parent);
bool containsChild = false;
- for (int i = 0; i < parent->childCount(); ++i)
- containsChild |= (parent->childAtIndex(i) == child);
+ for (QSGNode *n = parent->firstChild(); n; n = n->nextSibling())
+ containsChild |= (n == child);
Q_ASSERT(containsChild);
}
ip = ic;
@@ -2006,7 +2001,9 @@ QImage QSGCanvas::grabFrameBuffer()
void QSGCanvasRenderThread::run()
{
+#ifdef THREAD_DEBUG
qDebug("QML Rendering Thread Started");
+#endif
renderer->makeCurrent();
@@ -2099,7 +2096,7 @@ void QSGCanvasRenderThread::run()
// but we don't want to lock an extra time.
wake();
- if (!d->animationRunning && !isExternalUpdatePending && !shouldExit) {
+ if (!d->animationRunning && !isExternalUpdatePending && !shouldExit && !doGrab) {
#ifdef THREAD_DEBUG
printf(" RenderThread: nothing to do, going to sleep...\n");
#endif
@@ -2338,7 +2335,7 @@ QImage QSGCanvasRenderThread::grab()
doGrab = true;
isPaintCompleted = false;
while (isRunning() && !isPaintCompleted) {
- if (!isRenderBlocked)
+ if (isRenderBlocked)
wake();
wait();
}
diff --git a/src/declarative/items/qsgclipnode.cpp b/src/declarative/items/qsgclipnode.cpp
index 2e40972620..b0a0a56534 100644
--- a/src/declarative/items/qsgclipnode.cpp
+++ b/src/declarative/items/qsgclipnode.cpp
@@ -1,4 +1,3 @@
-
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgcontext2d.cpp b/src/declarative/items/qsgcontext2d.cpp
index 2e60de189f..9dddc99557 100644
--- a/src/declarative/items/qsgcontext2d.cpp
+++ b/src/declarative/items/qsgcontext2d.cpp
@@ -786,12 +786,15 @@ static QScriptValue ctx2d_isPointInPath(QScriptContext *c, QScriptEngine *e)
// text
static QScriptValue ctx2d_font(QScriptContext *c, QScriptEngine *e)
{
+ return QScriptValue();
}
static QScriptValue ctx2d_textAlign(QScriptContext *c, QScriptEngine *e)
{
+ return QScriptValue();
}
static QScriptValue ctx2d_textBaseline(QScriptContext *c, QScriptEngine *e)
{
+ return QScriptValue();
}
static QScriptValue ctx2d_fillText(QScriptContext *c, QScriptEngine *e)
{
@@ -846,53 +849,61 @@ static QScriptValue ctx2d_drawImage(QScriptContext *c, QScriptEngine *e)
static QScriptValue ctx2d_createImageData(QScriptContext *c, QScriptEngine *e)
{
//#TODO
+ return QScriptValue();
}
static QScriptValue ctx2d_getImageData(QScriptContext *c, QScriptEngine *e)
{
//#TODO
+ return QScriptValue();
}
static QScriptValue ctx2d_putImageData(QScriptContext *c, QScriptEngine *e)
{
//#TODO
+ return QScriptValue();
}
//Image Data Interface
static QScriptValue ctx2d_imageData_data(QScriptContext *c, QScriptEngine *e)
{
//#TODO
+ return QScriptValue();
}
static QScriptValue ctx2d_imageData_height(QScriptContext *c, QScriptEngine *e)
{
//#TODO
+ return QScriptValue();
}
static QScriptValue ctx2d_imageData_width(QScriptContext *c, QScriptEngine *e)
{
//#TODO
+ return QScriptValue();
}
//CanvasPixelArray interface
static QScriptValue ctx2d_pixelArray_length(QScriptContext *c, QScriptEngine *e)
{
//#TODO
+ return QScriptValue();
}
//getter/setter by index how to?
static QScriptValue ctx2d_pixelArray(QScriptContext *c, QScriptEngine *e)
{
//#TODO
+ return QScriptValue();
}
//CanvasGradient interface
static QScriptValue ctx2d_gradient_addColorStop(QScriptContext *c, QScriptEngine *e)
{
//#TODO
-
+ return QScriptValue();
}
//TextMetrics
static QScriptValue ctx2d_textMetrics_width(QScriptContext *c, QScriptEngine *e)
{
//#TODO
-
+ return QScriptValue();
}
diff --git a/src/declarative/items/qsgevents.cpp b/src/declarative/items/qsgevents.cpp
index 44ef38b037..773a3e3fe0 100644
--- a/src/declarative/items/qsgevents.cpp
+++ b/src/declarative/items/qsgevents.cpp
@@ -1,4 +1,3 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgflickable.cpp b/src/declarative/items/qsgflickable.cpp
index be0ac13bbf..48beef8422 100644
--- a/src/declarative/items/qsgflickable.cpp
+++ b/src/declarative/items/qsgflickable.cpp
@@ -1,4 +1,3 @@
-// Commit: d4fa1878ff1e7628d3e984d54f8a93810353c71b
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgflipable.cpp b/src/declarative/items/qsgflipable.cpp
index a856d6360b..0439a4d827 100644
--- a/src/declarative/items/qsgflipable.cpp
+++ b/src/declarative/items/qsgflipable.cpp
@@ -1,4 +1,3 @@
-// Commit: caee66da925949cf7aef2ff8e1a86c38dd6e6efd
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgfocusscope.cpp b/src/declarative/items/qsgfocusscope.cpp
index 84f19b1671..07fafc367f 100644
--- a/src/declarative/items/qsgfocusscope.cpp
+++ b/src/declarative/items/qsgfocusscope.cpp
@@ -1,4 +1,3 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsggridview.cpp b/src/declarative/items/qsggridview.cpp
index 41fe0345bd..fb109288c5 100644
--- a/src/declarative/items/qsggridview.cpp
+++ b/src/declarative/items/qsggridview.cpp
@@ -1,4 +1,3 @@
-// Commit: 806f031efeda71d3f4d7d2f949b437493e79cf52
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgimage.cpp b/src/declarative/items/qsgimage.cpp
index 706aaa7d5d..2e38313e80 100644
--- a/src/declarative/items/qsgimage.cpp
+++ b/src/declarative/items/qsgimage.cpp
@@ -1,4 +1,3 @@
-// Commit: 051a76c1d65d698f71dc75c89f91ae9021357eae
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgimagebase.cpp b/src/declarative/items/qsgimagebase.cpp
index 9f2de03bbe..70a6f6de4f 100644
--- a/src/declarative/items/qsgimagebase.cpp
+++ b/src/declarative/items/qsgimagebase.cpp
@@ -1,4 +1,3 @@
-// Commit: 051a76c1d65d698f71dc75c89f91ae9021357eae
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgimplicitsizeitem.cpp b/src/declarative/items/qsgimplicitsizeitem.cpp
index f2cc9bcbdb..f8e5b5f021 100644
--- a/src/declarative/items/qsgimplicitsizeitem.cpp
+++ b/src/declarative/items/qsgimplicitsizeitem.cpp
@@ -1,4 +1,3 @@
-// Commit: 6f78a6080b84cc3ef96b73a4ff58d1b5a72f08f4
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgitem.cpp b/src/declarative/items/qsgitem.cpp
index 328da16ff4..b87ba296e2 100644
--- a/src/declarative/items/qsgitem.cpp
+++ b/src/declarative/items/qsgitem.cpp
@@ -1,4 +1,3 @@
-// Commit: c44be8c0b27756a2025ebad1945632f3f7e4bebc
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
@@ -1181,7 +1180,7 @@ void QSGItemPrivate::initCanvas(InitializationState *state, QSGCanvas *c)
rootNode = 0;
groupNode = 0;
paintNode = 0;
- paintNodeIndex = 0;
+ beforePaintNode = 0;
InitializationState _dummy;
InitializationState *childState = state;
@@ -1286,7 +1285,7 @@ QSGItemPrivate::QSGItemPrivate()
dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
itemNodeInstance(0), opacityNode(0), clipNode(0), rootNode(0), groupNode(0), paintNode(0)
- , paintNodeIndex(0), effectRefCount(0), hideRefCount(0)
+ , beforePaintNode(0), effectRefCount(0), hideRefCount(0)
{
}
diff --git a/src/declarative/items/qsgitem_p.h b/src/declarative/items/qsgitem_p.h
index 300ccdc49e..0b3348d7fc 100644
--- a/src/declarative/items/qsgitem_p.h
+++ b/src/declarative/items/qsgitem_p.h
@@ -388,7 +388,7 @@ public:
QSGRootNode *rootNode;
QSGNode *groupNode;
QSGNode *paintNode;
- int paintNodeIndex;
+ QSGNode *beforePaintNode;
virtual QSGTransformNode *createTransformNode();
diff --git a/src/declarative/items/qsgitemsmodule.cpp b/src/declarative/items/qsgitemsmodule.cpp
index 057b3a2ed0..bd836d58d9 100644
--- a/src/declarative/items/qsgitemsmodule.cpp
+++ b/src/declarative/items/qsgitemsmodule.cpp
@@ -1,4 +1,3 @@
-// Commit: 2c7cab4172f1acc86fd49345a2847417e162f2c3
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsglistview.cpp b/src/declarative/items/qsglistview.cpp
index e2c148284d..e5b53ea148 100644
--- a/src/declarative/items/qsglistview.cpp
+++ b/src/declarative/items/qsglistview.cpp
@@ -1,4 +1,3 @@
-// Commit: 806f031efeda71d3f4d7d2f949b437493e79cf52
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgloader.cpp b/src/declarative/items/qsgloader.cpp
index 6717098506..e5b7e499ec 100644
--- a/src/declarative/items/qsgloader.cpp
+++ b/src/declarative/items/qsgloader.cpp
@@ -1,4 +1,3 @@
-// Commit: 501180c6fbed0857126da2bb0ff1f17ee35472c6
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgmousearea.cpp b/src/declarative/items/qsgmousearea.cpp
index 6b4311e698..6886ccca35 100644
--- a/src/declarative/items/qsgmousearea.cpp
+++ b/src/declarative/items/qsgmousearea.cpp
@@ -1,4 +1,3 @@
-// Commit: e1ffbc04131dc6f76fa76821c297d08162e4b1ee
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
@@ -502,9 +501,11 @@ void QSGMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
setHovered(true);
if (d->drag && d->drag->target()) {
+
if (!d->moved) {
- d->startX = drag()->target()->x();
- d->startY = drag()->target()->y();
+ d->targetStartPos = d->drag->target()->parentItem()
+ ? d->drag->target()->parentItem()->mapToScene(d->drag->target()->pos())
+ : d->drag->target()->pos();
}
QPointF startLocalPos;
@@ -540,8 +541,12 @@ void QSGMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
}
}
+ QPointF startPos = d->drag->target()->parentItem()
+ ? d->drag->target()->parentItem()->mapFromScene(d->targetStartPos)
+ : d->targetStartPos;
+
if (d->dragX && d->drag->active()) {
- qreal x = (curLocalPos.x() - startLocalPos.x()) + d->startX;
+ qreal x = (curLocalPos.x() - startLocalPos.x()) + startPos.x();
if (x < drag()->xmin())
x = drag()->xmin();
else if (x > drag()->xmax())
@@ -549,7 +554,7 @@ void QSGMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
drag()->target()->setX(x);
}
if (d->dragY && d->drag->active()) {
- qreal y = (curLocalPos.y() - startLocalPos.y()) + d->startY;
+ qreal y = (curLocalPos.y() - startLocalPos.y()) + startPos.y();
if (y < drag()->ymin())
y = drag()->ymin();
else if (y > drag()->ymax())
diff --git a/src/declarative/items/qsgmousearea_p_p.h b/src/declarative/items/qsgmousearea_p_p.h
index 11f7089503..0eb0444224 100644
--- a/src/declarative/items/qsgmousearea_p_p.h
+++ b/src/declarative/items/qsgmousearea_p_p.h
@@ -99,8 +99,7 @@ public:
bool dragRejected : 1;
QSGDrag *drag;
QPointF startScene;
- qreal startX;
- qreal startY;
+ QPointF targetStartPos;
QPointF lastPos;
QDeclarativeNullableValue<QPointF> lastScenePos;
Qt::MouseButton lastButton;
diff --git a/src/declarative/items/qsgpathview.cpp b/src/declarative/items/qsgpathview.cpp
index fc3d39aef7..35b6e038ab 100644
--- a/src/declarative/items/qsgpathview.cpp
+++ b/src/declarative/items/qsgpathview.cpp
@@ -1,4 +1,3 @@
-// Commit: 806f031efeda71d3f4d7d2f949b437493e79cf52
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgpincharea.cpp b/src/declarative/items/qsgpincharea.cpp
index f21d873e5e..6fc0c61359 100644
--- a/src/declarative/items/qsgpincharea.cpp
+++ b/src/declarative/items/qsgpincharea.cpp
@@ -1,4 +1,3 @@
-// Commit: f707672eb4c51ea82fbd98e1da16ece61a74c690
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgpositioners.cpp b/src/declarative/items/qsgpositioners.cpp
index f174612af6..0106d8fea9 100644
--- a/src/declarative/items/qsgpositioners.cpp
+++ b/src/declarative/items/qsgpositioners.cpp
@@ -1,4 +1,3 @@
-// Commit: 1f38d41854fa2daa51d938a4eb398752b1751e0b
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgrectangle.cpp b/src/declarative/items/qsgrectangle.cpp
index e97abe3e1c..09bf34dc15 100644
--- a/src/declarative/items/qsgrectangle.cpp
+++ b/src/declarative/items/qsgrectangle.cpp
@@ -1,4 +1,3 @@
-// Commit: acc903853d5ac54d646d324b7386c998bc07d464
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgrepeater.cpp b/src/declarative/items/qsgrepeater.cpp
index ac6086fc62..3a0ef84ed3 100644
--- a/src/declarative/items/qsgrepeater.cpp
+++ b/src/declarative/items/qsgrepeater.cpp
@@ -1,4 +1,3 @@
-// Commit: a9f1eaa6a368bf7a72b52c428728a3e3e0a76209
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgscalegrid.cpp b/src/declarative/items/qsgscalegrid.cpp
index 4a73801159..9f1b7bf8a6 100644
--- a/src/declarative/items/qsgscalegrid.cpp
+++ b/src/declarative/items/qsgscalegrid.cpp
@@ -1,4 +1,3 @@
-// Commit: 7ddec9f3179bfd854ae53e23ab292de1f9a26377
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgshadereffectmesh.cpp b/src/declarative/items/qsgshadereffectmesh.cpp
index dbc3472d09..05131285df 100644
--- a/src/declarative/items/qsgshadereffectmesh.cpp
+++ b/src/declarative/items/qsgshadereffectmesh.cpp
@@ -135,11 +135,6 @@ QSGGeometry *QSGGridMesh::updateGeometry(QSGGeometry *geometry, const QVector<QB
break;
}
- if (error) {
- delete geometry;
- return 0;
- }
-
geometry = new QSGGeometry(attrCount == 1
? QSGGeometry::defaultAttributes_Point2D()
: QSGGeometry::defaultAttributes_TexturedPoint2D(),
diff --git a/src/declarative/items/qsgshadereffectsource.cpp b/src/declarative/items/qsgshadereffectsource.cpp
index e2c50bb80e..c4c09868d2 100644
--- a/src/declarative/items/qsgshadereffectsource.cpp
+++ b/src/declarative/items/qsgshadereffectsource.cpp
@@ -214,8 +214,8 @@ void QSGShaderEffectTexture::grab()
return;
}
QSGNode *root = m_item;
- while (root->childCount() && root->type() != QSGNode::RootNodeType)
- root = root->childAtIndex(0);
+ while (root->firstChild() && root->type() != QSGNode::RootNodeType)
+ root = root->firstChild();
if (root->type() != QSGNode::RootNodeType)
return;
@@ -310,7 +310,7 @@ void QSGShaderEffectTexture::grab()
m_renderer->setDeviceRect(m_size);
m_renderer->setViewportRect(m_size);
QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
- m_renderer->setProjectMatrixToRect(mirrored);
+ m_renderer->setProjectionMatrixToRect(mirrored);
m_renderer->setClearColor(Qt::transparent);
if (m_multisampling) {
@@ -391,6 +391,7 @@ void QSGShaderEffectTexture::grab()
rather than each element individually.
\endlist
+ \table
\row
\o \image declarative-shadereffectsource.png
\o \qml
@@ -420,6 +421,7 @@ void QSGShaderEffectTexture::grab()
}
\endqml
\endrow
+ \endtable
The ShaderEffectSource element does not redirect any mouse or keyboard
input to \l sourceItem. If you hide the \l sourceItem by setting
diff --git a/src/declarative/items/qsgstateoperations.cpp b/src/declarative/items/qsgstateoperations.cpp
index 5390440e39..0c6491ed58 100644
--- a/src/declarative/items/qsgstateoperations.cpp
+++ b/src/declarative/items/qsgstateoperations.cpp
@@ -1,4 +1,3 @@
-// Commit: 726a8b16c52fe4608c89d740b47361a2b073ce01
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgtext.cpp b/src/declarative/items/qsgtext.cpp
index ae9bffc795..3398824f69 100644
--- a/src/declarative/items/qsgtext.cpp
+++ b/src/declarative/items/qsgtext.cpp
@@ -1,4 +1,3 @@
-// Commit: cce89db1e2555cbca8fc28072e1c6dd737cec6c4
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgtextedit.cpp b/src/declarative/items/qsgtextedit.cpp
index 1c199ecc28..01d068d131 100644
--- a/src/declarative/items/qsgtextedit.cpp
+++ b/src/declarative/items/qsgtextedit.cpp
@@ -1,4 +1,3 @@
-// Commit: ec40dd2bb51868bca10dbd0c9116f3224ff2b29b
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgtextinput.cpp b/src/declarative/items/qsgtextinput.cpp
index 1db4474d4a..94f54712c3 100644
--- a/src/declarative/items/qsgtextinput.cpp
+++ b/src/declarative/items/qsgtextinput.cpp
@@ -1,4 +1,3 @@
-// Commit: 47712d1f330e4b22ce6dd30e7557288ef7f7fca0
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgtextnode.cpp b/src/declarative/items/qsgtextnode.cpp
index 876c9785b4..6909d8cfca 100644
--- a/src/declarative/items/qsgtextnode.cpp
+++ b/src/declarative/items/qsgtextnode.cpp
@@ -81,8 +81,7 @@ void QSGTextNode::setColor(const QColor &color)
if (m_usePixmapCache) {
setUpdateFlag(UpdateNodes);
} else {
- for (int i=0; i<childCount(); ++i) {
- QSGNode *childNode = childAtIndex(i);
+ for (QSGNode *childNode = firstChild(); childNode; childNode = childNode->nextSibling()) {
if (childNode->subType() == GlyphNodeSubType) {
QSGGlyphNode *glyphNode = static_cast<QSGGlyphNode *>(childNode);
if (glyphNode->color() == m_color)
@@ -103,8 +102,7 @@ void QSGTextNode::setStyleColor(const QColor &styleColor)
if (m_usePixmapCache) {
setUpdateFlag(UpdateNodes);
} else {
- for (int i=0; i<childCount(); ++i) {
- QSGNode *childNode = childAtIndex(i);
+ for (QSGNode *childNode = firstChild(); childNode; childNode = childNode->nextSibling()) {
if (childNode->subType() == GlyphNodeSubType) {
QSGGlyphNode *glyphNode = static_cast<QSGGlyphNode *>(childNode);
if (glyphNode->color() == m_styleColor)
@@ -371,8 +369,8 @@ void QSGTextNode::addTextBlock(const QPointF &position, QTextDocument *textDocum
void QSGTextNode::deleteContent()
{
- while (childCount() > 0)
- delete childAtIndex(0);
+ while (firstChild() > 0)
+ delete firstChild();
}
#if 0
diff --git a/src/declarative/items/qsgtranslate.cpp b/src/declarative/items/qsgtranslate.cpp
index 5f7112bd42..1c453d6f57 100644
--- a/src/declarative/items/qsgtranslate.cpp
+++ b/src/declarative/items/qsgtranslate.cpp
@@ -1,4 +1,3 @@
-// Commit: ac5c099cc3c5b8c7eec7a49fdeb8a21037230350
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgview.cpp b/src/declarative/items/qsgview.cpp
index 1169c59a1b..830a232db2 100644
--- a/src/declarative/items/qsgview.cpp
+++ b/src/declarative/items/qsgview.cpp
@@ -1,4 +1,3 @@
-// Commit: 55c4d94dfea78951f3371d3697a3cb28539b3012
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/items/qsgvisualitemmodel.cpp b/src/declarative/items/qsgvisualitemmodel.cpp
index 6517ef4e20..85f97aae7d 100644
--- a/src/declarative/items/qsgvisualitemmodel.cpp
+++ b/src/declarative/items/qsgvisualitemmodel.cpp
@@ -1,4 +1,3 @@
-// Commit: dcb9148091cbf6872b60407c301d7c92427583a6
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/declarative/particles/qsgcustomparticle.cpp b/src/declarative/particles/qsgcustomparticle.cpp
index 808ff1c427..09cfdda143 100644
--- a/src/declarative/particles/qsgcustomparticle.cpp
+++ b/src/declarative/particles/qsgcustomparticle.cpp
@@ -44,16 +44,8 @@
#include <cstdlib>
QT_BEGIN_NAMESPACE
-/*
- "uniform highp mat4 qt_ModelViewProjectionMatrix; \n"
- "attribute highp vec4 qt_Vertex; \n"
- "attribute highp vec2 qt_MultiTexCoord0; \n"
- "varying highp vec2 qt_TexCoord0; \n"
- "void main() { \n"
- " qt_TexCoord0 = qt_MultiTexCoord0; \n"
- " gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex; \n"
- "}";
-*/
+
+//TODO: Can we make the code such that you don't have to copy the whole vertex shader just to add one little calculation?
//Includes comments because the code isn't self explanatory
static const char qt_particles_default_vertex_code[] =
"attribute highp vec2 vPos; \n"
@@ -86,23 +78,6 @@ static const char qt_particles_default_fragment_code[] =//TODO: Default frag req
" gl_FragColor = texture2D(source, fTex) * qt_Opacity; \n"
"}";
-/*
-static const char qt_particles_default_vertex_code[] =
- "attribute highp vec2 vPos; \n"
- "attribute highp vec2 vTex; \n"
- "uniform highp mat4 qt_ModelViewProjectionMatrix; \n"
- "void main() { \n"
- " highp float currentSize = 1000.0; \n"
- " highp vec2 pos = vec2(100.0,100.0) \n"
- " - currentSize / 2. + currentSize * vTex; // adjust size \n"
- " gl_Position = qt_ModelViewProjectionMatrix * vec4(pos.x, pos.y, 0, 1); \n"
- "}";
-static const char qt_particles_default_fragment_code[] =//TODO: Default frag requires source?
- "void main() { \n"
- " gl_FragColor = vec4(0,255,0,255); \n"
- "}";
-*/
-
static const char qt_position_attribute_name[] = "qt_Vertex";
static const char qt_texcoord_attribute_name[] = "qt_MultiTexCoord0";
@@ -199,12 +174,6 @@ void QSGCustomParticle::setVertexShader(const QByteArray &code)
emit vertexShaderChanged();
}
-void QSGCustomParticle::setCount(int c)
-{
- QSGParticlePainter::setCount(c);
- m_pleaseReset = true;
-}
-
void QSGCustomParticle::reset()
{
disconnectPropertySignals();
@@ -437,7 +406,6 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNode()
return 0;
}
-
//Create Particle Geometry
int vCount = m_count * 4;
int iCount = m_count * 6;
@@ -445,21 +413,7 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNode()
g->setDrawingMode(GL_TRIANGLES);
PlainVertex *vertices = (PlainVertex *) g->vertexData();
for (int p=0; p<m_count; ++p) {
- double r = rand()/(double)RAND_MAX;//TODO: Seed?
- for (int i=0; i<4; ++i) {
- vertices[i].x = 0;
- vertices[i].y = 0;
- vertices[i].t = -1;
- vertices[i].lifeSpan = 0;
- vertices[i].size = 0;
- vertices[i].endSize = 0;
- vertices[i].sx = 0;
- vertices[i].sy = 0;
- vertices[i].ax = 0;
- vertices[i].ay = 0;
- vertices[i].r = r;
- }
-
+ reload(p);
vertices[0].tx = 0;
vertices[0].ty = 0;
@@ -471,7 +425,6 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNode()
vertices[3].tx = 1;
vertices[3].ty = 1;
-
vertices += 4;
}
quint16 *indices = g->indexDataAsUShort();
@@ -493,23 +446,6 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNode()
node->setGeometry(g);
node->setMaterial(&m_material);
- /*
- //For debugging, just use grid vertices like ShaderEffect
- node->setGeometry(0);
- QSGShaderEffectMesh* mesh = new QSGGridMesh();
- node->setFlag(QSGNode::OwnsGeometry, false);
-
- qDebug() << m_source.attributeNames;
- QSGGeometry* geometry = node->geometry();
- geometry = mesh->updateGeometry(geometry, m_source.attributeNames, QRectF(0,0,width(),height()));
- if(!geometry)
- qDebug() << "Should have written the error handling";
- else
- qDebug() << "Mesh Loaded";
- node->setGeometry(geometry);
- qDebug() << QString("INIT") << geometry << (QObject*)node;
- node->setFlag(QSGNode::OwnsGeometry, true);
- */
QSGShaderEffectProgram s = m_source;
if (s.fragmentCode.isEmpty())
s.fragmentCode = qt_particles_default_fragment_code;
@@ -554,28 +490,31 @@ void QSGCustomParticle::buildData()
m_dirtyData = false;
}
-void QSGCustomParticle::load(QSGParticleData *d)
+void QSGCustomParticle::initialize(int idx)
{
- reload(d);//We don't do anything special in C++ here.
+ m_data[idx]->r = rand()/(qreal)RAND_MAX;
}
-void QSGCustomParticle::reload(QSGParticleData *d)
+void QSGCustomParticle::reload(int idx)
{
if (m_node == 0)
return;
PlainVertices *particles = (PlainVertices *) m_node->geometry()->vertexData();
-
- int pos = particleTypeIndex(d);
-
- PlainVertices &p = particles[pos];
-
- //Perhaps we could be more efficient?
- vertexCopy(p.v1, d->pv);
- vertexCopy(p.v2, d->pv);
- vertexCopy(p.v3, d->pv);
- vertexCopy(p.v4, d->pv);
-
+ PlainVertex *vertices = (PlainVertex *)&particles[idx];
+ for (int i=0; i<4; ++i) {
+ vertices[i].x = m_data[idx]->x - m_systemOffset.x();
+ vertices[i].y = m_data[idx]->y - m_systemOffset.y();
+ vertices[i].t = m_data[idx]->t;
+ vertices[i].lifeSpan = m_data[idx]->lifeSpan;
+ vertices[i].size = m_data[idx]->size;
+ vertices[i].endSize = m_data[idx]->endSize;
+ vertices[i].sx = m_data[idx]->sx;
+ vertices[i].sy = m_data[idx]->sy;
+ vertices[i].ax = m_data[idx]->ax;
+ vertices[i].ay = m_data[idx]->ay;
+ vertices[i].r = m_data[idx]->r;
+ }
}
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgcustomparticle_p.h b/src/declarative/particles/qsgcustomparticle_p.h
index 95144ef638..50ff37a2a0 100644
--- a/src/declarative/particles/qsgcustomparticle_p.h
+++ b/src/declarative/particles/qsgcustomparticle_p.h
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QSGNode;
-
+struct PlainVertices;
//Genealogy: Hybrid of UltraParticle and ShaderEffectItem
class QSGCustomParticle : public QSGParticlePainter
{
@@ -62,9 +62,6 @@ class QSGCustomParticle : public QSGParticlePainter
public:
explicit QSGCustomParticle(QSGItem* parent=0);
- virtual void load(QSGParticleData*);
- virtual void reload(QSGParticleData*);
- virtual void setCount(int c);
QByteArray fragmentShader() const { return m_source.fragmentCode; }
void setFragmentShader(const QByteArray &code);
@@ -78,20 +75,26 @@ Q_SIGNALS:
void fragmentShaderChanged();
void vertexShaderChanged();
protected:
+ virtual void initialize(int idx);
+ virtual void reload(int idx);
+
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
void prepareNextFrame();
void setSource(const QVariant &var, int index);
void disconnectPropertySignals();
void connectPropertySignals();
void reset();
+ void resize(int oldCount, int newCount);
void updateProperties();
void lookThroughShaderCode(const QByteArray &code);
virtual void componentComplete();
QSGShaderEffectNode *buildCustomNode();
+ void performPendingResize();
private:
void buildData();
+
bool m_pleaseReset;
bool m_dirtyData;
QSGShaderEffectProgram m_source;
@@ -105,6 +108,7 @@ private:
QSGShaderEffectMaterial m_material;
QSGShaderEffectNode* m_node;
qreal m_lastTime;
+
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgemitter.cpp b/src/declarative/particles/qsgemitter.cpp
index 081dd8dec5..c3ec3ffc9e 100644
--- a/src/declarative/particles/qsgemitter.cpp
+++ b/src/declarative/particles/qsgemitter.cpp
@@ -124,7 +124,6 @@ void QSGBasicEmitter::emitWindow(int timeStamp)
QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle]);
if(datum){//actually emit(otherwise we've been asked to skip this one)
datum->e = this;//###useful?
- ParticleVertex &p = datum->pv;
qreal t = 1 - (pt - opt) / dt;
qreal vx =
- 2 * ax * (1 - t)
@@ -137,8 +136,8 @@ void QSGBasicEmitter::emitWindow(int timeStamp)
// Particle timestamp
- p.t = pt;
- p.lifeSpan = //TODO:Promote to base class?
+ datum->t = pt;
+ datum->lifeSpan = //TODO:Promote to base class?
(m_particleDuration
+ ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
/ 1000.0;
@@ -153,20 +152,20 @@ void QSGBasicEmitter::emitWindow(int timeStamp)
, width(), height());
}
QPointF newPos = effectiveExtruder()->extrude(boundsRect);
- p.x = newPos.x();
- p.y = newPos.y();
+ datum->x = newPos.x();
+ datum->y = newPos.y();
// Particle speed
const QPointF &speed = m_speed->sample(newPos);
- p.sx = speed.x()
+ datum->sx = speed.x()
+ m_speed_from_movement * vx;
- p.sy = speed.y()
+ datum->sy = speed.y()
+ m_speed_from_movement * vy;
// Particle acceleration
const QPointF &accel = m_acceleration->sample(newPos);
- p.ax = accel.x();
- p.ay = accel.y();
+ datum->ax = accel.x();
+ datum->ay = accel.y();
// Particle size
float sizeVariation = -m_particleSizeVariation
@@ -175,8 +174,8 @@ void QSGBasicEmitter::emitWindow(int timeStamp)
float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
- p.size = size;// * float(m_emitting);
- p.endSize = endSize;// * float(m_emitting);
+ datum->size = size;// * float(m_emitting);
+ datum->endSize = endSize;// * float(m_emitting);
m_system->emitParticle(datum);
}
diff --git a/src/declarative/particles/qsgfollowemitter.cpp b/src/declarative/particles/qsgfollowemitter.cpp
index 442cff9ec8..ba31e8f834 100644
--- a/src/declarative/particles/qsgfollowemitter.cpp
+++ b/src/declarative/particles/qsgfollowemitter.cpp
@@ -54,6 +54,7 @@ QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
, m_emissionExtruder(0)
, m_defaultEmissionExtruder(new QSGParticleExtruder(this))
{
+ //TODO: If followed increased their size
connect(this, SIGNAL(followChanged(QString)),
this, SLOT(recalcParticlesPerSecond()));
connect(this, SIGNAL(particleDurationChanged(int)),
@@ -67,7 +68,7 @@ void QSGFollowEmitter::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 (causes crashes - test that when gone you don't crash with 0 PPPS)
+ setParticlesPerSecond(1);//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);
@@ -111,61 +112,59 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
int gId = m_system->m_groupIds[m_follow];
int gId2 = m_system->m_groupIds[m_particle];
- for(int i=0; i<m_system->m_groupData[gId]->size; i++){
- pt = m_lastEmission[i];
- QSGParticleData* d = m_system->m_data[i + m_system->m_groupData[gId]->start];
+ foreach(QSGParticleData *d, m_system->m_groupData[gId]->data){
if(!d || !d->stillAlive())
continue;
- if(pt < d->pv.t)
- pt = d->pv.t;
+ pt = m_lastEmission[d->index];
+ if(pt < d->t)
+ pt = d->t;
if(!effectiveExtruder()->contains(QRectF(offset.x(), offset.y(), width(), height()),QPointF(d->curX(), d->curY()))){
- m_lastEmission[i] = time;//jump over this time period without emitting, because it's outside
+ m_lastEmission[d->index] = time;//jump over this time period without emitting, because it's outside
continue;
}
while(pt < time || !m_burstQueue.isEmpty()){
QSGParticleData* datum = m_system->newDatum(gId2);
if(datum){//else, skip this emission
datum->e = this;//###useful?
- ParticleVertex &p = datum->pv;
// Particle timestamp
- p.t = pt;
- p.lifeSpan =
+ datum->t = pt;
+ datum->lifeSpan =
(m_particleDuration
+ ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
/ 1000.0;
// Particle position
// Note that burst location doesn't get used for follow emitter
- qreal followT = pt - d->pv.t;
+ qreal followT = pt - d->t;
qreal followT2 = followT * followT * 0.5;
- qreal sizeOffset = d->pv.size/2;//TODO: Current size? As an option
+ qreal sizeOffset = d->size/2;//TODO: Current size? As an option
//TODO: Set variations
//Subtract offset, because PS expects this in emitter coordinates
- QRectF boundsRect(d->pv.x - offset.x() + d->pv.sx * followT + d->pv.ax * followT2 - m_emitterXVariation/2,
- d->pv.y - offset.y() + d->pv.sy * followT + d->pv.ay * followT2 - m_emitterYVariation/2,
+ QRectF boundsRect(d->x - offset.x() + d->sx * followT + d->ax * followT2 - m_emitterXVariation/2,
+ d->y - offset.y() + d->sy * followT + d->ay * followT2 - m_emitterYVariation/2,
m_emitterXVariation,
m_emitterYVariation);
- // QRectF boundsRect(d->pv.x + d->pv.sx * followT + d->pv.ax * followT2 + offset.x() - sizeOffset,
- // d->pv.y + d->pv.sy * followT + d->pv.ay * followT2 + offset.y() - sizeOffset,
+ // QRectF boundsRect(d->x + d->sx * followT + d->ax * followT2 + offset.x() - sizeOffset,
+ // d->y + d->sy * followT + d->ay * followT2 + offset.y() - sizeOffset,
// sizeOffset*2,
// sizeOffset*2);
QSGParticleExtruder* effectiveEmissionExtruder = m_emissionExtruder ? m_emissionExtruder : m_defaultEmissionExtruder;
const QPointF &newPos = effectiveEmissionExtruder->extrude(boundsRect);
- p.x = newPos.x();
- p.y = newPos.y();
+ datum->x = newPos.x();
+ datum->y = newPos.y();
// Particle speed
const QPointF &speed = m_speed->sample(newPos);
- p.sx = speed.x();
- p.sy = speed.y();
+ datum->sx = speed.x();
+ datum->sy = speed.y();
// Particle acceleration
const QPointF &accel = m_acceleration->sample(newPos);
- p.ax = accel.x();
- p.ay = accel.y();
+ datum->ax = accel.x();
+ datum->ay = accel.y();
// Particle size
float sizeVariation = -m_particleSizeVariation
@@ -174,8 +173,8 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
float size = qMax((qreal)0.0, m_particleSize + sizeVariation);
float endSize = qMax((qreal)0.0, sizeAtEnd + sizeVariation);
- p.size = size * float(m_emitting);
- p.endSize = endSize * float(m_emitting);
+ datum->size = size * float(m_emitting);
+ datum->endSize = endSize * float(m_emitting);
m_system->emitParticle(datum);
}
@@ -187,7 +186,7 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
pt += particleRatio;
}
}
- m_lastEmission[i] = pt;
+ m_lastEmission[d->index] = pt;
}
m_lastTimeStamp = time;
diff --git a/src/declarative/particles/qsggravity.cpp b/src/declarative/particles/qsggravity.cpp
index de735da5ad..b1cf3e9481 100644
--- a/src/declarative/particles/qsggravity.cpp
+++ b/src/declarative/particles/qsggravity.cpp
@@ -64,11 +64,11 @@ bool QSGGravityAffector::affectParticle(QSGParticleData *d, qreal dt)
{
Q_UNUSED(dt);
bool changed = false;
- if(d->pv.ax != m_xAcc){
+ if(d->ax != m_xAcc){
d->setInstantaneousAX(m_xAcc);
changed = true;
}
- if(d->pv.ay != m_yAcc){
+ if(d->ay != m_yAcc){
d->setInstantaneousAY(m_yAcc);
changed = true;
}
diff --git a/src/declarative/particles/qsgimageparticle.cpp b/src/declarative/particles/qsgimageparticle.cpp
index c9df5f4dbd..836236c13e 100644
--- a/src/declarative/particles/qsgimageparticle.cpp
+++ b/src/declarative/particles/qsgimageparticle.cpp
@@ -355,7 +355,7 @@ void QSGImageParticle::setColor(const QColor &color)
return;
m_color = color;
emit colorChanged();
- if(perfLevel < Coloured)
+ if(perfLevel < Colored)
reset();
}
@@ -365,7 +365,7 @@ void QSGImageParticle::setColorVariation(qreal var)
return;
m_color_variation = var;
emit colorVariationChanged();
- if(perfLevel < Coloured)
+ if(perfLevel < Colored)
reset();
}
@@ -375,7 +375,7 @@ void QSGImageParticle::setAlphaVariation(qreal arg)
m_alphaVariation = arg;
emit alphaVariationChanged(arg);
}
- if(perfLevel < Coloured)
+ if(perfLevel < Colored)
reset();
}
@@ -385,7 +385,7 @@ void QSGImageParticle::setAlpha(qreal arg)
m_alpha = arg;
emit alphaChanged(arg);
}
- if(perfLevel < Coloured)
+ if(perfLevel < Colored)
reset();
}
@@ -395,7 +395,7 @@ void QSGImageParticle::setRedVariation(qreal arg)
m_redVariation = arg;
emit redVariationChanged(arg);
}
- if(perfLevel < Coloured)
+ if(perfLevel < Colored)
reset();
}
@@ -405,7 +405,7 @@ void QSGImageParticle::setGreenVariation(qreal arg)
m_greenVariation = arg;
emit greenVariationChanged(arg);
}
- if(perfLevel < Coloured)
+ if(perfLevel < Colored)
reset();
}
@@ -415,7 +415,7 @@ void QSGImageParticle::setBlueVariation(qreal arg)
m_blueVariation = arg;
emit blueVariationChanged(arg);
}
- if(perfLevel < Coloured)
+ if(perfLevel < Colored)
reset();
}
@@ -498,11 +498,6 @@ void QSGImageParticle::setBloat(bool arg)
if(perfLevel < 9999)
reset();
}
-void QSGImageParticle::setCount(int c)
-{
- QSGParticlePainter::setCount(c);
- m_pleaseReset = true;
-}
void QSGImageParticle::reset()
{
@@ -569,20 +564,19 @@ QSGGeometryNode* QSGImageParticle::buildSimpleParticleNode()
g->setDrawingMode(GL_TRIANGLES);
SimpleVertex *vertices = (SimpleVertex *) g->vertexData();
- for (int p=0; p<m_count; ++p) {
- for (int i=0; i<4; ++i) {
- vertices[i].x = 0;
- vertices[i].y = 0;
- vertices[i].t = -1;
- vertices[i].lifeSpan = 0;
- vertices[i].size = 0;
- vertices[i].endSize = 0;
- vertices[i].sx = 0;
- vertices[i].sy = 0;
- vertices[i].ax = 0;
- vertices[i].ay = 0;
+ for (int p=0; p<m_count; ++p){
+ for(int i=0; i<4; i++){
+ vertices[i].x = m_data[p]->x;
+ vertices[i].y = m_data[p]->y;
+ vertices[i].t = m_data[p]->t;
+ vertices[i].size = m_data[p]->size;
+ vertices[i].endSize = m_data[p]->endSize;
+ vertices[i].sx = m_data[p]->sx;
+ vertices[i].sy = m_data[p]->sy;
+ vertices[i].ax = m_data[p]->ax;
+ vertices[i].ay = m_data[p]->ay;
}
-
+ //reload(p);
vertices[0].tx = 0;
vertices[0].ty = 0;
@@ -610,6 +604,9 @@ QSGGeometryNode* QSGImageParticle::buildSimpleParticleNode()
indices += 6;
}
+ m_node = new QSGGeometryNode();
+ m_node->setGeometry(g);
+
if (m_material) {
delete m_material;
m_material = 0;
@@ -619,24 +616,21 @@ QSGGeometryNode* QSGImageParticle::buildSimpleParticleNode()
m_material->texture = sceneGraphEngine()->createTextureFromImage(image);
m_material->texture->setFiltering(QSGTexture::Linear);
m_material->framecount = 1;
- m_node = new QSGGeometryNode();
- m_node->setGeometry(g);
m_node->setMaterial(m_material);
m_last_particle = 0;
-
return m_node;
}
QSGGeometryNode* QSGImageParticle::buildParticleNode()
{
if (m_count * 4 > 0xffff) {
- printf("UltraParticle: Too many particles... \n");//####Why is this here?
+ printf("UltraParticle: Too many particles... \n");//### Why is this here?
return 0;
}
if(m_count <= 0) {
- printf("UltraParticle: Too few particles... \n");
+ qDebug() << "UltraParticle: Too few particles... \n";//XXX: Is now a vaild intermediate state...
return 0;
}
@@ -679,70 +673,12 @@ QSGGeometryNode* QSGImageParticle::buildParticleNode()
QSGGeometry *g = new QSGGeometry(UltraParticle_AttributeSet, vCount, iCount);
g->setDrawingMode(GL_TRIANGLES);
+ m_node = new QSGGeometryNode();
+ m_node->setGeometry(g);
UltraVertex *vertices = (UltraVertex *) g->vertexData();
- SimpleVertex *oldSimple = (SimpleVertex *) m_lastData;//TODO: Other levels
- if(m_lastLevel == 1)
- qDebug() << "Theta" << m_lastLevel << oldSimple[0].x << oldSimple[0].y << oldSimple[0].t;
for (int p=0; p<m_count; ++p) {
-
- if (m_lastLevel == 1) {//Transplant/IntermediateVertices?
- for (int i=0; i<4; ++i) {
- vertices[i].x = oldSimple[i].x;
- vertices[i].y = oldSimple[i].y;
- vertices[i].t = oldSimple[i].t;
- vertices[i].lifeSpan = oldSimple[i].lifeSpan;
- vertices[i].size = oldSimple[i].size;
- vertices[i].endSize = oldSimple[i].endSize;
- vertices[i].sx = oldSimple[i].sx;
- vertices[i].sy = oldSimple[i].sy;
- vertices[i].ax = oldSimple[i].ax;
- vertices[i].ay = oldSimple[i].ay;
- vertices[i].xx = 1;
- vertices[i].xy = 0;
- vertices[i].yx = 0;
- vertices[i].yy = 1;
- vertices[i].rotation = 0;
- vertices[i].rotationSpeed = 0;
- vertices[i].autoRotate = 0;
- vertices[i].animIdx = 0;
- vertices[i].frameDuration = oldSimple[i].lifeSpan;
- vertices[i].frameCount = 1;
- vertices[i].animT = oldSimple[i].t;
- vertices[i].color.r = 255;
- vertices[i].color.g = 255;
- vertices[i].color.b = 255;
- vertices[i].color.a = 255;
- }
- } else {
- for (int i=0; i<4; ++i) {
- vertices[i].x = 0;
- vertices[i].y = 0;
- vertices[i].t = -1;
- vertices[i].lifeSpan = 0;
- vertices[i].size = 0;
- vertices[i].endSize = 0;
- vertices[i].sx = 0;
- vertices[i].sy = 0;
- vertices[i].ax = 0;
- vertices[i].ay = 0;
- vertices[i].xx = 1;
- vertices[i].xy = 0;
- vertices[i].yx = 0;
- vertices[i].yy = 1;
- vertices[i].rotation = 0;
- vertices[i].rotationSpeed = 0;
- vertices[i].autoRotate = 0;
- vertices[i].animIdx = -1;
- vertices[i].frameDuration = 1;
- vertices[i].frameCount = 0;
- vertices[i].animT = -1;
- vertices[i].color.r = 0;//TODO:Some things never get used uninitialized. Consider dropping them here?
- vertices[i].color.g = 0;
- vertices[i].color.b = 0;
- vertices[i].color.a = 0;
- }
- }
+ reload(p);//reload gets geometry from node
vertices[0].tx = 0;
vertices[0].ty = 0;
@@ -757,10 +693,9 @@ QSGGeometryNode* QSGImageParticle::buildParticleNode()
vertices[3].ty = 1;
vertices += 4;
- oldSimple += 4;
}
- quint16 *indices = g->indexDataAsUShort();//TODO: Speed gains by copying this over if count unchanged?
+ quint16 *indices = g->indexDataAsUShort();
for (int i=0; i<m_count; ++i) {
int o = i * 4;
indices[0] = o;
@@ -804,8 +739,6 @@ QSGGeometryNode* QSGImageParticle::buildParticleNode()
m_spriteEngine->setCount(m_count);
}
- m_node = new QSGGeometryNode();
- m_node->setGeometry(g);
m_node->setMaterial(m_material);
m_last_particle = 0;
@@ -818,9 +751,9 @@ QSGNode *QSGImageParticle::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
if(m_pleaseReset){
if(m_node){
if(perfLevel == 1){
- qDebug() << "Beta";
- m_lastData = qMalloc(m_count*sizeof(SimpleVertices));//TODO: Account for count_changed possibility
- memcpy(m_lastData, m_node->geometry()->vertexData(), m_count * sizeof(SimpleVertices));//TODO: Multiple levels
+ m_lastCount = m_node->geometry()->vertexCount() / 4;
+ m_lastData = qMalloc(m_lastCount*sizeof(SimpleVertices));
+ memcpy(m_lastData, m_node->geometry()->vertexData(), m_lastCount * sizeof(SimpleVertices));//TODO: Multiple levels
}
m_lastLevel = perfLevel;
delete m_node;
@@ -845,7 +778,7 @@ QSGNode *QSGImageParticle::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
void QSGImageParticle::prepareNextFrame()
{
- if (m_node == 0){ //TODO: Staggered loading (as emitted)
+ if (m_node == 0){//TODO: Staggered loading (as emitted)
m_node = buildParticleNode();
if(m_node == 0)
return;
@@ -876,67 +809,14 @@ void QSGImageParticle::prepareNextFrame()
}
}
-template <typename VT>
-IntermediateVertices* transplant(IntermediateVertices* iv, VT &v)
-{//Deliberate typemangling cast
- iv->v1 = (UltraVertex*)&(v.v1);
- iv->v2 = (UltraVertex*)&(v.v2);
- iv->v3 = (UltraVertex*)&(v.v3);
- iv->v4 = (UltraVertex*)&(v.v4);
- return iv;
-}
-
-IntermediateVertices* QSGImageParticle::fetchIntermediateVertices(int pos)
-{
- //Note that this class ruins typesafety for you. Maybe even thread safety.
- //TODO: Something better, possibly with templates or inheritance
- static IntermediateVertices iv;
- SimpleVertices *sv;
- UltraVertices *uv;
- switch(perfLevel){
- case Simple:
- sv = (SimpleVertices *) m_node->geometry()->vertexData();
- return transplant(&iv, sv[pos]);
- case Coloured:
- case Deformable:
- case Tabled:
- case Sprites:
- default:
- uv = (UltraVertices *) m_node->geometry()->vertexData();
- return transplant(&iv,uv[pos]);
- }
-}
-
void QSGImageParticle::reloadColor(const Color4ub &c, QSGParticleData* d)
{
- UltraVertices *particles = (UltraVertices *) m_node->geometry()->vertexData();
- int pos = particleTypeIndex(d);
- UltraVertices &p = particles[pos];
- p.v1.color = p.v2.color = p.v3.color = p.v4.color = c;
-}
-
-void QSGImageParticle::reload(QSGParticleData *d)
-{
- if (m_node == 0)
- return;
-
- int pos = particleTypeIndex(d);
- IntermediateVertices* p = fetchIntermediateVertices(pos);
-
- //Perhaps we could be more efficient?
- vertexCopy(*p->v1, d->pv);
- vertexCopy(*p->v2, d->pv);
- vertexCopy(*p->v3, d->pv);
- vertexCopy(*p->v4, d->pv);
+ d->color = c;
+ //TODO: get index for reload - or make function take an index
}
-void QSGImageParticle::load(QSGParticleData *d)
+void QSGImageParticle::initialize(int idx)
{
- if (m_node == 0)
- return;
-
- int pos = particleTypeIndex(d);
- IntermediateVertices* p = fetchIntermediateVertices(pos);//Remember this removes typesafety!
Color4ub color;
qreal redVariation = m_color_variation + m_redVariation;
qreal greenVariation = m_color_variation + m_greenVariation;
@@ -944,50 +824,111 @@ void QSGImageParticle::load(QSGParticleData *d)
switch(perfLevel){//Fall-through is intended on all of them
case Sprites:
// Initial Sprite State
- p->v1->animT = p->v2->animT = p->v3->animT = p->v4->animT = p->v1->t;
- p->v1->animIdx = p->v2->animIdx = p->v3->animIdx = p->v4->animIdx = 0;
+ m_data[idx]->animT = m_data[idx]->t;
+ m_data[idx]->animIdx = 0;
if(m_spriteEngine){
- m_spriteEngine->startSprite(pos);
- p->v1->frameCount = p->v2->frameCount = p->v3->frameCount = p->v4->frameCount = m_spriteEngine->spriteFrames(pos);
- p->v1->frameDuration = p->v2->frameDuration = p->v3->frameDuration = p->v4->frameDuration = m_spriteEngine->spriteDuration(pos);
+ m_spriteEngine->startSprite(idx);
+ m_data[idx]->frameCount = m_spriteEngine->spriteFrames(idx);
+ m_data[idx]->frameDuration = m_spriteEngine->spriteDuration(idx);
}else{
- p->v1->frameCount = p->v2->frameCount = p->v3->frameCount = p->v4->frameCount = 1;
- p->v1->frameDuration = p->v2->frameDuration = p->v3->frameDuration = p->v4->frameDuration = 9999;
+ m_data[idx]->frameCount = 1;
+ m_data[idx]->frameDuration = 9999;
}
case Tabled:
case Deformable:
//Initial Rotation
if(m_xVector){
- const QPointF &ret = m_xVector->sample(QPointF(d->pv.x, d->pv.y));
- p->v1->xx = p->v2->xx = p->v3->xx = p->v4->xx = ret.x();
- p->v1->xy = p->v2->xy = p->v3->xy = p->v4->xy = ret.y();
+ const QPointF &ret = m_xVector->sample(QPointF(m_data[idx]->x, m_data[idx]->y));
+ m_data[idx]->xx = ret.x();
+ m_data[idx]->xy = ret.y();
}
if(m_yVector){
- const QPointF &ret = m_yVector->sample(QPointF(d->pv.x, d->pv.y));
- p->v1->yx = p->v2->yx = p->v3->yx = p->v4->yx = ret.x();
- p->v1->yy = p->v2->yy = p->v3->yy = p->v4->yy = ret.y();
+ const QPointF &ret = m_yVector->sample(QPointF(m_data[idx]->x, m_data[idx]->y));
+ m_data[idx]->yx = ret.x();
+ m_data[idx]->yy = ret.y();
}
- p->v1->rotation = p->v2->rotation = p->v3->rotation = p->v4->rotation =
+ m_data[idx]->rotation =
(m_rotation + (m_rotationVariation - 2*((qreal)rand()/RAND_MAX)*m_rotationVariation) ) * CONV;
- p->v1->rotationSpeed = p->v2->rotationSpeed = p->v3->rotationSpeed = p->v4->rotationSpeed =
+ m_data[idx]->rotationSpeed =
(m_rotationSpeed + (m_rotationSpeedVariation - 2*((qreal)rand()/RAND_MAX)*m_rotationSpeedVariation) ) * CONV;
- p->v1->autoRotate = p->v2->autoRotate = p->v3->autoRotate = p->v4->autoRotate = m_autoRotation?1.0:0.0;
- case Coloured:
+ m_data[idx]->autoRotate = m_autoRotation?1.0:0.0;
+ case Colored:
//Color initialization
// Particle color
color.r = m_color.red() * (1 - redVariation) + rand() % 256 * redVariation;
color.g = m_color.green() * (1 - greenVariation) + rand() % 256 * greenVariation;
color.b = m_color.blue() * (1 - blueVariation) + rand() % 256 * blueVariation;
color.a = m_alpha * m_color.alpha() * (1 - m_alphaVariation) + rand() % 256 * m_alphaVariation;
- p->v1->color = p->v2->color = p->v3->color = p->v4->color = color;
+ m_data[idx]->color = color;
default:
break;
}
+}
+
+void QSGImageParticle::reload(int idx)
+{
+ if(!m_node)
+ return;
+
+ m_node->setFlag(QSGNode::OwnsGeometry, false);
+ UltraVertex *ultraVertices = (UltraVertex *) m_node->geometry()->vertexData();
+ SimpleVertex *simpleVertices = (SimpleVertex *) m_node->geometry()->vertexData();
+ switch(perfLevel){
+ case Sprites:
+ ultraVertices += idx*4;
+ for(int i=0; i<4; i++){
+ ultraVertices[i].x = m_data[idx]->x - m_systemOffset.x();
+ ultraVertices[i].y = m_data[idx]->y - m_systemOffset.y();
+ ultraVertices[i].t = m_data[idx]->t;
+ ultraVertices[i].lifeSpan = m_data[idx]->lifeSpan;
+ ultraVertices[i].size = m_data[idx]->size;
+ ultraVertices[i].endSize = m_data[idx]->endSize;
+ ultraVertices[i].sx = m_data[idx]->sx;
+ ultraVertices[i].sy = m_data[idx]->sy;
+ ultraVertices[i].ax = m_data[idx]->ax;
+ ultraVertices[i].ay = m_data[idx]->ay;
+ ultraVertices[i].xx = m_data[idx]->xx;
+ ultraVertices[i].xy = m_data[idx]->xy;
+ ultraVertices[i].yx = m_data[idx]->yx;
+ ultraVertices[i].yy = m_data[idx]->yy;
+ ultraVertices[i].rotation = m_data[idx]->rotation;
+ ultraVertices[i].rotationSpeed = m_data[idx]->rotationSpeed;
+ ultraVertices[i].autoRotate = m_data[idx]->autoRotate;
+ ultraVertices[i].animIdx = m_data[idx]->animIdx;
+ ultraVertices[i].frameDuration = m_data[idx]->frameDuration;
+ ultraVertices[i].frameCount = m_data[idx]->frameCount;
+ ultraVertices[i].animT = m_data[idx]->animT;
+ ultraVertices[i].color.r = m_data[idx]->color.r;
+ ultraVertices[i].color.g = m_data[idx]->color.g;
+ ultraVertices[i].color.b = m_data[idx]->color.b;
+ ultraVertices[i].color.a = m_data[idx]->color.a;
+ }
+ break;
+ case Tabled://TODO: Us
+ case Deformable:
+ case Colored:
+ case Simple:
+ simpleVertices += idx*4;
+ for(int i=0; i<4; i++){
+ simpleVertices[i].x = m_data[idx]->x - m_systemOffset.x();
+ simpleVertices[i].y = m_data[idx]->y - m_systemOffset.y();
+ simpleVertices[i].t = m_data[idx]->t;
+ simpleVertices[i].lifeSpan = m_data[idx]->lifeSpan;
+ simpleVertices[i].size = m_data[idx]->size;
+ simpleVertices[i].endSize = m_data[idx]->endSize;
+ simpleVertices[i].sx = m_data[idx]->sx;
+ simpleVertices[i].sy = m_data[idx]->sy;
+ simpleVertices[i].ax = m_data[idx]->ax;
+ simpleVertices[i].ay = m_data[idx]->ay;
+ }
+ break;
+ default:
+ break;
+ }
- vertexCopy(*p->v1, d->pv);
- vertexCopy(*p->v2, d->pv);
- vertexCopy(*p->v3, d->pv);
- vertexCopy(*p->v4, d->pv);
+ m_node->setFlag(QSGNode::OwnsGeometry, true);
}
+
+
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgimageparticle_p.h b/src/declarative/particles/qsgimageparticle_p.h
index c6ec4c2c6a..dc79c5910e 100644
--- a/src/declarative/particles/qsgimageparticle_p.h
+++ b/src/declarative/particles/qsgimageparticle_p.h
@@ -57,13 +57,6 @@ class QSGGeometryNode;
class QSGSprite;
class QSGSpriteEngine;
-struct Color4ub {
- uchar r;
- uchar g;
- uchar b;
- uchar a;
-};
-
struct SimpleVertex {
float x;
float y;
@@ -165,9 +158,6 @@ public:
explicit QSGImageParticle(QSGItem *parent = 0);
virtual ~QSGImageParticle(){}
- virtual void load(QSGParticleData*);
- virtual void reload(QSGParticleData*);
- virtual void setCount(int c);
QDeclarativeListProperty<QSGSprite> sprites();
QSGSpriteEngine* spriteEngine() {return m_spriteEngine;}
@@ -175,7 +165,7 @@ public:
enum PerformanceLevel{//TODO: Expose?
Unknown = 0,
Simple,
- Coloured,
+ Colored,
Deformable,
Tabled,
Sprites
@@ -293,8 +283,11 @@ public slots:
void setBloat(bool arg);
protected:
- QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
void reset();
+ virtual void initialize(int idx);
+ virtual void reload(int idx);
+
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
void prepareNextFrame();
QSGGeometryNode* buildParticleNode();
QSGGeometryNode* buildSimpleParticleNode();
@@ -303,8 +296,6 @@ private slots:
void createEngine(); //### method invoked by sprite list changing (in engine.h) - pretty nasty
private:
- //void vertexCopy(UltraVertex &b,const ParticleVertex& a);
- IntermediateVertices* fetchIntermediateVertices(int pos);
bool m_do_reset;
QUrl m_image_name;
@@ -345,6 +336,7 @@ private:
PerformanceLevel m_lastLevel;
void* m_lastData;
+ int m_lastCount;
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgitemparticle.cpp b/src/declarative/particles/qsgitemparticle.cpp
index 42f0062148..5e324cd43d 100644
--- a/src/declarative/particles/qsgitemparticle.cpp
+++ b/src/declarative/particles/qsgitemparticle.cpp
@@ -85,11 +85,13 @@ void QSGItemParticle::give(QSGItem *item)
//TODO: This
}
-void QSGItemParticle::load(QSGParticleData* d)
+void QSGItemParticle::initialize(int idx)
+{
+ m_loadables << idx;//defer to other thread
+}
+
+void QSGItemParticle::reload(int idx)
{
- int pos = particleTypeIndex(d);
- m_data[pos] = d;
- m_loadables << pos;
}
void QSGItemParticle::tick()
@@ -106,63 +108,43 @@ void QSGItemParticle::tick()
m_deletables.clear();
foreach(int pos, m_loadables){
- if(m_stasis.contains(m_items[pos]))
+ if(m_stasis.contains(m_data[pos]->delegate))
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];
+ if(m_data[pos]->delegate){
+ m_deletables << m_data[pos]->delegate;
m_activeCount--;
}
- m_items[pos] = 0;
+ m_data[pos]->delegate = 0;
if(!m_pendingItems.isEmpty()){
- m_items[pos] = m_pendingItems.front();
+ m_data[pos]->delegate = m_pendingItems.front();
m_pendingItems.pop_front();
}else if(m_delegate){
- m_items[pos] = qobject_cast<QSGItem*>(m_delegate->create(qmlContext(this)));
+ m_data[pos]->delegate = qobject_cast<QSGItem*>(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<QSGItemParticleAttached*>(qmlAttachedPropertiesObject<QSGItemParticle>(m_items[pos]));
+ if(m_data[pos]->delegate && m_data[pos]){//###Data can be zero if creating an item leads to a reset - this screws things up.
+ m_data[pos]->delegate->setX(m_data[pos]->curX() - m_data[pos]->delegate->width()/2);//TODO: adjust for system?
+ m_data[pos]->delegate->setY(m_data[pos]->curY() - m_data[pos]->delegate->height()/2);
+ QSGItemParticleAttached* mpa = qobject_cast<QSGItemParticleAttached*>(qmlAttachedPropertiesObject<QSGItemParticle>(m_data[pos]->delegate));
if(mpa){
mpa->m_mp = this;
mpa->attach();
}
- m_items[pos]->setParentItem(this);
+ m_data[pos]->delegate->setParentItem(this);
if(m_fade)
- m_items[pos]->setOpacity(0.);
+ m_data[pos]->delegate->setOpacity(0.);
m_activeCount++;
}
}
m_loadables.clear();
}
-void QSGItemParticle::reload(QSGParticleData* d)
-{
- //No-op unless we start copying the data.
-}
-
-void QSGItemParticle::setCount(int c)
-{
- QSGParticlePainter::setCount(c);//###Do we need our own?
- m_particleCount = c;
- reset();
-}
-
-int QSGItemParticle::count()
-{
- return m_particleCount;
-}
-
void QSGItemParticle::reset()
{
QSGParticlePainter::reset();
//TODO: Cleanup items?
- m_items.resize(m_particleCount);
- m_data.resize(m_particleCount);
- m_items.fill(0);
- m_data.fill(0);
- //m_pendingItems.clear();//TODO: Should this be done? If so, Emit signal?
+ m_loadables.clear();
+ //deletables?
}
@@ -191,20 +173,19 @@ void QSGItemParticle::prepareNextFrame()
return;
//TODO: Size, better fade?
- for(int i=0; i<m_particleCount; i++){
- QSGItem* item = m_items[i];
+ for(int i=0; i<count(); i++){
QSGParticleData* data = m_data[i];
- if(!item || !data)
+ QSGItem* item = data->delegate;
+ if(!item)
continue;
- qreal t = ((timeStamp/1000.0) - data->pv.t) / data->pv.lifeSpan;
+ qreal t = ((timeStamp/1000.0) - data->t) / data->lifeSpan;
if(m_stasis.contains(item)) {
- m_data[i]->pv.t += dt;//Stasis effect
+ m_data[i]->t += dt;//Stasis effect
continue;
}
if(t >= 1.0){//Usually happens from load
m_deletables << item;
- m_items[i] = 0;
- m_data[i] = 0;
+ m_data[i]->delegate = 0;
m_activeCount--;
}else{//Fade
if(m_fade){
@@ -218,8 +199,8 @@ void QSGItemParticle::prepareNextFrame()
item->setOpacity(1.);//###Without fade, it's just a binary toggle - if we turn it off we have to turn it back on
}
}
- item->setX(data->curX() - item->width()/2);
- item->setY(data->curY() - item->height()/2);
+ item->setX(data->curX() - item->width()/2 - m_systemOffset.x());
+ item->setY(data->curY() - item->height()/2 - m_systemOffset.y());
}
}
diff --git a/src/declarative/particles/qsgitemparticle_p.h b/src/declarative/particles/qsgitemparticle_p.h
index 3b7db519de..24bbcf97d8 100644
--- a/src/declarative/particles/qsgitemparticle_p.h
+++ b/src/declarative/particles/qsgitemparticle_p.h
@@ -63,10 +63,6 @@ public:
bool fade() const { return m_fade; }
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- virtual void load(QSGParticleData*);
- virtual void reload(QSGParticleData*);
- virtual void setCount(int c);
- virtual int count();
static QSGItemParticleAttached *qmlAttachedProperties(QObject *object);
QDeclarativeComponent* delegate() const
@@ -97,19 +93,17 @@ public slots:
protected:
virtual void reset();
+ virtual void reload(int idx);
+ virtual void initialize(int idx);
void prepareNextFrame();
private slots:
void tick();
private:
QList<QSGItem* > m_deletables;
QList< int > m_loadables;
- int m_particleCount;
bool m_fade;
QList<QSGItem*> m_pendingItems;
- QVector<QSGItem*> m_items;
- QVector<QSGParticleData*> m_data;
- QVector<int> m_idx;
QList<int> m_available;
QSet<QSGItem*> m_stasis;
qreal m_lastT;
diff --git a/src/declarative/particles/qsgkill.cpp b/src/declarative/particles/qsgkill.cpp
index 1321898dc9..eb3a55d402 100644
--- a/src/declarative/particles/qsgkill.cpp
+++ b/src/declarative/particles/qsgkill.cpp
@@ -52,7 +52,7 @@ bool QSGKillAffector::affectParticle(QSGParticleData *d, qreal dt)
{
Q_UNUSED(dt);
if(d->stillAlive()){
- d->pv.t -= d->pv.lifeSpan + 1;
+ d->t -= d->lifeSpan + 1;
return true;
}
}
diff --git a/src/declarative/particles/qsgmodelparticle.cpp b/src/declarative/particles/qsgmodelparticle.cpp
index f87c0d31b9..47b8844ad5 100644
--- a/src/declarative/particles/qsgmodelparticle.cpp
+++ b/src/declarative/particles/qsgmodelparticle.cpp
@@ -149,26 +149,13 @@ void QSGModelParticle::unfreeze(QSGItem* item)
m_stasis.remove(item);
}
-void QSGModelParticle::load(QSGParticleData* d)
+void QSGModelParticle::initialize(int idx)
{
if(!m_model || !m_model->count())
return;
- int pos = particleTypeIndex(d);
if(m_available.isEmpty())
return;
- 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_deletables << m_items[pos];
- m_available << m_idx[pos];
- m_idx[pos] = -1;
- m_items[pos] = 0;
- m_data[pos] = 0;
- m_activeCount--;
- }
- m_requests << pos;
- m_data[pos] = d;
+ m_requests << idx;
m_activeCount++;
}
@@ -181,48 +168,42 @@ void QSGModelParticle::processPending()
m_deletables.clear();
foreach(int pos, m_requests){
+ if(m_data[pos]->delegate){
+ if(m_stasis.contains(m_data[pos]->delegate))
+ qWarning() << "Current model particles prefers overwrite:false";
+ //remove old item from the particle that is dying to make room for this one
+ m_deletables << m_data[pos]->delegate;
+ m_available << m_data[pos]->modelIndex;
+ m_data[pos]->modelIndex = -1;
+ m_data[pos]->delegate = 0;
+ m_data[pos] = 0;
+ m_activeCount--;
+ }
+
if(!m_available.isEmpty()){
- m_items[pos] = m_model->item(m_available.first());
- m_idx[pos] = m_available.first();
+ m_data[pos]->delegate = m_model->item(m_available.first());
+ m_data[pos]->modelIndex = m_available.first();
m_available.pop_front();
- QSGModelParticleAttached* mpa = qobject_cast<QSGModelParticleAttached*>(qmlAttachedPropertiesObject<QSGModelParticle>(m_items[pos]));
+ QSGModelParticleAttached* mpa = qobject_cast<QSGModelParticleAttached*>(qmlAttachedPropertiesObject<QSGModelParticle>(m_data[pos]->delegate));
if(mpa){
mpa->m_mp = this;
mpa->attach();
}
- m_items[pos]->setParentItem(this);
+ m_data[pos]->delegate->setParentItem(this);
}
}
m_requests.clear();
}
-void QSGModelParticle::reload(QSGParticleData* d)
+void QSGModelParticle::reload(int idx)
{
//No-op unless we start copying the data.
}
-void QSGModelParticle::setCount(int c)
-{
- QSGParticlePainter::setCount(c);//###Do we need our own?
- m_particleCount = c;
- reset();
-}
-
-int QSGModelParticle::count()
-{
- return m_particleCount;
-}
-
void QSGModelParticle::reset()
{
QSGParticlePainter::reset();
//TODO: Cleanup items?
- m_items.resize(m_particleCount);
- m_data.resize(m_particleCount);
- m_idx.resize(m_particleCount);
- m_items.fill(0);
- m_data.fill(0);
- m_idx.fill(-1);
//m_available.clear();//Should this be reset too?
//m_pendingItems.clear();//TODO: Should this be done? If so, Emit signal?
}
@@ -253,21 +234,20 @@ void QSGModelParticle::prepareNextFrame()
return;
//TODO: Size, better fade?
- for(int i=0; i<m_particleCount; i++){
- QSGItem* item = m_items[i];
+ for(int i=0; i<count(); i++){
QSGParticleData* data = m_data[i];
- if(!item || !data)
+ if(!data->delegate)
continue;
- qreal t = ((timeStamp/1000.0) - data->pv.t) / data->pv.lifeSpan;
- if(m_stasis.contains(item)) {
- m_data[i]->pv.t += dt;//Stasis effect
+ qreal t = ((timeStamp/1000.0) - data->t) / data->lifeSpan;
+ if(m_stasis.contains(m_data[i]->delegate)) {
+ m_data[i]->t += dt;//Stasis effect
continue;
}
if(t >= 1.0){//Usually happens from load
- m_available << m_idx[i];
- m_deletables << item;
- m_idx[i] = -1;
- m_items[i] = 0;
+ m_available << m_data[i]->modelIndex;
+ m_deletables << m_data[i]->delegate;
+ m_data[i]->modelIndex = -1;
+ m_data[i]->delegate = 0;
m_data[i] = 0;
m_activeCount--;
}else{//Fade
@@ -277,13 +257,13 @@ void QSGModelParticle::prepareNextFrame()
o = t*5;
if(t>0.8)
o = (1-t)*5;
- item->setOpacity(o);
+ m_data[i]->delegate->setOpacity(o);
}else{
- item->setOpacity(1.);//###Without fade, it's just a binary toggle - if we turn it off we have to turn it back on
+ m_data[i]->delegate->setOpacity(1.);//###Without fade, it's just a binary toggle - if we turn it off we have to turn it back on
}
}
- item->setX(data->curX() - item->width()/2);
- item->setY(data->curY() - item->height()/2);
+ m_data[i]->delegate->setX(data->curX() - m_data[i]->delegate->width()/2 - m_systemOffset.x());
+ m_data[i]->delegate->setY(data->curY() - m_data[i]->delegate->height()/2 - m_systemOffset.y());
}
}
diff --git a/src/declarative/particles/qsgmodelparticle_p.h b/src/declarative/particles/qsgmodelparticle_p.h
index 04533a73ce..31e4025bb4 100644
--- a/src/declarative/particles/qsgmodelparticle_p.h
+++ b/src/declarative/particles/qsgmodelparticle_p.h
@@ -74,10 +74,6 @@ public:
bool fade() const { return m_fade; }
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- virtual void load(QSGParticleData*);
- virtual void reload(QSGParticleData*);
- virtual void setCount(int c);
- virtual int count();
static QSGModelParticleAttached *qmlAttachedProperties(QObject *object);
signals:
@@ -93,6 +89,8 @@ public slots:
void setFade(bool arg){if(arg == m_fade) return; m_fade = arg; emit fadeChanged();}
protected:
virtual void reset();
+ virtual void reload(int idx);
+ virtual void initialize(int idx);
void prepareNextFrame();
private slots:
void updateCount();
@@ -104,13 +102,9 @@ private:
QVariant m_dataSource;
QList<QSGItem*> m_deletables;
QList< int > m_requests;
- int m_particleCount;
bool m_fade;
QList<QSGItem*> m_pendingItems;
- QVector<QSGItem*> m_items;
- QVector<QSGParticleData*> m_data;
- QVector<int> m_idx;
QList<int> m_available;
QSet<QSGItem*> m_stasis;
qreal m_lastT;
diff --git a/src/declarative/particles/qsgparticleaffector.cpp b/src/declarative/particles/qsgparticleaffector.cpp
index 96c5cfb25b..5b0936cc40 100644
--- a/src/declarative/particles/qsgparticleaffector.cpp
+++ b/src/declarative/particles/qsgparticleaffector.cpp
@@ -79,22 +79,22 @@ void QSGParticleAffector::affectSystem(qreal dt)
m_groups << m_system->m_groupIds[p];//###Can this occur before group ids are properly assigned?
m_updateIntSet = false;
}
- //foreach(ParticleData* d, m_system->m_data){
- for(int i=0; i<m_system->m_particle_count; i++){
- QSGParticleData* d = m_system->m_data[i];
- if(!d || (m_onceOff && m_onceOffed.contains(d->systemIndex)))
- continue;
- if(m_groups.isEmpty() || m_groups.contains(d->group)){
- //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());
+ foreach(QSGParticleGroupData* gd, m_system->m_groupData){
+ foreach(QSGParticleData* d, gd->data){
+ if(!d || (m_onceOff && m_onceOffed.contains(qMakePair(d->group, d->index))))
+ continue;
+ if(m_groups.isEmpty() || m_groups.contains(d->group)){
+ //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 << qMakePair(d->group, d->index);
+ if(m_signal)
+ emit affected(curPos.x(), curPos.y());
+ }
}
}
}
@@ -108,10 +108,10 @@ bool QSGParticleAffector::affectParticle(QSGParticleData *d, qreal dt)
return false;
}
-void QSGParticleAffector::reset(int idx)
+void QSGParticleAffector::reset(QSGParticleData* pd)
{//TODO: This, among other ones, should be restructured so they don't all need to remember to call the superclass
if(m_onceOff)
- m_onceOffed.remove(idx);
+ m_onceOffed.remove(qMakePair(pd->group, pd->index));
}
void QSGParticleAffector::updateOffsets()
diff --git a/src/declarative/particles/qsgparticleaffector_p.h b/src/declarative/particles/qsgparticleaffector_p.h
index b299158069..7418760941 100644
--- a/src/declarative/particles/qsgparticleaffector_p.h
+++ b/src/declarative/particles/qsgparticleaffector_p.h
@@ -65,7 +65,7 @@ class QSGParticleAffector : public QSGItem
public:
explicit QSGParticleAffector(QSGItem *parent = 0);
virtual void affectSystem(qreal dt);
- virtual void reset(int systemIdx);//As some store their own data per idx?
+ virtual void reset(QSGParticleData*);//As some store their own data per particle?
QSGParticleSystem* system() const
{
return m_system;
@@ -108,7 +108,7 @@ signals:
void shapeChanged(QSGParticleExtruder* arg);
- void affected(qreal x, qreal y);//###Idx too?
+ void affected(qreal x, qreal y);
void signalChanged(bool arg);
public slots:
@@ -174,7 +174,7 @@ protected:
QPointF m_offset;
private:
QSet<int> m_groups;
- QSet<int> m_onceOffed;
+ QSet<QPair<int, int> > m_onceOffed;
bool m_updateIntSet;
bool m_onceOff;
diff --git a/src/declarative/particles/qsgparticlepainter.cpp b/src/declarative/particles/qsgparticlepainter.cpp
index a5e8c0a3e6..cf1d3c2894 100644
--- a/src/declarative/particles/qsgparticlepainter.cpp
+++ b/src/declarative/particles/qsgparticlepainter.cpp
@@ -44,7 +44,7 @@
QT_BEGIN_NAMESPACE
QSGParticlePainter::QSGParticlePainter(QSGItem *parent) :
QSGItem(parent),
- m_system(0)
+ m_system(0), m_count(0), m_lastStart(0), m_sentinel(new QSGParticleData)
{
connect(this, SIGNAL(xChanged()),
this, SLOT(calcSystemOffset()));
@@ -67,7 +67,7 @@ void QSGParticlePainter::setSystem(QSGParticleSystem *arg)
if (m_system != arg) {
m_system = arg;
if(m_system){
- m_system->registerParticleType(this);
+ m_system->registerParticlePainter(this);
connect(m_system, SIGNAL(xChanged()),
this, SLOT(calcSystemOffset()));
connect(m_system, SIGNAL(yChanged()),
@@ -78,26 +78,81 @@ void QSGParticlePainter::setSystem(QSGParticleSystem *arg)
}
}
-void QSGParticlePainter::load(QSGParticleData*)
+void QSGParticlePainter::load(QSGParticleData* d)
{
+ int idx = particleTypeIndex(d);
+ m_data[idx] = d;
+ initialize(idx);
+ reload(idx);
}
-void QSGParticlePainter::reload(QSGParticleData*)
+void QSGParticlePainter::reload(QSGParticleData* d)
{
+ reload(particleTypeIndex(d));
}
void QSGParticlePainter::reset()
{
//Have to every time because what it's emitting may have changed and that affects particleTypeIndex
+ if(m_system && !m_inResize)
+ resize(0,1);//###Fix this by making resize take sensible arguments
+ //###This also means double resets. Make reset not virtual?
+}
+
+void QSGParticlePainter::resize(int oldSize, int newSize)
+{
+ if(newSize == oldSize)//TODO: What if particles switched so indices change but total count is the same?
+ return;
+
+ QHash<int, QPair<int, int> > oldStarts(m_particleStarts);
+ //Update particle starts datastore
m_particleStarts.clear();
m_lastStart = 0;
+ QList<int> particleList;
+ if(m_particles.isEmpty())
+ particleList << 0;
+ foreach(const QString &s, m_particles)
+ particleList << m_system->m_groupIds[s];
+ foreach(int gIdx, particleList){
+ QSGParticleGroupData *gd = m_system->m_groupData[gIdx];
+ m_particleStarts.insert(gIdx, qMakePair<int, int>(gd->size, m_lastStart));
+ m_lastStart += gd->size;
+ }
+
+ //Shuffle stuff around
+ //TODO: In place shuffling because it's faster
+ QVector<QSGParticleData*> oldData(m_data);
+ QVector<QObject*> oldAttached(m_attachedData);
+ m_data.clear();
+ m_data.resize(m_count);
+ m_attachedData.resize(m_count);
+ foreach(int gIdx, particleList){
+ QSGParticleGroupData *gd = m_system->m_groupData[gIdx];
+ for(int i=0; i<gd->data.size(); i++){//TODO: When group didn't exist before
+ int newIdx = m_particleStarts[gIdx].second + i;
+ int oldIdx = oldStarts[gIdx].second + i;
+ if(i >= oldStarts[gIdx].first || oldData.size() <= oldIdx){
+ m_data[newIdx] = m_sentinel;
+ }else{
+ m_data[newIdx] = oldData[oldIdx];
+ m_attachedData[newIdx] = oldAttached[oldIdx];
+ }
+ }
+ }
+ m_inResize = true;
+ reset();
+ m_inResize = false;
}
+
void QSGParticlePainter::setCount(int c)
{
+ Q_ASSERT(c >= 0); //XXX
if(c == m_count)
return;
+ int lastCount = m_count;
m_count = c;
+ resize(lastCount, m_count);
emit countChanged();
}
@@ -106,15 +161,11 @@ int QSGParticlePainter::count()
return m_count;
}
-
int QSGParticlePainter::particleTypeIndex(QSGParticleData* d)
{
- if(!m_particleStarts.contains(d->group)){
- m_particleStarts.insert(d->group, m_lastStart);
- m_lastStart += m_system->m_groupData[d->group]->size;
- }
- int ret = m_particleStarts[d->group] + d->particleIndex;
- Q_ASSERT(ret >=0 && ret < m_count);//XXX: Possibly shouldn't assert, but bugs here were hard to find in the past
+ Q_ASSERT(d && m_particleStarts.contains(d->group));//XXX
+ int ret = m_particleStarts[d->group].second + d->index;
+ Q_ASSERT(ret >=0 && ret < m_count);//XXX:shouldn't assert, but bugs here were hard to find in the past
return ret;
}
@@ -129,8 +180,8 @@ void QSGParticlePainter::calcSystemOffset()
//Reload all particles//TODO: Necessary?
foreach(const QString &g, m_particles){
int gId = m_system->m_groupIds[g];
- for(int i=0; i<m_system->m_groupData[gId]->size; i++)
- reload(m_system->m_data[m_system->m_groupData[gId]->start + i]);
+ foreach(QSGParticleData* d, m_system->m_groupData[gId]->data)
+ reload(d);
}
}
}
diff --git a/src/declarative/particles/qsgparticlepainter_p.h b/src/declarative/particles/qsgparticlepainter_p.h
index 8f1e13b70f..e506018f53 100644
--- a/src/declarative/particles/qsgparticlepainter_p.h
+++ b/src/declarative/particles/qsgparticlepainter_p.h
@@ -61,10 +61,11 @@ class QSGParticlePainter : public QSGItem
public:
explicit QSGParticlePainter(QSGItem *parent = 0);
- virtual void load(QSGParticleData*);
- virtual void reload(QSGParticleData*);
- virtual void setCount(int c);
- virtual int count();
+ //Data Interface to system
+ void load(QSGParticleData*);
+ void reload(QSGParticleData*);
+ void setCount(int c);
+ int count();
QSGParticleSystem* system() const
{
return m_system;
@@ -76,7 +77,6 @@ public:
return m_particles;
}
- int particleTypeIndex(QSGParticleData*);
signals:
void countChanged();
void systemChanged(QSGParticleSystem* arg);
@@ -95,40 +95,38 @@ void setParticles(QStringList arg)
}
private slots:
void calcSystemOffset();
+
protected:
+ /* Reset resets all your internal data structures. But anything attached to a particle should
+ be in attached data. So reset + reloads should have no visible effect.
+ ###Hunt down all cases where we do a complete reset for convenience and be more targeted
+ */
virtual void reset();
- virtual void componentComplete();
-// virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *){
-// qDebug() << "Shouldn't be here..." << this;
-// return 0;
-// }
+ virtual void componentComplete();
+ //Data interface to painters
+ QVector<QSGParticleData*> m_data; //Actually stored in arbitrary order,
+ QVector<QObject*> m_attachedData; //This data will be moved along with m_data in resizes (but you own it)
+ virtual void initialize(int){}
+ virtual void reload(int){}//If you need to do something on size changed, check m_data size in this? Or we reset you every time?
QSGParticleSystem* m_system;
friend class QSGParticleSystem;
int m_count;
bool m_pleaseReset;
QStringList m_particles;
- QHash<int,int> m_particleStarts;
- int m_lastStart;
QPointF m_systemOffset;
- template <typename VertexStruct>
- void vertexCopy(VertexStruct &b, const ParticleVertex& a)
- {
- b.x = a.x - m_systemOffset.x();
- b.y = a.y - m_systemOffset.y();
- b.t = a.t;
- b.lifeSpan = a.lifeSpan;
- b.size = a.size;
- b.endSize = a.endSize;
- b.sx = a.sx;
- b.sy = a.sy;
- b.ax = a.ax;
- b.ay = a.ay;
- }
private:
+ int m_lastStart;
+ QHash<int, QPair<int, int> > m_particleStarts;
+ int particleTypeIndex(QSGParticleData* d);//Now private
+ void resize(int, int);
+
+ QSGParticleData* m_sentinel;
+ //QVector<QSGParticleData*> m_shadowData;//For when we implement overwrite: false
+ bool m_inResize;
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticlesystem.cpp b/src/declarative/particles/qsgparticlesystem.cpp
index 4a8f75bb04..2dc21299cf 100644
--- a/src/declarative/particles/qsgparticlesystem.cpp
+++ b/src/declarative/particles/qsgparticlesystem.cpp
@@ -52,18 +52,35 @@ QT_BEGIN_NAMESPACE
QSGParticleData::QSGParticleData()
: group(0)
, e(0)
- , particleIndex(0)
- , systemIndex(0)
+ , index(0)
{
- pv.x = 0;
- pv.y = 0;
- pv.t = -1;
- pv.size = 0;
- pv.endSize = 0;
- pv.sx = 0;
- pv.sy = 0;
- pv.ax = 0;
- pv.ay = 0;
+ x = 0;
+ y = 0;
+ t = -1;
+ size = 0;
+ endSize = 0;
+ sx = 0;
+ sy = 0;
+ ax = 0;
+ ay = 0;
+ xx = 1;
+ xy = 0;
+ yx = 0;
+ yy = 1;
+ rotation = 0;
+ rotationSpeed = 0;
+ autoRotate = 0;
+ animIdx = -1;
+ frameDuration = 1;
+ frameCount = 0;
+ animT = -1;
+ color.r = 255;
+ color.g = 255;
+ color.b = 255;
+ color.a = 255;
+ r = 0;
+ delegate = 0;
+ modelIndex = -1;
}
QSGParticleSystem::QSGParticleSystem(QSGItem *parent) :
@@ -71,174 +88,202 @@ QSGParticleSystem::QSGParticleSystem(QSGItem *parent) :
, m_startTime(0), m_overwrite(false)
, m_componentComplete(false)
{
- m_groupIds = QHash<QString, int>();
+ QSGParticleGroupData* gd = new QSGParticleGroupData;//Default group
+ m_groupData.insert(0,gd);
+ m_groupIds.insert("",0);
+ m_nextGroupId = 1;
+
+ connect(&m_painterMapper, SIGNAL(mapped(QObject*)),
+ this, SLOT(loadPainter(QObject*)));
}
-void QSGParticleSystem::registerParticleType(QSGParticlePainter* p)
+void QSGParticleSystem::registerParticlePainter(QSGParticlePainter* p)
{
- m_particles << QPointer<QSGParticlePainter>(p);//###Set or uniqueness checking?
- reset();
+ //TODO: a way to Unregister emitters, painters and affectors
+ m_particlePainters << QPointer<QSGParticlePainter>(p);//###Set or uniqueness checking?
+ connect(p, SIGNAL(particlesChanged(QStringList)),
+ &m_painterMapper, SLOT(map()));
+ loadPainter(p);
+ p->update();//###Initial update here?
}
void QSGParticleSystem::registerParticleEmitter(QSGParticleEmitter* e)
{
m_emitters << QPointer<QSGParticleEmitter>(e);//###How to get them out?
connect(e, SIGNAL(particleCountChanged()),
- this, SLOT(countChanged()));
+ this, SLOT(emittersChanged()));
connect(e, SIGNAL(particleChanged(QString)),
- this, SLOT(countChanged()));
- reset();
+ this, SLOT(emittersChanged()));
+ emittersChanged();
+ e->reset();//Start, so that starttime factors appropriately
}
void QSGParticleSystem::registerParticleAffector(QSGParticleAffector* a)
{
m_affectors << QPointer<QSGParticleAffector>(a);
- //reset();//TODO: Slim down the huge batch of resets at the start
}
-void QSGParticleSystem::countChanged()
+void QSGParticleSystem::loadPainter(QObject *p)
{
- reset();//Need to give Particles new Count
-}
+ if(!m_componentComplete)
+ return;
-void QSGParticleSystem::setRunning(bool arg)
-{
- if (m_running != arg) {
- m_running = arg;
- emit runningChanged(arg);
- reset();
+ QSGParticlePainter* painter = qobject_cast<QSGParticlePainter*>(p);
+ Q_ASSERT(painter);//XXX
+ foreach(QSGParticleGroupData* sg, m_groupData)
+ sg->painters.remove(painter);
+ int particleCount = 0;
+ if(painter->particles().isEmpty()){//Uses default particle
+ particleCount += m_groupData[0]->size;
+ m_groupData[0]->painters << painter;
+ }else{
+ foreach(const QString &group, painter->particles()){
+ particleCount += m_groupData[m_groupIds[group]]->size;
+ m_groupData[m_groupIds[group]]->painters << painter;
+ }
}
+ painter->setCount(particleCount);
+ painter->update();//###Initial update here?
+ return;
}
-void QSGParticleSystem::componentComplete()
-{
- QSGItem::componentComplete();
- m_componentComplete = true;
- if(!m_emitters.isEmpty() && !m_particles.isEmpty())
- reset();
-}
-
-void QSGParticleSystem::initializeSystem()
+void QSGParticleSystem::emittersChanged()
{
- int oldCount = m_particle_count;
- m_particle_count = 0;//TODO: Only when changed?
-
- //### Reset the data too?
- for(int i=0; i<oldCount; i++){
- if(m_data[i]){
- delete m_data[i];
- m_data[i] = 0;
- }
- }
+ if(!m_componentComplete)
+ return;
- for(QHash<int, GroupData*>::iterator iter = m_groupData.begin(); iter != m_groupData.end(); iter++)
- delete (*iter);
- m_groupData.clear();
- m_groupIds.clear();
+ m_emitters.removeAll(0);
- GroupData* gd = new GroupData;//Default group
- gd->size = 0;
- gd->start = -1;
- gd->nextIdx = 0;
- m_groupData.insert(0,gd);
- m_groupIds.insert("",0);
- m_nextGroupId = 1;
+ //Recalculate all counts, as emitter 'particle' may have changed as well
+ //### Worth tracking previous 'particle' per emitter to do partial recalculations?
+ m_particle_count = 0;
- if(!m_emitters.count() || !m_particles.count())
- return;
+ int previousGroups = m_nextGroupId;
+ QVector<int> previousSizes;
+ previousSizes.resize(previousGroups);
+ for(int i=0; i<previousGroups; i++)
+ previousSizes[i] = m_groupData[i]->size;
+ for(int i=0; i<previousGroups; i++)
+ m_groupData[i]->size = 0;
- foreach(QSGParticleEmitter* e, m_emitters){
+ foreach(QSGParticleEmitter* e, m_emitters){//Populate groups and set sizes.
if(!m_groupIds.contains(e->particle())
|| (!e->particle().isEmpty() && !m_groupIds[e->particle()])){//or it was accidentally inserted by a failed lookup earlier
- GroupData* gd = new GroupData;
- gd->size = 0;
- gd->start = -1;
- gd->nextIdx = 0;
+ QSGParticleGroupData* gd = new QSGParticleGroupData;
int id = m_nextGroupId++;
m_groupIds.insert(e->particle(), id);
m_groupData.insert(id, gd);
}
m_groupData[m_groupIds[e->particle()]]->size += e->particleCount();
+ m_particle_count += e->particleCount();
+ //###: Cull emptied groups?
}
- for(QHash<int, GroupData*>::iterator iter = m_groupData.begin(); iter != m_groupData.end(); iter++){
- (*iter)->start = m_particle_count;
- m_particle_count += (*iter)->size;
- }
- m_data.resize(m_particle_count);
- for(int i=oldCount; i<m_particle_count; i++)
- m_data[i] = 0;//setup new ones
-
- if(m_particle_count > 16000)
- qWarning() << "Particle system contains a vast number of particles (>16000). Expect poor performance";
-
- foreach(QSGParticlePainter* particle, m_particles){
- int particleCount = 0;
- if(particle->particles().isEmpty()){//Uses default particle
- particleCount += m_groupData[0]->size;
- m_groupData[0]->types << particle;
- }else{
- foreach(const QString &group, particle->particles()){
- particleCount += m_groupData[m_groupIds[group]]->size;
- m_groupData[m_groupIds[group]]->types << particle;
+ foreach(QSGParticleGroupData* gd, m_groupData){//resize groups and update painters
+ int id = m_groupData.key(gd);
+
+ //TODO: Shrink back down! (but it has the problem of trying to remove the dead particles while maintaining integrity)
+ gd->size = qMax(gd->size, id < previousGroups?previousSizes[id]:0);
+
+ gd->data.resize(gd->size);
+ if(id < previousGroups){
+ for(int i=previousSizes[id]; i<gd->size; i++)
+ gd->data[i] = 0;
+ /*TODO:Consider salvaging partial updates, but have to batch changes to a single painter
+ int delta = 0;
+ delta = gd->size - previousSizes[id];
+ foreach(QSGParticlePainter* painter, gd->painters){
+ if(!painter->count() && delta){
+ painter->reset();
+ painter->update();
+ }
+ qDebug() << "Phi" << painter << painter->count() << delta;
+ painter->setCount(painter->count() + delta);
}
+ */
}
- particle->setCount(particleCount);
- particle->m_pleaseReset = true;
}
+ foreach(QSGParticlePainter *p, m_particlePainters)
+ loadPainter(p);
- m_timestamp.start();
- m_initialized = true;
- emit systemInitialized();
- qDebug() << "System Initialized. Size:" << m_particle_count;
+ if(m_particle_count > 16000)//###Investigate if these limits are worth warning about?
+ qWarning() << "Particle system arbitarily believes it has a vast number of particles (>16000). Expect poor performance";
+}
+
+void QSGParticleSystem::setRunning(bool arg)
+{
+ if (m_running != arg) {
+ m_running = arg;
+ emit runningChanged(arg);
+ reset();
+ }
}
-void QSGParticleSystem::reset()
+void QSGParticleSystem::componentComplete()
+{
+ QSGItem::componentComplete();
+ m_componentComplete = true;
+ //if(!m_emitters.isEmpty() && !m_particlePainters.isEmpty())
+ reset();
+}
+
+void QSGParticleSystem::reset()//TODO: Needed?
{
if(!m_componentComplete)
- return;//Batch starting reset()s a little
+ return;
+
//Clear guarded pointers which have been deleted
int cleared = 0;
cleared += m_emitters.removeAll(0);
- cleared += m_particles.removeAll(0);
+ cleared += m_particlePainters.removeAll(0);
cleared += m_affectors.removeAll(0);
//qDebug() << "Reset" << m_emitters.count() << m_particles.count() << "Cleared" << cleared;
- foreach(QSGParticlePainter* p, m_particles)
- p->reset();
- foreach(QSGParticleEmitter* e, m_emitters)
- e->reset();
+
+ emittersChanged();
+
+ //TODO: Reset data
+// foreach(QSGParticlePainter* p, m_particlePainters)
+// p->reset();
+// foreach(QSGParticleEmitter* e, m_emitters)
+// e->reset();
+ //### Do affectors need reset too?
+
if(!m_running)
return;
- initializeSystem();
- foreach(QSGParticlePainter* p, m_particles)
- p->update();
- foreach(QSGParticleEmitter* e, m_emitters)
- e->emitWindow(0);//Start, so that starttime factors appropriately
+
+ foreach(QSGParticlePainter *p, m_particlePainters){
+ loadPainter(p);
+ p->reset();
+ }
+
+ m_timestamp.start();//TODO: Better placement
+ m_initialized = true;
}
QSGParticleData* QSGParticleSystem::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;
+ int nextIdx = m_groupData[groupId]->nextIdx++;
- Q_ASSERT(nextIdx < m_data.size());
+ Q_ASSERT(nextIdx < m_groupData[groupId]->size);
QSGParticleData* ret;
- if(m_data[nextIdx]){//Recycle, it's faster.
- ret = m_data[nextIdx];
+ if(m_groupData[groupId]->data[nextIdx]){//Recycle, it's faster.
+ ret = m_groupData[groupId]->data[nextIdx];
if(!m_overwrite && ret->stillAlive()){
return 0;//Artificial longevity (or too fast emission) means this guy hasn't died. To maintain count, don't emit a new one
}//###Reset?
}else{
ret = new QSGParticleData;
- m_data[nextIdx] = ret;
+ m_groupData[groupId]->data[nextIdx] = ret;
}
ret->system = this;
- ret->systemIndex = nextIdx;
- ret->particleIndex = nextIdx - m_groupData[groupId]->start;
+ ret->index = nextIdx;
ret->group = groupId;
return ret;
}
@@ -248,14 +293,14 @@ void QSGParticleSystem::emitParticle(QSGParticleData* pd)
//Account for relative emitter position
QPointF offset = this->mapFromItem(pd->e, QPointF(0, 0));
if(!offset.isNull()){
- pd->pv.x += offset.x();
- pd->pv.y += offset.y();
+ pd->x += offset.x();
+ pd->y += offset.y();
}
foreach(QSGParticleAffector *a, m_affectors)
if(a && a->m_needsReset)
- a->reset(pd->systemIndex);
- foreach(QSGParticlePainter* p, m_groupData[pd->group]->types)
+ a->reset(pd);
+ foreach(QSGParticlePainter* p, m_groupData[pd->group]->painters)
if(p)
p->load(pd);
}
@@ -285,7 +330,7 @@ qint64 QSGParticleSystem::systemSync(QSGParticlePainter* p)
if(a)
a->affectSystem(dt);
foreach(QSGParticleData* d, m_needsReset)
- foreach(QSGParticlePainter* p, m_groupData[d->group]->types)
+ foreach(QSGParticlePainter* p, m_groupData[d->group]->painters)
if(p && d)
p->reload(d);
}
@@ -296,107 +341,107 @@ qint64 QSGParticleSystem::systemSync(QSGParticlePainter* p)
//sets the x accleration without affecting the instantaneous x velocity or position
void QSGParticleData::setInstantaneousAX(qreal ax)
{
- qreal t = (system->m_timeInt / 1000.0) - pv.t;
- qreal sx = (pv.sx + t*pv.ax) - t*ax;
- qreal ex = pv.x + pv.sx * t + 0.5 * pv.ax * t * t;
+ qreal t = (system->m_timeInt / 1000.0) - this->t;
+ qreal sx = (this->sx + t*this->ax) - t*ax;
+ qreal ex = this->x + this->sx * t + 0.5 * this->ax * t * t;
qreal x = ex - t*sx - 0.5 * t*t*ax;
- pv.ax = ax;
- pv.sx = sx;
- pv.x = x;
+ this->ax = ax;
+ this->sx = sx;
+ this->x = x;
}
//sets the x velocity without affecting the instantaneous x postion
void QSGParticleData::setInstantaneousSX(qreal vx)
{
- qreal t = (system->m_timeInt / 1000.0) - pv.t;
- qreal sx = vx - t*pv.ax;
- qreal ex = pv.x + pv.sx * t + 0.5 * pv.ax * t * t;
- qreal x = ex - t*sx - 0.5 * t*t*pv.ax;
+ qreal t = (system->m_timeInt / 1000.0) - this->t;
+ qreal sx = vx - t*this->ax;
+ qreal ex = this->x + this->sx * t + 0.5 * this->ax * t * t;
+ qreal x = ex - t*sx - 0.5 * t*t*this->ax;
- pv.sx = sx;
- pv.x = x;
+ this->sx = sx;
+ this->x = x;
}
//sets the instantaneous x postion
void QSGParticleData::setInstantaneousX(qreal x)
{
- qreal t = (system->m_timeInt / 1000.0) - pv.t;
- pv.x = x - t*pv.sx - 0.5 * t*t*pv.ax;
+ qreal t = (system->m_timeInt / 1000.0) - this->t;
+ this->x = x - t*this->sx - 0.5 * t*t*this->ax;
}
//sets the y accleration without affecting the instantaneous y velocity or position
void QSGParticleData::setInstantaneousAY(qreal ay)
{
- qreal t = (system->m_timeInt / 1000.0) - pv.t;
- qreal sy = (pv.sy + t*pv.ay) - t*ay;
- qreal ey = pv.y + pv.sy * t + 0.5 * pv.ay * t * t;
+ qreal t = (system->m_timeInt / 1000.0) - this->t;
+ qreal sy = (this->sy + t*this->ay) - t*ay;
+ qreal ey = this->y + this->sy * t + 0.5 * this->ay * t * t;
qreal y = ey - t*sy - 0.5 * t*t*ay;
- pv.ay = ay;
- pv.sy = sy;
- pv.y = y;
+ this->ay = ay;
+ this->sy = sy;
+ this->y = y;
}
//sets the y velocity without affecting the instantaneous y position
void QSGParticleData::setInstantaneousSY(qreal vy)
{
- qreal t = (system->m_timeInt / 1000.0) - pv.t;
- //qDebug() << t << (system->m_timeInt/1000.0) << pv.x << pv.sx << pv.ax << pv.x + pv.sx * t + 0.5 * pv.ax * t * t;
- qreal sy = vy - t*pv.ay;
- qreal ey = pv.y + pv.sy * t + 0.5 * pv.ay * t * t;
- qreal y = ey - t*sy - 0.5 * t*t*pv.ay;
-
- pv.sy = sy;
- pv.y = y;
+ qreal t = (system->m_timeInt / 1000.0) - this->t;
+ //qDebug() << t << (system->m_timeInt/1000.0) << this->x << this->sx << this->ax << this->x + this->sx * t + 0.5 * this->ax * t * t;
+ qreal sy = vy - t*this->ay;
+ qreal ey = this->y + this->sy * t + 0.5 * this->ay * t * t;
+ qreal y = ey - t*sy - 0.5 * t*t*this->ay;
+
+ this->sy = sy;
+ this->y = y;
}
//sets the instantaneous Y position
void QSGParticleData::setInstantaneousY(qreal y)
{
- qreal t = (system->m_timeInt / 1000.0) - pv.t;
- pv.y = y - t*pv.sy - 0.5 * t*t*pv.ay;
+ qreal t = (system->m_timeInt / 1000.0) - this->t;
+ this->y = y - t*this->sy - 0.5 * t*t*this->ay;
}
qreal QSGParticleData::curX() const
{
- qreal t = (system->m_timeInt / 1000.0) - pv.t;
- return pv.x + pv.sx * t + 0.5 * pv.ax * t * t;
+ qreal t = (system->m_timeInt / 1000.0) - this->t;
+ return this->x + this->sx * t + 0.5 * this->ax * t * t;
}
qreal QSGParticleData::curSX() const
{
- qreal t = (system->m_timeInt / 1000.0) - pv.t;
- return pv.sx + t*pv.ax;
+ qreal t = (system->m_timeInt / 1000.0) - this->t;
+ return this->sx + t*this->ax;
}
qreal QSGParticleData::curY() const
{
- qreal t = (system->m_timeInt / 1000.0) - pv.t;
- return pv.y + pv.sy * t + 0.5 * pv.ay * t * t;
+ qreal t = (system->m_timeInt / 1000.0) - this->t;
+ return y + sy * t + 0.5 * ay * t * t;
}
qreal QSGParticleData::curSY() const
{
- qreal t = (system->m_timeInt / 1000.0) - pv.t;
- return pv.sy + t*pv.ay;
+ qreal t = (system->m_timeInt / 1000.0) - this->t;
+ return sy + t*ay;
}
void QSGParticleData::debugDump()
{
qDebug() << "Particle" << group
- << "Pos: " << pv.x << "," << pv.y
- << "Vel: " << pv.sx << "," << pv.sy
- << "Acc: " << pv.ax << "," << pv.ay
- << "Size: " << pv.size << "," << pv.endSize
- << "Time: " << pv.t << "," <<pv.lifeSpan;
+ << "Pos: " << x << "," << y
+ << "Vel: " << sx << "," << sy
+ << "Acc: " << ax << "," << ay
+ << "Size: " << size << "," << endSize
+ << "Time: " << t << "," <<lifeSpan;
}
bool QSGParticleData::stillAlive()
{
if(!system)
return false;
- return (pv.t + pv.lifeSpan) > (system->m_timeInt/1000.0);
+ return (t + lifeSpan) > (system->m_timeInt/1000.0);
}
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticlesystem_p.h b/src/declarative/particles/qsgparticlesystem_p.h
index 9730ff35e8..45b4e164f1 100644
--- a/src/declarative/particles/qsgparticlesystem_p.h
+++ b/src/declarative/particles/qsgparticlesystem_p.h
@@ -47,6 +47,7 @@
#include <QVector>
#include <QHash>
#include <QPointer>
+#include <QSignalMapper>
QT_BEGIN_HEADER
@@ -61,11 +62,14 @@ class QSGParticlePainter;
class QSGParticleData;
-struct GroupData{
+class QSGParticleGroupData{
+public:
+ QSGParticleGroupData():size(0),nextIdx(0)
+ {}
int size;
- int start;
int nextIdx;
- QList<QSGParticlePainter*> types;
+ QSet<QSGParticlePainter*> painters;
+ QVector<QSGParticleData*> data;
};
class QSGParticleSystem : public QSGItem
@@ -131,20 +135,20 @@ protected:
void componentComplete();
private slots:
- void countChanged();
+ void emittersChanged();
+ void loadPainter(QObject* p);
public://but only really for related class usage. Perhaps we should all be friends?
void emitParticle(QSGParticleData* p);
QSGParticleData* newDatum(int groupId);
qint64 systemSync(QSGParticlePainter* p);
QElapsedTimer m_timestamp;
- QVector<QSGParticleData*> m_data;
QSet<QSGParticleData*> m_needsReset;
QHash<QString, int> m_groupIds;
- QHash<int, GroupData*> m_groupData;//id, size, start
+ QHash<int, QSGParticleGroupData*> m_groupData;
qint64 m_timeInt;
bool m_initialized;
- void registerParticleType(QSGParticlePainter* p);
+ void registerParticlePainter(QSGParticlePainter* p);
void registerParticleEmitter(QSGParticleEmitter* e);
void registerParticleAffector(QSGParticleAffector* a);
bool overwrite() const
@@ -158,36 +162,29 @@ private:
bool m_running;
QList<QPointer<QSGParticleEmitter> > m_emitters;
QList<QPointer<QSGParticleAffector> > m_affectors;
- QList<QPointer<QSGParticlePainter> > m_particles;
+ QList<QPointer<QSGParticlePainter> > m_particlePainters;
QList<QPointer<QSGParticlePainter> > m_syncList;
qint64 m_startTime;
int m_nextGroupId;
bool m_overwrite;
bool m_componentComplete;
-};
-//TODO: Clean up all this into ParticleData
+ QSignalMapper m_painterMapper;
+ QSignalMapper m_emitterMapper;
+};
-struct ParticleVertex {
- float x;
- float y;
- float t;
- float lifeSpan;
- float size;
- float endSize;
- float sx;
- float sy;
- float ax;
- float ay;
- //TODO: Need opacity over life control. More variable size over life?
+struct Color4ub {
+ uchar r;
+ uchar g;
+ uchar b;
+ uchar a;
};
class QSGParticleData{
public:
+ //TODO: QObject like memory management (without the cost, just attached to system)
QSGParticleData();
- ParticleVertex pv;
-
//Convenience functions for working backwards, because parameters are from the start of particle life
//If setting multiple parameters at once, doing the conversion yourself will be faster.
@@ -211,10 +208,38 @@ public:
qreal curSY() const;
int group;
- QSGParticleEmitter* e;
+ QSGParticleEmitter* e;//### Needed?
QSGParticleSystem* system;
- int particleIndex;
- int systemIndex;
+ int index;
+
+ //General Position Stuff
+ float x;
+ float y;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float sx;
+ float sy;
+ float ax;
+ float ay;
+
+ //Other stuff, now universally shared
+ Color4ub color;
+ float xx;
+ float xy;
+ float yx;
+ float yy;
+ float rotation;
+ float rotationSpeed;
+ float autoRotate;//Assume that GPUs prefer floats to bools
+ float animIdx;
+ float frameDuration;
+ float frameCount;
+ float animT;
+ float r;
+ QSGItem* delegate;
+ int modelIndex;
void debugDump();
bool stillAlive();
diff --git a/src/declarative/particles/qsgpointattractor.cpp b/src/declarative/particles/qsgpointattractor.cpp
index 4c675237ba..6f57ecaa36 100644
--- a/src/declarative/particles/qsgpointattractor.cpp
+++ b/src/declarative/particles/qsgpointattractor.cpp
@@ -60,27 +60,27 @@ bool QSGPointAttractorAffector::affectParticle(QSGParticleData *d, qreal dt)
qreal ds = 0;
switch(m_proportionalToDistance){
case Quadratic:
- ds = (m_strength / qMax(1.,r*r)) * dt;
+ ds = (m_strength / qMax<qreal>(1.,r*r)) * dt;
break;
case Linear://also default
default:
- ds = (m_strength / qMax(1.,r)) * dt;
+ ds = (m_strength / qMax<qreal>(1.,r)) * dt;
}
dx = ds * cos(theta);
dy = ds * sin(theta);
switch(m_physics){
case Position:
- d->pv.x = (d->pv.x + dx);
- d->pv.y = (d->pv.y + dy);
+ d->x = (d->x + dx);
+ d->y = (d->y + dy);
break;
case Acceleration:
- d->setInstantaneousAX(d->pv.ax + dx);
- d->setInstantaneousAY(d->pv.ay + dy);
+ d->setInstantaneousAX(d->ax + dx);
+ d->setInstantaneousAY(d->ay + dy);
break;
case Velocity: //also default
default:
- d->setInstantaneousSX(d->pv.sx + dx);
- d->setInstantaneousSY(d->pv.sy + dy);
+ d->setInstantaneousSX(d->sx + dx);
+ d->setInstantaneousSY(d->sy + dy);
}
return true;
diff --git a/src/declarative/particles/qsgspritegoal.cpp b/src/declarative/particles/qsgspritegoal.cpp
index 8dc98ae314..c97bfd1f26 100644
--- a/src/declarative/particles/qsgspritegoal.cpp
+++ b/src/declarative/particles/qsgspritegoal.cpp
@@ -81,7 +81,7 @@ bool QSGSpriteGoalAffector::affectParticle(QSGParticleData *d, qreal dt)
Q_UNUSED(dt);
//TODO: Affect all engines
QSGSpriteEngine *engine = 0;
- foreach(QSGParticlePainter *p, m_system->m_groupData[d->group]->types)
+ foreach(QSGParticlePainter *p, m_system->m_groupData[d->group]->painters)
if(qobject_cast<QSGImageParticle*>(p))
engine = qobject_cast<QSGImageParticle*>(p)->spriteEngine();
if(!engine)
@@ -89,8 +89,8 @@ bool QSGSpriteGoalAffector::affectParticle(QSGParticleData *d, qreal dt)
if(m_goalIdx == -2 || engine != m_lastEngine)
updateStateIndex(engine);
- if(engine->spriteState(d->particleIndex) != m_goalIdx){
- engine->setGoal(m_goalIdx, d->particleIndex, m_jump);
+ if(engine->spriteState(d->index) != m_goalIdx){
+ engine->setGoal(m_goalIdx, d->index, m_jump);
emit affected(QPointF(d->curX(), d->curY()));//###Expensive if unconnected? Move to Affector?
return true; //Doesn't affect particle data, but necessary for onceOff
}
diff --git a/src/declarative/particles/qsgturbulence.cpp b/src/declarative/particles/qsgturbulence.cpp
index 476db9c4b0..bb46b99f0d 100644
--- a/src/declarative/particles/qsgturbulence.cpp
+++ b/src/declarative/particles/qsgturbulence.cpp
@@ -128,30 +128,34 @@ void QSGTurbulenceAffector::affectSystem(qreal dt)
m_lastT += period;
}
- foreach(QSGParticleData *d, m_system->m_data){
- if(!d || !activeGroup(d->group))
+ foreach(QSGParticleGroupData *gd, m_system->m_groupData){
+ if(!activeGroup(m_system->m_groupData.key(gd)))//TODO: Surely this can be done better
return;
- qreal fx = 0.0;
- qreal fy = 0.0;
- QPointF pos = QPointF(d->curX() - x(), d->curY() - y());//TODO: Offset
- QPointF nodePos = QPointF(pos.x() / m_spacing.x(), pos.y() / m_spacing.y());
- QSet<QPair<int, int> > nodes;
- nodes << qMakePair((int)ceil(nodePos.x()), (int)ceil(nodePos.y()));
- nodes << qMakePair((int)ceil(nodePos.x()), (int)floor(nodePos.y()));
- nodes << qMakePair((int)floor(nodePos.x()), (int)ceil(nodePos.y()));
- nodes << qMakePair((int)floor(nodePos.x()), (int)floor(nodePos.y()));
- typedef QPair<int, int> intPair;
- foreach(const intPair &p, nodes){
- if(!QRect(0,0,m_gridSize-1,m_gridSize-1).contains(QPoint(p.first, p.second)))
- continue;
- qreal dist = magnitude(pos.x() - p.first*m_spacing.x(), pos.y() - p.second*m_spacing.y());//TODO: Mathematically valid
- fx += m_field[p.first][p.second].x() * ((m_magSum - dist)/m_magSum);//Proportionally weight nodes
- fy += m_field[p.first][p.second].y() * ((m_magSum - dist)/m_magSum);
- }
- if(fx || fy){
- d->setInstantaneousSX(d->curSX()+ fx * dt);
- d->setInstantaneousSY(d->curSY()+ fy * dt);
- m_system->m_needsReset << d;
+ foreach(QSGParticleData *d, gd->data){
+ if(!d || !activeGroup(d->group))
+ return;
+ qreal fx = 0.0;
+ qreal fy = 0.0;
+ QPointF pos = QPointF(d->curX() - x(), d->curY() - y());//TODO: Offset
+ QPointF nodePos = QPointF(pos.x() / m_spacing.x(), pos.y() / m_spacing.y());
+ QSet<QPair<int, int> > nodes;
+ nodes << qMakePair((int)ceil(nodePos.x()), (int)ceil(nodePos.y()));
+ nodes << qMakePair((int)ceil(nodePos.x()), (int)floor(nodePos.y()));
+ nodes << qMakePair((int)floor(nodePos.x()), (int)ceil(nodePos.y()));
+ nodes << qMakePair((int)floor(nodePos.x()), (int)floor(nodePos.y()));
+ typedef QPair<int, int> intPair;
+ foreach(const intPair &p, nodes){
+ if(!QRect(0,0,m_gridSize-1,m_gridSize-1).contains(QPoint(p.first, p.second)))
+ continue;
+ qreal dist = magnitude(pos.x() - p.first*m_spacing.x(), pos.y() - p.second*m_spacing.y());//TODO: Mathematically valid
+ fx += m_field[p.first][p.second].x() * ((m_magSum - dist)/m_magSum);//Proportionally weight nodes
+ fy += m_field[p.first][p.second].y() * ((m_magSum - dist)/m_magSum);
+ }
+ if(fx || fy){
+ d->setInstantaneousSX(d->curSX()+ fx * dt);
+ d->setInstantaneousSY(d->curSY()+ fy * dt);
+ m_system->m_needsReset << d;
+ }
}
}
}
diff --git a/src/declarative/particles/qsgwander.cpp b/src/declarative/particles/qsgwander.cpp
index 6e56d6a05b..26bea4ee04 100644
--- a/src/declarative/particles/qsgwander.cpp
+++ b/src/declarative/particles/qsgwander.cpp
@@ -116,10 +116,10 @@ bool QSGWanderAffector::affectParticle(QSGParticleData* data, qreal dt)
case Position:
newX = data->curX() + dx;
if(m_xVariance > qAbs(newX) )
- data->pv.x += dx;
+ data->x += dx;
newY = data->curY() + dy;
if(m_yVariance > qAbs(newY) )
- data->pv.y += dy;
+ data->y += dy;
break;
default:
case Velocity:
@@ -131,10 +131,10 @@ bool QSGWanderAffector::affectParticle(QSGParticleData* data, qreal dt)
data->setInstantaneousSY(newY);
break;
case Acceleration:
- newX = data->pv.ax + dx;
+ newX = data->ax + dx;
if(m_xVariance > qAbs(newX) )
data->setInstantaneousAX(newX);
- newY = data->pv.ay + dy;
+ newY = data->ay + dy;
if(m_yVariance > qAbs(newY) )
data->setInstantaneousAY(newY);
break;
diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
index 83b7d170a4..f74995ba0a 100644
--- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp
+++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
@@ -1163,10 +1163,12 @@ void QDeclarativeXMLHttpRequest::requestFromUrl(const QUrl &url)
m_network = networkAccessManager()->get(request);
else if (m_method == QLatin1String("HEAD"))
m_network = networkAccessManager()->head(request);
- else if(m_method == QLatin1String("POST"))
+ else if (m_method == QLatin1String("POST"))
m_network = networkAccessManager()->post(request, m_data);
- else if(m_method == QLatin1String("PUT"))
+ else if (m_method == QLatin1String("PUT"))
m_network = networkAccessManager()->put(request, m_data);
+ else if (m_method == QLatin1String("DELETE"))
+ m_network = networkAccessManager()->deleteResource(request);
QObject::connect(m_network, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(downloadProgress(qint64)));
@@ -1447,7 +1449,8 @@ static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngin
if (method != QLatin1String("GET") &&
method != QLatin1String("PUT") &&
method != QLatin1String("HEAD") &&
- method != QLatin1String("POST"))
+ method != QLatin1String("POST") &&
+ method != QLatin1String("DELETE"))
THROW_DOM(SYNTAX_ERR, "Unsupported HTTP method type");
diff --git a/src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp b/src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp
index e2bd8f6134..7279ff0216 100644
--- a/src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp
+++ b/src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp
@@ -111,55 +111,54 @@ static bool nodeLessThanWithRenderOrder(QSGGeometryNode *a, QSGGeometryNode *b)
return a->matrix() < b->matrix();
}
-// Minimum heap.
-template <typename T, int prealloc = 256>
-class Heap
+
+IndexGeometryNodePair::IndexGeometryNodePair(int i, QSGGeometryNode *node)
+ : QPair<int, QSGGeometryNode *>(i, node)
+{
+}
+
+bool IndexGeometryNodePair::operator < (const IndexGeometryNodePair &other) const
+{
+ return nodeLessThan(second, other.second);
+}
+
+
+IndexGeometryNodePairHeap::IndexGeometryNodePairHeap()
+ : v(64)
{
-public:
- void insert(const T &x);
- const T &top() const { return v[0]; }
- T pop();
- bool isEmpty() const { return v.isEmpty(); }
-private:
- static int parent(int i) { return (i - 1) >> 1; }
- static int left(int i) { return (i << 1) | 1; }
- static int right(int i) { return (i + 1) << 1; }
- QVarLengthArray<T, prealloc> v;
-};
-
-template <typename T, int prealloc>
-void Heap<T, prealloc>::insert(const T &x)
+}
+
+void IndexGeometryNodePairHeap::insert(const IndexGeometryNodePair &x)
{
int i = v.size();
- v.append(x);
- while (i != 0 && v[i] < v[parent(i)]) {
- qSwap(v[parent(i)], v[i]);
+ v.add(x);
+ while (i != 0 && v.at(i) < v.at(parent(i))) {
+ qSwap(v.at(parent(i)), v.at(i));
i = parent(i);
}
}
-template <typename T, int prealloc>
-T Heap<T, prealloc>::pop()
+IndexGeometryNodePair IndexGeometryNodePairHeap::pop()
{
- T x = top();
+ IndexGeometryNodePair x = top();
if (v.size() > 1)
- qSwap(v[0], v[v.size() - 1]);
- v.resize(v.size() - 1);
+ qSwap(v.first(), v.last());
+ v.pop_back();
int i = 0;
while (left(i) < v.size()) {
int low = left(i);
- if (right(i) < v.size() && v[right(i)] < v[low])
+ if (right(i) < v.size() && v.at(right(i)) < v.at(low))
low = right(i);
- if (!(v[low] < v[i]))
+ if (!(v.at(low) < v.at(i)))
break;
- qSwap(v[i], v[low]);
+ qSwap(v.at(i), v.at(low));
i = low;
}
return x;
}
-QMLRenderer::QMLRenderer(QSGContext *context)
+QSGDefaultRenderer::QSGDefaultRenderer(QSGContext *context)
: QSGRenderer(context)
, m_opaqueNodes(64)
, m_transparentNodes(64)
@@ -176,7 +175,7 @@ QMLRenderer::QMLRenderer(QSGContext *context)
#endif
}
-void QMLRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags)
+void QSGDefaultRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags)
{
QSGRenderer::nodeChanged(node, flags);
@@ -191,7 +190,7 @@ void QMLRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags)
m_needs_sorting = true;
}
-void QMLRenderer::render()
+void QSGDefaultRenderer::render()
{
#if defined (QML_RUNTIME_TESTING)
static bool dumpTree = qApp->arguments().contains(QLatin1String("--dump-tree"));
@@ -238,9 +237,8 @@ void QMLRenderer::render()
QRect r = viewportRect();
glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height());
- m_projectionMatrix = projectMatrix();
- m_projectionMatrix.push();
- m_modelViewMatrix.setToIdentity();
+ m_current_projection_matrix = projectionMatrix();
+ m_current_model_view_matrix.setToIdentity();
m_currentClip = 0;
glDisable(GL_STENCIL_TEST);
@@ -319,8 +317,6 @@ void QMLRenderer::render()
if (m_currentProgram)
m_currentProgram->deactivate();
- m_projectionMatrix.pop();
-
#ifdef RENDERER_DEBUG
if (debugTimer.elapsed() > DEBUG_THRESHOLD) {
printf(" --- Renderer breakdown:\n"
@@ -340,26 +336,18 @@ void QMLRenderer::render()
}
-class Foo : public QPair<int, QSGGeometryNode *>
-{
-public:
- Foo() { }
- Foo(int i, QSGGeometryNode *n) : QPair<int, QSGGeometryNode *>(i, n) { }
- bool operator < (const Foo &other) const { return nodeLessThan(second, other.second); }
-};
-
-void QMLRenderer::setSortFrontToBackEnabled(bool sort)
+void QSGDefaultRenderer::setSortFrontToBackEnabled(bool sort)
{
printf("setting sorting to... %d\n", sort);
m_sort_front_to_back = sort;
}
-bool QMLRenderer::isSortFrontToBackEnabled() const
+bool QSGDefaultRenderer::isSortFrontToBackEnabled() const
{
return m_sort_front_to_back;
}
-void QMLRenderer::buildLists(QSGNode *node)
+void QSGDefaultRenderer::buildLists(QSGNode *node)
{
if (node->isSubtreeBlocked())
return;
@@ -383,8 +371,7 @@ void QMLRenderer::buildLists(QSGNode *node)
}
}
- int count = node->childCount();
- if (!count)
+ if (!node->firstChild())
return;
#ifdef FORCE_NO_REORDER
@@ -393,33 +380,34 @@ void QMLRenderer::buildLists(QSGNode *node)
static bool reorder = !qApp->arguments().contains(QLatin1String("--no-reorder"));
#endif
- if (reorder && count > 1 && (node->flags() & QSGNode::ChildrenDoNotOverlap)) {
- QVarLengthArray<int, 16> beginIndices(count);
- QVarLengthArray<int, 16> endIndices(count);
+ if (reorder && node->firstChild() != node->lastChild() && (node->flags() & QSGNode::ChildrenDoNotOverlap)) {
+ QVarLengthArray<int, 16> beginIndices;
+ QVarLengthArray<int, 16> endIndices;
int baseCount = m_transparentNodes.size();
- for (int i = 0; i < count; ++i) {
- beginIndices[i] = m_transparentNodes.size();
- buildLists(node->childAtIndex(i));
- endIndices[i] = m_transparentNodes.size();
+ int count = 0;
+ for (QSGNode *c = node->firstChild(); c; c = c->nextSibling()) {
+ beginIndices.append(m_transparentNodes.size());
+ buildLists(c);
+ endIndices.append(m_transparentNodes.size());
+ ++count;
}
int childNodeCount = m_transparentNodes.size() - baseCount;
if (childNodeCount) {
- Heap<Foo, 16> heap;
m_tempNodes.reset();
m_tempNodes.reserve(childNodeCount);
while (childNodeCount) {
for (int i = 0; i < count; ++i) {
if (beginIndices[i] != endIndices[i])
- heap.insert(Foo(i, m_transparentNodes.at(beginIndices[i]++)));
+ m_heap.insert(IndexGeometryNodePair(i, m_transparentNodes.at(beginIndices[i]++)));
}
- while (!heap.isEmpty()) {
- Foo foo = heap.pop();
- m_tempNodes.add(foo.second);
+ while (!m_heap.isEmpty()) {
+ IndexGeometryNodePair pair = m_heap.pop();
+ m_tempNodes.add(pair.second);
--childNodeCount;
- int i = foo.first;
- if (beginIndices[i] != endIndices[i] && !nodeLessThan(m_transparentNodes.at(beginIndices[i]), foo.second))
- heap.insert(Foo(i, m_transparentNodes.at(beginIndices[i]++)));
+ int i = pair.first;
+ if (beginIndices[i] != endIndices[i] && !nodeLessThan(m_transparentNodes.at(beginIndices[i]), pair.second))
+ m_heap.insert(IndexGeometryNodePair(i, m_transparentNodes.at(beginIndices[i]++)));
}
}
Q_ASSERT(m_tempNodes.size() == m_transparentNodes.size() - baseCount);
@@ -427,16 +415,17 @@ void QMLRenderer::buildLists(QSGNode *node)
qMemCopy(&m_transparentNodes.at(baseCount), &m_tempNodes.at(0), m_tempNodes.size() * sizeof(QSGGeometryNode *));
}
} else {
- for (int i = 0; i < count; ++i)
- buildLists(node->childAtIndex(i));
+ for (QSGNode *c = node->firstChild(); c; c = c->nextSibling())
+ buildLists(c);
}
}
-void QMLRenderer::renderNodes(const QDataBuffer<QSGGeometryNode *> &list)
+void QSGDefaultRenderer::renderNodes(const QDataBuffer<QSGGeometryNode *> &list)
{
const float scale = 1.0f / m_currentRenderOrder;
int count = list.size();
int currentRenderOrder = 0x80000000;
+ m_current_projection_matrix.setColumn(2, scale * projectionMatrix().column(2));
//int clipChangeCount = 0;
//int programChangeCount = 0;
@@ -458,19 +447,18 @@ void QMLRenderer::renderNodes(const QDataBuffer<QSGGeometryNode *> &list)
if (changeMatrix) {
m_currentMatrix = geomNode->matrix();
if (m_currentMatrix)
- m_modelViewMatrix = *m_currentMatrix;
+ m_current_model_view_matrix = *m_currentMatrix;
else
- m_modelViewMatrix.setToIdentity();
+ m_current_model_view_matrix.setToIdentity();
updates |= QSGMaterialShader::RenderState::DirtyMatrix;
}
- bool changeOpacity = m_render_opacity != geomNode->inheritedOpacity();
+ bool changeOpacity = m_current_opacity != geomNode->inheritedOpacity();
if (changeOpacity) {
updates |= QSGMaterialShader::RenderState::DirtyOpacity;
- m_render_opacity = geomNode->inheritedOpacity();
+ m_current_opacity = geomNode->inheritedOpacity();
}
-
Q_ASSERT(geomNode->activeMaterial());
QSGMaterial *material = geomNode->activeMaterial();
@@ -485,7 +473,7 @@ void QMLRenderer::renderNodes(const QDataBuffer<QSGGeometryNode *> &list)
#ifdef FORCE_NO_REORDER
glDepthMask(false);
#else
- glDepthMask((material->flags() & QSGMaterial::Blending) == 0 && m_render_opacity == 1);
+ glDepthMask((material->flags() & QSGMaterial::Blending) == 0 && m_current_opacity == 1);
#endif
//++clipChangeCount;
}
@@ -507,10 +495,9 @@ void QMLRenderer::renderNodes(const QDataBuffer<QSGGeometryNode *> &list)
bool changeRenderOrder = currentRenderOrder != geomNode->renderOrder();
if (changeRenderOrder) {
currentRenderOrder = geomNode->renderOrder();
- m_renderOrderMatrix(2, 3) = currentRenderOrder * scale;
- m_projectionMatrix.pop();
- m_projectionMatrix.push();
- m_projectionMatrix *= m_renderOrderMatrix;
+ m_current_projection_matrix.setColumn(3, projectionMatrix().column(3)
+ + currentRenderOrder
+ * m_current_projection_matrix.column(2));
updates |= QSGMaterialShader::RenderState::DirtyMatrix;
}
diff --git a/src/declarative/scenegraph/coreapi/qsgdefaultrenderer_p.h b/src/declarative/scenegraph/coreapi/qsgdefaultrenderer_p.h
index ca1f5592cf..f2adb00391 100644
--- a/src/declarative/scenegraph/coreapi/qsgdefaultrenderer_p.h
+++ b/src/declarative/scenegraph/coreapi/qsgdefaultrenderer_p.h
@@ -52,11 +52,36 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class QMLRenderer : public QSGRenderer
+class IndexGeometryNodePair : public QPair<int, QSGGeometryNode *>
+{
+public:
+ IndexGeometryNodePair(int i, QSGGeometryNode *n);
+ bool operator < (const IndexGeometryNodePair &other) const;
+};
+
+
+// Minimum heap.
+class IndexGeometryNodePairHeap
+{
+public:
+ IndexGeometryNodePairHeap();
+ void insert(const IndexGeometryNodePair &x);
+ const IndexGeometryNodePair &top() const { return v.first(); }
+ IndexGeometryNodePair pop();
+ bool isEmpty() const { return v.isEmpty(); }
+private:
+ static int parent(int i) { return (i - 1) >> 1; }
+ static int left(int i) { return (i << 1) | 1; }
+ static int right(int i) { return (i + 1) << 1; }
+ QDataBuffer<IndexGeometryNodePair> v;
+};
+
+
+class QSGDefaultRenderer : public QSGRenderer
{
Q_OBJECT
public:
- QMLRenderer(QSGContext *context);
+ QSGDefaultRenderer(QSGContext *context);
void render();
@@ -77,14 +102,13 @@ private:
QDataBuffer<QSGGeometryNode *> m_opaqueNodes;
QDataBuffer<QSGGeometryNode *> m_transparentNodes;
QDataBuffer<QSGGeometryNode *> m_tempNodes;
+ IndexGeometryNodePairHeap m_heap;
bool m_rebuild_lists;
bool m_needs_sorting;
bool m_sort_front_to_back;
int m_currentRenderOrder;
-
-
#ifdef QML_RUNTIME_TESTING
bool m_render_opaque_nodes;
bool m_render_alpha_nodes;
diff --git a/src/declarative/scenegraph/coreapi/qsgmaterial.cpp b/src/declarative/scenegraph/coreapi/qsgmaterial.cpp
index afec4a59f3..687f949dbf 100644
--- a/src/declarative/scenegraph/coreapi/qsgmaterial.cpp
+++ b/src/declarative/scenegraph/coreapi/qsgmaterial.cpp
@@ -331,7 +331,7 @@ void QSGMaterialShader::compile()
float QSGMaterialShader::RenderState::opacity() const
{
Q_ASSERT(m_data);
- return static_cast<const QSGRenderer *>(m_data)->renderOpacity();
+ return static_cast<const QSGRenderer *>(m_data)->currentOpacity();
}
@@ -343,7 +343,7 @@ float QSGMaterialShader::RenderState::opacity() const
QMatrix4x4 QSGMaterialShader::RenderState::combinedMatrix() const
{
Q_ASSERT(m_data);
- return static_cast<const QSGRenderer *>(m_data)->combinedMatrix();
+ return static_cast<const QSGRenderer *>(m_data)->currentCombinedMatrix();
}
@@ -355,7 +355,7 @@ QMatrix4x4 QSGMaterialShader::RenderState::combinedMatrix() const
QMatrix4x4 QSGMaterialShader::RenderState::modelViewMatrix() const
{
Q_ASSERT(m_data);
- return const_cast<QSGRenderer *>(static_cast<const QSGRenderer *>(m_data))->modelViewMatrix().top();
+ return static_cast<const QSGRenderer *>(m_data)->currentModelViewMatrix();
}
diff --git a/src/declarative/scenegraph/coreapi/qsgmatrix4x4stack.cpp b/src/declarative/scenegraph/coreapi/qsgmatrix4x4stack.cpp
deleted file mode 100644
index 07ba21d17c..0000000000
--- a/src/declarative/scenegraph/coreapi/qsgmatrix4x4stack.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsgmatrix4x4stack.h"
-#include "qsgmatrix4x4stack_p.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QSGMatrix4x4Stack
- \brief The QSGMatrix4x4Stack class manages stacks of transformation matrices in GL applications.
- \since 4.8
- \ingroup qt3d
- \ingroup qt3d::enablers
-
- Transformation matrices are one of the basic building blocks of
- 3D applications, allowing object models to be positioned, scaled,
- rotated, and projected onto the screen.
-
- GL systems support several standard kinds of matrices, particularly
- modelview and projection matrices. These matrices are typically
- organized into stacks, which allow the current matrix state to be
- saved with push() and restored later with pop().
-
- QSGMatrix4x4Stack assists QGLPainter with the management of matrix
- stacks, providing operations to set and modify transformation
- matrices in each of the standard matrix stacks.
-
- In the following example, a standard orthographic projection matrix for a
- view is set via the QGLPainter::projectionMatrix() stack, and
- then a modelview matrix is set via the QGLPainter::modelViewMatrix()
- stack to scale and translate an object prior to drawing:
-
- \code
- QGLPainter painter(this);
-
- QMatrix4x4 projm;
- projm.ortho(window->rect());
- painter.projectionMatrix() = projm;
-
- painter.modelViewMatrix().setToIdentity();
- painter.modelViewMatrix().translate(-1.0f, 2.0f, 0.0f);
- painter.modelViewMatrix().scale(0.5f);
- \endcode
-
- Later, the application can save the current modelview matrix state
- and draw a different object with a different modelview matrix:
-
- \code
- painter.modelViewMatrix().push();
- painter.modelViewMatrix().setToIdentity();
- painter.modelViewMatrix().scale(2.0f);
- \endcode
-
- For efficiency, the matrix values are kept client-side until they
- are needed by a QGLPainter::draw() operation. Until then, changes
- to the matrix will not be reflected in the GL server. The application
- can force the GL server to update the server with a call to
- QGLPainter::update().
-
- QSGMatrix4x4Stack is supported on all GL platforms, including OpenGL/ES 2.0
- which doesn't support matrix stacks natively. On that platform, the
- matrix stack is simulated in client memory. When the application
- selects a shader program to draw under OpenGL/ES 2.0, it calls
- top() to obtain the actual value to be set on the shader program.
-
- \sa QGLPainter
-*/
-
-/*!
- Creates a matrix stack.
-*/
-QSGMatrix4x4Stack::QSGMatrix4x4Stack()
- : d_ptr(new QSGMatrix4x4StackPrivate)
-{
-}
-
-/*!
- Destroy this matrix stack.
-*/
-QSGMatrix4x4Stack::~QSGMatrix4x4Stack()
-{
-}
-
-/*!
- Pushes the current matrix onto the matrix stack. The matrix can
- be restored with pop(). The new top of stack will have the
- same value as the previous top of stack.
-
- The depths of the traditional \c{GL_MODELVIEW} and \c{GL_PROJECTION}
- matrix stacks in the GL server are system-dependent and easy to
- overflow in nested rendering code using \c{glPushMatrix()}.
- By contrast, the push() function provides an arbitrary-sized stack
- in client memory.
-
- \sa pop(), top()
-*/
-void QSGMatrix4x4Stack::push()
-{
- Q_D(QSGMatrix4x4Stack);
- d->stack.push(d->matrix);
-}
-
-/*!
- Pops the top-most matrix from this matrix stack and sets the
- current matrix to the next value down. Does nothing if the
- matrix stack contains a single entry.
-
- \sa push()
-*/
-void QSGMatrix4x4Stack::pop()
-{
- Q_D(QSGMatrix4x4Stack);
- if (!d->stack.isEmpty())
- d->matrix = d->stack.pop();
- d->isDirty = true;
-}
-
-/*!
- Set the matrix at the top of this matrix stack to the identity matrix.
-
- \sa operator=()
-*/
-void QSGMatrix4x4Stack::setToIdentity()
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix.setToIdentity();
- d->isDirty = true;
-}
-
-/*!
- Returns a const reference to the current matrix at the top of this
- matrix stack. This is typically used to fetch the matrix so it can
- be set on user-defined shader programs.
-
- \sa operator=()
-*/
-const QMatrix4x4 &QSGMatrix4x4Stack::top() const
-{
- Q_D(const QSGMatrix4x4Stack);
- return d->matrix;
-}
-
-/*!
- \fn QSGMatrix4x4Stack::operator const QMatrix4x4 &() const
-
- Returns a const reference to the current matrix at the top of
- this matrix stack.
-
- \sa top()
-*/
-
-/*!
- Assigns \a matrix to the matrix at the top of this matrix stack.
-
- \sa top()
-*/
-QSGMatrix4x4Stack& QSGMatrix4x4Stack::operator=(const QMatrix4x4& matrix)
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix = matrix;
- d->isDirty = true;
- return *this;
-}
-
-/*!
- Multiplies the matrix at the top of this matrix stack by \a matrix.
-
- \sa top()
-*/
-QSGMatrix4x4Stack& QSGMatrix4x4Stack::operator*=(const QMatrix4x4& matrix)
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix *= matrix;
- d->isDirty = true;
- return *this;
-}
-
-/*!
- Multiplies the current matrix at the top of this matrix stack by another
- that translates coordinates by (\a x, \a y, \a z). The following example
- translates the modelview matrix by (1, -3, 0):
-
- \code
- QGLPainter painter(this);
- painter.modelViewMatrix().translate(1.0f, -3.0f, 0.0f);
- \endcode
-
- \sa scale(), rotate()
-*/
-void QSGMatrix4x4Stack::translate(qreal x, qreal y, qreal z)
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix.translate(x, y, z);
- d->isDirty = true;
-}
-
-/*!
- Multiplies the current matrix at the top of this matrix statck by another
- that translates coordinates by the components of \a vector.
-
- \sa scale(), rotate()
-*/
-void QSGMatrix4x4Stack::translate(const QVector3D& vector)
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix.translate(vector);
- d->isDirty = true;
-}
-
-/*!
- Multiplies the current matrix at the top of this matrix stack by another
- that scales coordinates by the components \a x, \a y, and \a z.
- The following example scales the modelview matrix by (1, 2, 1):
-
- \code
- QGLPainter painter(this);
- painter.modelViewMatrix().scale(1.0f, 2.0f, 1.0f);
- \endcode
-
- \sa translate(), rotate()
-*/
-void QSGMatrix4x4Stack::scale(qreal x, qreal y, qreal z)
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix.scale(x, y, z);
- d->isDirty = true;
-}
-
-/*!
- Multiplies the current matrix at the top of this matrix stack by another
- that scales coordinates by the given \a factor. The following example
- scales the modelview matrix by a factor of 2:
-
- \code
- QGLPainter painter(this);
- painter.modelViewMatrix().scale(2.0f);
- \endcode
-
- \sa translate(), rotate()
-*/
-void QSGMatrix4x4Stack::scale(qreal factor)
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix.scale(factor);
- d->isDirty = true;
-}
-
-/*!
- Multiplies the current matrix at the top of this matrix stack by another
- that scales coordinates by the components of \a vector.
-
- \sa translate(), rotate()
-*/
-void QSGMatrix4x4Stack::scale(const QVector3D& vector)
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix.scale(vector);
- d->isDirty = true;
-}
-
-/*!
- Multiplies the current matrix at the top of this matrix stack by another
- that rotates coordinates through \a angle degrees about the vector
- (\a x, \a y, \a z). The following example rotates the modelview
- matrix by 45 degress about the vector (1, -3, 0):
-
- \code
- QGLPainter painter(this);
- painter.modelViewMatrix().rotate(45.0f, 1.0f, -3.0f, 0.0f);
- \endcode
-
- \sa scale(), translate()
-*/
-void QSGMatrix4x4Stack::rotate(qreal angle, qreal x, qreal y, qreal z)
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix.rotate(angle, x, y, z);
- d->isDirty = true;
-}
-
-/*!
- Multiplies the current matrix at the top of this matrix stack by another
- that rotates coordinates through \a angle degrees about \a vector.
-
- \sa scale(), translate()
-*/
-void QSGMatrix4x4Stack::rotate(qreal angle, const QVector3D& vector)
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix.rotate(angle, vector);
- d->isDirty = true;
-}
-
-/*!
- Multiplies the current matrix at the top of this matrix stack by the
- \a quaternion. Thus \c {painter->modelViewMatrix().rotate(quaternion)}
- is equivalent to the following code:
- \code
- QMatrix4x4 mat;
- mat.rotate(quaternion);
- painter->modelViewMatrix() *= mat;
- \endcode
- which rotates coordinates according to the given \a quaternion.
-
- \sa scale(), translate()
-*/
-void QSGMatrix4x4Stack::rotate(const QQuaternion &quaternion)
-{
- Q_D(QSGMatrix4x4Stack);
- d->matrix.rotate(quaternion);
- d->isDirty = true;
-}
-
-/*!
- Returns true if the top of this matrix stack has been modified;
- false otherwise.
-
- \sa setDirty()
-*/
-bool QSGMatrix4x4Stack::isDirty() const
-{
- Q_D(const QSGMatrix4x4Stack);
- return d->isDirty;
-}
-
-/*!
- Sets the \a dirty flag on this matrix stack, which indicates
- if it has been modified.
-
- A matrix stack may also be set to dirty by translate(),
- scale(), operator*(), etc.
-
- \sa isDirty()
-*/
-void QSGMatrix4x4Stack::setDirty(bool dirty)
-{
- Q_D(QSGMatrix4x4Stack);
- d->isDirty = dirty;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/coreapi/qsgmatrix4x4stack.h b/src/declarative/scenegraph/coreapi/qsgmatrix4x4stack.h
deleted file mode 100644
index 2336598fdc..0000000000
--- a/src/declarative/scenegraph/coreapi/qsgmatrix4x4stack.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSGMATRIX4X4STACK_H
-#define QSGMATRIX4X4STACK_H
-
-#include <QtGui/qmatrix4x4.h>
-#include <QtCore/qscopedpointer.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGMatrix4x4StackPrivate;
-
-class Q_DECLARATIVE_EXPORT QSGMatrix4x4Stack
-{
-public:
- QSGMatrix4x4Stack();
- ~QSGMatrix4x4Stack();
-
- const QMatrix4x4 &top() const;
-
- void push();
- void pop();
-
- void setToIdentity();
-
- void translate(qreal x, qreal y, qreal z);
- void translate(const QVector3D& vector);
- void scale(qreal x, qreal y, qreal z);
- void scale(qreal factor);
- void scale(const QVector3D& vector);
- void rotate(qreal angle, qreal x, qreal y, qreal z);
- void rotate(qreal angle, const QVector3D& vector);
- void rotate(const QQuaternion &quaternion);
-
- QSGMatrix4x4Stack& operator=(const QMatrix4x4& matrix);
- QSGMatrix4x4Stack& operator*=(const QMatrix4x4& matrix);
-
- operator const QMatrix4x4 &() const;
-
- bool isDirty() const;
- void setDirty(bool dirty);
-
-private:
- Q_DISABLE_COPY(QSGMatrix4x4Stack)
- Q_DECLARE_PRIVATE(QSGMatrix4x4Stack)
-
- QScopedPointer<QSGMatrix4x4StackPrivate> d_ptr;
-
- friend class QGLPainter;
-};
-
-inline QSGMatrix4x4Stack::operator const QMatrix4x4 &() const
-{
- return top();
-}
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif
diff --git a/src/declarative/scenegraph/coreapi/qsgmatrix4x4stack_p.h b/src/declarative/scenegraph/coreapi/qsgmatrix4x4stack_p.h
deleted file mode 100644
index 6e5c08ca03..0000000000
--- a/src/declarative/scenegraph/coreapi/qsgmatrix4x4stack_p.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSGMATRIX4X4STACK_P_H
-#define QSGMATRIX4X4STACK_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/qmatrix4x4.h>
-#include <QtCore/qstack.h>
-
-QT_BEGIN_NAMESPACE
-
-class QSGMatrix4x4StackPrivate
-{
-public:
- QSGMatrix4x4StackPrivate() : isDirty(true) {}
-
- QMatrix4x4 matrix;
- QStack<QMatrix4x4> stack;
- bool isDirty;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/declarative/scenegraph/coreapi/qsgnode.cpp b/src/declarative/scenegraph/coreapi/qsgnode.cpp
index 3472c933d7..bfe17ca72b 100644
--- a/src/declarative/scenegraph/coreapi/qsgnode.cpp
+++ b/src/declarative/scenegraph/coreapi/qsgnode.cpp
@@ -60,7 +60,7 @@ static void qt_print_node_count()
/*!
\class QSGNode
- \bried The QSGNode class is the base class for all nodes in the scene graph.
+ \brief The QSGNode class is the base class for all nodes in the scene graph.
The QSGNode class can be used as a child container. Children are added with
the appendChildNode(), prependChildNode(), insertChildNodeBefore() and
@@ -84,8 +84,13 @@ static void qt_print_node_count()
QSGNode::QSGNode()
: m_parent(0)
, m_type(BasicNodeType)
+ , m_subtreeGeometryCount(0)
, m_nodeFlags(OwnedByParent)
, m_flags(0)
+ , m_firstChild(0)
+ , m_lastChild(0)
+ , m_nextSibling(0)
+ , m_previousSibling(0)
{
init();
}
@@ -93,8 +98,13 @@ QSGNode::QSGNode()
QSGNode::QSGNode(NodeType type)
: m_parent(0)
, m_type(type)
+ , m_subtreeGeometryCount(type == GeometryNodeType ? 1 : 0)
, m_nodeFlags(OwnedByParent)
, m_flags(0)
+ , m_firstChild(0)
+ , m_lastChild(0)
+ , m_nextSibling(0)
+ , m_previousSibling(0)
{
init();
}
@@ -150,8 +160,6 @@ QSGNode::~QSGNode()
/*!
- \fn bool QSGNode::isSubtreeBlocked() const
-
Returns whether this node and its subtree is available for use.
Blocked subtrees will not get their dirty states updated and they
@@ -161,6 +169,22 @@ QSGNode::~QSGNode()
is 0, for instance.
*/
+bool QSGNode::isSubtreeBlocked() const
+{
+ return m_subtreeGeometryCount == 0;
+}
+
+/*!
+ \internal
+ Detaches the node from the scene graph and deletes any children it owns.
+
+ This function is called from QSGNode's and QSGRootNode's destructor. It
+ should not be called explicitly in user code. QSGRootNode needs to call
+ destroy() because destroy() calls removeChildNode() which in turn calls
+ markDirty() which type-casts the node to QSGRootNode. This type-cast is not
+ valid at the time QSGNode's destructor is called because the node will
+ already be partially destroyed at that point.
+*/
void QSGNode::destroy()
{
@@ -168,14 +192,15 @@ void QSGNode::destroy()
m_parent->removeChildNode(this);
Q_ASSERT(m_parent == 0);
}
- for (int ii = m_children.count() - 1; ii >= 0; --ii) {
- QSGNode *child = m_children.at(ii);
+ while (m_firstChild) {
+ QSGNode *child = m_firstChild;
removeChildNode(child);
Q_ASSERT(child->m_parent == 0);
if (child->flags() & OwnedByParent)
delete child;
}
- Q_ASSERT(m_children.isEmpty());
+
+ Q_ASSERT(m_firstChild == 0 && m_lastChild == 0);
}
@@ -188,7 +213,7 @@ void QSGNode::destroy()
void QSGNode::prependChildNode(QSGNode *node)
{
- Q_ASSERT_X(!m_children.contains(node), "QSGNode::prependChildNode", "QSGNode is already a child!");
+ //Q_ASSERT_X(!m_children.contains(node), "QSGNode::prependChildNode", "QSGNode is already a child!");
Q_ASSERT_X(!node->m_parent, "QSGNode::prependChildNode", "QSGNode already has a parent");
#ifndef QT_NO_DEBUG
@@ -199,7 +224,12 @@ void QSGNode::prependChildNode(QSGNode *node)
}
#endif
- m_children.prepend(node);
+ if (m_firstChild)
+ m_firstChild->m_previousSibling = node;
+ else
+ m_lastChild = node;
+ node->m_nextSibling = m_firstChild;
+ m_firstChild = node;
node->m_parent = this;
node->markDirty(DirtyNodeAdded);
@@ -214,7 +244,7 @@ void QSGNode::prependChildNode(QSGNode *node)
void QSGNode::appendChildNode(QSGNode *node)
{
- Q_ASSERT_X(!m_children.contains(node), "QSGNode::appendChildNode", "QSGNode is already a child!");
+ //Q_ASSERT_X(!m_children.contains(node), "QSGNode::appendChildNode", "QSGNode is already a child!");
Q_ASSERT_X(!node->m_parent, "QSGNode::appendChildNode", "QSGNode already has a parent");
#ifndef QT_NO_DEBUG
@@ -225,7 +255,12 @@ void QSGNode::appendChildNode(QSGNode *node)
}
#endif
- m_children.append(node);
+ if (m_lastChild)
+ m_lastChild->m_nextSibling = node;
+ else
+ m_firstChild = node;
+ node->m_previousSibling = m_lastChild;
+ m_lastChild = node;
node->m_parent = this;
node->markDirty(DirtyNodeAdded);
@@ -242,9 +277,9 @@ void QSGNode::appendChildNode(QSGNode *node)
void QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before)
{
- Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeBefore", "QSGNode is already a child!");
+ //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeBefore", "QSGNode is already a child!");
Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeBefore", "QSGNode already has a parent");
- Q_ASSERT_X(node->type() != RootNodeType, "QSGNode::insertChildNodeBefore", "RootNodes cannot be children of other nodes");
+ Q_ASSERT_X(before && before->m_parent == this, "QSGNode::insertChildNodeBefore", "The parent of \'before\' is wrong");
#ifndef QT_NO_DEBUG
if (node->type() == QSGNode::GeometryNodeType) {
@@ -254,11 +289,14 @@ void QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before)
}
#endif
- int idx = before?m_children.indexOf(before):-1;
- if (idx == -1)
- m_children.append(node);
+ QSGNode *previous = before->m_previousSibling;
+ if (previous)
+ previous->m_nextSibling = node;
else
- m_children.insert(idx, node);
+ m_firstChild = node;
+ node->m_previousSibling = previous;
+ node->m_nextSibling = before;
+ before->m_previousSibling = node;
node->m_parent = this;
node->markDirty(DirtyNodeAdded);
@@ -275,9 +313,9 @@ void QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before)
void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
{
- Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeAfter", "QSGNode is already a child!");
+ //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeAfter", "QSGNode is already a child!");
Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeAfter", "QSGNode already has a parent");
- Q_ASSERT_X(node->type() != RootNodeType, "QSGNode::insertChildNodeAfter", "RootNodes cannot be children of other nodes");
+ Q_ASSERT_X(after && after->m_parent == this, "QSGNode::insertChildNodeBefore", "The parent of \'before\' is wrong");
#ifndef QT_NO_DEBUG
if (node->type() == QSGNode::GeometryNodeType) {
@@ -287,11 +325,14 @@ void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
}
#endif
- int idx = after?m_children.indexOf(after):-1;
- if (idx == -1)
- m_children.append(node);
+ QSGNode *next = after->m_nextSibling;
+ if (next)
+ next->m_previousSibling = node;
else
- m_children.insert(idx + 1, node);
+ m_lastChild = node;
+ node->m_nextSibling = next;
+ node->m_previousSibling = after;
+ after->m_nextSibling = node;
node->m_parent = this;
node->markDirty(DirtyNodeAdded);
@@ -300,15 +341,26 @@ void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
/*!
- Removes \a node fromt his node's list of children.
+ Removes \a node from this node's list of children.
*/
void QSGNode::removeChildNode(QSGNode *node)
{
- Q_ASSERT(m_children.contains(node));
+ //Q_ASSERT(m_children.contains(node));
Q_ASSERT(node->parent() == this);
- m_children.removeOne(node);
+ QSGNode *previous = node->m_previousSibling;
+ QSGNode *next = node->m_nextSibling;
+ if (previous)
+ previous->m_nextSibling = next;
+ else
+ m_firstChild = next;
+ if (next)
+ next->m_previousSibling = previous;
+ else
+ m_lastChild = previous;
+ node->m_previousSibling = 0;
+ node->m_nextSibling = 0;
node->markDirty(DirtyNodeRemoved);
node->m_parent = 0;
@@ -316,6 +368,49 @@ void QSGNode::removeChildNode(QSGNode *node)
/*!
+ Removes all child nodes from this node's list of children.
+ */
+
+void QSGNode::removeAllChildNodes()
+{
+ while (m_firstChild) {
+ QSGNode *node = m_firstChild;
+ m_firstChild = node->m_nextSibling;
+ node->m_nextSibling = 0;
+ if (m_firstChild)
+ m_firstChild->m_previousSibling = 0;
+ else
+ m_lastChild = 0;
+ node->markDirty(DirtyNodeRemoved);
+ node->m_parent = 0;
+ }
+}
+
+
+int QSGNode::childCount() const
+{
+ int count = 0;
+ QSGNode *n = m_firstChild;
+ while (n) {
+ ++count;
+ n = n->m_nextSibling;
+ }
+ return count;
+}
+
+
+QSGNode *QSGNode::childAtIndex(int i) const
+{
+ QSGNode *n = m_firstChild;
+ while (i && n) {
+ --i;
+ n = n->m_nextSibling;
+ }
+ return n;
+}
+
+
+/*!
Sets the flag \a f on this node if \a enabled is true;
otherwise clears the flag.
@@ -360,9 +455,17 @@ void QSGNode::markDirty(DirtyFlags flags)
m_flags |= (flags & DirtyPropagationMask);
DirtyFlags subtreeFlags = DirtyFlags((flags & DirtyPropagationMask) << 16);
+
+ int geometryCountDiff = 0;
+ if (flags & DirtyNodeAdded)
+ geometryCountDiff = m_subtreeGeometryCount;
+ if (flags & DirtyNodeRemoved)
+ geometryCountDiff = -m_subtreeGeometryCount;
+
QSGNode *p = m_parent;
while (p) {
p->m_flags |= subtreeFlags;
+ p->m_subtreeGeometryCount += geometryCountDiff;
if (p->type() == RootNodeType)
static_cast<QSGRootNode *>(p)->notifyNodeChange(this, flags);
p = p->m_parent;
@@ -401,7 +504,6 @@ QSGBasicGeometryNode::QSGBasicGeometryNode(NodeType type)
QSGBasicGeometryNode::~QSGBasicGeometryNode()
{
- destroy();
if (flags() & OwnsGeometry)
delete m_geometry;
}
@@ -477,7 +579,6 @@ QSGGeometryNode::QSGGeometryNode()
QSGGeometryNode::~QSGGeometryNode()
{
- destroy();
if (flags() & OwnsMaterial)
delete m_material;
if (flags() & OwnsOpaqueMaterial)
@@ -639,7 +740,6 @@ QSGClipNode::QSGClipNode()
QSGClipNode::~QSGClipNode()
{
- destroy();
}
@@ -715,7 +815,6 @@ QSGTransformNode::QSGTransformNode()
QSGTransformNode::~QSGTransformNode()
{
- destroy();
}
@@ -789,7 +888,7 @@ QSGRootNode::~QSGRootNode()
{
while (!m_renderers.isEmpty())
m_renderers.last()->setRootNode(0);
- destroy();
+ destroy(); // Must call destroy() here because markDirty() casts this to QSGRootNode.
}
@@ -848,7 +947,6 @@ QSGOpacityNode::QSGOpacityNode()
QSGOpacityNode::~QSGOpacityNode()
{
- destroy();
}
@@ -912,22 +1010,21 @@ void QSGOpacityNode::setCombinedOpacity(qreal opacity)
/*!
- For performance reasons, we block the subtree when the nested opacity
- gets below a certain threshold.
+ For performance reasons, we block the subtree when the opacity
+ is below a certain threshold.
\internal
*/
bool QSGOpacityNode::isSubtreeBlocked() const
{
- return m_combined_opacity < 0.001;
+ return QSGNode::isSubtreeBlocked() || m_opacity < 0.001;
}
-
/*!
\class QSGNodeVisitor
- \bried The QSGNodeVisitor class is a helper class for traversing the scene graph.
+ \brief The QSGNodeVisitor class is a helper class for traversing the scene graph.
\internal
*/
@@ -973,10 +1070,8 @@ void QSGNodeVisitor::visitNode(QSGNode *n)
void QSGNodeVisitor::visitChildren(QSGNode *n)
{
- int count = n->childCount();
- for (int i=0; i<count; ++i) {
- visitNode(n->childAtIndex(i));
- }
+ for (QSGNode *c = n->firstChild(); c; c = c->nextSibling())
+ visitNode(c);
}
diff --git a/src/declarative/scenegraph/coreapi/qsgnode.h b/src/declarative/scenegraph/coreapi/qsgnode.h
index a391b55bc5..cee6b76869 100644
--- a/src/declarative/scenegraph/coreapi/qsgnode.h
+++ b/src/declarative/scenegraph/coreapi/qsgnode.h
@@ -118,13 +118,18 @@ public:
QSGNode *parent() const { return m_parent; }
void removeChildNode(QSGNode *node);
+ void removeAllChildNodes();
void prependChildNode(QSGNode *node);
void appendChildNode(QSGNode *node);
void insertChildNodeBefore(QSGNode *node, QSGNode *before);
void insertChildNodeAfter(QSGNode *node, QSGNode *after);
- int childCount() const { return m_children.size(); }
- QSGNode *childAtIndex(int i) const { return m_children.at(i); }
+ int childCount() const;
+ QSGNode *childAtIndex(int i) const;
+ QSGNode *firstChild() const { return m_firstChild; }
+ QSGNode *lastChild() const { return m_lastChild; }
+ QSGNode *nextSibling() const { return m_nextSibling; }
+ QSGNode* previousSibling() const { return m_previousSibling; }
inline NodeType type() const { return m_type; }
@@ -132,7 +137,7 @@ public:
void markDirty(DirtyFlags flags);
DirtyFlags dirtyFlags() const { return m_flags; }
- virtual bool isSubtreeBlocked() const { return false; }
+ virtual bool isSubtreeBlocked() const;
Flags flags() const { return m_nodeFlags; }
void setFlag(Flag, bool = true);
@@ -147,20 +152,19 @@ public:
protected:
QSGNode(NodeType type);
- // When a node is destroyed, it will detach from the scene graph and the renderer will be
- // notified about the change. If the node is detached in the base node's destructor, the
- // renderer can't safely cast the node to its original type, since at this point it has been
- // partly destroyed already. To solve this problem, all the node destructors must call a common
- // destroy method.
-
- void destroy();
-
private:
+ friend class QSGRootNode;
+
void init();
+ void destroy();
QSGNode *m_parent;
NodeType m_type;
- QList<QSGNode *> m_children;
+ QSGNode *m_firstChild;
+ QSGNode *m_lastChild;
+ QSGNode *m_nextSibling;
+ QSGNode *m_previousSibling;
+ int m_subtreeGeometryCount;
Flags m_nodeFlags;
DirtyFlags m_flags;
diff --git a/src/declarative/scenegraph/coreapi/qsgnodeupdater.cpp b/src/declarative/scenegraph/coreapi/qsgnodeupdater.cpp
index 6eff011e85..3c3ff31fd5 100644
--- a/src/declarative/scenegraph/coreapi/qsgnodeupdater.cpp
+++ b/src/declarative/scenegraph/coreapi/qsgnodeupdater.cpp
@@ -46,10 +46,14 @@ QT_BEGIN_NAMESPACE
// #define QSG_UPDATER_DEBUG
QSGNodeUpdater::QSGNodeUpdater()
- : m_current_clip(0)
+ : m_matrix_stack(64)
+ , m_combined_matrix_stack(64)
+ , m_opacity_stack(64)
+ , m_current_clip(0)
, m_force_update(0)
{
- m_opacity_stack.push(1);
+ m_opacity_stack.add(1);
+ m_matrix_stack.add(QMatrix4x4());
}
void QSGNodeUpdater::updateStates(QSGNode *n)
@@ -58,7 +62,6 @@ void QSGNodeUpdater::updateStates(QSGNode *n)
m_force_update = 0;
Q_ASSERT(m_opacity_stack.size() == 1); // The one we added in the constructr...
- // Q_ASSERT(m_matrix_stack.isEmpty()); ### no such function?
Q_ASSERT(m_combined_matrix_stack.isEmpty());
visitNode(n);
@@ -121,13 +124,11 @@ void QSGNodeUpdater::enterTransformNode(QSGTransformNode *t)
#endif
if (!t->matrix().isIdentity()) {
- m_combined_matrix_stack.push(&t->combinedMatrix());
-
- m_matrix_stack.push();
- m_matrix_stack *= t->matrix();
+ m_combined_matrix_stack.add(&t->combinedMatrix());
+ m_matrix_stack.add(m_matrix_stack.last() * t->matrix());
}
- t->setCombinedMatrix(m_matrix_stack.top());
+ t->setCombinedMatrix(m_matrix_stack.last());
}
@@ -141,8 +142,8 @@ void QSGNodeUpdater::leaveTransformNode(QSGTransformNode *t)
--m_force_update;
if (!t->matrix().isIdentity()) {
- m_matrix_stack.pop();
- m_combined_matrix_stack.pop();
+ m_matrix_stack.pop_back();
+ m_combined_matrix_stack.pop_back();
}
}
@@ -154,11 +155,10 @@ void QSGNodeUpdater::enterClipNode(QSGClipNode *c)
qDebug() << "enter clip:" << c;
#endif
- if (c->dirtyFlags() & QSGNode::DirtyClipList) {
+ if (c->dirtyFlags() & QSGNode::DirtyClipList)
++m_force_update;
- }
- c->m_matrix = m_combined_matrix_stack.isEmpty() ? 0 : m_combined_matrix_stack.top();
+ c->m_matrix = m_combined_matrix_stack.isEmpty() ? 0 : m_combined_matrix_stack.last();
c->m_clip_list = m_current_clip;
m_current_clip = c;
}
@@ -170,9 +170,8 @@ void QSGNodeUpdater::leaveClipNode(QSGClipNode *c)
qDebug() << "leave clip:" << c;
#endif
- if (c->dirtyFlags() & QSGNode::DirtyClipList) {
+ if (c->dirtyFlags() & QSGNode::DirtyClipList)
--m_force_update;
- }
m_current_clip = c->m_clip_list;
}
@@ -184,9 +183,16 @@ void QSGNodeUpdater::enterGeometryNode(QSGGeometryNode *g)
qDebug() << "enter geometry:" << g;
#endif
- g->m_matrix = m_combined_matrix_stack.isEmpty() ? 0 : m_combined_matrix_stack.top();
+ g->m_matrix = m_combined_matrix_stack.isEmpty() ? 0 : m_combined_matrix_stack.last();
g->m_clip_list = m_current_clip;
- g->setInheritedOpacity(m_opacity_stack.top());
+ g->setInheritedOpacity(m_opacity_stack.last());
+}
+
+void QSGNodeUpdater::leaveGeometryNode(QSGGeometryNode *g)
+{
+#ifdef QSG_UPDATER_DEBUG
+ qDebug() << "leave geometry" << g;
+#endif
}
void QSGNodeUpdater::enterOpacityNode(QSGOpacityNode *o)
@@ -194,9 +200,9 @@ void QSGNodeUpdater::enterOpacityNode(QSGOpacityNode *o)
if (o->dirtyFlags() & QSGNode::DirtyOpacity)
++m_force_update;
- qreal opacity = m_opacity_stack.top() * o->opacity();
+ qreal opacity = m_opacity_stack.last() * o->opacity();
o->setCombinedOpacity(opacity);
- m_opacity_stack.push(opacity);
+ m_opacity_stack.add(opacity);
#ifdef QSG_UPDATER_DEBUG
qDebug() << "enter opacity" << o;
@@ -211,13 +217,13 @@ void QSGNodeUpdater::leaveOpacityNode(QSGOpacityNode *o)
if (o->flags() & QSGNode::DirtyOpacity)
--m_force_update;
- m_opacity_stack.pop();
+ m_opacity_stack.pop_back();
}
void QSGNodeUpdater::visitChildren(QSGNode *n)
{
- if (!n->isSubtreeBlocked())
- QSGNodeVisitor::visitChildren(n);
+ for (QSGNode *c = n->firstChild(); c; c = c->nextSibling())
+ visitNode(c);
}
void QSGNodeUpdater::visitNode(QSGNode *n)
@@ -226,18 +232,49 @@ void QSGNodeUpdater::visitNode(QSGNode *n)
qDebug() << "enter:" << n;
#endif
- if (n->dirtyFlags() || m_force_update) {
- bool forceUpdate = n->dirtyFlags() & (QSGNode::DirtyNodeAdded | QSGNode::DirtyForceUpdate);
- if (forceUpdate)
- ++m_force_update;
-
- QSGNodeVisitor::visitNode(n);
+ if (!n->dirtyFlags() && !m_force_update)
+ return;
+ if (n->isSubtreeBlocked())
+ return;
- if (forceUpdate)
- --m_force_update;
+ bool forceUpdate = n->dirtyFlags() & (QSGNode::DirtyNodeAdded | QSGNode::DirtyForceUpdate);
+ if (forceUpdate)
+ ++m_force_update;
- n->clearDirty();
+ switch (n->type()) {
+ case QSGNode::TransformNodeType: {
+ QSGTransformNode *t = static_cast<QSGTransformNode *>(n);
+ enterTransformNode(t);
+ visitChildren(t);
+ leaveTransformNode(t);
+ break; }
+ case QSGNode::GeometryNodeType: {
+ QSGGeometryNode *g = static_cast<QSGGeometryNode *>(n);
+ enterGeometryNode(g);
+ visitChildren(g);
+ leaveGeometryNode(g);
+ break; }
+ case QSGNode::ClipNodeType: {
+ QSGClipNode *c = static_cast<QSGClipNode *>(n);
+ enterClipNode(c);
+ visitChildren(c);
+ leaveClipNode(c);
+ break; }
+ case QSGNode::OpacityNodeType: {
+ QSGOpacityNode *o = static_cast<QSGOpacityNode *>(n);
+ enterOpacityNode(o);
+ visitChildren(o);
+ leaveOpacityNode(o);
+ break; }
+ default:
+ visitChildren(n);
+ break;
}
+
+ if (forceUpdate)
+ --m_force_update;
+
+ n->clearDirty();
}
QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/coreapi/qsgnodeupdater_p.h b/src/declarative/scenegraph/coreapi/qsgnodeupdater_p.h
index 518cf9eff9..a1ecc65220 100644
--- a/src/declarative/scenegraph/coreapi/qsgnodeupdater_p.h
+++ b/src/declarative/scenegraph/coreapi/qsgnodeupdater_p.h
@@ -43,12 +43,11 @@
#define NODEUPDATER_P_H
#include "qsgnode.h"
-#include "qsgmatrix4x4stack.h"
-#include <qstack.h>
+#include <QtGui/private/qdatabuffer_p.h>
QT_BEGIN_NAMESPACE
-class Q_DECLARATIVE_EXPORT QSGNodeUpdater : public QSGNodeVisitor
+class Q_DECLARATIVE_EXPORT QSGNodeUpdater
{
public:
QSGNodeUpdater();
@@ -56,25 +55,26 @@ public:
virtual void updateStates(QSGNode *n);
virtual bool isNodeBlocked(QSGNode *n, QSGNode *root) const;
- void setToplevelOpacity(qreal alpha) { m_opacity_stack.top() = alpha; }
- qreal toplevelOpacity() const { return m_opacity_stack.top(); }
+ void setToplevelOpacity(qreal alpha) { m_opacity_stack.last() = alpha; }
+ qreal toplevelOpacity() const { return m_opacity_stack.last(); }
protected:
- void enterTransformNode(QSGTransformNode *);
- void leaveTransformNode(QSGTransformNode *);
+ virtual void enterTransformNode(QSGTransformNode *);
+ virtual void leaveTransformNode(QSGTransformNode *);
void enterClipNode(QSGClipNode *c);
void leaveClipNode(QSGClipNode *c);
void enterOpacityNode(QSGOpacityNode *o);
void leaveOpacityNode(QSGOpacityNode *o);
void enterGeometryNode(QSGGeometryNode *);
+ void leaveGeometryNode(QSGGeometryNode *);
void visitNode(QSGNode *n);
void visitChildren(QSGNode *n);
- QSGMatrix4x4Stack m_matrix_stack;
- QStack<const QMatrix4x4 *> m_combined_matrix_stack;
- QStack<qreal> m_opacity_stack;
+ QDataBuffer<QMatrix4x4> m_matrix_stack;
+ QDataBuffer<const QMatrix4x4 *> m_combined_matrix_stack;
+ QDataBuffer<qreal> m_opacity_stack;
const QSGClipNode *m_current_clip;
int m_force_update;
diff --git a/src/declarative/scenegraph/coreapi/qsgrenderer.cpp b/src/declarative/scenegraph/coreapi/qsgrenderer.cpp
index cc24cc066b..48c34d39dd 100644
--- a/src/declarative/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/declarative/scenegraph/coreapi/qsgrenderer.cpp
@@ -122,7 +122,7 @@ QSGRenderer::QSGRenderer(QSGContext *context)
: QObject()
, m_clear_color(Qt::transparent)
, m_clear_mode(ClearColorBuffer | ClearDepthBuffer)
- , m_render_opacity(1)
+ , m_current_opacity(1)
, m_context(context)
, m_root_node(0)
, m_node_updater(0)
@@ -264,12 +264,12 @@ void QSGRenderer::renderScene(const Bindable &bindable)
#endif
}
-void QSGRenderer::setProjectMatrixToDeviceRect()
+void QSGRenderer::setProjectionMatrixToDeviceRect()
{
- setProjectMatrixToRect(m_device_rect);
+ setProjectionMatrixToRect(m_device_rect);
}
-void QSGRenderer::setProjectMatrixToRect(const QRectF &rect)
+void QSGRenderer::setProjectionMatrixToRect(const QRectF &rect)
{
QMatrix4x4 matrix;
matrix.ortho(rect.x(),
@@ -278,10 +278,10 @@ void QSGRenderer::setProjectMatrixToRect(const QRectF &rect)
rect.y(),
qreal(0.01),
-1);
- setProjectMatrix(matrix);
+ setProjectionMatrix(matrix);
}
-void QSGRenderer::setProjectMatrix(const QMatrix4x4 &matrix)
+void QSGRenderer::setProjectionMatrix(const QMatrix4x4 &matrix)
{
m_projection_matrix = matrix;
// Mirrored relative to the usual Qt coordinate system with origin in the top left corner.
@@ -293,6 +293,14 @@ void QSGRenderer::setClearColor(const QColor &color)
m_clear_color = color;
}
+/*!
+ Updates internal data structures and emits the sceneGraphChanged() signal.
+
+ If \a flags contains the QSGNode::DirtyNodeRemoved flag, the node might be
+ in the process of being destroyed. It is then not safe to downcast the node
+ pointer.
+*/
+
void QSGRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags)
{
Q_UNUSED(node);
@@ -346,16 +354,16 @@ void QSGRenderer::preprocess()
void QSGRenderer::addNodesToPreprocess(QSGNode *node)
{
- for (int i = 0; i < node->childCount(); ++i)
- addNodesToPreprocess(node->childAtIndex(i));
+ for (QSGNode *c = node->firstChild(); c; c = c->nextSibling())
+ addNodesToPreprocess(c);
if (node->flags() & QSGNode::UsePreprocess)
m_nodes_to_preprocess.insert(node);
}
void QSGRenderer::removeNodesToPreprocess(QSGNode *node)
{
- for (int i = 0; i < node->childCount(); ++i)
- removeNodesToPreprocess(node->childAtIndex(i));
+ for (QSGNode *c = node->firstChild(); c; c = c->nextSibling())
+ removeNodesToPreprocess(c);
if (node->flags() & QSGNode::UsePreprocess)
m_nodes_to_preprocess.remove(node);
}
@@ -384,11 +392,9 @@ QSGRenderer::ClipType QSGRenderer::updateStencilClip(const QSGClipNode *clip)
int clipDepth = 0;
QRect clipRect;
while (clip) {
- QMatrix4x4 matrix = m_projectionMatrix.top();
+ QMatrix4x4 m = m_current_projection_matrix;
if (clip->matrix())
- matrix *= *clip->matrix();
-
- const QMatrix4x4 &m = matrix;
+ m *= *clip->matrix();
// TODO: Check for multisampling and pixel grid alignment.
bool canUseScissor = clip->isRectangular()
diff --git a/src/declarative/scenegraph/coreapi/qsgrenderer_p.h b/src/declarative/scenegraph/coreapi/qsgrenderer_p.h
index 272df8082c..0218caed15 100644
--- a/src/declarative/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/declarative/scenegraph/coreapi/qsgrenderer_p.h
@@ -45,8 +45,6 @@
#include <qset.h>
#include <qhash.h>
-#include "qsgmatrix4x4stack.h"
-
#include <qglfunctions.h>
#include <qglshaderprogram.h>
@@ -103,18 +101,18 @@ public:
inline void setViewportRect(const QSize &size) { setViewportRect(QRect(QPoint(), size)); }
QRect viewportRect() const { return m_viewport_rect; }
- QSGMatrix4x4Stack &projectionMatrix() { return m_projectionMatrix; }
- QSGMatrix4x4Stack &modelViewMatrix() { return m_modelViewMatrix; }
- QMatrix4x4 combinedMatrix() const { return m_projectionMatrix.top() * m_modelViewMatrix.top(); }
+ // Accessed by QSGMaterialShader::RenderState.
+ QMatrix4x4 currentProjectionMatrix() const { return m_current_projection_matrix; }
+ QMatrix4x4 currentModelViewMatrix() const { return m_current_model_view_matrix; }
+ QMatrix4x4 currentCombinedMatrix() const { return m_current_projection_matrix * m_current_model_view_matrix; }
+ qreal currentOpacity() const { return m_current_opacity; }
- void setProjectMatrixToDeviceRect();
- void setProjectMatrixToRect(const QRectF &rect);
- void setProjectMatrix(const QMatrix4x4 &matrix);
- QMatrix4x4 projectMatrix() const { return m_projection_matrix; }
+ void setProjectionMatrixToDeviceRect();
+ void setProjectionMatrixToRect(const QRectF &rect);
+ void setProjectionMatrix(const QMatrix4x4 &matrix);
+ QMatrix4x4 projectionMatrix() const { return m_projection_matrix; }
bool isMirrored() const { return m_mirrored; }
- qreal renderOpacity() const { return m_render_opacity; }
-
void setClearColor(const QColor &color);
QColor clearColor() const { return m_clear_color; }
@@ -155,9 +153,9 @@ protected:
QColor m_clear_color;
ClearMode m_clear_mode;
- QSGMatrix4x4Stack m_projectionMatrix;
- QSGMatrix4x4Stack m_modelViewMatrix;
- qreal m_render_opacity;
+ QMatrix4x4 m_current_projection_matrix;
+ QMatrix4x4 m_current_model_view_matrix;
+ qreal m_current_opacity;
QSGContext *m_context;
diff --git a/src/declarative/scenegraph/qsgcontext.cpp b/src/declarative/scenegraph/qsgcontext.cpp
index 55942bebe4..682b514b9c 100644
--- a/src/declarative/scenegraph/qsgcontext.cpp
+++ b/src/declarative/scenegraph/qsgcontext.cpp
@@ -63,7 +63,7 @@
DEFINE_BOOL_CONFIG_OPTION(qmlFlashMode, QML_FLASH_MODE)
DEFINE_BOOL_CONFIG_OPTION(qmlTranslucentMode, QML_TRANSLUCENT_MODE)
-/*!
+/*
Comments about this class from Gunnar:
The QSGContext class is right now two things.. The first is the
@@ -78,8 +78,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlTranslucentMode, QML_TRANSLUCENT_MODE)
If we ever move the scene graph core API into its own thing, this class
needs to be split in two. Right now its one because we're lazy when it comes
to defining plugin interfaces..
-
- */
+*/
QT_BEGIN_NAMESPACE
@@ -308,7 +307,7 @@ QSGRenderer *QSGContext::createRenderer()
{
// ### Do something with this before release...
static bool doFrontToBack = qApp->arguments().contains(QLatin1String("--opaque-front-to-back"));
- QMLRenderer *renderer = new QMLRenderer(this);
+ QSGDefaultRenderer *renderer = new QSGDefaultRenderer(this);
if (doFrontToBack) {
printf("QSGContext: Sorting opaque nodes front to back...\n");
renderer->setSortFrontToBackEnabled(true);
@@ -400,7 +399,7 @@ QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material)
/*!
- Sets weither the scene graph should render with flashing update rectangles or not
+ Sets whether the scene graph should render with flashing update rectangles or not
*/
void QSGContext::setFlashModeEnabled(bool enabled)
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp b/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp
index 50c946a849..c63ff9d4cc 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp
@@ -51,6 +51,7 @@
#include <qglfunctions.h>
#include <qglyphrun.h>
#include <qrawfont.h>
+#include <qdir.h>
QT_BEGIN_NAMESPACE
@@ -344,10 +345,8 @@ static QImage makeDistanceField(int imgSize, const QPainterPath &path, int dfSca
bool isShortData = polys.indices.type() == QVertexIndexVector::UnsignedShort;
const void *indices = polys.indices.data();
int index = 0;
- QVector<DFPoint> normals;
- QVector<DFVertex> vertices;
- normals.reserve(polys.vertices.count());
- vertices.reserve(polys.vertices.count());
+ QVarLengthArray<DFPoint> normals(polys.vertices.count());
+ QVarLengthArray<DFVertex> vertices(polys.vertices.count());
while (index < polys.indices.size()) {
normals.clear();
@@ -386,7 +385,7 @@ static QImage makeDistanceField(int imgSize, const QPainterPath &path, int dfSca
vertices.append(v);
}
- QVector<bool> isConvex(normals.count());
+ QVarLengthArray<bool> isConvex(normals.count());
for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++)
isConvex[prev] = (normals.at(prev).x * normals.at(next).y - normals.at(prev).y * normals.at(next).x > 0);
@@ -473,11 +472,14 @@ static void convert_to_Format_Alpha(QImage *image)
const int width = image->width();
const int height = image->height();
uchar *data = image->bits();
+ const uint *src = (const uint *) data;
+ int stride = image->bytesPerLine() / sizeof(uint);
for (int i = 0; i < height; ++i) {
uchar *o = data + i * width;
for (int x = 0; x < width; ++x)
- o[x] = (uchar)qAlpha(image->pixel(x, i));
+ o[x] = (uchar)qAlpha(src[x]);
+ src += stride;
}
}
@@ -910,17 +912,45 @@ void QSGDistanceFieldGlyphCache::updateCache()
if (m_textureData->pendingGlyphs.isEmpty())
return;
- int requiredWidth = m_textureData->currY == 0 ? m_textureData->currX : maxTextureSize();
- int requiredHeight = qMin(maxTextureSize(), m_textureData->currY + QT_DISTANCEFIELD_TILESIZE);
+ int requiredWidth = maxTextureSize();
+ int rows = 128 / (requiredWidth / QT_DISTANCEFIELD_TILESIZE); // Enough rows to fill the latin1 set by default..
+ int requiredHeight = qMin(maxTextureSize(), qMax(m_textureData->currY + QT_DISTANCEFIELD_TILESIZE, QT_DISTANCEFIELD_TILESIZE * rows));
resizeTexture((requiredWidth), (requiredHeight));
glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
+ // ### Remove before final release
+ static bool cacheDistanceFields = QApplication::arguments().contains("--cache-distance-fields");
+
+ QString tmpPath = QString::fromLatin1("%1/.qt/").arg(QDir::tempPath());
+ QString keyBase = QString::fromLatin1("%1%2%3_%4_%5_%6.fontblob")
+ .arg(tmpPath)
+ .arg(m_font.familyName())
+ .arg(m_font.styleName())
+ .arg(m_font.weight())
+ .arg(m_font.style());
+
+ if (cacheDistanceFields && !QFile::exists(tmpPath))
+ QDir(tmpPath).mkpath(tmpPath);
+
for (int i = 0; i < m_textureData->pendingGlyphs.size(); ++i) {
glyph_t glyphIndex = m_textureData->pendingGlyphs.at(i);
- QImage glyph = renderDistanceFieldGlyph(glyphIndex);
TexCoord c = m_textureData->texCoords.value(glyphIndex);
+ if (cacheDistanceFields) {
+ QString key = keyBase.arg(glyphIndex);
+ QFile file(key);
+ if (file.open(QFile::ReadOnly)) {
+ int fileSize = file.size();
+ int dim = sqrt(float(fileSize));
+ QByteArray blob = file.readAll();
+ glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, dim, dim, GL_ALPHA, GL_UNSIGNED_BYTE, blob.constData());
+ continue;
+ }
+ }
+
+ QImage glyph = renderDistanceFieldGlyph(glyphIndex);
+
if (ctx->d_ptr->workaround_brokenFBOReadBack) {
QPainter p(&m_textureData->image);
p.setCompositionMode(QPainter::CompositionMode_Source);
@@ -930,6 +960,13 @@ void QSGDistanceFieldGlyphCache::updateCache()
convert_to_Format_Alpha(&glyph);
glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits());
+
+ if (cacheDistanceFields) {
+ QString key = keyBase.arg(glyphIndex);
+ QFile file(key);
+ file.open(QFile::WriteOnly);
+ file.write((const char *) glyph.constBits(), glyph.width() * glyph.height());
+ }
}
m_textureData->pendingGlyphs.reset();
}
diff --git a/src/declarative/scenegraph/qsgflashnode.cpp b/src/declarative/scenegraph/qsgflashnode.cpp
index c2c1919f82..7573b182fc 100644
--- a/src/declarative/scenegraph/qsgflashnode.cpp
+++ b/src/declarative/scenegraph/qsgflashnode.cpp
@@ -30,7 +30,7 @@
**
**
**
-**˚
+**
**
**
**
diff --git a/src/declarative/scenegraph/scenegraph.pri b/src/declarative/scenegraph/scenegraph.pri
index 17370804a3..3a2a7fafee 100644
--- a/src/declarative/scenegraph/scenegraph.pri
+++ b/src/declarative/scenegraph/scenegraph.pri
@@ -9,8 +9,6 @@ HEADERS += \
$$PWD/coreapi/qsgdefaultrenderer_p.h \
$$PWD/coreapi/qsggeometry.h \
$$PWD/coreapi/qsgmaterial.h \
- $$PWD/coreapi/qsgmatrix4x4stack.h \
- $$PWD/coreapi/qsgmatrix4x4stack_p.h \
$$PWD/coreapi/qsgnode.h \
$$PWD/coreapi/qsgnodeupdater_p.h \
$$PWD/coreapi/qsgrenderer_p.h
@@ -18,7 +16,6 @@ SOURCES += \
$$PWD/coreapi/qsgdefaultrenderer.cpp \
$$PWD/coreapi/qsggeometry.cpp \
$$PWD/coreapi/qsgmaterial.cpp \
- $$PWD/coreapi/qsgmatrix4x4stack.cpp \
$$PWD/coreapi/qsgnode.cpp \
$$PWD/coreapi/qsgnodeupdater.cpp \
$$PWD/coreapi/qsgrenderer.cpp
diff --git a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp
index 8044b8097a..b5aaa007e9 100644
--- a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp
+++ b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp
@@ -328,7 +328,6 @@ void tst_qdeclarativeimage::mirror()
p_e.drawPixmap(QRect(0, 0, width, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
break;
case QDeclarativeImage::PreserveAspectFit:
- QEXPECT_FAIL("", "QTBUG-19538", Continue);
p_e.drawPixmap(QRect(25, 0, width / (width/height), height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
break;
case QDeclarativeImage::PreserveAspectCrop:
diff --git a/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp b/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp
index fda16409b7..1aa9a5d5b1 100644
--- a/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp
+++ b/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp
@@ -332,6 +332,7 @@ void tst_qdeclarativeinstruction::dump()
i.storeScriptString.propertyIndex = 24;
i.storeScriptString.value = 3;
i.storeScriptString.scope = 1;
+ i.storeScriptString.bindingId = 3;
data->addInstruction(i);
}
@@ -535,7 +536,7 @@ void tst_qdeclarativeinstruction::dump()
<< "25\t\tSTORE_VARIANT_OBJECT\t22"
<< "26\t\tSTORE_INTERFACE\t\t23"
<< "27\t\tSTORE_SIGNAL\t\t2\t3\t\t\"console.log(1921)\""
- << "28\t\tSTORE_SCRIPT_STRING\t24\t3\t1\t0"
+ << "28\t\tSTORE_SCRIPT_STRING\t24\t3\t1\t3"
<< "29\t\tASSIGN_SIGNAL_OBJECT\t0\t\t\t\"mySignal\""
<< "30\t\tASSIGN_CUSTOMTYPE\t25\t6\t9"
<< "31\t\tSTORE_BINDING\t26\t3\t2"
diff --git a/tests/auto/declarative/qdeclarativetranslation/data/idtranslation.qml b/tests/auto/declarative/qdeclarativetranslation/data/idtranslation.qml
new file mode 100644
index 0000000000..4a5498281a
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetranslation/data/idtranslation.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+QtObject {
+ property string _idTranslation2: QT_TRID_NOOP("qtn_hello_world")
+ property string idTranslation: qsTrId("qtn_hello_world")
+ property string idTranslation2: qsTrId(_idTranslation2)
+}
diff --git a/tests/auto/declarative/qdeclarativetranslation/data/qml_fr.qm b/tests/auto/declarative/qdeclarativetranslation/data/qml_fr.qm
new file mode 100644
index 0000000000..252022515a
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetranslation/data/qml_fr.qm
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativetranslation/data/qml_fr.ts b/tests/auto/declarative/qdeclarativetranslation/data/qml_fr.ts
new file mode 100644
index 0000000000..b003e239bc
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetranslation/data/qml_fr.ts
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr" sourcelanguage="en">
+<context>
+ <name>CustomContext</name>
+ <message>
+ <location filename="translation.qml" line="5"/>
+ <location filename="translation.qml" line="11"/>
+ <source>goodbye</source>
+ <translation>au revoir</translation>
+ </message>
+ <message>
+ <location filename="translation.qml" line="8"/>
+ <source>see ya</source>
+ <comment>informal &apos;goodbye&apos;</comment>
+ <translation>à plus tard</translation>
+ </message>
+</context>
+<context>
+ <name>translation</name>
+ <message>
+ <location filename="translation.qml" line="4"/>
+ <location filename="translation.qml" line="10"/>
+ <source>hello</source>
+ <translation>bonjour</translation>
+ </message>
+ <message>
+ <location filename="translation.qml" line="7"/>
+ <source>hi</source>
+ <comment>informal &apos;hello&apos;</comment>
+ <translation>salut</translation>
+ </message>
+ <message numerus="yes">
+ <location filename="translation.qml" line="15"/>
+ <location filename="translation.qml" line="16"/>
+ <source>%n duck(s)</source>
+ <translation>
+ <numerusform>%n canard</numerusform>
+ <numerusform>%n canards</numerusform>
+ </translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/declarative/qdeclarativetranslation/data/qmlid_fr.qm b/tests/auto/declarative/qdeclarativetranslation/data/qmlid_fr.qm
new file mode 100644
index 0000000000..265164916f
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetranslation/data/qmlid_fr.qm
Binary files differ
diff --git a/tests/auto/declarative/qdeclarativetranslation/data/qmlid_fr.ts b/tests/auto/declarative/qdeclarativetranslation/data/qmlid_fr.ts
new file mode 100644
index 0000000000..bff39b80b6
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetranslation/data/qmlid_fr.ts
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr">
+<context>
+ <name></name>
+ <message id="qtn_hello_world">
+ <location filename="idtranslation.qml" line="4"/>
+ <location filename="idtranslation.qml" line="5"/>
+ <source></source>
+ <translation>bonjour tout le monde</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/declarative/qdeclarativetranslation/data/translation.qml b/tests/auto/declarative/qdeclarativetranslation/data/translation.qml
new file mode 100644
index 0000000000..89db1d2262
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetranslation/data/translation.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.0
+
+QtObject {
+ property string basic: qsTr("hello")
+ property string basic2: qsTranslate("CustomContext", "goodbye")
+
+ property string disambiguation: qsTr("hi", "informal 'hello'")
+ property string disambiguation2: qsTranslate("CustomContext", "see ya", "informal 'goodbye'")
+
+ property string _noop: QT_TR_NOOP("hello")
+ property string _noop2: QT_TRANSLATE_NOOP("CustomContext", "goodbye")
+ property string noop: qsTr(_noop)
+ property string noop2: qsTranslate("CustomContext", _noop2)
+
+ property string singular: qsTr("%n duck(s)", "", 1)
+ property string plural: qsTr("%n duck(s)", "", 2)
+}
diff --git a/tests/auto/declarative/qdeclarativetranslation/qdeclarativetranslation.pro b/tests/auto/declarative/qdeclarativetranslation/qdeclarativetranslation.pro
new file mode 100644
index 0000000000..c970a0c70e
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetranslation/qdeclarativetranslation.pro
@@ -0,0 +1,17 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativetranslation.cpp
+
+symbian: {
+ importFiles.files = data
+ importFiles.path = .
+ DEPLOYMENT += importFiles
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private
diff --git a/tests/auto/declarative/qdeclarativetranslation/tst_qdeclarativetranslation.cpp b/tests/auto/declarative/qdeclarativetranslation/tst_qdeclarativetranslation.cpp
new file mode 100644
index 0000000000..5b88b548c9
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativetranslation/tst_qdeclarativetranslation.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QDeclarativeEngine>
+#include <QDeclarativeComponent>
+#include <QTranslator>
+#include <QDebug>
+
+#ifdef Q_OS_SYMBIAN
+// In Symbian OS test data is located in applications private dir
+#define SRCDIR "."
+#endif
+
+class tst_qdeclarativetranslation : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qdeclarativetranslation() {}
+
+private slots:
+ void translation();
+ void idTranslation();
+};
+
+inline QUrl TEST_FILE(const QString &filename)
+{
+ return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
+}
+
+void tst_qdeclarativetranslation::translation()
+{
+ QTranslator translator;
+ translator.load(QLatin1String("qml_fr"), QLatin1String(SRCDIR) + QLatin1String("/data"));
+ QApplication::installTranslator(&translator);
+
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, TEST_FILE("translation.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("basic").toString(), QLatin1String("bonjour"));
+ QCOMPARE(object->property("basic2").toString(), QLatin1String("au revoir"));
+ QCOMPARE(object->property("disambiguation").toString(), QLatin1String("salut"));
+ QCOMPARE(object->property("disambiguation2").toString(), QString::fromUtf8("\xc3\xa0 plus tard"));
+ QCOMPARE(object->property("noop").toString(), QLatin1String("bonjour"));
+ QCOMPARE(object->property("noop2").toString(), QLatin1String("au revoir"));
+ QCOMPARE(object->property("singular").toString(), QLatin1String("1 canard"));
+ QCOMPARE(object->property("plural").toString(), QLatin1String("2 canards"));
+
+ QApplication::removeTranslator(&translator);
+ delete object;
+}
+
+void tst_qdeclarativetranslation::idTranslation()
+{
+ QTranslator translator;
+ translator.load(QLatin1String("qmlid_fr"), QLatin1String(SRCDIR) + QLatin1String("/data"));
+ QApplication::installTranslator(&translator);
+
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, TEST_FILE("idtranslation.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("idTranslation").toString(), QLatin1String("bonjour tout le monde"));
+ QCOMPARE(object->property("idTranslation2").toString(), QLatin1String("bonjour tout le monde"));
+
+ QApplication::removeTranslator(&translator);
+ delete object;
+}
+
+QTEST_MAIN(tst_qdeclarativetranslation)
+
+#include "tst_qdeclarativetranslation.moc"
diff --git a/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData.qml b/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData.qml
index c98555cd2f..442932be26 100644
--- a/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData.qml
+++ b/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData.qml
@@ -14,7 +14,7 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
if (x.readyState == XMLHttpRequest.DONE) {
- if (reqType == "HEAD")
+ if (reqType == "HEAD" || reqType == "DELETE")
dataOK = (x.responseText == "");
else
dataOK = (x.responseText == "QML Rocks!\n");
diff --git a/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData_DELETE.expect b/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData_DELETE.expect
new file mode 100644
index 0000000000..b2d177aa20
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData_DELETE.expect
@@ -0,0 +1,7 @@
+DELETE /testdocument.html HTTP/1.1
+ACCEPT-LANGUAGE: en-US
+Connection: Keep-Alive
+Accept-Encoding: gzip
+User-Agent: Mozilla/5.0
+Host: 127.0.0.1:14445
+
diff --git a/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData_PUT.expect b/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData_HEAD.expect
index 74a979817d..74a979817d 100644
--- a/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData_PUT.expect
+++ b/tests/auto/declarative/qdeclarativexmlhttprequest/data/send_ignoreData_HEAD.expect
diff --git a/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp b/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp
index de16cf41f5..aad68c5926 100644
--- a/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp
+++ b/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp
@@ -497,7 +497,7 @@ void tst_qdeclarativexmlhttprequest::send_alreadySent()
delete object;
}
-// Test that send for a GET or HEAD ignores data
+// Test that sends for GET, HEAD and DELETE ignore data
void tst_qdeclarativexmlhttprequest::send_ignoreData()
{
{
@@ -522,7 +522,7 @@ void tst_qdeclarativexmlhttprequest::send_ignoreData()
{
TestHTTPServer server(SERVER_PORT);
QVERIFY(server.isValid());
- QVERIFY(server.wait(TEST_FILE("send_ignoreData_PUT.expect"),
+ QVERIFY(server.wait(TEST_FILE("send_ignoreData_HEAD.expect"),
TEST_FILE("send_ignoreData.reply"),
QUrl()));
@@ -537,6 +537,25 @@ void tst_qdeclarativexmlhttprequest::send_ignoreData()
delete object;
}
+
+ {
+ TestHTTPServer server(SERVER_PORT);
+ QVERIFY(server.isValid());
+ QVERIFY(server.wait(TEST_FILE("send_ignoreData_DELETE.expect"),
+ TEST_FILE("send_ignoreData.reply"),
+ QUrl()));
+
+ QDeclarativeComponent component(&engine, TEST_FILE("send_ignoreData.qml"));
+ QObject *object = component.beginCreate(engine.rootContext());
+ QVERIFY(object != 0);
+ object->setProperty("reqType", "DELETE");
+ object->setProperty("url", "http://127.0.0.1:14445/testdocument.html");
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("dataOK").toBool() == true);
+
+ delete object;
+ }
}
// Test that send()'ing data works
diff --git a/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp b/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp
index 7d74c0add8..ea9260772e 100644
--- a/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp
+++ b/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp
@@ -408,10 +408,7 @@ void tst_qsgtextedit::alignments()
ob->setProperty("horizontalAlignment",hAlign);
ob->setProperty("verticalAlignment",vAlign);
QTRY_COMPARE(ob->property("running").toBool(),false);
- QImage actual(canvas.width(), canvas.height(), QImage::Format_RGB32);
- actual.fill(qRgb(255,255,255));
- QPainter p(&actual);
- canvas.render(&p);
+ QImage actual = canvas.grabFrameBuffer();
expectfile = createExpectedFileIfNotFound(expectfile, actual);
@@ -458,6 +455,7 @@ void tst_qsgtextedit::hAlign()
void tst_qsgtextedit::hAlign_RightToLeft()
{
+ QSKIP("QTBUG-20017", SkipAll);
QSGView canvas(QUrl::fromLocalFile(SRCDIR "/data/horizontalAlignment_RightToLeft.qml"));
QSGTextEdit *textEdit = canvas.rootObject()->findChild<QSGTextEdit*>("text");
QVERIFY(textEdit != 0);
diff --git a/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp b/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp
index cbe14a5563..77427253a6 100644
--- a/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp
+++ b/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp
@@ -1037,12 +1037,7 @@ void tst_qsgtextinput::horizontalAlignment()
QObject *ob = canvas.rootObject();
QVERIFY(ob != 0);
ob->setProperty("horizontalAlignment",hAlign);
- QImage actual(canvas.width(), canvas.height(), QImage::Format_RGB32);
- actual.fill(qRgb(255,255,255));
- {
- QPainter p(&actual);
- canvas.render(&p);
- }
+ QImage actual = canvas.grabFrameBuffer();
expectfile = createExpectedFileIfNotFound(expectfile, actual);
@@ -1053,6 +1048,7 @@ void tst_qsgtextinput::horizontalAlignment()
void tst_qsgtextinput::horizontalAlignment_RightToLeft()
{
+ QSKIP("QTBUG-20017", SkipAll);
QSGView canvas(QUrl::fromLocalFile(SRCDIR "/data/horizontalAlignment_RightToLeft.qml"));
QSGTextInput *textInput = canvas.rootObject()->findChild<QSGTextInput*>("text");
QVERIFY(textInput != 0);
@@ -1446,6 +1442,7 @@ void tst_qsgtextinput::navigation()
void tst_qsgtextinput::navigation_RTL()
{
+ QSKIP("QTBUG-20017", SkipAll);
QSGView canvas(QUrl::fromLocalFile(SRCDIR "/data/navigation.qml"));
canvas.show();
canvas.setFocus();
@@ -1734,7 +1731,7 @@ void tst_qsgtextinput::cursorRectangle()
// Check the cursor rectangle remains within the input bounding rect when auto scrolling.
QVERIFY(r.left() < input.boundingRect().width());
- QVERIFY(r.right() >= input.width());
+ QVERIFY(r.right() >= input.width() - error);
for (int i = 6; i < text.length(); ++i) {
input.setCursorPosition(i);
@@ -2219,18 +2216,25 @@ void tst_qsgtextinput::preeditAutoScroll()
QCOMPARE(input->positionAt(0), 0);
QCOMPARE(input->positionAt(input->width()), 5);
+ // some tolerance for different fonts.
+#ifdef Q_OS_LINUX
+ const int error = 2;
+#else
+ const int error = 5;
+#endif
+
// test if the preedit is larger than the text input that the
// character preceding the cursor is still visible.
qreal x = input->positionToRectangle(0).x();
for (int i = 0; i < 3; ++i) {
ic.sendPreeditText(preeditText, i + 1);
- QVERIFY(input->cursorRectangle().right() >= fm.width(preeditText.at(i)));
+ QVERIFY(input->cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
QVERIFY(input->positionToRectangle(0).x() < x);
x = input->positionToRectangle(0).x();
}
for (int i = 1; i >= 0; --i) {
ic.sendPreeditText(preeditText, i + 1);
- QVERIFY(input->cursorRectangle().right() >= fm.width(preeditText.at(i)));
+ QVERIFY(input->cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
QVERIFY(input->positionToRectangle(0).x() > x);
x = input->positionToRectangle(0).x();
}