1 /***************************************************************************
2 * Copyright (C) 2004 by E.Ros *
3 * rosenric@dei.unipd.it *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 ***************************************************************************/
21 #include <kstandarddirs.h>
22 #include <kdeversion.h>
24 #include "firesaverwriter.h"
27 /* Word: SINGLE WORD */
29 Word::Word( const char * _text
, QMap
<char, Symbol
*> * sMap
, float _scale
)
30 : width(0), scale(_scale
), cX(0), cY(0), vScale(0), vX(0), vY(0),
31 activateTime(0.0), lifeTime(2), currentTime(0)
33 for ( ; *_text
!= 0 && *_text
!= ' '; _text
++ )
36 if ( !sMap
->contains(c
) ) //search for a symbol in the map
38 Symbol
* symbol
= (*sMap
)[c
]; //get the symbol*
39 width
+= symbol
->scale
; //increase word's half-width
40 symbolList
.append( symbol
); //insert it to the list
43 color
[1] = 0.8 * drand48();
44 color
[2] = 0.2 + 0.8 * drand48();
48 inline void Word::renderWord( double dT
)
50 if ( (currentTime
+= dT
) < activateTime
)
54 if ( activateTime
>= 0 ) {
55 if ( currentTime
< activateTime
+ 0.4 )
56 color
[3] = (currentTime
- activateTime
) / 0.4;
58 color
[3] = 1 - (currentTime
- activateTime
- 0.4) / (lifeTime
- 0.4);
60 color
[3] = 1 - currentTime
/ lifeTime
;
62 //word's global transforms
64 glTranslatef( cX
- scale
* width
, cY
, 0 );
65 glScalef( scale
, scale
, 1 );
68 //for each symbol draw it!
69 Symbol
* symbol
= symbolList
.first();
70 for( ; symbol
; symbol
= symbolList
.next() )
71 symbol
->renderSymbol();
74 //physical update to position and scale
77 scale
+= scale
* vScale
* dT
;
80 inline bool Word::isDead()
82 if ( activateTime
> 0 )
83 return (currentTime
- activateTime
) >= lifeTime
;
84 return currentTime
>= lifeTime
;
89 /* Writer: engine that spawns and manages words */
91 Writer::Writer( QString descFileName
)
94 wordList
.setAutoDelete( true );
96 if ( !loadMap( descFileName
) )
99 QString welcomeString
= i18n("Welcome to KDE %1.%2.%3")
100 .arg(KDE_VERSION_MAJOR
)
101 .arg(KDE_VERSION_MINOR
)
102 .arg(KDE_VERSION_RELEASE
);
103 spawnWords(welcomeString
, Fun1
);
108 glDeleteTextures( numTextures
, texArray
);
110 QMap
<char, Symbol
*>::Iterator it
= symbolMap
.begin();
111 for ( ; it
!= symbolMap
.end(); ++it
)
112 delete (Symbol
*)it
.data();
115 void Writer::spawnWords( QString phrase
, effectType fX
)
119 yCenter
= drand48()*40 - 20,
121 Q3PtrList
<Word
> localWords
;
122 while ( phrase
.length() > 0 )
124 QString letters
= phrase
.section(" ",0,0);
125 Word
* word
= new Word( letters
.latin1(), &symbolMap
);
126 wordList
.append( word
);
127 localWords
.append( word
);
132 float angle
= 2*M_PI
* drand48(),
133 module
= 0.25 * (drand48() + drand48());
134 word
->vX
= module
* cos( angle
);
135 word
->vY
= module
* sin( angle
);
137 word
->scale
= 0.7 + 0.3*(drand48() + drand48());}
138 word
->activateTime
= 0.3 * wordCount
;
139 //fall to the case below for word spacing
142 wordsWidth
+= word
->width
;
143 word
->cX
+= wordsWidth
;
144 wordsWidth
+= word
->width
+ 1;
147 word
->lifeTime
= 1.2;
148 word
->activateTime
= 0.6 + 0.9 * wordCount
;
153 phrase
.remove(0, letters
.length() + 1);
155 if ( localWords
.count() < 1 )
157 //some computations to 'center' the string
158 float displace
= -(wordsWidth
- 1) / 2;
159 Word
* word
= localWords
.first();
160 for( ; word
; word
= localWords
.next() )
161 word
->cX
+= displace
;
164 void Writer::render( double dT
)
169 glEnable( GL_TEXTURE_2D
);
172 glScalef( 0.6, 0.6, 1.0 );
173 Word
* word
= wordList
.first();
175 word
->renderWord( dT
);
176 if ( word
->isDead() ) {
178 word
= wordList
.current();
180 word
= wordList
.next();
186 * parses the description file to create the internal symbols map.
187 * This map is then used when building words.
189 bool Writer::loadMap( QString descFile
)
191 QFile
desc( locate("data","kfiresaver/"+descFile
) );
192 if ( !desc
.open( QIODevice::ReadOnly
) )
195 unsigned int currentNumber
;
196 float xres
= 0, yres
= 0;
197 bool generatedFirst
= false;
199 while ( !desc
.atEnd() )
202 int count
= desc
.readLine( line
, 100 );
203 //skip comments / invalid lines
204 if ( count
< 6 || line
.at(0) == '#')
207 if ( line
.at(0) == '"' && numTextures
< 15 )
209 //load and generate texture
210 QString fileName
= line
.section("\"", 1,1 );
212 if ( !tmp
.load( locate("data","kfiresaver/"+fileName
) ) ) {
213 kdWarning() << "can't load filename:" << fileName
<< endl
;
214 generatedFirst
= false;
217 glGenTextures( 1, ¤tNumber
);
218 texArray
[ numTextures
++ ] = currentNumber
;
219 glBindTexture(GL_TEXTURE_2D
, currentNumber
);
220 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
221 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
222 QImage texture
= QGLWidget::convertToGLFormat( tmp
);
223 xres
= (float)texture
.width();
224 yres
= (float)texture
.height();
225 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, (int)xres
, (int)yres
, 0,
226 GL_RGBA
, GL_UNSIGNED_BYTE
, texture
.bits());
227 generatedFirst
= true;
230 if ( !generatedFirst
)
232 if ( line
.contains(' ') != 4 ) {
233 kdWarning() << "wrong line on symbols.desc (4 spaces expected):" << endl
;
234 kdWarning() << " '" << line
<< "'" << endl
;
237 //parse the line describing a symbol and create it
238 char p
= *(line
.latin1());
239 if ( symbolMap
.contains(p
) )
241 float left
= (float)(line
.section(" ",1,1).toInt())/xres
,
242 top
= (float)(line
.section(" ",2,2).toInt())/yres
,
243 right
= (float)(line
.section(" ",3,3).toInt() + 1)/xres
,
244 bottom
= (float)(line
.section(" ",4,4).toInt() + 1)/yres
;
245 symbolMap
[p
] = new Symbol( currentNumber
, left
,top
,right
,bottom
);
248 return symbolMap
.size() > 0;