Use a shader to animate the applet's busy state

This is just an experiment to show how we can use shaders for our
animations within the containment. It seems to work nicely.

The shader code has been borrowed from the shadereffects example in Qt's
declarative module.
This commit is contained in:
Sebastian Kügler 2013-03-07 05:37:48 +01:00
parent 239fe72c47
commit 9bbb2f33f5

View File

@ -43,11 +43,14 @@ Item {
Component { Component {
id: appletContainerComponent id: appletContainerComponent
PlasmaCore.FrameSvgItem { Item {
id: frame id: frameParent
x: 50 x: 50
y: 50 y: 50
property int small: 90
property int large: 400
width: large + frame.margins.left + frame.margins.right width: large + frame.margins.left + frame.margins.right
height: large + frame.margins.top + frame.margins.bottom height: large + frame.margins.top + frame.margins.bottom
@ -57,9 +60,9 @@ Item {
killAnim.running = true killAnim.running = true
} }
} }
PlasmaCore.FrameSvgItem {
property int small: 90 id: frame
property int large: 400 anchors.fill: parent
property int tm: 0 property int tm: 0
property int lm: 0 property int lm: 0
@ -69,24 +72,24 @@ Item {
onImagePathChanged: { onImagePathChanged: {
// Reposition applet so it fits into the frame // Reposition applet so it fits into the frame
if (imagePath == "") { if (imagePath == "") {
frame.x = frame.x + lm; frameParent.x = frameParent.x + lm;
frame.y = frame.y + tm; frameParent.y = frameParent.y + tm;
} else { } else {
// Cache values, so we can subtract them when the background is removed // Cache values, so we can subtract them when the background is removed
frame.lm = frame.margins.left; frame.lm = frame.margins.left;
frame.tm = frame.margins.top; frame.tm = frame.margins.top;
frame.x = frame.x - frame.margins.left; frameParent.x = frameParent.x - frame.margins.left;
frame.y = frame.y - frame.margins.top; frameParent.y = frameParent.y - frame.margins.top;
} }
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
drag.target: parent drag.target: frameParent
onClicked: { onClicked: {
var s = (frame.width == frame.large) ? frame.small : frame.large; var s = (frameParent.width == frameParent.large) ? frameParent.small : frameParent.large;
frame.height = s frameParent.height = s
frame.width = s frameParent.width = s
} }
} }
@ -102,6 +105,7 @@ Item {
} }
PlasmaComponents.BusyIndicator { PlasmaComponents.BusyIndicator {
id: busyIndicator
z: 1000 z: 1000
visible: applet.length > 0 && applet[0].busy visible: applet.length > 0 && applet[0].busy
running: visible running: visible
@ -118,6 +122,60 @@ Item {
ScriptAction { script: frame.destroy()} ScriptAction { script: frame.destroy()}
} }
} }
ShaderEffect {
id: wobbleShader
anchors.fill: frame
property variant source: ShaderEffectSource {
id: theSource
sourceItem: frame
}
opacity: 0
property int fadeDuration: 250
property real amplitude: busyIndicator.visible ? 0.04 * 0.2 : 0
property real frequency: 20
property real time: 0
NumberAnimation on time { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 600 }
Behavior on amplitude { NumberAnimation { duration: wobbleShader.fadeDuration } }
//! [fragment]
fragmentShader: {
"uniform lowp float qt_Opacity;" +
"uniform highp float amplitude;" +
"uniform highp float frequency;" +
"uniform highp float time;" +
"uniform sampler2D source;" +
"varying highp vec2 qt_TexCoord0;" +
"void main() {" +
" highp vec2 p = sin(time + frequency * qt_TexCoord0);" +
" gl_FragColor = texture2D(source, qt_TexCoord0 + amplitude * vec2(p.y, -p.x)) * qt_Opacity;" +
"}"
}
// compose the item on-screen, we want to render
// either the shader item or the source item,
// so swap their opacity as the wobbling fades in
// and after it fades out
Connections {
target: busyIndicator
onVisibleChanged: {
if (busyIndicator.visible) {
wobbleShader.opacity = 1;
frame.opacity = 0;
} else {
hideTimer.start();
}
}
}
Timer {
id: hideTimer
interval: wobbleShader.fadeDuration
onTriggered: {
wobbleShader.opacity = 0;
frame.opacity = 1;
}
}
//! [fragment]
}
}
} }
Component.onCompleted: { Component.onCompleted: {