Other fix compile error
[kdeartwork.git] / kscreensaver / xsavers / space.cpp
blob3618f90a65ff61392f3626de9dfcceb31c45bed6
1 /*
3 * kStart OpenGL screensave for KDE
5 * $Id$
7 * Copyright (C) 1998 Bernd Johannes Wuebben
8 * wuebben@math.cornell.edu
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this program; if not, write to the Free
22 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 * Based on star.c:
26 * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
28 * Permission to use, copy, modify, distribute, and sell this software and
29 * its documentation for any purpose is hereby granted without fee, provided
30 * that (i) the above copyright notices and this permission notice appear in
31 * all copies of the software and related documentation, and (ii) the name of
32 * Silicon Graphics may not be used in any advertising or
33 * publicity relating to the software without the specific, prior written
34 * permission of Silicon Graphics.
36 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
37 * ANY KIND,
38 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
39 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
41 * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
42 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
43 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
44 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
45 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
46 * OF THIS SOFTWARE.
49 #define LONG64
50 //#define QT_CLEAN_NAMESPACE
52 #include <qslider.h>
53 #include <qlayout.h>
54 //Added by qt3to4:
55 #include <QVBoxLayout>
56 #include <QHBoxLayout>
57 #include <kglobal.h>
58 #include <kconfig.h>
59 #include <krandomsequence.h>
60 #include <kdebug.h>
61 #include "xlock.h"
62 #include "helpers.h"
63 #ifdef HAVE_CONFIG_H
64 #include "../../config.h"
65 #endif
67 #ifdef HAVE_GL
69 #include <klocale.h>
71 #undef index
72 #include "space.h"
73 #include <math.h>
74 #include <X11/Intrinsic.h>
75 #ifdef HAVE_GL_XMESA_H
76 #include <GL/xmesa.h>
77 #endif
78 #include <GL/gl.h>
79 #include <GL/glx.h>
80 #ifdef HAVE_GL_GLUT_H
81 // We don't need GLUT, but some BROKEN GLU implemenations, such as the one
82 // used in SuSE Linux 6.3, do. :(
83 #include <GL/glut.h>
84 #endif
85 #include <GL/glu.h>
87 #ifndef PI
88 #ifdef M_PI
89 #define PI M_PI
90 #else
91 #define PI 3.141592657
92 #endif
93 #endif
95 enum {
96 NORMAL = 0,
97 WEIRD = 1
98 } flag = NORMAL;
100 enum {
101 STREAK = 0,
102 CIRCLE = 1
105 #define MAXSTARS 400
106 #define MAXPOS 10000
107 #define MAXWARP1 10
108 #define MAXANGLES 6000
111 typedef struct _starRec {
112 GLint type;
113 float x[2], y[2], z[2];
114 float offsetX, offsetY, offsetR, rotation;
115 } starRec;
118 GLenum doubleBuffer, directRender;
119 GLint windW, windH;
121 GLint starCount = MAXSTARS / 2;
122 float speed = 1.0;
123 float warpinterval = 30000.0;
124 GLint nitro = 0;
125 starRec stars[MAXSTARS];
126 float sinTable[MAXANGLES];
128 static GLXContext glx_context;
129 static KRandomSequence *rnd = 0;
131 float Sin(float angle)
134 return (sinTable[(GLint)angle]);
137 float Cos(float angle)
140 return (sinTable[((GLint)angle+(MAXANGLES/4))%MAXANGLES]);
143 void NewStar(GLint n, GLint d)
146 if (rnd->getLong(4) == 0) {
147 stars[n].type = CIRCLE;
148 } else {
149 stars[n].type = STREAK;
151 stars[n].x[0] = rnd->getDouble() * MAXPOS - MAXPOS / 2;
152 stars[n].y[0] = rnd->getDouble() * MAXPOS - MAXPOS / 2;
153 stars[n].z[0] = rnd->getDouble() * MAXPOS + d;
154 if (rnd->getLong(4) == 0 && flag == WEIRD) {
155 stars[n].offsetX = rnd->getDouble()* 100 - 100 / 2;
156 stars[n].offsetY = rnd->getDouble()* 100 - 100 / 2;
157 stars[n].offsetR = rnd->getDouble()* 25 - 25 / 2;
158 } else {
159 stars[n].offsetX = 0.0;
160 stars[n].offsetY = 0.0;
161 stars[n].offsetR = 0.0;
165 void RotatePoint(float *x, float *y, float rotation)
167 float tmpX, tmpY;
169 tmpX = *x * Cos(rotation) - *y * Sin(rotation);
170 tmpY = *y * Cos(rotation) + *x * Sin(rotation);
171 *x = tmpX;
172 *y = tmpY;
175 void MoveStars(void)
177 float offset;
178 GLint n;
180 offset = speed * 60.0;
182 for (n = 0; n < starCount; n++) {
183 stars[n].x[1] = stars[n].x[0];
184 stars[n].y[1] = stars[n].y[0];
185 stars[n].z[1] = stars[n].z[0];
186 stars[n].x[0] += stars[n].offsetX;
187 stars[n].y[0] += stars[n].offsetY;
188 stars[n].z[0] -= offset;
189 stars[n].rotation += stars[n].offsetR;
190 if (stars[n].rotation > MAXANGLES) {
191 stars[n].rotation = 0.0;
196 GLenum StarPoint(GLint n)
198 float x0, y0, x1, y1, width;
199 GLint i;
201 x0 = stars[n].x[0] * windW / stars[n].z[0];
202 y0 = stars[n].y[0] * windH / stars[n].z[0];
203 RotatePoint(&x0, &y0, stars[n].rotation);
204 x0 += windW / 2.0;
205 y0 += windH / 2.0;
207 if (x0 >= 0.0 && x0 < windW && y0 >= 0.0 && y0 < windH) {
208 if (stars[n].type == STREAK) {
209 x1 = stars[n].x[1] * windW / stars[n].z[1];
210 y1 = stars[n].y[1] * windH / stars[n].z[1];
211 RotatePoint(&x1, &y1, stars[n].rotation);
212 x1 += windW / 2.0;
213 y1 += windH / 2.0;
215 glLineWidth(MAXPOS/100.0/stars[n].z[0]+1.0);
216 glColor3f((MAXWARP1-speed)/MAXWARP1, (MAXWARP1-speed)/MAXWARP1, .9);
217 if (fabs(x0-x1) < 1.0 && fabs(y0-y1) < 1.0) {
218 glBegin(GL_POINTS);
219 glVertex2f(x0, y0);
220 glEnd();
221 } else {
222 glBegin(GL_LINES);
223 glVertex2f(x0, y0);
224 glVertex2f(x1, y1);
225 glEnd();
227 } else {
228 width = MAXPOS / 10.0 / stars[n].z[0] + 1.0;
229 glColor3f(1.0, 0.0, 0.0);
230 glBegin(GL_POLYGON);
231 for (i = 0; i < 8; i++) {
232 float x = x0 + width * Cos((float)i*MAXANGLES/8.0);
233 float y = y0 + width * Sin((float)i*MAXANGLES/8.0);
234 glVertex2f(x, y);
236 glEnd();
238 return GL_TRUE;
239 } else {
240 return GL_FALSE;
244 void ShowStars(void)
246 GLint n;
248 glClear(GL_COLOR_BUFFER_BIT);
250 for (n = 0; n < starCount; n++) {
251 if (stars[n].z[0] > speed || (stars[n].z[0] > 0.0 && speed < MAXWARP1)) {
252 if (StarPoint(n) == GL_FALSE) {
253 NewStar(n, MAXPOS);
255 } else {
256 NewStar(n, MAXPOS);
261 static void Init(void)
263 float angle;
264 GLint n;
266 for (n = 0; n < MAXSTARS; n++) {
267 NewStar(n, 100);
270 angle = 0.0;
271 for (n = 0; n < MAXANGLES ; n++) {
272 sinTable[n] = sin(angle);
273 angle += PI / (MAXANGLES / 2.0);
276 glClearColor(0.0, 0.0, 0.0, 0.0);
278 glDisable(GL_DITHER);
281 void reshape(int width, int height)
284 windW = (GLint)width;
285 windH = (GLint)height;
287 glViewport(0, 0, windW, windH);
289 glMatrixMode(GL_PROJECTION);
290 glLoadIdentity();
291 gluOrtho2D(-0.5, windW+0.5, -0.5, windH+0.5);
292 glMatrixMode(GL_MODELVIEW);
296 void Idle(void)
299 MoveStars();
300 ShowStars();
301 if (nitro > 0) {
302 speed = (float)(nitro / 10) + 1.0;
303 if (speed > MAXWARP1) {
304 speed = MAXWARP1;
306 if (++nitro > MAXWARP1*10) {
307 nitro = -nitro;
309 } else if (nitro < 0) {
310 nitro++;
311 speed = (float)(-nitro / 10) + 1.0;
312 if (speed > MAXWARP1) {
313 speed = MAXWARP1;
317 glFlush();
319 /* if (doubleBuffer) {
320 tkSwapBuffers();
325 void
326 drawSpace(Window /*window*/)
330 Display *display = dsp;
331 //glXMakeCurrent(display, window, mp->glx_context);
332 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
333 glFlush();
334 glXSwapBuffers(display, window);
337 Idle();
342 void release_Space(){
344 glXDestroyContext(dsp, glx_context);
348 static XVisualInfo *glVis[MAXSCREENS];
351 getVisual(XVisualInfo * wantVis, int visual_count)
353 Display *display = dsp;
354 static int first;
355 int i;
357 if (first) {
358 for (screen = 0; screen < MAXSCREENS; screen++)
359 glVis[screen] = NULL;
362 if (!glVis[screen]) {
363 if (mono) {
364 /* Monochrome display - use color index mode */
365 int attribList[] = {GLX_DOUBLEBUFFER, None};
367 glVis[screen] = glXChooseVisual(display, screen, attribList);
368 } else {
369 int attribList[] =
370 {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None};
372 glVis[screen] = glXChooseVisual(display, screen, attribList);
375 // Make sure we have a visual
376 if (!glVis[screen]) {
377 return (0);
380 /* check if GL can render into root window. */
381 for(i=0;i<visual_count;i++)
382 if ( (glVis[screen]->visual == (wantVis+i)->visual) )
383 return (1); // success
385 // The visual we received did not match one we asked for
386 return (0);
389 void
390 initSpace(Window window)
392 Display *display = dsp;
393 XWindowAttributes xwa;
396 (void) XGetWindowAttributes(dsp, window, &xwa);
397 int n;
398 XVisualInfo *wantVis, vTemplate;
399 int VisualClassWanted=-1;
401 vTemplate.screen = screen;
402 vTemplate.depth = xwa.depth;
404 if (VisualClassWanted == -1) {
405 vTemplate.c_class = DefaultVisual(display, screen)->c_class;
406 } else {
407 vTemplate.c_class = VisualClassWanted;
410 wantVis = XGetVisualInfo(display,
411 VisualScreenMask | VisualDepthMask | VisualClassMask,
412 &vTemplate, &n);
414 if (VisualClassWanted != -1 && n == 0) {
415 /* Wanted visual not found so use default */
417 vTemplate.c_class = DefaultVisual(display, screen)->c_class;
419 wantVis = XGetVisualInfo(display,
420 VisualScreenMask | VisualDepthMask | VisualClassMask,
421 &vTemplate, &n);
423 /* if User asked for color, try that first, then try mono */
424 /* if User asked for mono. Might fail on 16/24 bit displays,
425 so fall back on color, but keep the mono "look & feel". */
427 if (!getVisual(wantVis, n)) {
428 if (!getVisual(wantVis, n)) {
429 kdError() << i18n("GL can not render with root visual\n") << endl;
430 return;
434 /* PURIFY 3.0a on SunOS4 reports a 104 byte memory leak on the next line each
435 * time that morph3d mode is run in random mode. */
437 glx_context = glXCreateContext(display, wantVis, 0, True);
439 XFree((char *) wantVis);
442 glXMakeCurrent(display, window, glx_context);
443 glDrawBuffer(GL_FRONT);
445 if (mono) {
446 glIndexi(WhitePixel(display, screen));
447 glClearIndex(BlackPixel(display, screen));
450 reshape(xwa.width, xwa.height);
451 Init();
457 #endif
459 #define MINSPEED 1
460 #define MAXSPEED 100
461 #define DEFSPEED 50
462 #define MINWARP 1
463 #define MAXWARP 30
464 #define DEFWARP 2
465 #define WARPFACTOR 100
466 //-----------------------------------------------------------------------------
468 #include <qpushbutton.h>
469 #include <qcheckbox.h>
470 #include <qlabel.h>
471 #include <qcolor.h>
473 #include <kmessagebox.h>
475 #include "space.moc"
477 #undef Below
479 static kSpaceSaver *saver = NULL;
481 void startScreenSaver( Drawable d )
483 if ( saver )
484 return;
485 saver = new kSpaceSaver( d );
488 void stopScreenSaver()
490 if ( saver )
491 delete saver;
492 saver = NULL;
495 int setupScreenSaver()
497 kSpaceSetup dlg;
499 return dlg.exec();
502 //-----------------------------------------------------------------------------
504 kSpaceSaver::kSpaceSaver( Drawable drawable ) : kScreenSaver( drawable )
506 rnd = new KRandomSequence();
507 readSettings();
508 counter = (int)warpinterval *WARPFACTOR;
510 colorContext = QColor::enterAllocContext();
512 initXLock( mGc );
513 initSpace( mDrawable );
515 timer.start( speed );
516 connect( &timer, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
519 kSpaceSaver::~kSpaceSaver()
521 timer.stop();
522 release_Space();
523 QColor::leaveAllocContext();
524 QColor::destroyAllocContext( colorContext );
525 delete rnd; rnd = 0;
528 void kSpaceSaver::setSpeed( int spd )
530 timer.stop();
531 speed = MAXSPEED - spd ;
532 // printf("speed %d\n",speed);
533 timer.stop();
534 timer.start( speed );
537 void kSpaceSaver::setWarp( int w )
539 warpinterval = w;
540 counter = (int)warpinterval;
541 initSpace( mDrawable );
544 void kSpaceSaver::readSettings()
546 KConfig *config = klock_config();
547 config->setGroup( "Settings" );
549 QString str;
551 str = config->readEntry( "Speed" );
552 if ( !str.isNull() )
553 speed = MAXSPEED - str.toInt();
554 else
555 speed = DEFSPEED;
557 warpinterval = config->readNumEntry( "WarpInterval", 15 );
558 delete config;
561 void kSpaceSaver::slotTimeout()
563 //printf("%d %d \n",(int)warpinterval, MAXWARP);
564 if(warpinterval != MAXWARP){
565 if(nitro == 0)
566 counter -= speed +1;
568 if(counter <= 0){
569 nitro = 1;
570 counter = (int) warpinterval *WARPFACTOR;
573 else
574 nitro = 0;
576 drawSpace( mDrawable );
579 //-----------------------------------------------------------------------------
581 kSpaceSetup::kSpaceSetup( QWidget *parent, const char *name )
582 : KDialogBase( parent, name, true, i18n("Setup Space Screen Saver"),
583 Ok|Cancel|Help, Ok, true )
585 setButtonText( Help, i18n( "A&bout" ) );
586 readSettings();
588 QWidget *page = new QWidget( this );
589 setMainWidget( page );
590 QHBoxLayout *hb = new QHBoxLayout( page, 0, spacingHint() );
591 QVBoxLayout *vb = new QVBoxLayout( hb, spacingHint() );
593 QLabel *label;
594 QSlider *slider;
596 label = new QLabel( i18n("Speed:"), page );
597 vb->addWidget( label );
599 slider = new QSlider(MINSPEED, MAXSPEED, 10, speed, QSlider::Horizontal,
600 page );
601 vb->addWidget( slider );
602 slider->setTickmarks(QSlider::TicksBelow);
603 slider->setTickInterval(10);
604 connect( slider, SIGNAL( valueChanged( int ) ), SLOT( slotSpeed( int ) ) );
606 label = new QLabel( i18n("Warp interval:"), page );
607 vb->addWidget( label );
609 slider = new QSlider(MINWARP, MAXWARP, 3, warpinterval, Horizontal, page );
610 vb->addWidget( slider );
611 slider->setTickmarks(QSlider::TicksBelow);
612 slider->setTickInterval(3);
613 connect( slider, SIGNAL( valueChanged( int ) ), SLOT( slotWarp( int ) ) );
615 vb->addStrut( 150 );
616 vb->addStretch();
618 preview = new QWidget( page );
619 hb->addWidget( preview );
620 preview->setFixedSize( 220, 170 );
621 preview->setBackgroundColor( black );
622 preview->show(); // otherwise saver does not get correct size
623 saver = new kSpaceSaver( preview->winId() );
626 void kSpaceSetup::readSettings()
628 KConfig *config = klock_config();
629 config->setGroup( "Settings" );
631 speed = config->readNumEntry( "Speed", speed );
633 if ( speed > MAXSPEED )
634 speed = MAXSPEED;
635 else if ( speed < MINSPEED )
636 speed = MINSPEED;
638 warpinterval = config->readNumEntry( "WarpInterval", 15 );
640 delete config;
643 void kSpaceSetup::slotSpeed( int num )
645 speed = num ;
647 if ( saver )
648 saver->setSpeed( speed );
651 void kSpaceSetup::slotWarp( int num )
653 warpinterval = num;
654 if ( saver )
655 saver->setWarp( warpinterval );
658 void kSpaceSetup::slotOk()
660 KConfig *config = klock_config();
661 config->setGroup( "Settings" );
663 QString sspeed;
664 sspeed.setNum( speed );
665 config->writeEntry( "Speed", sspeed );
667 QString interval;
668 interval.setNum( (int)warpinterval );
669 config->writeEntry( "WarpInterval", interval );
671 config->sync();
672 delete config;
673 accept();
676 void kSpaceSetup::slotHelp()
678 KMessageBox::about(this,
679 i18n("KSpace\nCopyright (c) 1998\n"
680 "Bernd Johannes Wuebben <wuebben@kde.org>"));
685 static GLenum Args(int argc, char **argv)
687 GLint i;
689 doubleBuffer = GL_FALSE;
690 directRender = GL_TRUE;
692 for (i = 1; i < argc; i++) {
693 if (strcmp(argv[i], "-sb") == 0) {
694 doubleBuffer = GL_FALSE;
695 } else if (strcmp(argv[i], "-db") == 0) {
696 doubleBuffer = GL_TRUE;
697 } else if (strcmp(argv[i], "-dr") == 0) {
698 directRender = GL_TRUE;
699 } else if (strcmp(argv[i], "-ir") == 0) {
700 directRender = GL_FALSE;
703 return GL_TRUE;
708 void main(int argc, char **argv)
710 GLenum type;
712 if (Args(argc, argv) == GL_FALSE) {
713 tkQuit();
716 windW = 300;
717 windH = 300;
718 tkInitPosition(0, 0, 300, 300);
720 type = TK_RGB;
721 type |= (doubleBuffer) ? TK_DOUBLE : TK_SINGLE;
722 type |= (directRender) ? TK_DIRECT : TK_INDIRECT;
723 tkInitDisplayMode(type);
725 if (tkInitWindow("Stars") == GL_FALSE) {
726 tkQuit();
729 Init();
731 tkExposeFunc(Reshape);
732 tkReshapeFunc(Reshape);
733 tkKeyDownFunc(Key);
734 tkIdleFunc(Idle);
735 tkExec();