Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / kwin / effects / explosioneffect.cpp
blob6536a8e9eba14f12f4dde2940c6acc2c380d3468
1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
21 #include "explosioneffect.h"
23 #include <kwinglutils.h>
26 #include <KStandardDirs>
27 #include <kdebug.h>
29 #include <math.h>
32 namespace KWin
35 KWIN_EFFECT( explosion, ExplosionEffect )
36 KWIN_EFFECT_SUPPORTED( explosion, ExplosionEffect::supported() )
38 ExplosionEffect::ExplosionEffect() : Effect()
40 mShader = 0;
41 mStartOffsetTex = 0;
42 mEndOffsetTex = 0;
44 mActiveAnimations = 0;
45 mValid = true;
46 mInited = false;
49 ExplosionEffect::~ExplosionEffect()
51 delete mShader;
52 delete mStartOffsetTex;
53 delete mEndOffsetTex;
56 bool ExplosionEffect::supported()
58 return GLShader::fragmentShaderSupported() &&
59 (effects->compositingType() == OpenGLCompositing);
62 bool ExplosionEffect::loadData()
64 mInited = true;
65 QString shadername("explosion");
66 QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/explosion.frag");
67 QString vertexshader = KGlobal::dirs()->findResource("data", "kwin/explosion.vert");
68 QString starttexture = KGlobal::dirs()->findResource("data", "kwin/explosion-start.png");
69 QString endtexture = KGlobal::dirs()->findResource("data", "kwin/explosion-end.png");
70 if(fragmentshader.isEmpty() || vertexshader.isEmpty())
72 kError() << "Couldn't locate shader files" << endl;
73 return false;
75 if(starttexture.isEmpty() || endtexture.isEmpty())
77 kError() << "Couldn't locate texture files" << endl;
78 return false;
81 mShader = new GLShader(vertexshader, fragmentshader);
82 if(!mShader->isValid())
84 kError() << "The shader failed to load!" << endl;
85 return false;
87 else
89 mShader->bind();
90 mShader->setUniform("winTexture", 0);
91 mShader->setUniform("startOffsetTexture", 4);
92 mShader->setUniform("endOffsetTexture", 5);
93 mShader->unbind();
96 mStartOffsetTex = new GLTexture(starttexture);
97 mEndOffsetTex = new GLTexture(endtexture);
98 if(mStartOffsetTex->isNull() || mEndOffsetTex->isNull())
100 kError() << "The textures failed to load!" << endl;
101 return false;
103 else
105 mStartOffsetTex->setFilter( GL_LINEAR );
106 mEndOffsetTex->setFilter( GL_LINEAR );
109 return true;
112 void ExplosionEffect::prePaintScreen( ScreenPrePaintData& data, int time )
114 if( mActiveAnimations > 0 )
115 // We need to mark the screen as transformed. Otherwise the whole screen
116 // won't be repainted, resulting in artefacts
117 data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
119 effects->prePaintScreen(data, time);
122 void ExplosionEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
124 if( mWindows.contains( w ))
126 if( mValid && !mInited )
127 mValid = loadData();
128 if( mValid )
130 mWindows[ w ] += time / 700.0; // complete change in 700ms
131 if( mWindows[ w ] < 1 )
133 data.setTranslucent();
134 data.setTransformed();
135 w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DELETE );
137 else
139 mWindows.remove( w );
140 w->unrefWindow();
141 mActiveAnimations--;
146 effects->prePaintWindow( w, data, time );
149 void ExplosionEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
151 // Make sure we have OpenGL compositing and the window is vidible and not a
152 // special window
153 bool useshader = ( mValid && mWindows.contains( w ) );
154 if( useshader )
156 double maxscaleadd = 1.5f;
157 double scale = 1 + maxscaleadd*mWindows[w];
158 data.xScale = scale;
159 data.yScale = scale;
160 data.xTranslate += int( w->width() / 2 * ( 1 - scale ));
161 data.yTranslate += int( w->height() / 2 * ( 1 - scale ));
162 data.opacity *= 0.99; // Force blending
163 mShader->bind();
164 mShader->setUniform("factor", (float)mWindows[w]);
165 mShader->setUniform("scale", (float)scale);
166 glActiveTexture(GL_TEXTURE4);
167 mStartOffsetTex->bind();
168 glActiveTexture(GL_TEXTURE5);
169 mEndOffsetTex->bind();
170 glActiveTexture(GL_TEXTURE0);
171 data.shader = mShader;
174 // Call the next effect.
175 effects->paintWindow( w, mask, region, data );
177 if( useshader )
179 mShader->unbind();
180 glActiveTexture(GL_TEXTURE4);
181 mStartOffsetTex->unbind();
182 glActiveTexture(GL_TEXTURE5);
183 mEndOffsetTex->unbind();
184 glActiveTexture(GL_TEXTURE0);
188 void ExplosionEffect::postPaintScreen()
190 if( mActiveAnimations > 0 )
191 effects->addRepaintFull();
193 // Call the next effect.
194 effects->postPaintScreen();
197 void ExplosionEffect::windowClosed( EffectWindow* c )
199 if( c->isOnCurrentDesktop() && !c->isMinimized())
201 mWindows[ c ] = 0; // count up to 1
202 c->addRepaintFull();
203 c->refWindow();
204 mActiveAnimations++;
208 void ExplosionEffect::windowDeleted( EffectWindow* c )
210 mWindows.remove( c );
213 } // namespace