You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
462 lines
14 KiB
462 lines
14 KiB
//-----------------------------------------------------------------------------
|
|
//
|
|
// kfountain - Partical Fountain Screen Saver for KDE 2
|
|
//
|
|
// Copyright (c) Ian Reinhart Geiser 2001
|
|
//
|
|
// KConfig code and KScreenSaver "Setup..." improvements by
|
|
// Nick Betcher <nbetcher@usinternet.com> 2001
|
|
//
|
|
#include <stdlib.h>
|
|
#include <tqlabel.h>
|
|
#include <tqlayout.h>
|
|
#include <kapplication.h>
|
|
#include <klocale.h>
|
|
#include <kconfig.h>
|
|
#include <kcolordialog.h>
|
|
#include <kbuttonbox.h>
|
|
#include <kcolorbutton.h>
|
|
#include <kglobal.h>
|
|
#include "fountain.h"
|
|
#include "fountain.moc"
|
|
#ifdef TQ_WS_MACX
|
|
#include <OpenGL/gl.h>
|
|
#include <OpenGL/glu.h>
|
|
#else
|
|
#include <GL/glu.h>
|
|
#include <GL/gl.h>
|
|
#endif
|
|
#include <tqimage.h>
|
|
#include <kdebug.h>
|
|
#include <tqpainter.h>
|
|
#include <tqradiobutton.h>
|
|
#include <tqspinbox.h>
|
|
#include <kstandarddirs.h>
|
|
#include <math.h>
|
|
#include <kmessagebox.h>
|
|
// libkscreensaver interface
|
|
extern "C"
|
|
{
|
|
KDE_EXPORT const char *kss_applicationName = "kfountain.kss";
|
|
KDE_EXPORT const char *kss_description = I18N_NOOP( "Particle Fountain Screen Saver" );
|
|
KDE_EXPORT const char *kss_version = "2.2.0";
|
|
|
|
KDE_EXPORT KScreenSaver *kss_create( WId id )
|
|
{
|
|
return new KFountainSaver( id );
|
|
}
|
|
|
|
KDE_EXPORT TQDialog *kss_setup()
|
|
{
|
|
return new KFountainSetup();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// dialog to setup screen saver parameters
|
|
//
|
|
KFountainSetup::KFountainSetup( TQWidget *parent, const char *name )
|
|
: SetupUi( parent, name, TRUE )
|
|
{
|
|
readSettings();
|
|
|
|
//TQLabel *label;
|
|
//TQPushButton *button;
|
|
|
|
//setCaption( i18n("Setup Particle Fountain") );
|
|
|
|
//TQVBoxLayout *tl = new TQVBoxLayout(this, 10);
|
|
//TQHBoxLayout *tl1 = new TQHBoxLayout;
|
|
//tl->addLayout(tl1);
|
|
|
|
//TQVBoxLayout *tl11 = new TQVBoxLayout(5);
|
|
//tl1->addLayout(tl11);
|
|
|
|
//label = new TQLabel( i18n("No options here yet...:"), this );
|
|
///tl11->addWidget(label);;
|
|
|
|
//preview = new TQWidget( this );
|
|
preview->setFixedSize( 220, 170 );
|
|
preview->setBackgroundColor( black );
|
|
preview->show(); // otherwise saver does not get correct size
|
|
saver = new KFountainSaver( preview->winId() );
|
|
//tl1->addWidget(preview);
|
|
|
|
//KButtonBox *bbox = new KButtonBox(this);
|
|
//bbox->addStretch(1);
|
|
;
|
|
connect( PushButton1, TQT_SIGNAL( clicked() ), TQT_SLOT( slotOkPressed() ) );
|
|
connect( PushButton2, TQT_SIGNAL( clicked() ), TQT_SLOT( reject() ) );
|
|
connect( PushButton3, TQT_SIGNAL( clicked() ), TQT_SLOT( aboutPressed() ) );
|
|
connect( SpinBox1, TQT_SIGNAL( valueChanged(int)), saver, TQT_SLOT( updateSize(int)));
|
|
connect( RadioButton1, TQT_SIGNAL( toggled(bool)), saver, TQT_SLOT( doStars(bool)));
|
|
|
|
}
|
|
|
|
// read settings from config file
|
|
void KFountainSetup::readSettings()
|
|
{
|
|
KConfig config("kssfountainrc", false, false);
|
|
|
|
config.setGroup( "Settings" );
|
|
TQString boolval = config.readEntry( "Stars", "false" );
|
|
if (boolval == "true") {
|
|
RadioButton1->setDown(true);
|
|
RadioButton1_2->setDown(false);
|
|
} else {
|
|
if (boolval == "false")
|
|
{
|
|
RadioButton1->setDown(false);
|
|
RadioButton1_2->setDown(true);
|
|
}
|
|
}
|
|
|
|
TQString starammount = config.readEntry("StarSize", "75");
|
|
SpinBox1->setValue(starammount.toInt());
|
|
|
|
}
|
|
|
|
// Ok pressed - save settings and exit
|
|
void KFountainSetup::slotOkPressed()
|
|
{
|
|
KConfig config("kssfountainrc", false, false);
|
|
config.setGroup( "Settings" );
|
|
|
|
if (RadioButton1->isOn() == true)
|
|
{
|
|
config.writeEntry( "Stars", "true" );
|
|
} else {
|
|
if (RadioButton1_2->isOn() == true)
|
|
{
|
|
config.writeEntry( "Stars", "false" );
|
|
}
|
|
}
|
|
config.writeEntry( "StarSize", TQString::number(SpinBox1->value()) );
|
|
|
|
config.sync();
|
|
|
|
accept();
|
|
}
|
|
|
|
void KFountainSetup::aboutPressed()
|
|
{
|
|
KMessageBox::about(this,
|
|
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>"));
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
KFountainSaver::KFountainSaver( WId id ) : KScreenSaver( id )
|
|
{
|
|
|
|
kdDebug() << "Blank" << endl;
|
|
|
|
timer = new TQTimer( this );
|
|
timer->start( 25, TRUE );
|
|
setBackgroundColor( black );
|
|
erase();
|
|
fountain = new Fountain();
|
|
embed(fountain);
|
|
fountain->show();
|
|
connect( timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(blank()) );
|
|
}
|
|
|
|
KFountainSaver::~KFountainSaver()
|
|
{
|
|
|
|
}
|
|
|
|
// read configuration settings from config file
|
|
void KFountainSaver::readSettings()
|
|
{
|
|
// Please remove me
|
|
|
|
}
|
|
|
|
void KFountainSaver::blank()
|
|
{
|
|
// Play fountain
|
|
|
|
fountain->updateGL();
|
|
timer->start( 25, TRUE );
|
|
|
|
}
|
|
Fountain::Fountain( TQWidget * parent, const char * name) : TQGLWidget (parent,name)
|
|
{
|
|
rainbow=true;
|
|
slowdown=2.0f;
|
|
zoom=-40.0f;
|
|
index=0;
|
|
size = 0.75f;
|
|
obj = gluNewQuadric();
|
|
|
|
// This has to be here because you can't update the fountain until 'fountain' is created!
|
|
KConfig config("kssfountainrc", false, false);
|
|
config.setGroup( "Settings" );
|
|
TQString boolval = config.readEntry( "Stars", "false" );
|
|
if (boolval == "true") {
|
|
setStars(true);
|
|
} else {
|
|
if (boolval == "false")
|
|
{
|
|
setStars(false);
|
|
}
|
|
}
|
|
|
|
TQString starammount = config.readEntry("StarSize", "75");
|
|
float passvalue = (starammount.toInt() / 100.0);
|
|
setSize(passvalue);
|
|
|
|
}
|
|
|
|
Fountain::~Fountain()
|
|
{
|
|
glDeleteTextures( 1, &texture[0] );
|
|
gluDeleteQuadric(obj);
|
|
}
|
|
|
|
/** load the particle file */
|
|
bool Fountain::loadParticle()
|
|
{
|
|
/* tqStatus indicator */
|
|
bool tqStatus = TRUE;
|
|
TQImage buf;
|
|
|
|
kdDebug() << "Loading: " << locate("data", "kscreensaver/particle.png") << endl;
|
|
if (buf.load( locate("data", "kscreensaver/particle.png") ) )
|
|
|
|
{
|
|
tex = convertToGLFormat(buf); // flipped 32bit RGBA
|
|
kdDebug() << "Texture loaded: " << tex.numBytes () << endl;
|
|
}
|
|
else
|
|
{
|
|
TQImage dummy( 32, 32, 32 );
|
|
dummy.fill( TQt::white.rgb() );
|
|
buf = dummy;
|
|
tex = convertToGLFormat( buf );
|
|
}
|
|
|
|
/* Set the status to true */
|
|
//tqStatus = TRUE;
|
|
glGenTextures(1, &texture[0]); /* create three textures */
|
|
glBindTexture(GL_TEXTURE_2D, texture[0]);
|
|
/* use linear filtering */
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
/* actually generate the texture */
|
|
glTexImage2D(GL_TEXTURE_2D, 0, 4, tex.width(), tex.height(), 0,
|
|
GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
|
|
|
|
|
|
|
|
return tqStatus;
|
|
}
|
|
/** setup the GL enviroment */
|
|
void Fountain::initializeGL ()
|
|
{
|
|
|
|
kdDebug() << "InitGL" << endl;
|
|
GLfloat colors[12][3]=
|
|
{{1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
|
|
{0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
|
|
{0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}};
|
|
|
|
if (loadParticle()) // Jump To Texture Loading Routine
|
|
{
|
|
/* Enable smooth shading */
|
|
glShadeModel( GL_SMOOTH );
|
|
|
|
/* Set the background black */
|
|
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
|
|
|
/* Depth buffer setup */
|
|
glClearDepth( 1.0f );
|
|
|
|
/* Enables Depth Testing */
|
|
glDisable( GL_DEPTH_TEST );
|
|
|
|
/* Enable Blending */
|
|
glEnable( GL_BLEND );
|
|
/* Type Of Blending To Perform */
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
|
|
|
|
|
/* Really Nice Perspective Calculations */
|
|
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
|
/* Really Nice Point Smoothing */
|
|
glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );
|
|
|
|
/* Enable Texture Mapping */
|
|
glEnable( GL_TEXTURE_2D );
|
|
/* Select Our Texture */
|
|
glBindTexture( GL_TEXTURE_2D, texture[0] );
|
|
|
|
for (loop=0;loop<MAX_PARTICLES;loop++) // Initials All The Textures
|
|
{
|
|
particle[loop].active=true; // Make All The Particles Active
|
|
particle[loop].life=1.0f; // Give All The Particles Full Life
|
|
particle[loop].fade=float(KApplication::random()%100)/1000.0f+0.003f; // Random Fade Speed
|
|
particle[loop].r=colors[(loop+1)/(MAX_PARTICLES/12)][0]; // Select Red Rainbow Color
|
|
particle[loop].g=colors[(loop+1)/(MAX_PARTICLES/12)][1]; // Select Green Rainbow Color
|
|
particle[loop].b=colors[(loop+1)/(MAX_PARTICLES/12)][2]; // Select Blue Rainbow Color
|
|
particle[loop].xi=float((KApplication::random()%50)-26.0f)*10.0f; // Random Speed On X Axis
|
|
particle[loop].yi=float((KApplication::random()%50)-25.0f)*10.0f; // Random Speed On Y Axis
|
|
particle[loop].zi=float((KApplication::random()%50)-25.0f)*10.0f; // Random Speed On Z Axis
|
|
particle[loop].xg=0.0f; // SetQt::Horizontal Pull To Zero
|
|
particle[loop].yg=-0.8f; // SetQt::Vertical Pull Downward
|
|
particle[loop].zg=0.0f; // Set Pull On Z Axis To Zero
|
|
particle[loop].size=size; // Set particle size.
|
|
}
|
|
}
|
|
else
|
|
exit(0);
|
|
}
|
|
/** resize the gl view */
|
|
void Fountain::resizeGL ( int width, int height )
|
|
{
|
|
kdDebug() << "ResizeGL " << width << "," <<height<< endl;
|
|
if (height==0) // Prevent A Divide By Zero By
|
|
{
|
|
height=1; // Making Height Equal One
|
|
}
|
|
|
|
glViewport(0,0,width,height); // Reset The Current Viewport
|
|
|
|
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
|
|
glLoadIdentity(); // Reset The Projection Matrix
|
|
|
|
// Calculate The Aspect Ratio Of The Window
|
|
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,200.0f);
|
|
|
|
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
|
|
glLoadIdentity();
|
|
}
|
|
/** paint the GL view */
|
|
void Fountain::paintGL ()
|
|
{
|
|
//kdDebug() << "PaintGL" << endl;
|
|
|
|
GLfloat colors[12][3]=
|
|
{{1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
|
|
{0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
|
|
{0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}};
|
|
col = ( ++col ) % 12;
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
|
|
|
|
glLoadIdentity();
|
|
// Reset The ModelView Matrix
|
|
transIndex++;
|
|
glTranslatef( GLfloat(5.0*sin(4*3.14*transIndex/360)), GLfloat(4.0*cos(2*3.14*transIndex/360)), 0.0 );
|
|
xspeed = GLfloat(100.0*cos(3*3.14*transIndex/360)+100);
|
|
yspeed = GLfloat(100.0*sin(3*3.14*transIndex/360)+100);
|
|
//slowdown = GLfloat(4.0*sin(2*3.14*transIndex/360)+4.01);
|
|
|
|
for (loop=0;loop<MAX_PARTICLES;loop++) // Loop Through All The Particles
|
|
{
|
|
if (particle[loop].active) // If The Particle Is Active
|
|
{
|
|
float x=particle[loop].x; // Grab Our Particle X Position
|
|
float y=particle[loop].y; // Grab Our Particle Y Position
|
|
float z=particle[loop].z+zoom; // Particle Z Pos + Zoom
|
|
/* Select Our Texture */
|
|
|
|
/* Draw The Particle Using Our RGB Values,
|
|
* Fade The Particle Based On It's Life
|
|
*/
|
|
|
|
glColor4f( particle[loop].r,
|
|
particle[loop].g,
|
|
particle[loop].b,
|
|
particle[loop].life );
|
|
|
|
/* Build Quad From A Triangle Strip */
|
|
if( !stars )
|
|
glBegin( GL_TRIANGLE_STRIP );
|
|
else
|
|
glBegin( GL_TRIANGLE_FAN );
|
|
/* Top Right */
|
|
glTexCoord2d( 1, 1 );
|
|
glVertex3f( x + particle[loop].size, y + particle[loop].size, z );
|
|
/* Top Left */
|
|
glTexCoord2d( 0, 1 );
|
|
glVertex3f( x - particle[loop].size, y + particle[loop].size, z );
|
|
/* Bottom Right */
|
|
glTexCoord2d( 1, 0 );
|
|
glVertex3f( x + particle[loop].size, y - particle[loop].size, z );
|
|
/* Bottom Left */
|
|
glTexCoord2d( 0, 0 );
|
|
glVertex3f( x - particle[loop].size, y - particle[loop].size, z );
|
|
glEnd( );
|
|
|
|
particle[loop].x+=particle[loop].xi/(slowdown*1000);// Move On The X Axis By X Speed
|
|
particle[loop].y+=particle[loop].yi/(slowdown*1000);// Move On The Y Axis By Y Speed
|
|
particle[loop].z+=particle[loop].zi/(slowdown*1000);// Move On The Z Axis By Z Speed
|
|
|
|
particle[loop].xi+=particle[loop].xg; // Take Pull On X Axis Into Account
|
|
particle[loop].yi+=particle[loop].yg; // Take Pull On Y Axis Into Account
|
|
particle[loop].zi+=particle[loop].zg; // Take Pull On Z Axis Into Account
|
|
particle[loop].life-=particle[loop].fade; // Reduce Particles Life By 'Fade'
|
|
|
|
if (particle[loop].life<0.0f) // If Particle Is Burned Out
|
|
{
|
|
particle[loop].life=2.0f; // Give It New Life
|
|
particle[loop].fade=float(KApplication::random()%100)/1000.0f+0.003f; // Random Fade Value
|
|
particle[loop].x=0.0f; // Center On X Axis
|
|
particle[loop].y=0.0f; // Center On Y Axis
|
|
particle[loop].z=0.0f; // Center On Z Axis
|
|
particle[loop].xi=xspeed+float((KApplication::random()%60)-32.0f); // X Axis Speed And Direction
|
|
particle[loop].yi=yspeed+float((KApplication::random()%60)-30.0f); // Y Axis Speed And Direction
|
|
particle[loop].zi=float((KApplication::random()%60)-30.0f); // Z Axis Speed And Direction
|
|
particle[loop].r=colors[col][0]; // Select Red From Color Table
|
|
particle[loop].g=colors[col][1]; // Select Green From Color Table
|
|
particle[loop].b=colors[col][2]; // Select Blue From Color Table
|
|
particle[loop].size=size;
|
|
if ((1+(random()%20)) == 10)
|
|
{
|
|
// Explode
|
|
particle[loop].active=true; // Make All The Particles Active
|
|
particle[loop].life=1.0f; // Give All The Particles Full Life
|
|
particle[loop].fade=float(KApplication::random()%100)/1000.0f+0.003f; // Random Fade Speed
|
|
particle[loop].r=colors[(loop+1)/(MAX_PARTICLES/12)][0]; // Select Red Rainbow Color
|
|
particle[loop].g=colors[(loop+1)/(MAX_PARTICLES/12)][1]; // Select Green Rainbow Color
|
|
particle[loop].b=colors[(loop+1)/(MAX_PARTICLES/12)][2]; // Select Blue Rainbow Color
|
|
particle[loop].xi=float((KApplication::random()%50)-26.0f)*10.0f; // Random Speed On X Axis
|
|
particle[loop].yi=float((KApplication::random()%50)-25.0f)*10.0f; // Random Speed On Y Axis
|
|
particle[loop].zi=float((KApplication::random()%50)-25.0f)*10.0f; // Random Speed On Z Axis
|
|
particle[loop].xg=0.0f; // SetQt::Horizontal Pull To Zero
|
|
particle[loop].yg=-0.8f; // SetQt::Vertical Pull Downward
|
|
particle[loop].zg=0.0f; // Set Pull On Z Axis To Zero
|
|
particle[loop].size=size; // Set particle size.
|
|
}
|
|
}
|
|
// Lets stir some things up
|
|
index += 0.001;
|
|
particle[loop].yg =2.0*sin(2*3.14*transIndex/360);
|
|
particle[loop].xg =2.0*cos(2*3.14*transIndex/360);
|
|
particle[loop].zg =4.0+(4.0*cos(2*3.14*transIndex/360));
|
|
|
|
}
|
|
}
|
|
|
|
glFlush();
|
|
}
|
|
void Fountain::setSize( float newSize )
|
|
{
|
|
size = newSize;
|
|
}
|
|
void Fountain::setStars( bool doStars )
|
|
{
|
|
stars = doStars;
|
|
}
|
|
|
|
void KFountainSaver::updateSize(int newSize)
|
|
{
|
|
fountain->setSize(newSize/100);
|
|
}
|
|
void KFountainSaver::doStars(bool starState)
|
|
{
|
|
fountain->setStars(starState);
|
|
}
|
|
|