Added improvements to the snow effect. Patch by Torgny Johansson.
svn path=/trunk/KDE/kdebase/workspace/; revision=870683
This commit is contained in:
parent
6fd28f8260
commit
4982bb9909
4 changed files with 233 additions and 29 deletions
150
effects/snow.cpp
150
effects/snow.cpp
|
@ -2,7 +2,8 @@
|
|||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2007 Martin Gräßlin <ubuntu@martin-graesslin.com
|
||||
Copyright (C) 2007 Martin Gräßlin <ubuntu@martin-graesslin.com>
|
||||
Copyright (C) 2008 Torgny Johansson <torgny.johansson@gmail.com>
|
||||
|
||||
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
|
||||
|
@ -39,7 +40,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
|
@ -70,9 +70,11 @@ SnowEffect::~SnowEffect()
|
|||
void SnowEffect::reconfigure( ReconfigureFlags )
|
||||
{
|
||||
KConfigGroup conf = effects->effectConfig("Snow");
|
||||
mNumberFlakes = conf.readEntry("Number", 50);
|
||||
mNumberFlakes = conf.readEntry("Number", 200);
|
||||
mMinFlakeSize = conf.readEntry("MinFlakes", 10);
|
||||
mMaxFlakeSize = conf.readEntry("MaxFlakes", 50);
|
||||
mMaxVSpeed = conf.readEntry("MaxVSpeed", 2);
|
||||
mMaxHSpeed = conf.readEntry("MaxHSpeed", 1);
|
||||
}
|
||||
|
||||
void SnowEffect::prePaintScreen( ScreenPrePaintData& data, int time )
|
||||
|
@ -81,29 +83,30 @@ void SnowEffect::prePaintScreen( ScreenPrePaintData& data, int time )
|
|||
{
|
||||
if (! flakes )
|
||||
{
|
||||
flakes = new QList<QRect>();
|
||||
flakes = new QList<SnowFlake>();
|
||||
lastFlakeTime.start();
|
||||
}
|
||||
int count = flakes->count();
|
||||
for (int i=0; i<count; i++)
|
||||
{
|
||||
// move flake to bottom. Therefore pop the flake, change y and push
|
||||
// move flake to bottom. Therefore pop the flake, change x and y and push
|
||||
// flake back to QVector
|
||||
QRect flake = flakes->first();
|
||||
SnowFlake flake = flakes->first();
|
||||
flakes->pop_front();
|
||||
int size = flake.height();
|
||||
int y = flake.y();
|
||||
// if flake has reached bottom, don't push it back
|
||||
if ( y >= QApplication::desktop()->geometry().bottom() )
|
||||
// if flake has reached bottom, left or right don't push it back
|
||||
if ( flake.getY() >= QApplication::desktop()->geometry().bottom() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int speed;
|
||||
float factor = (float)(size-mMinFlakeSize) / (float)(mMaxFlakeSize-mMinFlakeSize);
|
||||
if (factor >= 0.5) speed = 2;
|
||||
else speed = 1;
|
||||
flake.setY(y + speed);
|
||||
flake.setHeight(size);
|
||||
else if (flake.getX()+flake.getWidth() <= QApplication::desktop()->geometry().left() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (flake.getX() >= QApplication::desktop()->geometry().right() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
flake.updateSpeedAndRotation();
|
||||
flakes->append(flake);
|
||||
}
|
||||
// if number of active snowflakes is smaller than maximum number
|
||||
|
@ -113,17 +116,13 @@ void SnowEffect::prePaintScreen( ScreenPrePaintData& data, int time )
|
|||
int size = 0;
|
||||
while ( size < mMinFlakeSize )
|
||||
size = random() % mMaxFlakeSize;
|
||||
QRect flake = QRect( random() % (QApplication::desktop()->geometry().right() - size), -1 * size, size, size );
|
||||
SnowFlake flake = SnowFlake( random() % (QApplication::desktop()->geometry().right() - size), -1 * size, size, size, mMaxVSpeed, mMaxHSpeed );
|
||||
flakes->append( flake );
|
||||
|
||||
// calculation of next time of snowflake
|
||||
// depends on the time the flow needs to get to the bottom (screen size)
|
||||
// and the fps
|
||||
int speed;
|
||||
float factor = (float)(size-mMinFlakeSize) / (float)(mMaxFlakeSize-mMinFlakeSize);
|
||||
if (factor >= 0.5) speed = 4;
|
||||
else speed = 2;
|
||||
long next = ((1000/(time+5))*(Effect::displayHeight()/speed))/mNumberFlakes;
|
||||
long next = ((500/(time+5))*(Effect::displayHeight()/flake.getVSpeed()))/mNumberFlakes;
|
||||
nextFlakeMillis = next;
|
||||
lastFlakeTime.restart();
|
||||
}
|
||||
|
@ -144,9 +143,28 @@ void SnowEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
|
|||
texture->bind();
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
for (int i=0; i<flakes->count(); i++)
|
||||
{
|
||||
texture->render( region, flakes->at(i));
|
||||
SnowFlake flake = flakes->at(i);
|
||||
|
||||
// save the matrix
|
||||
glPushMatrix();
|
||||
|
||||
// translate to the center of the flake
|
||||
glTranslatef(flake.getWidth()/2 + flake.getX(), flake.getHeight()/2 + flake.getY(), 0);
|
||||
|
||||
// rotate around the Z-axis
|
||||
glRotatef(flake.getRotationAngle(), 0.0, 0.0, 1.0);
|
||||
|
||||
// translate back to the starting point
|
||||
glTranslatef(-flake.getWidth()/2 - flake.getX(), -flake.getHeight()/2 - flake.getY(), 0);
|
||||
|
||||
// paint the snowflake
|
||||
texture->render( region, flake.getRect());
|
||||
|
||||
// restore the matrix
|
||||
glPopMatrix();
|
||||
}
|
||||
texture->unbind();
|
||||
glPopAttrib();
|
||||
|
@ -182,4 +200,90 @@ void SnowEffect::loadTexture()
|
|||
}
|
||||
|
||||
|
||||
// the snowflake class
|
||||
SnowFlake::SnowFlake(int x, int y, int width, int height, int maxVSpeed, int maxHSpeed)
|
||||
{
|
||||
int minVSpeed = maxVSpeed - 8; // 8 gives a nice difference in speed
|
||||
if(minVSpeed < 1) minVSpeed = 1;
|
||||
vSpeed = random()%maxVSpeed + minVSpeed;
|
||||
|
||||
hSpeed = random()%(maxHSpeed+1);
|
||||
if(random()%2 < 1) hSpeed = -hSpeed; // to create negativ hSpeeds at random
|
||||
|
||||
rotationAngle = 0;
|
||||
rotationSpeed = random()%4 - 2;
|
||||
if(rotationSpeed == 0) rotationSpeed = 0.5;
|
||||
rect = QRect(x, y, width, height);
|
||||
}
|
||||
|
||||
SnowFlake::~SnowFlake()
|
||||
{
|
||||
}
|
||||
|
||||
int SnowFlake::getHSpeed()
|
||||
{
|
||||
return hSpeed;
|
||||
}
|
||||
|
||||
QRect SnowFlake::getRect()
|
||||
{
|
||||
return rect;
|
||||
}
|
||||
|
||||
void SnowFlake::updateSpeedAndRotation()
|
||||
{
|
||||
rotationAngle = rotationAngle+rotationSpeed;
|
||||
rect.translate(hSpeed, vSpeed);
|
||||
}
|
||||
|
||||
float SnowFlake::getRotationAngle()
|
||||
{
|
||||
return rotationAngle;
|
||||
}
|
||||
|
||||
int SnowFlake::getVSpeed()
|
||||
{
|
||||
return vSpeed;
|
||||
}
|
||||
|
||||
int SnowFlake::getHeight()
|
||||
{
|
||||
return rect.height();
|
||||
}
|
||||
|
||||
int SnowFlake::getWidth()
|
||||
{
|
||||
return rect.width();
|
||||
}
|
||||
|
||||
int SnowFlake::getX()
|
||||
{
|
||||
return rect.x();
|
||||
}
|
||||
|
||||
int SnowFlake::getY()
|
||||
{
|
||||
return rect.y();
|
||||
}
|
||||
|
||||
void SnowFlake::setHeight(int height)
|
||||
{
|
||||
rect.setHeight(height);
|
||||
}
|
||||
|
||||
void SnowFlake::setWidth(int width)
|
||||
{
|
||||
rect.setWidth(width);
|
||||
}
|
||||
|
||||
void SnowFlake::setX(int x)
|
||||
{
|
||||
rect.setX(x);
|
||||
}
|
||||
|
||||
void SnowFlake::setY(int y)
|
||||
{
|
||||
rect.setY(y);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2007 Martin Gräßlin <ubuntu@martin-graesslin.com
|
||||
Copyright (C) 2007 Martin Gräßlin <ubuntu@martin-graesslin.com>
|
||||
Copyright (C) 2008 Torgny Johansson <torgny.johansson@gmail.com>
|
||||
|
||||
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
|
||||
|
@ -32,6 +33,33 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
class SnowFlake
|
||||
{
|
||||
public:
|
||||
SnowFlake(int x, int y, int width, int height, int maxVSpeed, int maxHSpeed);
|
||||
virtual ~SnowFlake();
|
||||
int getHSpeed();
|
||||
int getVSpeed();
|
||||
float getRotationAngle();
|
||||
void updateSpeedAndRotation();
|
||||
int getHeight();
|
||||
int getWidth();
|
||||
int getX();
|
||||
int getY();
|
||||
QRect getRect();
|
||||
void setHeight(int height);
|
||||
void setWidth(int width);
|
||||
void setX(int x);
|
||||
void setY(int y);
|
||||
|
||||
private:
|
||||
QRect rect;
|
||||
int vSpeed;
|
||||
int hSpeed;
|
||||
float rotationAngle;
|
||||
float rotationSpeed;
|
||||
};
|
||||
|
||||
class SnowEffect
|
||||
: public QObject, public Effect
|
||||
{
|
||||
|
@ -49,12 +77,14 @@ class SnowEffect
|
|||
private:
|
||||
void loadTexture();
|
||||
GLTexture* texture;
|
||||
QList<QRect>* flakes;
|
||||
QList<SnowFlake>* flakes;
|
||||
QTime lastFlakeTime;
|
||||
long nextFlakeMillis;
|
||||
int mNumberFlakes;
|
||||
int mMinFlakeSize;
|
||||
int mMaxFlakeSize;
|
||||
int mMaxVSpeed;
|
||||
int mMaxHSpeed;
|
||||
bool active;
|
||||
};
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ SnowEffectConfig::SnowEffectConfig(QWidget* parent, const QVariantList& args) :
|
|||
connect(m_ui->numberFlakes, SIGNAL(valueChanged(int)), this, SLOT(changed()));
|
||||
connect(m_ui->minSizeFlake, SIGNAL(valueChanged(int)), this, SLOT(changed()));
|
||||
connect(m_ui->maxSizeFlake, SIGNAL(valueChanged(int)), this, SLOT(changed()));
|
||||
connect(m_ui->maxVSpeed, SIGNAL(valueChanged(int)), this, SLOT(changed()));
|
||||
connect(m_ui->maxHSpeed, SIGNAL(valueChanged(int)), this, SLOT(changed()));
|
||||
|
||||
m_actionCollection = new KActionCollection( this, componentData() );
|
||||
m_actionCollection->setConfigGroup("Snow");
|
||||
|
@ -81,12 +83,16 @@ void SnowEffectConfig::load()
|
|||
|
||||
KConfigGroup conf = EffectsHandler::effectConfig("Snow");
|
||||
|
||||
int number = conf.readEntry("Number", 50);
|
||||
int number = conf.readEntry("Number", 200);
|
||||
int minFlake = conf.readEntry("MinFlakes", 10);
|
||||
int maxFlake = conf.readEntry("MaxFlakes", 50);
|
||||
int maxVSpeed = conf.readEntry("MaxVSpeed", 2);
|
||||
int maxHSpeed = conf.readEntry("MaxHSpeed", 1);
|
||||
m_ui->numberFlakes->setValue( number );
|
||||
m_ui->minSizeFlake->setValue( minFlake );
|
||||
m_ui->maxSizeFlake->setValue( maxFlake );
|
||||
m_ui->maxVSpeed->setValue( maxVSpeed );
|
||||
m_ui->maxHSpeed->setValue( maxHSpeed );
|
||||
|
||||
|
||||
emit changed(false);
|
||||
|
@ -100,6 +106,8 @@ void SnowEffectConfig::save()
|
|||
conf.writeEntry("Number", m_ui->numberFlakes->value());
|
||||
conf.writeEntry("MinFlakes", m_ui->minSizeFlake->value());
|
||||
conf.writeEntry("MaxFlakes", m_ui->maxSizeFlake->value());
|
||||
conf.writeEntry("MaxVSpeed", m_ui->maxVSpeed->value());
|
||||
conf.writeEntry("MaxHSpeed", m_ui->maxHSpeed->value());
|
||||
|
||||
m_ui->editor->save(); // undo() will restore to this state from now on
|
||||
|
||||
|
@ -112,9 +120,11 @@ void SnowEffectConfig::save()
|
|||
void SnowEffectConfig::defaults()
|
||||
{
|
||||
kDebug() ;
|
||||
m_ui->numberFlakes->setValue( 50 );
|
||||
m_ui->numberFlakes->setValue( 200 );
|
||||
m_ui->minSizeFlake->setValue( 10 );
|
||||
m_ui->maxSizeFlake->setValue( 50 );
|
||||
m_ui->maxVSpeed->setValue( 2 );
|
||||
m_ui->maxHSpeed->setValue( 1 );
|
||||
m_ui->editor->allDefault();
|
||||
emit changed(true);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>50</number>
|
||||
<number>200</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -87,7 +87,67 @@
|
|||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>50</number>
|
||||
<number>200</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>Maximum &vertical speed:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>maxVSpeed</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QSpinBox" name="maxVSpeed" >
|
||||
<property name="suffix" >
|
||||
<string> px/frame</string>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="minimum" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="text" >
|
||||
<string>Maximum &horizontal speed:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>maxHSpeed</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<widget class="QSpinBox" name="maxHSpeed" >
|
||||
<property name="suffix" >
|
||||
<string> px/frame</string>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="minimum" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
Loading…
Reference in a new issue