Falling leaves wallpaper plugin

Using QtQuick's particle shader to render a wallpaper.

change the wallpaperPlugin in your appletsrc to org.kde.autumn to try
it.

The code for the wallpaper has been borrowed from QtDeclarative
examples.
This commit is contained in:
Sebastian Kügler 2013-03-07 05:50:01 +01:00
parent 9bbb2f33f5
commit b4fb6a0bde
11 changed files with 371 additions and 0 deletions

View File

@ -2,3 +2,4 @@
add_subdirectory(desktop)
add_subdirectory(toolbox)
add_subdirectory(wallpaper)
add_subdirectory(autumn)

View File

@ -0,0 +1,4 @@
install(DIRECTORY . DESTINATION ${DATA_INSTALL_DIR}/plasma/wallpapers/org.kde.autumn PATTERN .svn EXCLUDE PATTERN CMakeLists.txt EXCLUDE PATTERN Messages.sh EXCLUDE)

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name=""/>
<group name="General">
<entry name="Color" type="Color">
<label>Color of the wallpaper</label>
<default>#0000ff</default>
</entry>
</group>
</kcfg>

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,168 @@
/*
* Copyright 2013 Marco Martin <mart@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.0
import org.kde.plasma.components 0.1 as PlasmaComponents
Column {
id: root
property alias cfg_Color: picker.color
Column {
id: picker
property color color
property real hue
property real saturation
property real lightness
onColorChanged: {
var min = Math.min(color.r, Math.min(color.g, color.b))
var max = Math.max(color.r, Math.max(color.g, color.b))
var c = max - min
var h
if (c == 0) {
h = 0
} else if (max == color.r) {
h = ((color.g - color.b) / c) % 6
} else if (max == color.g) {
h = ((color.b - color.r) / c) + 2
} else if (max == color.b) {
h = ((color.r - color.g) / c) + 4
}
picker.hue = (1/6) * h
picker.saturation = c / (1 - Math.abs(2 * ((max+min)/2) - 1))
picker.lightness = (max + min)/2
}
onHueChanged: redrawTimer.restart()
onSaturationChanged: redrawTimer.restart()
onLightnessChanged: redrawTimer.restart()
Timer {
id: redrawTimer
interval: 10
onTriggered: {
hsCanvas.requestPaint();
vCanvas.requestPaint();
hsMarker.x = Math.round(hsCanvas.width*picker.hue - 2)
hsMarker.y = Math.round(hsCanvas.width*(1-picker.saturation) - 2)
vMarker.y = Math.round(hsCanvas.height*(1-picker.lightness) - 2)
//this to work assumes the above rgb->hsl conversion is correct
picker.color = Qt.hsla(picker.hue, picker.saturation, picker.lightness, 1)
}
}
Row {
MouseArea {
width: 255
height: 255
onPressed: {
hsMarker.x = mouse.x - 2
hsMarker.y = mouse.y - 2
picker.hue = mouse.x/width
picker.saturation = 1 - hsMarker.y/height
}
onPositionChanged: {
hsMarker.x = mouse.x - 2
hsMarker.y = mouse.y - 2
picker.hue = mouse.x/width
picker.saturation = 1 - hsMarker.y/height
}
Canvas {
id: hsCanvas
anchors.fill: parent
onPaint: {
var ctx = getContext('2d');
var gradient = ctx.createLinearGradient(0, 0, width, 0)
for (var i = 0; i < 10; ++i) {
gradient.addColorStop(i/10, Qt.hsla(i/10, 1, picker.lightness, 1));
}
ctx.fillStyle = gradient
ctx.fillRect(0, 0, width, height);
gradient = ctx.createLinearGradient(0, 0, 0, height)
gradient.addColorStop(0, Qt.hsla(0, 0, picker.lightness, 0));
gradient.addColorStop(1, Qt.hsla(0, 0, picker.lightness, 1));
ctx.fillStyle = gradient
ctx.fillRect(0, 0, width, height);
}
}
Rectangle {
id: hsMarker
width: 5
height: 5
radius: 5
color: "black"
border {
color: "white"
width: 1
}
}
}
MouseArea {
width: 30
height: 255
onPressed: {
vMarker.y = mouse.y - 2
picker.lightness = 1 - vMarker.y/height
}
onPositionChanged: {
vMarker.y = mouse.y - 2
picker.lightness = 1 - vMarker.y/height
}
Canvas {
id: vCanvas
width: 30
height: 255
onPaint: {
var ctx = getContext('2d');
var gradient = ctx.createLinearGradient(0, 0, 0, height)
gradient.addColorStop(0, Qt.hsla(picker.hue, picker.saturation, 1, 1));
gradient.addColorStop(0.5, Qt.hsla(picker.hue, picker.saturation, 0.5, 1));
gradient.addColorStop(1, Qt.hsla(picker.hue, picker.saturation, 0, 1));
ctx.fillStyle = gradient
ctx.fillRect(0, 0, width, height);
}
}
Rectangle {
id: vMarker
width: 30
height: 5
radius: 5
color: "black"
border {
color: "white"
width: 1
}
}
}
}
Rectangle {
anchors {
left: parent.left
right: parent.right
}
height: 30
color: Qt.hsla(picker.hue, picker.saturation, picker.lightness, 1)
}
}
}

View File

@ -0,0 +1,167 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
import QtQuick.Particles 2.0
Item {
width: 360
height: 600
Image {
source: "../images/backgroundLeaves.jpg"
anchors.fill: parent
}
ParticleSystem {
anchors.fill: parent
Emitter {
width: parent.width
emitRate: 4
lifeSpan: 14000
size: 80
velocity: PointDirection { y: 60 }
}
Wander {
anchors.fill: parent
anchors.bottomMargin: 100
xVariance: 60
pace: 60
}
//! [0]
Affector {
property real coefficient: 0.1
property real velocity: 1.5
width: parent.width
height: parent.height - 100
onAffectParticles: {
/* //Linear movement
if (particle.r == 0) {
particle.r = Math.random() > 0.5 ? -1 : 1;
} else if (particle.r == 1) {
particle.rotation += velocity * dt;
if (particle.rotation >= maxAngle)
particle.r = -1;
} else if (particle.r == -1) {
particle.rotation -= velocity * dt;
if (particle.rotation <= -1 * maxAngle)
particle.r = 1;
}
*/
//Wobbly movement
for (var i=0; i<particles.length; i++) {
var particle = particles[i];
if (particle.r == 0.0) {
particle.r = Math.random() + 0.01;
}
particle.rotation += velocity * particle.r * dt;
particle.r -= particle.rotation * coefficient;
if (particle.r == 0.0)
particle.r -= particle.rotation * 0.000001;
particle.update = 1;
}
}
}
//! [0]
//! [1]
Affector {//Custom Friction, adds some 'randomness'
x: -60
width: parent.width + 120
height: 100
anchors.bottom: parent.bottom
onAffectParticles: {
for (var i=0; i<particles.length; i++) {
var particle = particles[i];
var pseudoRand = (Math.floor(particle.t*1327) % 10) + 1;
var yslow = dt * pseudoRand * 0.5 + 1;
var xslow = dt * pseudoRand * 0.05 + 1;
if (particle.vy < 1)
particle.vy = 0;
else
particle.vy = (particle.vy / yslow);
if (particle.vx < 1)
particle.vx = 0;
else
particle.vx = (particle.vx / xslow);
particle.update = true;
}
}
}
//! [1]
ImageParticle {
anchors.fill: parent
id: particles
sprites: [Sprite {
source: "../images/realLeaf1.png"
frameCount: 1
frameDuration: 1
to: {"a":1, "b":1, "c":1, "d":1}
}, Sprite {
name: "a"
source: "../images/realLeaf1.png"
frameCount: 1
frameDuration: 10000
},
Sprite {
name: "b"
source: "../images/realLeaf2.png"
frameCount: 1
frameDuration: 10000
},
Sprite {
name: "c"
source: "../images/realLeaf3.png"
frameCount: 1
frameDuration: 10000
},
Sprite {
name: "d"
source: "../images/realLeaf4.png"
frameCount: 1
frameDuration: 10000
}
]
z:4
}
}
}

View File

@ -0,0 +1,16 @@
[Desktop Entry]
Encoding=UTF-8
Keywords=
Name=Autumn
Type=Service
Icon=java
X-KDE-ParentApp=
X-KDE-PluginInfo-Author=Sebastian Kügler
X-KDE-PluginInfo-Category=
X-KDE-PluginInfo-Email=sebas@kde.org
X-KDE-PluginInfo-License=GPLv2+
X-KDE-PluginInfo-Name=org.kde.autumn
X-KDE-PluginInfo-Version=
X-KDE-PluginInfo-Website=
X-Plasma-MainScript=ui/main.qml