diff --git a/effects/snow.cpp b/effects/snow.cpp index c72692b7b1..204a466e69 100644 --- a/effects/snow.cpp +++ b/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 + Copyright (C) 2008 Torgny Johansson 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 . #include #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(); + flakes = new QList(); lastFlakeTime.start(); } int count = flakes->count(); for (int i=0; ifirst(); + 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; icount(); 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 diff --git a/effects/snow.h b/effects/snow.h index bff35e1b74..187153867b 100644 --- a/effects/snow.h +++ b/effects/snow.h @@ -2,7 +2,8 @@ KWin - the KDE window manager This file is part of the KDE project. - Copyright (C) 2007 Martin Gräßlin + Copyright (C) 2008 Torgny Johansson 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 . 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* flakes; + QList* flakes; QTime lastFlakeTime; long nextFlakeMillis; int mNumberFlakes; int mMinFlakeSize; int mMaxFlakeSize; + int mMaxVSpeed; + int mMaxHSpeed; bool active; }; diff --git a/effects/snow_config.cpp b/effects/snow_config.cpp index 326a328a08..ab594836fd 100644 --- a/effects/snow_config.cpp +++ b/effects/snow_config.cpp @@ -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); } diff --git a/effects/snow_config.ui b/effects/snow_config.ui index 704ed728c3..b781026bc1 100644 --- a/effects/snow_config.ui +++ b/effects/snow_config.ui @@ -35,7 +35,7 @@ 1000 - 50 + 200 @@ -87,10 +87,70 @@ 1000 - 50 + 200 + + + + + + Maximum &vertical speed: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + maxVSpeed + + + + + + + px/frame + + + 30 + + + 1 + + + 2 + + + + + + + Maximum &horizontal speed: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + maxHSpeed + + + + + + + px/frame + + + 30 + + + 0 + + + 1 + + +