uic4 port
[kdeartwork.git] / kscreensaver / kdesavers / fountain.cpp
blob679c20c8f448ba00b6a772bb95e272bd3b10c7b5
1 //-----------------------------------------------------------------------------
2 //
3 // kfountain - Partical Fountain Screen Saver for KDE 2
4 //
5 // Copyright (c) Ian Reinhart Geiser 2001
6 //
7 // KConfig code and KScreenSaver "Setup..." improvements by
8 // Nick Betcher <nbetcher@usinternet.com> 2001
9 //
10 #include <stdlib.h>
11 #include <qlabel.h>
12 #include <qlayout.h>
13 #include <kapplication.h>
14 #include <klocale.h>
15 #include <kconfig.h>
16 #include <kcolordialog.h>
17 #include <kbuttonbox.h>
18 #include <kcolorbutton.h>
19 #include <kglobal.h>
20 #include "fountain.h"
21 #include "fountain.moc"
22 #ifdef Q_WS_MACX
23 #include <OpenGL/gl.h>
24 #include <OpenGL/glu.h>
25 #else
26 #include <GL/glu.h>
27 #include <GL/gl.h>
28 #endif
29 #include <qimage.h>
30 #include <kdebug.h>
31 #include <qpainter.h>
32 #include <qradiobutton.h>
33 #include <qspinbox.h>
34 #include <kstandarddirs.h>
35 #include <math.h>
36 #include <kmessagebox.h>
37 #include <krandom.h>
38 // libkscreensaver interface
39 class KFountainSaverInterface : public KScreenSaverInterface
43 public:
44 virtual KAboutData* aboutData() {
45 return new KAboutData( "kfountain.kss", I18N_NOOP( "Particle Fountain Screen Saver" ), "2.2.0", I18N_NOOP( "Particle Fountain Screen Saver" ) );
49 virtual KScreenSaver* create( WId id )
51 return new KFountainSaver( id );
54 virtual QDialog* setup()
56 return new KFountainSetup();
60 int main( int argc, char *argv[] )
62 KFountainSaverInterface kss;
63 return kScreenSaverMain( argc, argv, kss );
66 //-----------------------------------------------------------------------------
67 // dialog to setup screen saver parameters
69 KFountainSetup::KFountainSetup( QWidget *parent )
70 : QDialog( parent)
72 setupUi(this);
73 setModal(true);
74 readSettings();
76 //QLabel *label;
77 //QPushButton *button;
79 //setCaption( i18n("Setup Particle Fountain") );
81 //QVBoxLayout *tl = new QVBoxLayout(this, 10);
82 //QHBoxLayout *tl1 = new QHBoxLayout;
83 //tl->addLayout(tl1);
85 //QVBoxLayout *tl11 = new QVBoxLayout(5);
86 //tl1->addLayout(tl11);
88 //label = new QLabel( i18n("No options here yet...:"), this );
89 ///tl11->addWidget(label);;
91 //preview = new QWidget( this );
92 preview->setFixedSize( 220, 170 );
93 preview->setBackgroundColor( Qt::black );
94 preview->show(); // otherwise saver does not get correct size
95 saver = new KFountainSaver( preview->winId() );
96 //tl1->addWidget(preview);
98 //KButtonBox *bbox = new KButtonBox(this);
99 //bbox->addStretch(1);
101 connect( PushButton1, SIGNAL( clicked() ), SLOT( slotOkPressed() ) );
102 connect( PushButton2, SIGNAL( clicked() ), SLOT( reject() ) );
103 connect( PushButton3, SIGNAL( clicked() ), SLOT( aboutPressed() ) );
104 connect( SpinBox1, SIGNAL( valueChanged(int)), saver, SLOT( updateSize(int)));
105 connect( RadioButton1, SIGNAL( toggled(bool)), saver, SLOT( doStars(bool)));
109 // read settings from config file
110 void KFountainSetup::readSettings()
112 KConfig config("kssfountainrc", false, false);
114 config.setGroup( "Settings" );
115 QString boolval = config.readEntry( "Stars", "false" );
116 if (boolval == "true") {
117 RadioButton1->setDown(true);
118 RadioButton1_2->setDown(false);
119 } else {
120 if (boolval == "false")
122 RadioButton1->setDown(false);
123 RadioButton1_2->setDown(true);
127 QString starammount = config.readEntry("StarSize", "75");
128 SpinBox1->setValue(starammount.toInt());
132 // Ok pressed - save settings and exit
133 void KFountainSetup::slotOkPressed()
135 KConfig config("kssfountainrc", false, false);
136 config.setGroup( "Settings" );
138 if (RadioButton1->isOn() == true)
140 config.writeEntry( "Stars", "true" );
141 } else {
142 if (RadioButton1_2->isOn() == true)
144 config.writeEntry( "Stars", "false" );
147 config.writeEntry( "StarSize", QString::number(SpinBox1->value()) );
149 config.sync();
151 accept();
154 void KFountainSetup::aboutPressed()
156 KMessageBox::about(this,
157 i18n("<h3>Particle Fountain</h3>\n<p>Particle Fountain Screen Saver for KDE</p>\nCopyright (c) Ian Reinhart Geiser 2001<br>\n\n<p>KConfig code and KScreenSaver \"Setup...\" improvements by Nick Betcher <nbetcher@usinternet.com> 2001</p>"));
159 //-----------------------------------------------------------------------------
162 KFountainSaver::KFountainSaver( WId id ) : KScreenSaver( id )
165 kDebug() << "Blank" << endl;
167 timer = new QTimer( this );
168 timer->setSingleShot(true);
169 timer->start( 25);
170 setBackgroundColor( Qt::black );
171 erase();
172 fountain = new Fountain();
173 embed(fountain);
174 fountain->show();
175 connect( timer, SIGNAL(timeout()), this, SLOT(blank()) );
178 KFountainSaver::~KFountainSaver()
183 // read configuration settings from config file
184 void KFountainSaver::readSettings()
186 // Please remove me
190 void KFountainSaver::blank()
192 // Play fountain
194 fountain->updateGL();
195 timer->setSingleShot(true);
196 timer->start( 25);
199 Fountain::Fountain( QWidget * parent, const char * name) : QGLWidget (parent,name)
201 rainbow=true;
202 slowdown=2.0f;
203 zoom=-40.0f;
204 index=0;
205 size = 0.75f;
206 obj = gluNewQuadric();
208 // This has to be here because you can't update the fountain until 'fountain' is created!
209 KConfig config("kssfountainrc", false, false);
210 config.setGroup( "Settings" );
211 QString boolval = config.readEntry( "Stars", "false" );
212 if (boolval == "true") {
213 setStars(true);
214 } else {
215 if (boolval == "false")
217 setStars(false);
221 QString starammount = config.readEntry("StarSize", "75");
222 float passvalue = (starammount.toInt() / 100.0);
223 setSize(passvalue);
227 Fountain::~Fountain()
229 glDeleteTextures( 1, &texture[0] );
230 gluDeleteQuadric(obj);
233 /** load the particle file */
234 bool Fountain::loadParticle()
236 /* Status indicator */
237 bool Status = TRUE;
238 QImage buf;
240 kDebug() << "Loading: " << KStandardDirs::locate("data", "kscreensaver/particle.png") << endl;
241 if (buf.load( KStandardDirs::locate("data", "kscreensaver/particle.png") ) )
244 tex = convertToGLFormat(buf); // flipped 32bit RGBA
245 kDebug() << "Texture loaded: " << tex.numBytes () << endl;
247 else
249 QImage dummy( 32, 32, 32 );
250 dummy.fill( Qt::white );
251 buf = dummy;
252 tex = convertToGLFormat( buf );
255 /* Set the status to true */
256 //Status = TRUE;
257 glGenTextures(1, &texture[0]); /* create three textures */
258 glBindTexture(GL_TEXTURE_2D, texture[0]);
259 /* use linear filtering */
260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
262 /* actually generate the texture */
263 glTexImage2D(GL_TEXTURE_2D, 0, 4, tex.width(), tex.height(), 0,
264 GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
268 return Status;
270 /** setup the GL enviroment */
271 void Fountain::initializeGL ()
274 kDebug() << "InitGL" << endl;
275 GLfloat colors[12][3]=
276 {{1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
277 {0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
278 {0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}};
280 if (loadParticle()) // Jump To Texture Loading Routine
282 /* Enable smooth shading */
283 glShadeModel( GL_SMOOTH );
285 /* Set the background black */
286 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
288 /* Depth buffer setup */
289 glClearDepth( 1.0f );
291 /* Enables Depth Testing */
292 glDisable( GL_DEPTH_TEST );
294 /* Enable Blending */
295 glEnable( GL_BLEND );
296 /* Type Of Blending To Perform */
297 glBlendFunc( GL_SRC_ALPHA, GL_ONE );
300 /* Really Nice Perspective Calculations */
301 glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
302 /* Really Nice Point Smoothing */
303 glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );
305 /* Enable Texture Mapping */
306 glEnable( GL_TEXTURE_2D );
307 /* Select Our Texture */
308 glBindTexture( GL_TEXTURE_2D, texture[0] );
310 for (loop=0;loop<MAX_PARTICLES;loop++) // Initials All The Textures
312 particle[loop].active=true; // Make All The Particles Active
313 particle[loop].life=1.0f; // Give All The Particles Full Life
314 particle[loop].fade=float(KRandom::random()%100)/1000.0f+0.003f; // Random Fade Speed
315 int color_index = (loop+1)/(MAX_PARTICLES/12);
316 color_index = qMin(11, color_index);
317 particle[loop].r=colors[color_index][0]; // Select Red Rainbow Color
318 particle[loop].g=colors[color_index][1]; // Select Green Rainbow Color
319 particle[loop].b=colors[color_index][2]; // Select Blue Rainbow Color
320 particle[loop].xi=float((KRandom::random()%50)-26.0f)*10.0f; // Random Speed On X Axis
321 particle[loop].yi=float((KRandom::random()%50)-25.0f)*10.0f; // Random Speed On Y Axis
322 particle[loop].zi=float((KRandom::random()%50)-25.0f)*10.0f; // Random Speed On Z Axis
323 particle[loop].xg=0.0f; // Set Horizontal Pull To Zero
324 particle[loop].yg=-0.8f; // Set Vertical Pull Downward
325 particle[loop].zg=0.0f; // Set Pull On Z Axis To Zero
326 particle[loop].size=size; // Set particle size.
329 else
330 exit(0);
332 /** resize the gl view */
333 void Fountain::resizeGL ( int width, int height )
335 kDebug() << "ResizeGL " << width << "," <<height<< endl;
336 if (height==0) // Prevent A Divide By Zero By
338 height=1; // Making Height Equal One
341 glViewport(0,0,width,height); // Reset The Current Viewport
343 glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
344 glLoadIdentity(); // Reset The Projection Matrix
346 // Calculate The Aspect Ratio Of The Window
347 gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,200.0f);
349 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
350 glLoadIdentity();
352 /** paint the GL view */
353 void Fountain::paintGL ()
355 //kDebug() << "PaintGL" << endl;
357 GLfloat colors[12][3]=
358 {{1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
359 {0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
360 {0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}};
361 col = ( ++col ) % 12;
362 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
364 glLoadIdentity();
365 // Reset The ModelView Matrix
366 transIndex++;
367 glTranslatef( GLfloat(5.0*sin(4*3.14*transIndex/360)), GLfloat(4.0*cos(2*3.14*transIndex/360)), 0.0 );
368 xspeed = GLfloat(100.0*cos(3*3.14*transIndex/360)+100);
369 yspeed = GLfloat(100.0*sin(3*3.14*transIndex/360)+100);
370 //slowdown = GLfloat(4.0*sin(2*3.14*transIndex/360)+4.01);
372 for (loop=0;loop<MAX_PARTICLES;loop++) // Loop Through All The Particles
374 if (particle[loop].active) // If The Particle Is Active
376 float x=particle[loop].x; // Grab Our Particle X Position
377 float y=particle[loop].y; // Grab Our Particle Y Position
378 float z=particle[loop].z+zoom; // Particle Z Pos + Zoom
379 /* Select Our Texture */
381 /* Draw The Particle Using Our RGB Values,
382 * Fade The Particle Based On It's Life
385 glColor4f( particle[loop].r,
386 particle[loop].g,
387 particle[loop].b,
388 particle[loop].life );
390 /* Build Quad From A Triangle Strip */
391 if( !stars )
392 glBegin( GL_TRIANGLE_STRIP );
393 else
394 glBegin( GL_TRIANGLE_FAN );
395 /* Top Right */
396 glTexCoord2d( 1, 1 );
397 glVertex3f( x + particle[loop].size, y + particle[loop].size, z );
398 /* Top Left */
399 glTexCoord2d( 0, 1 );
400 glVertex3f( x - particle[loop].size, y + particle[loop].size, z );
401 /* Bottom Right */
402 glTexCoord2d( 1, 0 );
403 glVertex3f( x + particle[loop].size, y - particle[loop].size, z );
404 /* Bottom Left */
405 glTexCoord2d( 0, 0 );
406 glVertex3f( x - particle[loop].size, y - particle[loop].size, z );
407 glEnd( );
409 particle[loop].x+=particle[loop].xi/(slowdown*1000);// Move On The X Axis By X Speed
410 particle[loop].y+=particle[loop].yi/(slowdown*1000);// Move On The Y Axis By Y Speed
411 particle[loop].z+=particle[loop].zi/(slowdown*1000);// Move On The Z Axis By Z Speed
413 particle[loop].xi+=particle[loop].xg; // Take Pull On X Axis Into Account
414 particle[loop].yi+=particle[loop].yg; // Take Pull On Y Axis Into Account
415 particle[loop].zi+=particle[loop].zg; // Take Pull On Z Axis Into Account
416 particle[loop].life-=particle[loop].fade; // Reduce Particles Life By 'Fade'
418 if (particle[loop].life<0.0f) // If Particle Is Burned Out
420 particle[loop].life=2.0f; // Give It New Life
421 particle[loop].fade=float(KRandom::random()%100)/1000.0f+0.003f; // Random Fade Value
422 particle[loop].x=0.0f; // Center On X Axis
423 particle[loop].y=0.0f; // Center On Y Axis
424 particle[loop].z=0.0f; // Center On Z Axis
425 particle[loop].xi=xspeed+float((KRandom::random()%60)-32.0f); // X Axis Speed And Direction
426 particle[loop].yi=yspeed+float((KRandom::random()%60)-30.0f); // Y Axis Speed And Direction
427 particle[loop].zi=float((KRandom::random()%60)-30.0f); // Z Axis Speed And Direction
428 particle[loop].r=colors[col][0]; // Select Red From Color Table
429 particle[loop].g=colors[col][1]; // Select Green From Color Table
430 particle[loop].b=colors[col][2]; // Select Blue From Color Table
431 particle[loop].size=size;
432 if ((1+(random()%20)) == 10)
434 // Explode
435 particle[loop].active=true; // Make All The Particles Active
436 particle[loop].life=1.0f; // Give All The Particles Full Life
437 particle[loop].fade=float(KRandom::random()%100)/1000.0f+0.003f; // Random Fade Speed
438 int color_index = (loop+1)/(MAX_PARTICLES/12);
439 color_index = qMin(11, color_index);
440 particle[loop].r=colors[color_index][0]; // Select Red Rainbow Color
441 particle[loop].g=colors[color_index][1]; // Select Green Rainbow Color
442 particle[loop].b=colors[color_index][2]; // Select Blue Rainbow Color
443 particle[loop].xi=float((KRandom::random()%50)-26.0f)*10.0f; // Random Speed On X Axis
444 particle[loop].yi=float((KRandom::random()%50)-25.0f)*10.0f; // Random Speed On Y Axis
445 particle[loop].zi=float((KRandom::random()%50)-25.0f)*10.0f; // Random Speed On Z Axis
446 particle[loop].xg=0.0f; // Set Horizontal Pull To Zero
447 particle[loop].yg=-0.8f; // Set Vertical Pull Downward
448 particle[loop].zg=0.0f; // Set Pull On Z Axis To Zero
449 particle[loop].size=size; // Set particle size.
452 // Lets stir some things up
453 index += 0.001;
454 particle[loop].yg =2.0*sin(2*3.14*transIndex/360);
455 particle[loop].xg =2.0*cos(2*3.14*transIndex/360);
456 particle[loop].zg =4.0+(4.0*cos(2*3.14*transIndex/360));
461 glFlush();
463 void Fountain::setSize( float newSize )
465 size = newSize;
467 void Fountain::setStars( bool doStars )
469 stars = doStars;
472 void KFountainSaver::updateSize(int newSize)
474 fountain->setSize(newSize/100);
476 void KFountainSaver::doStars(bool starState)
478 fountain->setStars(starState);