1 /***************************************************************************
2                     mainmenu.cpp  -  The game's main menu
3                              -------------------
4     begin                : Tue Aug 12 2003
5     copyright            : (C) 2003 by Gabor Torok
6     email                : cctorok@yahoo.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 #include "common/constants.h"
18 #include "mainmenu.h"
19 #include "render/renderlib.h"
20 #include "sdlhandler.h"
21 #include "scourge.h"
22 #include "text.h"
23 #include "partyeditor.h"
24 #include "gui/window.h"
25 #include "gui/label.h"
26 #include "gui/button.h"
27 #include "gui/scrollinglabel.h"
28 #include "gui/progress.h"
29 #include "shapepalette.h"
30 #include "savegamedialog.h"
31 #include "freetype/fontmgr.h"
32 #include "sound.h"
33 #include "texteffect.h"
34 
35 using namespace std;
36 
37 // ###### MS Visual C++ specific ######
38 #if defined(_MSC_VER) && defined(_DEBUG)
39 # define new DEBUG_NEW
40 # undef THIS_FILE
41   static char THIS_FILE[] = __FILE__;
42 #endif
43 
44 #define LOGO_DELTA 0.05f
45 #define LOGO_ROT_POS 30.0f
46 #define LOGO_ROT_NEG 0
47 #define LOGO_ZOOM 0.8f
48 
49 #define LOGO_SPRITE_DELTA 1.0f
50 //#define PI 3.14159f
51 
52 #define WATER_HEIGHT 130
53 
54 #define MENU_ITEM_WIDTH 256
55 #define MENU_ITEM_HEIGHT 32
56 #define MENU_ITEM_ZOOM 1.5f
57 #define MENU_ITEM_PARTICLE_ZOOM 1.1f
58 #define MAX_PARTICLE_LIFE 50
59 
60 bool eventsEnabled = false;
61 
62 const char *MainMenu::menuText[] = {
63 	N_( "New Game" ),
64 	N_( "Continue Game" ),
65 //	N_( "Multiplayer Game" ), ...skip multiplayer for now
66 	N_( "Options" ),
67 	N_( "About S.c.o.u.r.g.e." ),
68 	N_( "Quit" ),
69 	""
70 };
71 
72 int activeMenuItem = -1;
73 
74 const int MainMenu::values[] = {
75 	NEW_GAME, CONTINUE_GAME,
76 	// MULTIPLAYER, ...skip multiplayer for now
77 	OPTIONS, ABOUT, QUIT, 0
78 };
79 
80 Texture slide;
81 
MainMenu(Scourge * scourge)82 MainMenu::MainMenu( Scourge *scourge ) {
83 	this->scourge = scourge;
84 	this->cloudCount = 30;
85 	this->lastMenuTick = 0;
86 	this->savegameDialog = new SavegameDialog( scourge );
87 	for ( int i = 0; i < cloudCount; i++ ) {
88 		cloud[i].x = Util::dice( scourge->getSDLHandler()->getScreen()->w );
89 		cloud[i].y = Util::dice( 50 );
90 		cloud[i].w = Util::pickOne( 200, 254 );
91 		cloud[i].h = Util::pickOne( 100, 127 );
92 		cloud[i].speed = Util::pickOne( 1, 2 );
93 	}
94 
95 	//logoRot = -scourge->getShapePalette()->logo->h;
96 	logoRot = -173;
97 	logoRotDelta = LOGO_DELTA;
98 	logoTicks = 0;
99 	logoTicksDelta = 50;
100 	logoSpriteCount = 0;
101 	candleFlameX = candleFlameY = 0;
102 	slideMode = false;
103 
104 	top = ( scourge->getSDLHandler()->getScreen()->h - 600 ) / 2;
105 	openingTop = scourge->getSDLHandler()->getScreen()->h / 2;
106 	musicStarted = false;
107 	lastTick = 0;
108 	lastTickMenu = 0;
109 	initTextures = false;
110 
111 	starCount = 200;
112 	for ( int i = 0; i < starCount; i++ ) {
113 		star[i].x = Util::dice( scourge->getSDLHandler()->getScreen()->w );
114 		star[i].y = Util::pickOne( top, top + 599 - WATER_HEIGHT - 160 );
115 	}
116 	// The new style gui
117 	int w = 250;
118 	int h = 120;
119 	newGameConfirm = new Window( scourge->getSDLHandler(),
120 	                             ( scourge->getSDLHandler()->getScreen()->w / 2 ) - ( w / 2 ),
121 	                             ( scourge->getSDLHandler()->getScreen()->h / 2 ) - ( h / 2 ),
122 	                             w, h,
123 	                             _( "New Game Confirmation" ),
124 	                             scourge->getShapePalette()->getGuiTexture(), false );
125 	newGameConfirmOK = newGameConfirm->createButton( 40, 55, 110, 75, Constants::getMessage( Constants::OK_LABEL ) );
126 	newGameConfirmCancel = newGameConfirm->createButton( 140, 55, 210, 75, Constants::getMessage( Constants::CANCEL_LABEL ) );
127 	newGameConfirm->createLabel( 20, 20, Constants::getMessage( Constants::DELETE_OLD_SAVED_GAME ) );
128 	newGameConfirm->setVisible( false );
129 	newGameConfirm->setModal( true );
130 
131 	partyEditor = NULL;
132 
133 	// about dialog
134 	w = 500;
135 	h = 350;
136 	aboutDialog = new Window( scourge->getSDLHandler(),
137 	                          ( scourge->getSDLHandler()->getScreen()->w / 2 ) - ( w / 2 ),
138 	                          ( scourge->getSDLHandler()->getScreen()->h / 2 ) - ( h / 2 ),
139 	                          w, h,
140 	                          _( "About S.c.o.u.r.g.e." ),
141 	                          scourge->getShapePalette()->getGuiTexture(), true );
142 	aboutText = new ScrollingLabel( 8, 0,
143 	                                w - 18,
144 	                                h - 65,
145 	                                scourge->getShapePalette()->getAboutText() );
146 	aboutDialog->addWidget( aboutText );
147 	aboutOK = aboutDialog->createButton( ( w / 2 ) - 40,
148 	                                     ( h - 55 ),
149 	                                     ( w / 2 ) + 40,
150 	                                     ( h - 35 ),
151 	                                     Constants::getMessage( Constants::OK_LABEL ) );
152 	aboutDialog->setVisible( false );
153 
154 
155 	progress = new Progress( scourge->getSDLHandler(),
156 	                         scourge->getSession()->getShapePalette()->getProgressTexture(),
157 	                         scourge->getSession()->getShapePalette()->getProgressHighlightTexture(),
158 	                         100, false, false );
159 }
160 
~MainMenu()161 MainMenu::~MainMenu() {
162 	for ( unsigned int i = 0; i < textEffects.size(); i++ ) {
163 		TextEffect *textEffect = textEffects[i];
164 		delete textEffect;
165 	}
166 	textEffects.clear();
167 	delete partyEditor;
168 	delete savegameDialog;
169 	delete newGameConfirm;
170 	delete aboutDialog;
171 	delete progress;
172 }
173 
174 /// Draws the whole main menu view.
175 
drawView()176 void MainMenu::drawView() {
177 	int tickNow = SDL_GetTicks();
178 	if ( ( tickNow - lastMenuTick ) < 15 ) SDL_Delay( 15 - ( tickNow - lastMenuTick ) );
179 	lastMenuTick = SDL_GetTicks();
180 
181 	if ( !slideMode ) {
182 		glDisable( GL_CULL_FACE );
183 
184 		drawStars();
185 
186 		glDisable( GL_TEXTURE_2D );
187 		glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
188 
189 		drawBackdrop();
190 
191 		glEnable( GL_TEXTURE_2D );
192 
193 		// create a stencil for the water
194 		glDisable( GL_DEPTH_TEST );
195 		glColorMask( 0, 0, 0, 0 );
196 
197 		if ( scourge->getUserConfiguration()->getStencilbuf() && scourge->getUserConfiguration()->getStencilBufInitialized() ) {
198 			glEnable( GL_STENCIL_TEST );
199 			glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
200 			glStencilFunc( GL_ALWAYS, 1, 1 );
201 		}
202 
203 		drawWater();
204 
205 		// Use the stencil to draw
206 		glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
207 		glEnable( GL_DEPTH_TEST );
208 
209 		if ( scourge->getUserConfiguration()->getStencilbuf() && scourge->getUserConfiguration()->getStencilBufInitialized() ) {
210 			glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
211 			glStencilFunc( GL_EQUAL, 1, 0xffffffff );  // draw if stencil==1
212 		}
213 
214 		drawClouds( false, true );
215 
216 		glDisable( GL_STENCIL_TEST );
217 
218 		// draw the blended water
219 		glEnable( GL_BLEND );
220 		glDepthMask( GL_FALSE );
221 		glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_COLOR );
222 		drawWater();
223 		glDepthMask( GL_TRUE );
224 		glDisable( GL_BLEND );
225 
226 		glDisable( GL_DEPTH_TEST );
227 
228 		drawClouds( true, false );
229 
230 		glDisable( GL_TEXTURE_2D );
231 		glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
232 		glDisable( GL_DEPTH_TEST );
233 
234 		drawScourge();
235 
236 		glEnable( GL_TEXTURE_2D );
237 		glEnable( GL_DEPTH_TEST );
238 
239 		drawMenu();
240 	}
241 
242 	// draw the boards
243 	if ( openingTop > 0 ) {
244 		glPushMatrix();
245 		glColor3f( 1, 1, 1 );
246 
247 		//    float TILE_W = 510 / 2.0f;
248 		float TILE_W = 256.0f;
249 		float TILE_H = 256.0f;
250 		glEnable( GL_TEXTURE_2D );
251 		Texture const& yellow = scourge->getShapePalette()->getNamedTexture( "menu" );
252 
253 		glPushMatrix();
254 		glLoadIdentity();
255 		glTranslatef( 0, openingTop, 0 );
256 		yellow.glBind();
257 		glBegin( GL_TRIANGLE_STRIP );
258 		glTexCoord2f( 0, scourge->getSDLHandler()->getScreen()->h / TILE_H );
259 		glVertex2i( 0, 0 );
260 		glTexCoord2f( scourge->getSDLHandler()->getScreen()->w / TILE_W, scourge->getSDLHandler()->getScreen()->h / TILE_H );
261 		glVertex2i( scourge->getSDLHandler()->getScreen()->w, 0 );
262 		glTexCoord2f( 0, 0 );
263 		glVertex2i( 0, -scourge->getSDLHandler()->getScreen()->h / 2 );
264 		glTexCoord2f( scourge->getSDLHandler()->getScreen()->w / TILE_W, 0 );
265 		glVertex2i( scourge->getSDLHandler()->getScreen()->w, -scourge->getSDLHandler()->getScreen()->h / 2 );
266 		glEnd();
267 		glPopMatrix();
268 
269 		glPushMatrix();
270 		glLoadIdentity();
271 		glTranslatef( 0, scourge->getSDLHandler()->getScreen()->h - openingTop, 0 );
272 		yellow.glBind();
273 		glBegin( GL_TRIANGLE_STRIP );
274 		glTexCoord2f( 0, 0 );
275 		glVertex2i( 0, 0 );
276 		glTexCoord2f( scourge->getSDLHandler()->getScreen()->w / TILE_W, 0 );
277 		glVertex2i( scourge->getSDLHandler()->getScreen()->w, 0 );
278 		glTexCoord2f( 0, scourge->getSDLHandler()->getScreen()->h / TILE_H );
279 		glVertex2i( 0, scourge->getSDLHandler()->getScreen()->h / 2 );
280 		glTexCoord2f( scourge->getSDLHandler()->getScreen()->w / TILE_W, scourge->getSDLHandler()->getScreen()->h / TILE_H );
281 		glVertex2i( scourge->getSDLHandler()->getScreen()->w, scourge->getSDLHandler()->getScreen()->h / 2 );
282 		glEnd();
283 		glPopMatrix();
284 		glDisable( GL_TEXTURE_2D );
285 
286 		for ( int i = 0; i < 2; i++ ) {
287 			glLoadIdentity();
288 			glTranslatef( 0, ( i == 0 ? openingTop : scourge->getSDLHandler()->getScreen()->h - openingTop ), 0 );
289 			glColor4f( 1, 0.7f, 0, 1 );
290 			glBegin( GL_LINES );
291 			glVertex2i( 0, 0 );
292 			glVertex2i( scourge->getSDLHandler()->getScreen()->w, 0 );
293 			glEnd();
294 		}
295 
296 		if ( slideMode ) {
297 			int w = scourge->getSDLHandler()->getScreen()->w;
298 			int h = ( scourge->getSDLHandler()->getScreen()->w / 2 ) - 1;
299 
300 			glEnable( GL_TEXTURE_2D );
301 			//glPushMatrix();
302 			glLoadIdentity();
303 			glTranslatef( 0, openingTop + 1, 0 );
304 			slide.glBind();
305 			glBegin( GL_TRIANGLE_STRIP );
306 			glTexCoord2f( 0, 0 );
307 			glVertex3f( 0, 0, 0 );
308 			glTexCoord2f( 1, 0 );
309 			glVertex3f( w, 0, 0 );
310 			glTexCoord2f( 0, 1 );
311 			glVertex3f( 0, h, 0 );
312 			glTexCoord2f( 1, 1 );
313 			glVertex3f( w, h, 0 );
314 			glEnd();
315 			//glPopMatrix();
316 			glDisable( GL_TEXTURE_2D );
317 		} else {
318 			glLoadIdentity();
319 			glTranslatef( 10, scourge->getSDLHandler()->getScreen()->h - openingTop + 12, 0 );
320 			char version[100];
321 			snprintf( version, 100, _( "Scourge version %s" ), SCOURGE_VERSION );
322 			scourge->getSDLHandler()->setFontType( Constants::SCOURGE_DEFAULT_FONT );
323 			scourge->getSDLHandler()->texPrint( 0, 0, version );
324 			glColor3f( 0.8f, 0.75f, 0.65f );
325 			int y = 14;
326 			scourge->getSDLHandler()->texPrint( 0, y, _( "Optionally compiled modules:" ) );
327 			y += 14;
328 #ifdef HAVE_SDL_NET
329 			scourge->getSDLHandler()->texPrint( 0, y, _( "[Network]" ) );
330 			y += 14;
331 #endif
332 #ifdef HAVE_SDL_MIXER
333 			scourge->getSDLHandler()->texPrint( 0, y, _( "[Sound]" ) );
334 			y += 14;
335 #endif
336 			glPopMatrix();
337 
338 			if ( openingTop > top && scourge->getSession()->isDataInitialized() ) {
339 				Uint32 t = SDL_GetTicks();
340 				if ( t - lastTick > 40 ) {
341 					int d = ( scourge->getSDLHandler()->getScreen()->h - openingTop ) / 20;
342 					openingTop -= ( 10 + static_cast<int>( d * 1.2 ) );
343 					if ( openingTop < top ) openingTop = top;
344 					lastTick = t;
345 				}
346 			}
347 		}
348 	}
349 
350 	if ( openingTop <= top ) {
351 		drawLogo();
352 		if ( !musicStarted ) {
353 			scourge->getSession()->getSound()->playMusicMenu();
354 			musicStarted = true;
355 		}
356 	}
357 
358 	// initialize universe (nice how this is hidden here...)
359 	scourge->getSession()->initData();
360 }
361 
362 /// Draws the loading screen if still loading data.
363 
drawAfter()364 void MainMenu::drawAfter() {
365 	if ( strlen( getUpdate() ) ) {
366 		glPushMatrix();
367 
368 		/*
369 		glLoadIdentity();
370 		glEnable( GL_BLEND );
371 		glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
372 		glDisable( GL_TEXTURE_2D );
373 		glColor4f( 0, 0, 0, 0.75f );
374 		glBegin( GL_QUADS );
375 		glVertex3f( 0, 0, 0 );
376 		glVertex3f( 0, scourge->getScreenHeight(), 0 );
377 		glVertex3f( scourge->getScreenWidth(), scourge->getScreenHeight(), 0 );
378 		glVertex3f( scourge->getScreenWidth(), 0, 0 );
379 		glEnd();
380 		glEnable( GL_TEXTURE_2D );
381 		glDisable( GL_BLEND );
382 		*/
383 
384 		glLoadIdentity();
385 		glTranslatef( 10, scourge->getSDLHandler()->getScreen()->h - openingTop + 12, 0 );
386 		int y = 70;
387 		int x = 100;
388 		float maxStatus = ( scourge->getScreenWidth() - 200 ) / 20.0f;
389 		glColor3f( 0.8f, 0.75f, 0.65f );
390 		if ( getUpdateTotal() > -1 ) {
391 			scourge->getSDLHandler()->
392 			texPrint( x, y - 3, "%s: %d%%",
393 			          getUpdate(),
394 			          static_cast<int>( ( getUpdateValue() + 1 ) / ( getUpdateTotal() / 100.0f ) ) );
395 			glTranslatef( x + 150, y - 15, 0 );
396 
397 			progress->updateStatusLight( NULL,
398 			                             static_cast<int>( ( getUpdateValue() + 1 ) / ( getUpdateTotal() / maxStatus ) ),
399 			                             static_cast<int>( maxStatus ) );
400 		} else {
401 			scourge->getSDLHandler()->texPrint( x, y - 3, getUpdate() );
402 		}
403 		glPopMatrix();
404 	}
405 	eventsEnabled = scourge->getSession()->isDataInitialized();
406 	if ( eventsEnabled ) scourge->getSDLHandler()->setCursorMode( Constants::CURSOR_NORMAL );
407 	else scourge->getSDLHandler()->setCursorMode( Constants::CURSOR_FORBIDDEN );
408 }
409 
show()410 void MainMenu::show() {
411 	//logoRot = -scourge->getShapePalette()->logo->h;
412 	logoRot = -173;
413 	setValue( -1 );
414 }
415 
hide()416 void MainMenu::hide() {
417 	musicStarted = false;
418 }
419 
420 /// Draws the menu.
421 
drawMenu()422 void MainMenu::drawMenu() {
423 
424 	if ( textEffects.empty() && openingTop <= top ) {
425 		int x = 50;
426 		int y = top + 230;
427 		for ( int i = 0; strlen( menuText[i] ); i++ ) {
428 			TextEffect *textEffect = new TextEffect( scourge, x - 40, y - 20, _( menuText[i] ) );
429 			textEffects.push_back( textEffect );
430 			y += 50;
431 		}
432 	}
433 
434 	glDisable( GL_STENCIL_TEST );
435 	glDisable( GL_SCISSOR_TEST );
436 	glDisable( GL_CULL_FACE );
437 	glDisable( GL_DEPTH_TEST );
438 
439 	for ( int i = 0; i < static_cast<int>( textEffects.size() ); i++ ) {
440 		if ( this->scourge->getSession()->getPreferences()->getFlaky() == false ) {
441 			TextEffect *textEffect = textEffects[i];
442 			textEffect->setActive( i == activeMenuItem );
443 			textEffect->draw();
444 		} else {
445 			glDisable( GL_DEPTH_TEST );
446 			scourge->getSDLHandler()->setFontType( Constants::SCOURGE_LARGE_FONT );
447 			if ( i == activeMenuItem ) {
448 				glColor4f( 1, 1, 0, 1 );
449 			} else {
450 				glColor4f( 1, 1, 1, 1 );
451 			}
452 			scourge->getSDLHandler()->texPrint( 50, top + 230 + ( i * 50 ), _( menuText[i] ) );
453 			scourge->getSDLHandler()->setFontType( Constants::SCOURGE_DEFAULT_FONT );
454 			glEnable( GL_DEPTH_TEST );
455 		}
456 	}
457 }
458 
459 /// Draws the logo in the upper left.
460 
drawLogo()461 void MainMenu::drawLogo() {
462 
463 	glEnable( GL_BLEND );
464 	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
465 	glEnable( GL_TEXTURE_2D );
466 
467 	//Draw the Scourge logo
468 	glPushMatrix();
469 	glLoadIdentity();
470 	glTranslatef( 70, logoRot, 0 );
471 //  float w = scourge->getShapePalette()->logo->w;
472 //  float h = scourge->getShapePalette()->logo->h;
473 	float w = 352.0f;
474 	float h = 173.0f;
475 	glColor4f( 1, 1, 1, 1 );
476 	scourge->getShapePalette()->logo_texture.glBind();
477 
478 	glBegin( GL_TRIANGLE_STRIP );
479 	glTexCoord2f( 0.0f, 0.0f );
480 	glVertex3f( 0, 0, 0 );
481 	glTexCoord2f( 1.0f, 0.0f );
482 	glVertex3f( w, 0, 0 );
483 	glTexCoord2f( 0.0f, 1.0f );
484 	glVertex3f( 0, h, 0 );
485 	glTexCoord2f( 1.0f, 1.0f );
486 	glVertex3f( w, h, 0 );
487 	glEnd();
488 	glPopMatrix();
489 
490 	for ( int i = 0; i < 2; i++ ) {
491 		glPushMatrix();
492 		glLoadIdentity();
493 //    glTranslatef( ( !i ? 100 :
494 //                    70 + scourge->getShapePalette()->logo->w - 30 -
495 //                    scourge->getShapePalette()->chain->w ),
496 //                  logoRot - scourge->getShapePalette()->chain->h, 0 );
497 //    float w = scourge->getShapePalette()->chain->w;
498 //    float h = scourge->getShapePalette()->chain->h;
499 		glTranslatef( ( !i ? 100 : 70 + 352 - 30 - 32 ), logoRot - 256, 0 );
500 		float w = 32.0f;
501 		float h = 256.0f;
502 		glColor4f( 1, 1, 1, 1 );
503 		scourge->getShapePalette()->chain_texture.glBind();
504 
505 		glBegin( GL_TRIANGLE_STRIP );
506 		glTexCoord2f( 0.0f, 0.0f );
507 		glVertex3f( 0, 0, 0 );
508 		glTexCoord2f( 1.0f, 0.0f );
509 		glVertex3f( w, 0, 0 );
510 		glTexCoord2f( 0.0f, 1.0f );
511 		glVertex3f( 0, h, 0 );
512 		glTexCoord2f( 1.0f, 1.0f );
513 		glVertex3f( w, h, 0 );
514 		glEnd();
515 		glPopMatrix();
516 	}
517 
518 	GLint t = SDL_GetTicks();
519 	if ( t - logoTicks > logoTicksDelta ) {
520 		if ( logoRot < 120 - ( ( 1024 - scourge->getScreenHeight() ) / 4 ) ) {
521 			logoTicks = t;
522 			logoRot += 8;
523 		}
524 		candleFlameX = scourge->getSDLHandler()->getScreen()->w - 215 + Util::dice( 4 ) - 4;
525 		candleFlameY = top + 385 + Util::dice( 4 ) - 4;
526 	}
527 
528 	glBlendFunc( GL_SRC_COLOR, GL_ONE );
529 
530 	scourge->getShapePalette()->candle.glBind();
531 	glColor4f( 0.7f, 0.7f, 0.3f, 0.5f );
532 	glPushMatrix();
533 	glLoadIdentity();
534 	glTranslatef( candleFlameX, candleFlameY, 0 );
535 	w = 64;
536 	h = 64;
537 
538 	glBegin( GL_TRIANGLE_STRIP );
539 	glTexCoord2f( 0.0f, 0.0f );
540 	glVertex3f( 0, 0, 0 );
541 	glTexCoord2f( 1.0f, 0.0f );
542 	glVertex3f( w, 0, 0 );
543 	glTexCoord2f( 0.0f, 1.0f );
544 	glVertex3f( 0, h, 0 );
545 	glTexCoord2f( 1.0f, 1.0f );
546 	glVertex3f( w, h, 0 );
547 	glEnd();
548 	glPopMatrix();
549 
550 	glDisable( GL_TEXTURE_2D );
551 	glDisable( GL_BLEND );
552 }
553 
554 /// Draws the stars.
555 
drawStars()556 void MainMenu::drawStars() {
557 	glDisable( GL_TEXTURE_2D );
558 	for ( int i = 0; i < starCount; i++ ) {
559 		glPushMatrix();
560 		glLoadIdentity();
561 		glTranslatef( star[i].x, star[i].y, -200 );
562 		glColor3f( Util::roll( 0.2f, 0.99f ),
563 		           Util::roll( 0.2f, 0.99f ),
564 		           Util::roll( 0.2f, 0.99f ) );
565 		int n = 1;
566 		glBegin( GL_TRIANGLE_STRIP );
567 		glVertex2d( 0, 0 );
568 		glVertex2d( n, 0 );
569 		glVertex2d( 0, n );
570 		glVertex2d( n, n );
571 		glEnd();
572 		glPopMatrix();
573 	}
574 	glEnable( GL_TEXTURE_2D );
575 
576 }
577 
578 /// Draws the scourge (the house entrance to the right).
579 
drawScourge()580 void MainMenu::drawScourge() {
581 
582 	glEnable( GL_BLEND );
583 	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
584 	glEnable( GL_TEXTURE_2D );
585 
586 	float w = 554; //scourge->getShapePalette()->scourge->w;
587 	float h = 600; //scourge->getShapePalette()->scourge->h;
588 
589 	//Draw the scourge
590 	glPushMatrix();
591 	glLoadIdentity();
592 	glTranslatef( scourge->getSDLHandler()->getScreen()->w - w, top, 0 );
593 	glColor4f( 1, 1, 1, 1 );
594 	scourge->getShapePalette()->getNamedTexture( "scourge" ).glBind();
595 
596 	glBegin( GL_TRIANGLE_STRIP );
597 	glTexCoord2f( 0.005f, 0.005f );
598 	glVertex3f( 0, 0, 0 );
599 	glTexCoord2f( 0.995f, 0.005f );
600 	glVertex3f( w, 0, 0 );
601 	glTexCoord2f( 0.005f, 0.995f );
602 	glVertex3f( 0, h, 0 );
603 	glTexCoord2f( 0.995f, 0.995f );
604 	glVertex3f( w, h, 0 );
605 	glEnd();
606 	glPopMatrix();
607 
608 	glDisable( GL_TEXTURE_2D );
609 	glDisable( GL_BLEND );
610 }
611 
612 /// Draws the mountains in the back.
613 
drawBackdrop()614 void MainMenu::drawBackdrop() {
615 	glEnable( GL_BLEND );
616 	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
617 	glEnable( GL_TEXTURE_2D );
618 
619 //  float w = scourge->getShapePalette()->scourgeBackdrop->w;
620 	float w = scourge->getSDLHandler()->getScreen()->w;
621 	//float h = scourge->getShapePalette()->scourgeBackdrop->h;
622 	float h = 256.0f;
623 
624 	//Draw the backdrop image
625 	glPushMatrix();
626 	glLoadIdentity();
627 	glTranslatef( 0, top + ( 600 - WATER_HEIGHT - h ), 0 );
628 	glColor4f( 1, 1, 1, 1 );
629 	scourge->getShapePalette()->scourgeBackdrop_texture.glBind();
630 
631 	glBegin( GL_TRIANGLE_STRIP );
632 	glTexCoord2f( 0.0f, 0.0f );
633 	glVertex3f( 0, 0, 0 );
634 	glTexCoord2f( 1.0f, 0.0f );
635 	glVertex3f( w, 0, 0 );
636 	glTexCoord2f( 0.0f, 1.0f );
637 	glVertex3f( 0, h, 0 );
638 	glTexCoord2f( 1.0f, 1.0f );
639 	glVertex3f( w, h, 0 );
640 	glEnd();
641 	glPopMatrix();
642 
643 	glDisable( GL_TEXTURE_2D );
644 	glDisable( GL_BLEND );
645 
646 }
647 
648 /// Draws the clouds.
649 
drawClouds(bool moveClouds,bool flipped)650 void MainMenu::drawClouds( bool moveClouds, bool flipped ) {
651 	// draw clouds
652 	float w, h;
653 
654 	glEnable( GL_TEXTURE_2D );
655 	glEnable( GL_BLEND );
656 	glBlendFunc( GL_ONE_MINUS_DST_COLOR, GL_ONE );
657 
658 	scourge->getShapePalette()->cloud.glBind();
659 
660 	for ( int i = 0; i < cloudCount; i++ ) {
661 		w = cloud[i].w;
662 		h = cloud[i].h;
663 		glPushMatrix();
664 		glTranslatef( cloud[i].x,
665 		              top + ( flipped ? 600 - ( cloud[i].y + h / 2.0 ) : cloud[i].y + 130 ),
666 		              0 );
667 
668 		glBegin( GL_TRIANGLE_STRIP );
669 		if ( flipped ) {
670 			glColor4f( 0.1f, 0.1f, 0.3f, 0.5f );
671 		} else {
672 			glColor4f( 1, 1, 1, 1 );
673 		}
674 		glTexCoord2f( 0.0f, ( flipped ? 1.0f : 0.0f ) );
675 		glVertex3f( 0, 0, 0 );
676 
677 		if ( flipped ) {
678 			glColor4f( 0.1f, 0.1f, 0.3f, 0.5f );
679 		} else {
680 			glColor4f( 1, 1, 1, 1 );
681 		}
682 		glTexCoord2f( 1.0f, ( flipped ? 1.0f : 0.0f ) );
683 		glVertex3f( w, 0, 0 );
684 
685 		glColor4f( 1, 0.3f, 0, 0.5f );
686 		glTexCoord2f( 0.0f, ( flipped ? 0.0f : 1.0f ) );
687 		glVertex3f( 0, ( flipped ? h / 2.0 : h ), 0 );
688 
689 		glColor4f( 1, 0.3f, 0, 0.5f );
690 		glTexCoord2f( 1.0f, ( flipped ? 0.0f : 1.0f ) );
691 		glVertex3f( w, ( flipped ? h / 2.0 : h ), 0 );
692 		glEnd();
693 		glPopMatrix();
694 
695 		if ( moveClouds ) {
696 			cloud[i].x += cloud[i].speed;
697 			if ( cloud[i].x >= scourge->getSDLHandler()->getScreen()->w ) {
698 				cloud[i].x = -cloud[i].w;
699 			}
700 		}
701 	}
702 	glDisable( GL_BLEND );
703 	glDisable( GL_TEXTURE_2D );
704 }
705 
706 /// Draws the water.
707 
drawWater()708 void MainMenu::drawWater() {
709 	float w, h;
710 	// draw the water
711 	glPushMatrix();
712 	w = scourge->getSDLHandler()->getScreen()->w;
713 	h = WATER_HEIGHT;
714 	glLoadIdentity();
715 	glTranslatef( 0, top + ( 600 - h ), 0 );
716 	glDisable( GL_TEXTURE_2D );
717 	//  glDisable( GL_LIGHTING );
718 	//glEnable( GL_BLEND );
719 	//glBlendFunc( GL_ONE_MINUS_DST_COLOR, GL_ONE );
720 
721 	glBegin( GL_TRIANGLE_STRIP );
722 	glColor4f( 0, 0, 0.1f, 1 );
723 	glVertex3f( 0, 0, 0 );
724 	glColor4f( 0, 0, 0.1f, 1 );
725 	glVertex3f( w, 0, 0 );
726 	glColor4f( 0, 0.1f, 0.4f, 1 );
727 	glVertex3f( 0, h, 0 );
728 	glColor4f( 0, 0.1f, 0.4f, 1 );
729 	glVertex3f( w, h, 0 );
730 	glEnd();
731 	//glDisable( GL_BLEND );
732 	glPopMatrix();
733 }
734 
handleEvent(Widget * widget,SDL_Event * event)735 bool MainMenu::handleEvent( Widget *widget, SDL_Event *event ) {
736 
737 	if ( !eventsEnabled ) return false;
738 
739 	if ( aboutDialog->isVisible() ) {
740 		if ( widget == aboutOK || widget == aboutDialog->closeButton ) {
741 			aboutDialog->setVisible( false );
742 		}
743 		return false;
744 	}
745 
746 //	if ( scourge->getMultiplayerDialog()->isVisible() ) {
747 //		scourge->getMultiplayerDialog()->handleEvent( widget, event );
748 //		if ( !scourge->getMultiplayerDialog()->isVisible() ) {
749 //			if ( scourge->getMultiplayerDialog()->getValue() == MultiplayerDialog::START_SERVER ) {
750 //				value = MULTIPLAYER_START;
751 //				return true;
752 //			} else if ( scourge->getMultiplayerDialog()->getValue() == MultiplayerDialog::JOIN_SERVER ) {
753 //				if ( !( strlen( scourge->getMultiplayerDialog()->getServerName() ) &&
754 //				        strlen( scourge->getMultiplayerDialog()->getServerPort() ) &&
755 //				        strlen( scourge->getMultiplayerDialog()->getUserName() ) ) ) {
756 //					scourge->showMessageDialog( Constants::getMessage( Constants::JOIN_SERVER_ERROR ) );
757 //				} else {
758 //					value = MULTIPLAYER_START;
759 //					return true;
760 //				}
761 //			}
762 //		}
763 //		return false;
764 //	}
765 
766 	return false;
767 }
768 
handleEvent(SDL_Event * event)769 bool MainMenu::handleEvent( SDL_Event *event ) {
770 
771 	if ( !eventsEnabled ) return false;
772 
773 	if ( aboutDialog->isVisible() ) {
774 		return false;
775 	}
776 
777 	if ( scourge->getSaveDialog()->getWindow()->isVisible() ) {
778 		return false;
779 	}
780 
781 	if ( savegameDialog->getWindow()->isVisible() ) {
782 //		savegameDialog->handleEvent( NULL, event );
783 		return false;
784 	}
785 
786 	if ( scourge->getOptionsMenu()->isVisible() ) {
787 //		scourge->getOptionsMenu()->handleEvent( event );
788 		return false;
789 	}
790 
791 	if ( scourge->getMultiplayerDialog()->isVisible() ) {
792 //		scourge->getMultiplayerDialog()->handleEvent( event );
793 		return false;
794 	}
795 
796 	if ( partyEditor && partyEditor->isVisible() ) {
797 //		partyEditor->handleEvent( NULL, event );
798 		return false;
799 	}
800 
801 	/*
802 	// esc to close new game confirmation (doesn't work)
803 	if((event->type == SDL_KEYDOWN || event->type == SDL_KEYUP) &&
804 	   newGameConfirm->isVisible() &&
805 	   event->key.keysym.sym == SDLK_ESCAPE) {
806 	  newGameConfirm->setVisible( false );
807 	  return false;
808 	}
809 	*/
810 
811 	switch ( event->type ) {
812 		//case SDL_KEYDOWN:
813 	case SDL_KEYUP:
814 		switch ( event->key.keysym.sym ) {
815 		case SDLK_1: value = NEW_GAME; showPartyEditor(); return false;
816 		case SDLK_2: value = CONTINUE_GAME; scourge->getSaveDialog()->show( false ); return false;
817 		case SDLK_3: value = MULTIPLAYER; return true;
818 		case SDLK_4: value = OPTIONS; return true;
819 		case SDLK_5: value = ABOUT; return true;
820 	case SDLK_6: case SDLK_ESCAPE: value = QUIT; return true;
821 		case SDLK_7: value = EDITOR; return true;
822 		default: break;
823 		}
824 		//break;
825 		//case SDL_KEYUP:
826 		if ( event->key.keysym.sym == '8' ) {
827 			Scourge::blendA++; if ( Scourge::blendA >= 11 ) Scourge::blendA = 0;
828 			fprintf( stderr, "blend: a=%d b=%d\n", Scourge::blendA, Scourge::blendB );
829 		} else if ( event->key.keysym.sym == '9' ) {
830 			Scourge::blendB++; if ( Scourge::blendB >= 11 ) Scourge::blendB = 0;
831 			fprintf( stderr, "blend: a=%d b=%d\n", Scourge::blendA, Scourge::blendB );
832 		}
833 		break;
834 	case SDL_MOUSEMOTION:
835 	case SDL_MOUSEBUTTONUP:
836 		if ( event->motion.x >= 50 && event->motion.x < 400 ) {
837 			if ( this->scourge->getSession()->getPreferences()->getFlaky() == false ) {
838 				activeMenuItem = ( event->motion.y - ( top + 240 ) ) / 50;
839 			} else {
840 				activeMenuItem = ( event->motion.y - ( top + 230 + SDLHandler::fontInfos[ Constants::SCOURGE_LARGE_FONT ]->yoffset ) ) / 50;
841 			}
842 		}
843 		if ( event->button.button != SDL_BUTTON_LEFT ) return false;
844 		if ( event->type == SDL_MOUSEBUTTONUP && activeMenuItem > -1 && activeMenuItem < static_cast<int>( textEffects.size() ) ) {
845 			value = values[activeMenuItem];
846 			if ( value == ABOUT ) {
847 				aboutDialog->setVisible( true );
848 				//value = ABOUT;
849 				return false;
850 			} else if ( value == NEW_GAME ) {
851 				showPartyEditor();
852 				return false;
853 			} else if ( value == CONTINUE_GAME ) {
854 				scourge->getSaveDialog()->show( false );
855 				return false;
856 			} else {
857 				return true;
858 			}
859 		}
860 		break;
861 	default: break;
862 	}
863 	return false;
864 }
865 
866 /// Returns the selected menu entry.
867 
getValue()868 int MainMenu::getValue() {
869 	return value;
870 }
871 
showNewGameConfirmationDialog()872 void MainMenu::showNewGameConfirmationDialog() {
873 	newGameConfirm->setVisible( true );
874 }
875 
showSavegameDialog(bool inSaveMode)876 void MainMenu::showSavegameDialog( bool inSaveMode ) {
877 	savegameDialog->show( inSaveMode );
878 }
879 
showPartyEditor()880 void MainMenu::showPartyEditor() {
881 	if ( !partyEditor ) partyEditor = new PartyEditor( scourge );
882 	partyEditor->setVisible( true );
883 }
884 
createParty(Creature ** pc,int * partySize)885 void MainMenu::createParty( Creature **pc, int *partySize ) {
886 	if ( !partyEditor ) partyEditor = new PartyEditor( scourge );
887 	partyEditor->createParty( pc, partySize );
888 }
889 
createWanderingHero(int level)890 RenderedCreature *MainMenu::createWanderingHero( int level ) {
891 	if ( !partyEditor ) partyEditor = new PartyEditor( scourge );
892 	return partyEditor->createWanderingHero( level );
893 }
894 
setSlideMode(bool b)895 void MainMenu::setSlideMode( bool b ) {
896   slideMode = b;
897 
898   if ( slideMode ) {
899     openingTop = ( scourge->getSDLHandler()->getScreenHeight() / 2 ) - ( scourge->getSDLHandler()->getScreenWidth() / 4 );
900     slide = scourge->getShapePalette()->getRandomSlide();
901 
902   } else {
903     openingTop = scourge->getSDLHandler()->getScreenHeight() / 2;
904   }
905 }