Immense Particles Refactor Part C
[profile/ivi/qtdeclarative.git] / demos / declarative / flickr / content / ImageDetails.qml
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 import QtQuick 2.0
43 import QtQuick.Particles 2.0
44
45 Flipable {
46     id: container
47
48     property alias frontContainer: containerFront
49     property string photoTitle: ""
50     property string photoTags: ""
51     property int photoWidth
52     property int photoHeight
53     property string photoType
54     property string photoAuthor
55     property string photoDate
56     property string photoUrl
57     property int rating: 2
58     property variant prevScale: 1.0
59
60     property int flipDuration: 1600
61
62     signal closed
63
64     transform: Rotation {
65         id: itemRotation
66         origin.x: container.width / 2;
67         axis.y: 1; axis.z: 0
68     }
69
70     front: Item {
71         id: containerFront; anchors.fill: container
72
73         Rectangle {
74             anchors.fill: parent
75             color: "black"; opacity: 0.4
76         }
77
78         Column {
79             spacing: 10
80             anchors {
81                 left: parent.left; leftMargin: 10
82                 right: parent.right; rightMargin: 10
83                 top: parent.top; topMargin: 120
84             }
85             Text { font.bold: true; color: "white"; elide: Text.ElideRight; text: container.photoTitle; width: parent.width }
86             Text { color: "white"; elide: Text.ElideRight; text: "Size: " + container.photoWidth + 'x' + container.photoHeight; width: parent.width }
87             Text { color: "white"; elide: Text.ElideRight; text: "Type: " + container.photoType; width: parent.width }
88             Text { color: "white"; elide: Text.ElideRight; text: "Author: " + container.photoAuthor; width: parent.width }
89             Text { color: "white"; elide: Text.ElideRight; text: "Published: " + container.photoDate; width: parent.width }
90             Text { color: "white"; elide: Text.ElideRight; text: container.photoTags == "" ? "" : "Tags: "; width: parent.width }
91             Text { color: "white"; elide: Text.ElideRight; text: container.photoTags; width: parent.width }
92         }
93     }
94
95     back: Item {
96         anchors.fill: container
97
98         Rectangle { anchors.fill: parent; color: "black"; opacity: 0.4 }
99
100         Progress {
101             anchors.centerIn: parent; width: 200; height: 22
102             progress: bigImage.progress; visible: bigImage.status != Image.Ready
103         }
104
105         Flickable {
106             id: flickable; anchors.fill: parent; clip: true
107             contentWidth: imageContainer.width; contentHeight: imageContainer.height
108
109             function updateMinimumScale() {
110                 if (bigImage.status == Image.Ready && bigImage.width != 0) {
111                     slider.minimum = Math.min(flickable.width / bigImage.width, flickable.height / bigImage.height);
112                     if (bigImage.width * slider.value > flickable.width) {
113                         var xoff = (flickable.width/2 + flickable.contentX) * slider.value / prevScale;
114                         flickable.contentX = xoff - flickable.width/2;
115                     }
116                     if (bigImage.height * slider.value > flickable.height) {
117                         var yoff = (flickable.height/2 + flickable.contentY) * slider.value / prevScale;
118                         flickable.contentY = yoff - flickable.height/2;
119                     }
120                     prevScale = slider.value;
121                 }
122             }
123
124             onWidthChanged: updateMinimumScale()
125             onHeightChanged: updateMinimumScale()
126
127             Item {
128                 id: imageContainer
129                 width: Math.max(bigImage.width * bigImage.scale, flickable.width);
130                 height: Math.max(bigImage.height * bigImage.scale, flickable.height);
131                 Image {
132                     id: bigImage; source: container.photoUrl; scale: slider.value
133                     anchors.centerIn: parent; smooth: !flickable.movingVertically
134                     onStatusChanged : {
135                         // Default scale shows the entire image.
136                         if (bigImage.status == Image.Ready && bigImage.width != 0) {
137                             slider.minimum = Math.min(flickable.width / bigImage.width, flickable.height / bigImage.height);
138                             prevScale = Math.min(slider.minimum, 1);
139                             slider.value = prevScale;
140                         }
141                         if (inBackState && bigImage.status == Image.Ready)
142                             effectBox.imageInAnim();
143                     }
144                     property bool inBackState: false
145                     onInBackStateChanged:{
146                         if(inBackState && bigImage.status == Image.Ready)
147                             effectBox.imageInAnim();
148                         else if (!inBackState && bigImage.status == Image.Ready)
149                             effectBox.imageOutAnim();
150                     }
151                 }
152                 ShaderEffectSource{
153                     id: pictureSource
154                     sourceItem: bigImage 
155                     smooth: true
156                     //Workaround: Doesn't work below lines
157                     width: bigImage.width
158                     height: bigImage.width
159                     visible: false
160                 }
161                 Turbulence{//only fill visible rect
162                     id: turbulence
163                     system: imageSystem
164                     anchors.fill: parent 
165                     frequency: 100
166                     strength: 250
167                     active: false
168                 }
169
170                 Item{
171                     id: effectBox
172                     width: bigImage.width * bigImage.scale
173                     height: bigImage.height * bigImage.scale
174                     anchors.centerIn: parent
175                     function imageInAnim(){
176                         bigImage.visible = false;
177                         noiseIn.visible = true;
178                         endEffectTimer.start();
179                     }
180                     function imageOutAnim(){
181                         bigImage.visible = false;
182                         noiseIn.visible = false;
183                         turbulence.active = true;
184                         endEffectTimer.start();
185                         pixelEmitter.burst(2048);
186                     }
187                     Timer{
188                         id: endEffectTimer
189                         interval: flipDuration
190                         repeat: false
191                         running: false
192                         onTriggered:{
193                             turbulence.active = false;
194                             noiseIn.visible = false;
195                             bigImage.visible = true;
196                         }
197                     }
198                     ShaderEffectItem{
199                         id: noiseIn
200                         anchors.fill: parent
201                         property real t: 0
202                         visible: false
203                         onVisibleChanged: tAnim.start()
204                         NumberAnimation{
205                             id: tAnim
206                             target: noiseIn
207                             property: "t"
208                             from: 0.0 
209                             to: 1.0
210                             duration: flipDuration
211                         }
212                         property variant source: pictureSource
213                         property variant noise: ShaderEffectSource{
214                             sourceItem:Image{
215                                 source: "images/noise.png"
216                             }
217                             hideSource: true
218                             smooth: false
219                         }
220                         fragmentShader:"
221                             uniform sampler2D noise;
222                             uniform sampler2D source;
223                             uniform highp float t;
224                             uniform lowp float qt_Opacity;
225                             varying highp vec2 qt_TexCoord0;
226                             void main(){
227                                 //Want to use noise2, but it always returns (0,0)?
228                                 if(texture2D(noise, qt_TexCoord0).w <= t)
229                                     gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity;
230                                 else
231                                     gl_FragColor = vec4(0.,0.,0.,0.);
232                             }
233                         "
234                     }
235                     ParticleSystem{
236                         id: imageSystem
237                     }
238                     Emitter{
239                         id: pixelEmitter
240                         system: imageSystem
241                         //anchors.fill: parent
242                         width: Math.min(bigImage.width * bigImage.scale, flickable.width);
243                         height: Math.min(bigImage.height * bigImage.scale, flickable.height);
244                         anchors.centerIn: parent
245                         particleSize: 4
246                         particleDuration: flipDuration
247                         particlesPerSecond: 2048
248                         emitting: false
249                     }
250                     CustomParticle{
251                         id: blowOut
252                         system: imageSystem
253                         property real maxWidth: effectBox.width
254                         property real maxHeight: effectBox.height
255                         vertexShader:"
256                             attribute highp vec2 vPos;
257                             attribute highp vec2 vTex;
258                             attribute highp vec4 vData; //  x = time,  y = lifeSpan, z = size,  w = endSize
259                             attribute highp vec4 vVec; // x,y = constant speed,  z,w = acceleration
260                             attribute highp float r;
261
262                             uniform highp float maxWidth;
263                             uniform highp float maxHeight;
264
265                             uniform highp mat4 qt_ModelViewProjectionMatrix;
266                             uniform highp float timestamp;
267                             uniform lowp float qt_Opacity;
268
269                             varying highp vec2 fTex2;
270                             varying lowp float fFade;
271
272                             void main() {
273                                 fTex2 = vec2(vPos.x / maxWidth, vPos.y / maxHeight);
274                                 highp float size = vData.z;
275                                 highp float endSize = vData.w;
276
277                                 highp float t = (timestamp - vData.x) / vData.y;
278
279                                 highp float currentSize = mix(size, endSize, t * t);
280
281                                 if (t < 0. || t > 1.)
282                                 currentSize = 0.;
283
284                                 highp vec2 pos = vPos
285                                 - currentSize / 2. + currentSize * vTex          // adjust size
286                                 + vVec.xy * t * vData.y         // apply speed vector..
287                                 + 0.5 * vVec.zw * pow(t * vData.y, 2.);
288
289                                 gl_Position = qt_ModelViewProjectionMatrix * vec4(pos.x, pos.y, 0, 1);
290
291                                 highp float fadeIn = min(t * 10., 1.);
292                                 highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
293
294                                 fFade = 1.0;//fadeIn * fadeOut * qt_Opacity;
295                             }
296                         "
297                         property variant pictureTexture: pictureSource
298                         fragmentShader: "
299                             uniform sampler2D pictureTexture;
300                             varying highp vec2 fTex2;
301                             varying highp float fFade;
302                             void main() {
303                                 gl_FragColor = texture2D(pictureTexture, fTex2) * fFade;
304                         }"
305                     }
306
307
308
309                 }
310             }
311         }
312
313         Text {
314             text: "Image Unavailable"
315             visible: bigImage.status == Image.Error
316             anchors.centerIn: parent; color: "white"; font.bold: true
317         }
318
319         Slider {
320             id: slider; visible: { bigImage.status == Image.Ready && maximum > minimum }
321             anchors {
322                 bottom: parent.bottom; bottomMargin: 65
323                 left: parent.left; leftMargin: 25
324                 right: parent.right; rightMargin: 25
325             }
326             onValueChanged: {
327                 if (bigImage.width * value > flickable.width) {
328                     var xoff = (flickable.width/2 + flickable.contentX) * value / prevScale;
329                     flickable.contentX = xoff - flickable.width/2;
330                 }
331                 if (bigImage.height * value > flickable.height) {
332                     var yoff = (flickable.height/2 + flickable.contentY) * value / prevScale;
333                     flickable.contentY = yoff - flickable.height/2;
334                 }
335                 prevScale = value;
336             }
337         }
338     }
339
340     states: State {
341         name: "Back"
342         PropertyChanges { target: itemRotation; angle: 180 }
343         PropertyChanges { target: toolBar; button2Visible: false }
344         PropertyChanges { target: toolBar; button1Label: "Back" }
345         PropertyChanges { target: bigImage; inBackState: true }
346     }
347
348     transitions: Transition {
349         SequentialAnimation {
350             PropertyAction { target: bigImage; property: "smooth"; value: false }
351             NumberAnimation { easing.type: Easing.InOutQuad; properties: "angle"; duration: flipDuration }
352             PropertyAction { target: bigImage; property: "smooth"; value: !flickable.movingVertically }
353         }
354     }
355 }