add more spacing
[personal-kdebase.git] / workspace / kwin / effects / cylinder.cpp
blob7393c21f9c889a2ac21cc7679ea1b4873c932583
1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.com>
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 *********************************************************************/
20 #include "cube.h"
21 #include "cylinder.h"
23 #include <kdebug.h>
24 #include <KStandardDirs>
26 #include <math.h>
28 #include <GL/gl.h>
30 namespace KWin
33 KWIN_EFFECT( cylinder, CylinderEffect )
34 KWIN_EFFECT_SUPPORTED( cylinder, CylinderEffect::supported() )
36 CylinderEffect::CylinderEffect()
37 : CubeEffect()
38 , mInited( false )
39 , mValid( true )
40 , mShader( 0 )
42 if( wallpaper )
43 wallpaper->discard();
44 reconfigure( ReconfigureAll );
47 CylinderEffect::~CylinderEffect()
49 delete mShader;
52 void CylinderEffect::reconfigure( ReconfigureFlags )
54 loadConfig( "Cylinder" );
55 animateDesktopChange = false;
56 bigCube = true;
59 bool CylinderEffect::supported()
61 return GLShader::fragmentShaderSupported() &&
62 (effects->compositingType() == OpenGLCompositing);
65 bool CylinderEffect::loadData()
67 mInited = true;
68 QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/cylinder.frag");
69 QString vertexshader = KGlobal::dirs()->findResource("data", "kwin/cylinder.vert");
70 if(fragmentshader.isEmpty() || vertexshader.isEmpty())
72 kError(1212) << "Couldn't locate shader files" << endl;
73 return false;
76 mShader = new GLShader(vertexshader, fragmentshader);
77 if(!mShader->isValid())
79 kError(1212) << "The shader failed to load!" << endl;
80 return false;
82 else
84 mShader->bind();
85 mShader->setUniform( "winTexture", 0 );
86 mShader->setUniform( "opacity", cubeOpacity );
87 QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop());
88 if( effects->numScreens() > 1 && (slide || bigCube ) )
89 rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() );
90 mShader->setUniform( "width", (float)rect.width() );
91 mShader->unbind();
93 return true;
96 void CylinderEffect::paintScene( int mask, QRegion region, ScreenPaintData& data )
98 glPushMatrix();
99 QRect rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop());
101 float cubeAngle = (effects->numberOfDesktops() - 2 )/(float)effects->numberOfDesktops() * 180.0f;
102 float radian = (cubeAngle*0.5)*M_PI/180;
103 // height of the triangle compound of one side of the cube and the two bisecting lines
104 float midpoint = rect.width()*0.5*tan(radian);
105 // radius of the circle
106 float radius = (rect.width()*0.5)/cos(radian);
107 glTranslatef( 0.0, 0.0, midpoint - radius );
108 CubeEffect::paintScene( mask, region, data );
109 glPopMatrix();
112 void CylinderEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
114 if( activated )
116 if( cube_painting )
118 if( w->isOnDesktop( painting_desktop ))
120 data.quads = data.quads.makeGrid( 40 );
121 QRect rect = effects->clientArea( FullArea, activeScreen, painting_desktop );
122 if( w->x() < rect.width()/2 && w->x() + w->width() > rect.width()/ 2 )
123 data.quads = data.quads.splitAtX( rect.width()/2 - w->x() );
124 w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
126 else
128 w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
132 effects->prePaintWindow( w, data, time );
135 void CylinderEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
137 if( activated && cube_painting )
139 if( mValid && !mInited )
140 mValid = loadData();
141 bool useShader = mValid;
142 if( useShader )
144 mShader->bind();
145 mShader->setUniform( "windowWidth", (float)w->width() );
146 mShader->setUniform( "windowHeight", (float)w->height() );
147 mShader->setUniform( "xCoord", (float)w->x() );
148 mShader->setUniform( "cubeAngle", (effects->numberOfDesktops() - 2 )/(float)effects->numberOfDesktops() * 180.0f );
149 data.shader = mShader;
151 CubeEffect::paintWindow( w, mask, region, data );
152 if( useShader )
154 mShader->unbind();
157 else
158 effects->paintWindow( w, mask, region, data );
161 void CylinderEffect::desktopChanged( int old )
163 // cylinder effect is not useful to slide
166 void CylinderEffect::paintCap( float z, float zTexture )
168 if( ( !paintCaps ) || effects->numberOfDesktops() <= 2 )
169 return;
170 CubeEffect::paintCap( z, zTexture );
171 QRect rect = effects->clientArea( FullArea, activeScreen, painting_desktop );
173 float cubeAngle = (effects->numberOfDesktops() - 2 )/(float)effects->numberOfDesktops() * 180.0f;
174 float radian = (cubeAngle*0.5)*M_PI/180;
175 // height of the triangle compound of one side of the cube and the two bisecting lines
176 float midpoint = rect.width()*0.5*tan(radian);
177 // radius of the circle
178 float radius = (rect.width()*0.5)/cos(radian);
180 // paint round part of the cap
181 glPushMatrix();
182 float zTranslate = zPosition + zoom;
183 if( start )
184 zTranslate *= timeLine.value();
185 if( stop )
186 zTranslate *= ( 1.0 - timeLine.value() );
187 glTranslatef( 0.0, 0.0, -zTranslate );
188 float triangleWidth = 40.0;
190 for( int i=0; i<effects->numberOfDesktops(); i++ )
192 glPushMatrix();
193 glTranslatef( rect.width()/2, 0.0, -z );
194 glRotatef( i*(360.0f/effects->numberOfDesktops()), 0.0, 1.0, 0.0 );
195 glTranslatef( -rect.width()/2, 0.0, z );
196 glBegin( GL_TRIANGLE_STRIP );
197 for( int j=0; j<rect.width()/triangleWidth; j++ )
199 float zValue = 0.0;
200 // distance from midpoint of desktop to x coord
201 // calculation is same as in shader -> see comments
202 float distance = rect.width()*0.5 - (j*triangleWidth);
203 if( (j*triangleWidth) > rect.width()*0.5 )
205 distance = (j*triangleWidth) - rect.width()*0.5;
207 // distance in correct format
208 float angle = acos( distance/radius );
209 float h = radius;
210 // if distance == 0 -> angle=90 -> tan(90) singularity
211 if( distance != 0.0 )
212 h = tan( angle ) * distance;
213 zValue = h - midpoint;
214 glVertex3f( j*triangleWidth, 0.0, zValue );
215 glVertex3f( (j+1)*triangleWidth, 0.0, 0.0 );
217 glEnd();
218 glPopMatrix();
220 glPopMatrix();
223 } // namespace