1 /***************************************************************************
2                      sdlhandler.cpp  -  Interface to SDL
3                              -------------------
4     begin                : Sat May 3 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 
18 #include "common/constants.h"
19 #include "sdlhandler.h"
20 #include "gameadapter.h"
21 #include "gui/window.h"
22 #include "gui/eventhandler.h"
23 #include "preferences.h"
24 #include "sdleventhandler.h"
25 #include "sdlscreenview.h"
26 #include "session.h"
27 #include "party.h"
28 #include "debug.h"
29 #include "freetype/fontmgr.h"
30 #include "sound.h"
31 #include "sqbinding/sqbinding.h"
32 #include "render/cutscene.h"
33 #include "render/texture.h"
34 
35 // ###### MS Visual C++ specific ######
36 #if defined(_MSC_VER) && defined(_DEBUG)
37 # define new DEBUG_NEW
38 # undef THIS_FILE
39 static char THIS_FILE[] = __FILE__;
40 #endif
41 
42 using namespace std;
43 
44 // FIXME: use static member variable, std::string is clear by default
45 string willSavePath = "";
46 
47 vector<SDLHandler::FontInfo*> SDLHandler::fontInfos;
48 vector<string> modeDescriptions;
49 int videoModeCount;
50 
51 #define FORBIDDEN_CURSOR_TIME 2000
52 
53 #define FADEOUT_SPEED 10
54 
55 //#define DEBUG_MOUSE_FOCUS 1
56 
57 bool SDLHandler::stencilBufferUsed = false;
58 bool SDLHandler::showDebugInfo = SHOW_FPS;
59 
60 // milllis
61 #define DOUBLE_CLICK_INTERVAL 500
62 // pixel range
63 #define DOUBLE_CLICK_TOLERANCE 5
64 
65 #define DEFAULT_MIN_DEPTH -3000
66 #define DEFAULT_MAX_DEPTH 1000
67 
SDLHandler(GameAdapter * gameAdapter)68 SDLHandler::SDLHandler( GameAdapter *gameAdapter ) {
69 	/* These are to calculate our fps */
70 	this->gameAdapter = gameAdapter;
71 	T0     = 0;
72 	Frames = 0;
73 	fps = 0;
74 	screen = NULL;
75 	lastMouseX = lastMouseY = mouseX = mouseY = mouseButton = mouseEvent = 0;
76 	mouseFocusX = mouseFocusY = 0;
77 	mouseDragging = false;
78 	mouseIsMovingOverMap = false;
79 	handlerCount = 0;
80 	invertMouse = false;
81 	cursorMode = Constants::CURSOR_NORMAL;
82 	font_initialized = false;
83 	debugStr = NULL;
84 	lastLeftClick = 0;
85 	lastMouseMoveTime = SDL_GetTicks();
86 	isDoubleClick = false;
87 	dontUpdateScreen = false;
88 	mouseLock = NULL;
89 	willUnlockMouse = false;
90 	willBlockEvent = false;
91 	forbiddenTimer = 0;
92 	fadeoutStartAlpha = fadeoutEndAlpha = 0;
93 	fadeoutSteps = 16;
94 	fadeoutCurrentStep = 0;
95 	fadeoutTimer = 0;
96 	cursorVisible = true;
97 	continueFunc = "";
98 	continueTimeout = continueStart = 0;
99 	orthoDepthMin = DEFAULT_MIN_DEPTH;
100 	orthoDepthMax = DEFAULT_MAX_DEPTH;
101 }
102 
~SDLHandler()103 SDLHandler::~SDLHandler() {
104 	// undoing XXX by ShapePalette::initFonts() + SDLHandler::initFonts()
105 	for ( size_t i = 0; i < fontInfos.size(); ++i ) {
106 		delete fontInfos[ i ]->fontMgr;
107 		delete fontInfos[ i ];
108 	}
109 	fontInfos.clear();
110 }
111 
pushHandlers(SDLEventHandler * eventHandler,SDLScreenView * screenView)112 void SDLHandler::pushHandlers( SDLEventHandler *eventHandler,
113                                SDLScreenView *screenView ) {
114 	if ( handlerCount == 10 ) {
115 		fprintf( stderr, "Error: can't push any more handlers." );
116 		exit( 1 );
117 	}
118 	eventHandlers[handlerCount] = this->eventHandler;
119 	screenViews[handlerCount] = this->screenView;
120 	handlerCount++;
121 	setHandlers( eventHandler, screenView );
122 }
123 
popHandlers()124 bool SDLHandler::popHandlers() {
125 	if ( handlerCount == 0 ) return true;
126 	handlerCount--;
127 	setHandlers( eventHandlers[handlerCount], screenViews[handlerCount] );
128 	return false;
129 }
130 
setHandlers(SDLEventHandler * eventHandler,SDLScreenView * screenView)131 void SDLHandler::setHandlers( SDLEventHandler *eventHandler,
132                               SDLScreenView *screenView ) {
133 	this->eventHandler = eventHandler;
134 	this->screenView = screenView;
135 	if ( screen ) resizeWindow( screen->w, screen->h );
136 }
137 
138 /* function to release/destroy our resources and restoring the old desktop */
quit(int returnCode)139 void SDLHandler::quit( int returnCode ) {
140 	gameAdapter->getSession()->setExiting( true );
141 
142 #ifdef HAVE_SDL_NET
143 	// shutdown SDL_net
144 	SDLNet_Quit();
145 #endif
146 
147 	/* clean up the window */
148 	SDL_Quit( );
149 
150 	/* and exit appropriately */
151 	exit( returnCode );
152 }
153 
resetDepthLimits()154 void SDLHandler::resetDepthLimits() {
155 	setDepthLimits( DEFAULT_MIN_DEPTH, DEFAULT_MAX_DEPTH );
156 }
157 
setDepthLimits(float min,float max)158 void SDLHandler::setDepthLimits( float min, float max ) {
159 	this->orthoDepthMin = min;
160 	this->orthoDepthMax = max;
161 	resizeWindow( screen->w, screen->h );
162 }
163 
164 /* function to reset our viewport after a window resize */
resizeWindow(int width,int height)165 int SDLHandler::resizeWindow( int width, int height ) {
166 	// Height / width ratio
167 //    GLfloat ratio;
168 
169 	// Protect against a divide by zero
170 	if ( height == 0 ) height = 1;
171 	lastWidth = width;
172 	lastHeight = height;
173 
174 //    ratio = ( GLfloat )width / ( GLfloat )height;
175 
176 	// Setup our viewport.
177 	glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height );
178 
179 	// change to the projection matrix and set our viewing volume.
180 	glMatrixMode( GL_PROJECTION );
181 	glLoadIdentity( );
182 
183 	// Set our perspective
184 	//gluPerspective( 45.0f, ratio, 0.1f, 100.0f );
185 	setOrthoView();
186 
187 	// Make sure we're chaning the model view and not the projection
188 	glMatrixMode( GL_MODELVIEW );
189 
190 	// Reset The View
191 	glLoadIdentity( );
192 
193 	return( TRUE );
194 }
195 
196 // Note: !!! also called from Map::getMapXYZAtScreenXY !!!
setOrthoView()197 void SDLHandler::setOrthoView() {
198 	glOrtho( 0.0f, lastWidth, lastHeight, 0.0f, orthoDepthMin, orthoDepthMax );
199 }
200 
201 /* general OpenGL initialization function */
initGL()202 int SDLHandler::initGL() {
203 	/* Enable Texture Mapping */
204 	glEnable( GL_TEXTURE_2D );
205 
206 	/* Enable smooth shading */
207 	glShadeModel( GL_SMOOTH );
208 
209 	// We use ortho projection, so perspective correction isn't needed
210 	glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
211 
212 	// Create really nice mipmaps.
213 	glHint( GL_GENERATE_MIPMAP_HINT, GL_NICEST );
214 
215 	// Use per-vertex fog.
216 	glHint( GL_FOG_HINT, GL_FASTEST );
217 
218 	// Faster antialiasing for primitives.
219 	glHint( GL_POINT_SMOOTH_HINT, GL_FASTEST );
220 	glHint( GL_LINE_SMOOTH_HINT, GL_FASTEST );
221 
222 	// which one to use?
223 	// default is good
224 	//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
225 	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
226 	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
227 
228 	/* Set the background black */
229 	glClearColor( 0.0f, 0.0f, 0.0f, 0.5f );
230 
231 	/* Depth buffer setup */
232 	glClearDepth( 1.0f );
233 	if ( stencilBufferUsed ) glClearStencil( 0 ); // Clear The Stencil Buffer To 0
234 
235 	/* Enables Depth Testing */
236 	glEnable( GL_DEPTH_TEST );
237 
238 	/* The Type Of Depth Test To Do */
239 	glDepthFunc( GL_LEQUAL );
240 
241 	// Don't dither textures on truecolor displays.
242 	if ( gameAdapter->getPreferences()->getBpp() > 16 ) {
243 		glDisable( GL_DITHER );
244 	} else {
245 		glEnable( GL_DITHER );
246 	}
247 
248 	glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
249 	glEnable( GL_COLOR_MATERIAL );
250 
251 	/* initialize opengl extensions */
252 	if ( Constants::multitexture ) {
253 //   fprintf(stderr, "BEFORE: glSDLActiveTextureARB=%u\n", glSDLActiveTextureARB);
254 		glSDLActiveTextureARB =
255 		  ( PFNGLACTIVETEXTUREARBPROC )SDL_GL_GetProcAddress ( "glActiveTextureARB" );
256 //   fprintf(stderr, "AFTER: glSDLActiveTextureARB=%u\n", glSDLActiveTextureARB);
257 		glSDLMultiTexCoord2fARB =
258 		  ( PFNGLMULTITEXCOORD2FARBPROC )SDL_GL_GetProcAddress ( "glMultiTexCoord2fARB" );
259 		glSDLMultiTexCoord2iARB =
260 		  ( PFNGLMULTITEXCOORD2IARBPROC )SDL_GL_GetProcAddress ( "glMultiTexCoord2iARB" );
261 	}
262 	return( TRUE );
263 }
264 
testModesInFormat(SDL_PixelFormat * format,Uint32 flags)265 bool testModesInFormat( SDL_PixelFormat *format, Uint32 flags ) {
266 	SDL_Rect **modes;
267 	int i;
268 
269 	printf( "Available modes with given flags in %d bpp:\n", format->BitsPerPixel );
270 
271 	/* Get available fullscreen/hardware modes */
272 	modes = SDL_ListModes( format, flags );
273 
274 	/* Check is there are any modes available */
275 	if ( modes == ( SDL_Rect ** )0 ) {
276 		printf( "\tNo modes available!\n" );
277 		return false;
278 	}
279 
280 	/* Check if our resolution is restricted */
281 	if ( modes == ( SDL_Rect ** ) - 1 ) {
282 		printf( "\tAll resolutions available.\n" );
283 		return true;
284 	}
285 
286 	/* Print valid modes */
287 	for ( i = 0;modes[i];++i )
288 		printf( "\t%d x %d\n", modes[i]->w, modes[i]->h );
289 
290 	//free(modes); // crashes; ok to not free since we only do this a few times
291 	return true;
292 }
293 
testModes(Uint32 flags,bool findMaxBpp=false)294 int testModes( Uint32 flags, bool findMaxBpp = false ) {
295 	int bpp[] = { 32, 24, 16, 15, 8, 0 };
296 	SDL_PixelFormat format;
297 	for ( int i = 0; bpp[i]; i++ ) {
298 		format.BitsPerPixel = bpp[i];
299 		if ( testModesInFormat( &format, flags ) && findMaxBpp ) return bpp[i];
300 	}
301 	return -1;
302 }
303 
304 
getVideoModes()305 void SDLHandler::getVideoModes() {
306 	SDL_Rect **modes;
307 	Uint32 flags;
308 
309 	modeDescriptions.clear();
310 
311 	if ( !screen ) {
312 		fprintf( stderr, "SDLHandler :: you must allocate screen before calling getVideoModes!!\n" );
313 		exit( -1 );
314 	}
315 
316 	// Get current video flags (hwsurface/swsurface, fullscreen/not fullscreen..)
317 	flags = screen->flags;
318 
319 	// Get available modes for the current flags
320 	modes = SDL_ListModes( NULL, flags );
321 
322 	// Copy them to a char array
323 	if ( modes != ( SDL_Rect ** )0 ) {
324 		videoModeCount = 0;
325 		if ( modes == ( SDL_Rect ** ) - 1 ) {
326 			// All modes are available, so let's go..
327 			videoModeCount = 14;
328 			modeDescriptions.push_back( "800 x 600" );
329 			modeDescriptions.push_back( "1024 x 600" );
330 			modeDescriptions.push_back( "1024 x 768" );
331 			modeDescriptions.push_back( "1152 x 864" );
332 			modeDescriptions.push_back( "1280 x 768" );
333 			modeDescriptions.push_back( "1280 x 800" );
334 			modeDescriptions.push_back( "1280 x 960" );
335 			modeDescriptions.push_back( "1280 x 1024" );
336 			modeDescriptions.push_back( "1400 x 1050" );
337 			modeDescriptions.push_back( "1440 x 900" );
338 			modeDescriptions.push_back( "1600 x 1200" );
339 			modeDescriptions.push_back( "1680 x 1050" );
340 			modeDescriptions.push_back( "1920 x 1200" );
341 			modeDescriptions.push_back( "2048 x 1536" );
342 		} else {
343 			// Only a few modes available, which ones ?
344 			for ( videoModeCount = 0; modes[videoModeCount]; videoModeCount++ );
345 			if ( videoModeCount ) {
346 				for ( int i = 0; i < videoModeCount; i++ ) {
347 					if ( modes[i]->h > 599 && modes[i]->w < 2049 ) {
348 						char temp[ 50 ];
349 						snprintf( temp, 50, "%d x %d", modes[i]->w, modes[i]->h );
350 						modeDescriptions.push_back( temp );
351 					}
352 				}
353 				videoModeCount = modeDescriptions.size();
354 			} else {
355 				videoModeCount = 1;
356 				modeDescriptions.push_back( "No modes available!\n" );
357 			}
358 		}
359 	} else {
360 		videoModeCount = 1;
361 		modeDescriptions.push_back( "No modes available!\n" );
362 	}
363 }
364 
getVideoModeCount()365 int SDLHandler::getVideoModeCount() {
366 	getVideoModes();
367 	return videoModeCount;
368 }
369 
getVideoMode(int mode)370 std::string SDLHandler::getVideoMode( int mode ) {
371 //  char vm[255];
372 //  snprintf(vm, 255, "%s", modeDescriptions[mode].c_str());
373 	return modeDescriptions[mode];
374 //  return vm;
375 }
376 
setVideoMode(Preferences * uc)377 void SDLHandler::setVideoMode( Preferences * uc ) {
378 	/* this holds some info about our display */
379 	const SDL_VideoInfo *videoInfo;
380 
381 	/* initialize SDL */
382 	if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
383 		fprintf( stderr, "Video initialization failed: %s\n", SDL_GetError( ) );
384 		quit( 1 );
385 	}
386 
387 	if ( TTF_Init() < 0 ) {
388 		fprintf( stderr, "Couldn't initialize SDL_ttf: %s\n", SDL_GetError() );
389 		quit( 1 );
390 	}
391 
392 #ifdef HAVE_SDL_NET
393 	// initialize SDL_net
394 	if ( SDLNet_Init() == -1 ) {
395 		cerr << "*** error: SDLNet_Init: " << SDL_GetError() << endl;
396 		exit( 2 );
397 	}
398 #endif
399 
400 	/* Fetch the video info */
401 	videoInfo = SDL_GetVideoInfo( );
402 
403 	if ( !videoInfo ) {
404 		fprintf( stderr, "Video query failed: %s\n", SDL_GetError( ) );
405 		quit( 1 );
406 	}
407 
408 
409 	videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL */
410 
411 	// these make no sense, accrd. to: http://osdl.sourceforge.net/main/documentation/rendering/SDL-openGL.html#flags
412 	//if(uc->getDoublebuf()) {
413 	//videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
414 	//}
415 	//if(uc->getHwpal())
416 	//videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */
417 	/* This checks to see if surfaces can be stored in memory */
418 // if(uc->getForce_hwsurf()) videoFlags |= SDL_HWSURFACE;
419 // else if(uc->getForce_swsurf()) videoFlags |= SDL_SWSURFACE;
420 // else {
421 	//if ( videoInfo->hw_available ) videoFlags |= SDL_HWSURFACE;
422 	//else videoFlags |= SDL_SWSURFACE;
423 	//}
424 	///* This checks if hardware blits can be done */
425 	//if ( uc->getHwaccel() && videoInfo->blit_hw ) videoFlags |= SDL_HWACCEL;
426 
427 	if ( uc->getFullscreen() ) {
428 		videoFlags |= SDL_FULLSCREEN;
429 	} else if ( uc->getResizeable() ) {
430 		videoFlags |= SDL_RESIZABLE;       // Enable window resizing
431 	}
432 
433 	if ( uc->getTest() ) {
434 		testModes( videoFlags );
435 		quit( 0 );
436 	}
437 
438 	// try to find the highest bpp for this mode
439 	int bpp;
440 	if ( uc->getBpp() == -1 ) {
441 		bpp = testModes( videoFlags, true );
442 		if ( bpp == -1 ) {
443 			fprintf( stderr, "Could not detect suitable opengl video mode.\n" );
444 			fprintf( stderr, "You can manually select one with the -bpp option\n" );
445 			quit( 0 );
446 		} else {
447 			uc->setBpp( bpp );
448 		}
449 	}
450 
451 	/* Sets up OpenGL double buffering */
452 	if ( uc->getDoublebuf() ) {
453 		SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
454 	} else {
455 		SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 0 );
456 	}
457 
458 	// vertical retrace (0-off, 1-on, >1 every n-th retrace)
459 	SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 0 );
460 
461 	if ( uc->getStencilbuf() ) {
462 		uc->setStencilBufInitialized( true );
463 		stencilBufferUsed = true;
464 		SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 );
465 	}
466 
467 	cout << "Setting video mode: " << uc->getW() << "x" << uc->getH() << "x" << uc->getBpp() << endl;
468 
469 	/* get a SDL surface */
470 	screen = SDL_SetVideoMode( uc->getW(), uc->getH(), uc->getBpp(), videoFlags );
471 	/* Verify there is a surface */
472 	if ( !screen ) {
473 		fprintf( stderr,  "Video mode set failed: %s\n", SDL_GetError( ) );
474 		quit( 1 );
475 	}
476 
477 	/* hide the mouse cursor; we have our own */
478 	SDL_ShowCursor( SDL_DISABLE );
479 	SDL_WM_SetCaption( "Scourge", NULL );
480 
481 	/* initialize OpenGL */
482 	initGL( );
483 
484 	/* resize the initial window */
485 	resizeWindow( screen->w, screen->h );
486 	SDL_WarpMouse ( uc->getW() / 2, uc->getH() / 2 );
487 }
488 
fireEvent(Widget * widget,SDL_Event * event)489 void SDLHandler::fireEvent( Widget *widget, SDL_Event *event ) {
490 	storedWidget = widget;
491 	storedEvent = event;
492 }
493 
firedEventWaiting()494 bool SDLHandler::firedEventWaiting() {
495 	return storedEvent != NULL;
496 }
497 
applyMouseOffset(int x,int y,int * newX,int * newY)498 void SDLHandler::applyMouseOffset( int x, int y, int *newX, int *newY ) {
499 	if ( cursorMode == Constants::CURSOR_CROSSHAIR ) {
500 		mouseFocusX = mouseFocusY = 24;
501 	} else {
502 		mouseFocusX = mouseFocusY = 0;
503 	}
504 	*newX = x + mouseFocusX;
505 	*newY = y + mouseFocusY;
506 }
507 
508 Uint32 lastAmbientTime = 0;
mainLoop()509 void SDLHandler::mainLoop() {
510 	bool isActive = true;
511 	running = true;
512 	while ( true ) {
513 		if ( processEvents( &isActive ) ) return;
514 		if ( !running && popHandlers() ) return;
515 
516 		/*if ( isActive )*/ drawScreen();
517 		gameAdapter->getSession()->getSound()->checkMusic( gameAdapter->getCurrentCombatMusic() || gameAdapter->inTurnBasedCombat(),
518 		                                                   gameAdapter->getCurrentCombatMusic() );
519 		Uint32 now = SDL_GetTicks();
520 		if ( !gameAdapter->getAmbientPaused() && now - lastAmbientTime > AMBIENT_PAUSE_MIN ) {
521 			lastAmbientTime = now;
522 			if ( Util::dice( AMBIENT_ROLL ) == 0 ) {
523 				gameAdapter->getSession()->getSound()->
524 				startAmbientSound( gameAdapter->getSession()->getAmbientSoundName(),
525 				                   gameAdapter->getCurrentDepth() );
526 			}
527 		}
528 		if ( continueTimeout > 0 && now - continueStart > continueTimeout ) {
529 			char tmp[200];
530 			strcpy( tmp, continueFunc.c_str() );
531 			// clear it first, in case continueAt is called again from squirrel
532 			continueStart = continueTimeout = 0;
533 			continueFunc = "";
534 			gameAdapter->getSession()->getSquirrel()->callNoArgMethod( tmp );
535 		}
536 	}
537 }
538 
processEvents(bool * isActive)539 bool SDLHandler::processEvents( bool *isActive ) {
540 	SDL_Event event;
541 	int mx, my;
542 
543 	Uint32 now = SDL_GetTicks();
544 	mouseIsMovingOverMap = false;
545 	while ( SDL_PollEvent( &event ) ) {
546 		isDoubleClick = false;
547 		mouseEvent = mouseButton = 0;
548 		Widget *widget = NULL;
549 		Window *win = NULL;
550 		switch ( event.type ) {
551 		case SDL_MOUSEMOTION:
552 			if ( invertMouse ) event.motion.y = screen->h - event.motion.y;
553 			applyMouseOffset( event.motion.x, event.motion.y, &mx, &my );
554 			mouseX = mx;
555 			mouseY = my;
556 			mouseButton = event.button.button;
557 			mouseEvent = SDL_MOUSEMOTION;
558 			// don't process events during a fade
559 			if ( fadeoutTimer <= 0 && cursorVisible ) widget = Window::delegateEvent( &event, mouseX, mouseY, &win );
560 			if ( !widget && !win ) {
561 				mouseIsMovingOverMap = true;
562 				lastMouseMoveTime = now;
563 			}
564 			break;
565 		case SDL_MOUSEBUTTONUP:
566 			if ( invertMouse ) event.button.y = screen->h - event.button.y;
567 			applyMouseOffset( event.button.x, event.button.y, &mx, &my );
568 			mouseEvent = SDL_MOUSEBUTTONUP;
569 			mouseButton = event.button.button;
570 			mouseDragging = false;
571 			if ( event.button.button == SDL_BUTTON_LEFT || event.button.button == SDL_BUTTON_RIGHT ) {
572 				isDoubleClick = ( now - lastLeftClick < DOUBLE_CLICK_INTERVAL &&
573 				                  abs( lastMouseX - event.button.x ) < DOUBLE_CLICK_TOLERANCE &&
574 				                  abs( lastMouseY - event.button.y ) < DOUBLE_CLICK_TOLERANCE );
575 				lastLeftClick = now;
576 				// don't process events during a fade
577 				if ( fadeoutTimer <= 0 && cursorVisible ) widget = Window::delegateEvent( &event, mx, my, &win );
578 			}
579 			lastMouseX = event.button.x;
580 			lastMouseY = event.button.y;
581 			break;
582 		case SDL_MOUSEBUTTONDOWN:
583 			if ( invertMouse ) event.button.y = screen->h - event.button.y;
584 			applyMouseOffset( event.button.x, event.button.y, &mx, &my );
585 			mouseEvent = SDL_MOUSEBUTTONDOWN;
586 			mouseButton = event.button.button;
587 			mouseDragging = ( event.button.button == SDL_BUTTON_LEFT );
588 			//if(event.button.button == SDL_BUTTON_LEFT || event.button.button == SDL_BUTTON_RIGHT) {
589 			// don't process events during a fade
590 			if ( fadeoutTimer <= 0 && cursorVisible ) widget = Window::delegateEvent( &event, mx, my, &win );
591 			//}
592 			break;
593 		case SDL_ACTIVEEVENT:
594 			/* Something's happend with our focus
595 			 * If we lost focus or we are iconified, we
596 			 * shouldn't draw the screen
597 			 */
598 			if ( isActive ) {
599 				*isActive = ( event.active.gain == 0 ? false : true );
600 			}
601 			break;
602 		case SDL_VIDEORESIZE:
603 			/* handle resize event */
604 			screen = SDL_SetVideoMode( event.resize.w,
605 			                           event.resize.h,
606 			                           16, videoFlags );
607 			if ( !screen ) {
608 				fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
609 				quit( 1 );
610 			}
611 			resizeWindow( event.resize.w, event.resize.h );
612 			break;
613 		case SDL_KEYUP:
614 			// only process CTRL + F1 once (on keyup)
615 			if ( event.key.keysym.sym == SDLK_F1 &&
616 			        event.key.keysym.mod & KMOD_CTRL ) {
617 				SDL_WM_ToggleFullScreen( screen );
618 				break;
619 			}
620 		case SDL_KEYDOWN:
621 			applyMouseOffset( mouseX, mouseY, &mx, &my );
622 			// don't process events during a fade
623 			if ( fadeoutTimer <= 0 && cursorVisible ) widget = Window::delegateEvent( &event, mx, my, &win );
624 			break;
625 		case SDL_QUIT:
626 			quit( 0 ); // handle quit requests
627 			break;
628 		default:
629 			break;
630 		}
631 
632 		// Show pointer over widgets unless casting a spell
633 		if ( getCursorMode() == Constants::CURSOR_FORBIDDEN &&
634 		        SDL_GetTicks() - forbiddenTimer > FORBIDDEN_CURSOR_TIME ) {
635 			setCursorMode( Constants::CURSOR_NORMAL );
636 		}
637 
638 		if ( !mouseIsMovingOverMap && getCursorMode() != Constants::CURSOR_CROSSHAIR ) {
639 			setCursorMode( Constants::CURSOR_NORMAL );
640 		}
641 
642 		// swallow this event
643 		if ( willBlockEvent ) {
644 			willBlockEvent = false;
645 			continue;
646 		}
647 
648 		bool res = false;
649 		// don't process events during a fade
650 		if ( fadeoutTimer <= 0 ) {
651 			if ( widget ) {
652 				if ( !mouseLock || mouseLock == widget ) {
653 					EventHandler *eh = getEventHandler( widget );
654 					if( eh ) {
655 						// new-style event handling
656 						res = eh->handleEvent( widget, &event );
657 					} else {
658 						// old-style event handling
659 						res = eventHandler->handleEvent( widget, &event );
660 					}
661 					if ( event.type == SDL_MOUSEMOTION ) {
662 						if( win && win->getRawEventHandler() ) {
663 							res = win->getRawEventHandler()->handleEvent( &event );
664 						}
665 
666 						// also run the generic event handler.
667 						// this is so that moving the cursor over a
668 						// window doesn't scroll the map forever
669 						res = eventHandler->handleEvent( &event );
670 					}
671 				}
672 			} else {
673 				if ( !mouseLock ) {
674 					if( win && win->getRawEventHandler() ) {
675 						res = win->getRawEventHandler()->handleEvent( &event );
676 					}
677 
678 					// also run the generic event handler
679 					res = eventHandler->handleEvent( &event );
680 				}
681 			}
682 			if ( res ) {
683 				if ( popHandlers() ) {
684 					return true;
685 				}
686 			}
687 		}
688 	}
689 
690 	if ( willUnlockMouse ) {
691 		mouseLock = NULL;
692 		willUnlockMouse = false;
693 	}
694 
695 	return false;
696 }
697 
drawCursor()698 void SDLHandler::drawCursor() {
699 	// for cursor: do alpha bit testing
700 	//  glEnable( GL_ALPHA_TEST );
701 	//  glAlphaFunc( GL_NOTEQUAL, 0 ); // this works better for people with the reverse alpha problem (see forums)
702 	glEnable( GL_BLEND );
703 	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
704 	glEnable( GL_TEXTURE_2D );
705 	glDisable( GL_DEPTH_TEST );
706 	glDisable( GL_CULL_FACE );
707 	glPushMatrix();
708 	glLoadIdentity();
709 	glTranslatef( mouseX - mouseFocusX, mouseY - mouseFocusY, 0 );
710 	gameAdapter->getCursorTexture( cursorMode ).glBind();
711 	glColor4f( 1, 1, 1, 1 );
712 //  glNormal3f( 0, 0, 1 );
713 	glBegin( GL_TRIANGLE_STRIP );
714 	glTexCoord2f( 0, 0 );
715 	glVertex2f( 0, 0 );
716 	glTexCoord2f( 1, 0 );
717 	glVertex2f( gameAdapter->getCursorWidth(), 0 );
718 	glTexCoord2f( 0, 1 );
719 	glVertex2f( 0, gameAdapter->getCursorHeight() );
720 	glTexCoord2f( 1, 1 );
721 	glVertex2f( gameAdapter->getCursorWidth(), gameAdapter->getCursorHeight() );
722 	glEnd();
723 	glPopMatrix();
724 
725 	//  glDisable( GL_ALPHA_TEST );
726 	glDisable( GL_TEXTURE_2D );
727 	glDisable( GL_BLEND );
728 
729 #ifdef DEBUG_MOUSE_FOCUS
730 	// cursor focus
731 	glPushMatrix();
732 	glLoadIdentity();
733 	glTranslatef( mouseX, mouseY, 0 );
734 	glColor4f( 1, 1, 1, 1 );
735 	glBegin( GL_TRIANGLE_STRIP );
736 	glVertex2f( 0, 0 );
737 	glVertex2f( 10, 0 );
738 	glVertex2f( 0, 10 );
739 	glVertex2f( 10, 10 );
740 	glEnd();
741 	glPopMatrix();
742 #endif
743 
744 	glEnable( GL_DEPTH_TEST );
745 	glEnable( GL_CULL_FACE );
746 }
747 
processEventsAndRepaint()748 void SDLHandler::processEventsAndRepaint() {
749 	processEvents();
750 	drawScreen();
751 }
752 
drawScreen()753 void SDLHandler::drawScreen() {
754 
755 	if ( eventHandler == NULL ) { // it's never set to NULL
756 		SDL_GL_SwapBuffers();
757 		return;
758 	}
759 
760 	drawScreenInternal();
761 
762 	if ( !willSavePath.empty() ) { // it's always empty
763 		saveScreenInternal( willSavePath );
764 		willSavePath.clear();
765 	}
766 
767 	/* Gather our frames per second */
768 	calculateFps();
769 }
770 
saveScreen(string & path,bool thumbnail)771 void SDLHandler::saveScreen( string& path, bool thumbnail ) {
772 	drawScreenInternal();
773 	saveScreenInternal( path, thumbnail );
774 }
775 
drawScreenInternal()776 void SDLHandler::drawScreenInternal() {
777 	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
778 	if ( stencilBufferUsed ) glClear( GL_STENCIL_BUFFER_BIT );
779 	glClearColor( 0.0f, 0.0f, 0.0f, 0.5f );
780 	glClearDepth( 1.0f );
781 	screenView->drawView();
782 
783 	// redraw the gui
784 	Window::drawVisibleWindows();
785 
786 	screenView->drawAfter();
787 
788 	if ( fadeoutTimer > 0 ) {
789 		drawFadeout();
790 	}
791 
792 	if ( cursorVisible ) drawCursor();
793 
794 	if ( showDebugInfo ) {
795 		drawDebugInfo();
796 	}
797 
798 	// these tie cpu execution to the gpu's so there is no benefit from the overlap
799 	//glFlush();
800 	//glFinish();
801 
802 	/* Draw it to the screen */
803 	SDL_GL_SwapBuffers( );
804 }
805 
806 #define SCREEN_SHOT_WIDTH 160
807 #define SCREEN_SHOT_HEIGHT 120
808 
saveScreenInternal(string & path,bool thumbnail)809 void SDLHandler::saveScreenInternal( string& path, bool thumbnail ) {
810 	if ( !gameAdapter->getPreferences()->getEnableScreenshots() ) {
811 		cerr << "*** Screenshots disabled in options. Not saving: " << path << endl;
812 		return;
813 	}
814 
815 	SDL_Surface *surface = SDL_CreateRGBSurface( SDL_SWSURFACE, screen->w, screen->h, 24,
816 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
817 	                        0x00FF0000, 0x0000FF00, 0x000000FF, 0 );
818 #else
819 	                        0x000000FF, 0x0000FF00, 0x00FF0000, 0 );
820 #endif
821 
822 	// read the center of the screen
823 	int sx = ( screen->w - surface->w ) / 2;
824 	int sy = ( screen->h - surface->h ) / 2;
825 
826 	glReadPixels( sx, sy, surface->w, surface->h, GL_BGR, GL_UNSIGNED_BYTE, surface->pixels );
827 
828 	int w, h;
829 	if ( thumbnail ) {
830 		w = SCREEN_SHOT_WIDTH; h = SCREEN_SHOT_HEIGHT;
831 	} else {
832 		w = surface->w; h = surface->h;
833 	}
834 
835 	SDL_Surface *scaled = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, 24,
836 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
837 	                        0x00FF0000, 0x0000FF00, 0x000000FF, 0 );
838 #else
839 	                        0x000000FF, 0x0000FF00, 0x00FF0000, 0 );
840 #endif
841 
842 	// scale to desired size (also flip image at the same time)
843 	Uint8 *src = ( Uint8* )surface->pixels;
844 	Uint8 *dst = ( Uint8* )scaled->pixels;
845 	float dx = ( static_cast<float>( surface->w ) / static_cast<float>( scaled->w ) );
846 	float dy = ( static_cast<float>( surface->h ) / static_cast<float>( scaled->h ) );
847 
848 	for ( int x = 0; x < w; x++ ) {
849 		for ( int y = 0; y < h; y++ ) {
850 			memcpy( dst + ( scaled->pitch * y + x * scaled->format->BytesPerPixel ), src + ( surface->pitch * ( surface->h - 1 - static_cast<int>( y * dy ) ) + static_cast<int>( x * dx ) * surface->format->BytesPerPixel ), scaled->format->BytesPerPixel );
851 		}
852 	}
853 
854 	SDL_SaveBMP( scaled, path.c_str() );
855 
856 	SDL_FreeSurface( surface );
857 	SDL_FreeSurface( scaled );
858 }
859 
calculateFps()860 void SDLHandler::calculateFps() {
861 	Frames++;
862 	GLint t = SDL_GetTicks();
863 	if ( t - T0 >= 2500 ) {
864 		GLfloat seconds = ( t - T0 ) / 1000.0;
865 		fps = Frames / seconds;
866 		//printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
867 		T0 = t;
868 		Frames = 0;
869 	}
870 }
871 
drawDebugInfo()872 void SDLHandler::drawDebugInfo() {
873 	glPushMatrix();
874 	glDisable( GL_DEPTH_TEST );
875 	glDepthMask( GL_FALSE );
876 	glDisable( GL_CULL_FACE );
877 	glLoadIdentity();
878 	glColor3f( 0, 0, 0 );
879 	glBegin( GL_TRIANGLE_STRIP );
880 	glVertex2f( 400, 0 );
881 	glVertex2f( screen->w, 0 );
882 	glVertex2f( 400, 12 );
883 	glVertex2f( screen->w, 12 );
884 	glEnd();
885 	glEnable( GL_TEXTURE_2D );
886 	glColor4f( 0.8f, 0.7f, 0.2f, 1.0f );
887 	texPrint( 400, 10, "FPS: %g %s", getFPS(), ( debugStr ? debugStr : "" ) );
888 	glEnable( GL_DEPTH_TEST );
889 	glDepthMask( GL_TRUE );
890 	glPopMatrix();
891 }
892 
drawFadeout()893 void SDLHandler::drawFadeout() {
894 	glPushMatrix();
895 	glEnable( GL_BLEND );
896 	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
897 	glDisable( GL_TEXTURE_2D );
898 	glDisable( GL_DEPTH_TEST );
899 
900 	if ( fadeoutStartAlpha < fadeoutEndAlpha ) {
901 		glColor4f( 0, 0, 0, ( fadeoutStartAlpha + ( ( ( fadeoutEndAlpha - fadeoutStartAlpha ) *
902 		                                              fadeoutCurrentStep ) / static_cast<float>( fadeoutSteps ) ) ) );
903 	} else {
904 		glColor4f( 0, 0, 0, ( fadeoutStartAlpha - ( ( ( fadeoutStartAlpha - fadeoutEndAlpha ) *
905 		                                              fadeoutCurrentStep ) / static_cast<float>( fadeoutSteps ) ) ) );
906 	}
907 	glLoadIdentity();
908 	glBegin( GL_TRIANGLE_STRIP );
909 	glVertex2d( 0, 0 );
910 	glVertex2d( screen->w, 0 );
911 	glVertex2d( 0, screen->h );
912 	glVertex2d( screen->w, screen->h );
913 	glEnd();
914 
915 	glEnable( GL_DEPTH_TEST );
916 	glDisable( GL_BLEND );
917 	glEnable( GL_TEXTURE_2D );
918 	glPopMatrix();
919 
920 
921 	Uint32 t = SDL_GetTicks();
922 	if ( t - fadeoutTimer > FADEOUT_SPEED ) {
923 		fadeoutCurrentStep++;
924 		if ( fadeoutCurrentStep > fadeoutSteps ) {
925 			fadeoutTimer = 0;
926 		} else {
927 			fadeoutTimer = t;
928 		}
929 	}
930 }
931 
fade(float startAlpha,float endAlpha,int steps)932 void SDLHandler::fade( float startAlpha, float endAlpha, int steps ) {
933 	fadeoutEndAlpha = endAlpha;
934 	fadeoutStartAlpha = startAlpha;
935 	fadeoutSteps = steps;
936 	fadeoutCurrentStep = 0;
937 	fadeoutTimer = SDL_GetTicks();
938 	while ( fadeoutTimer > 0 ) {
939 		processEventsAndRepaint();
940 	}
941 	setCursorMode( Constants::CURSOR_NORMAL );
942 }
943 
getCurrentTTFFont()944 TTF_Font *SDLHandler::getCurrentTTFFont() {
945 	initFonts();
946 	return fontInfos[ fontType ]->font;
947 }
948 
getCurrentFontManager()949 FontMgr *SDLHandler::getCurrentFontManager() {
950 	initFonts();
951 	return fontInfos[ fontType ]->fontMgr;
952 }
953 
954 
textWidth(const char * fmt,...)955 int SDLHandler::textWidth( const char *fmt, ... ) {
956 	char str[256]; // Holds our string
957 	va_list ap;     // Pointer to our list of elements
958 
959 	// If there's no text, do nothing
960 	if ( fmt == NULL ) return 0;
961 
962 	// Parses The String For Variables
963 	va_start( ap, fmt );
964 
965 	// Converts Symbols To Actual Numbers
966 	vsprintf( str, fmt, ap );
967 	va_end( ap );
968 
969 	initFonts();
970 
971 	//return getTextLengthSimple( *(getCurrentFont()), str );
972 	SDL_Rect r;
973 	getCurrentFontManager()->textSizeUTF8( str, &r );
974 	return r.w;
975 }
976 
texPrint(GLfloat x,GLfloat y,const char * fmt,...)977 void SDLHandler::texPrint( GLfloat x, GLfloat y,
978                            const char *fmt, ... ) {
979 	char str[256]; // Holds our string
980 	va_list ap;     // Pointer to our list of elements
981 
982 	// If there's no text, do nothing
983 	if ( fmt == NULL ) return;
984 
985 	// Parses The String For Variables
986 	va_start( ap, fmt );
987 
988 	// Converts Symbols To Actual Numbers
989 	vsprintf( str, fmt, ap );
990 	va_end( ap );
991 
992 	initFonts();
993 
994 //  freetype_print_simple( *(getCurrentFont()), x, y, str );
995 	fontInfos[ fontType ]->fontMgr->drawTextUTF8( str,
996 	                                              toint( x ),
997 	                                              toint( y + fontInfos[ fontType ]->yoffset ) );
998 }
999 
1000 // XXX: second-half-initializing first half is done by ShapePalette
initFonts()1001 void SDLHandler::initFonts() {
1002 	if ( !font_initialized ) {
1003 		//cerr << "Loading " << fontInfos.size() << " fonts: " << endl;
1004 		for ( unsigned int i = 0; i < fontInfos.size(); i++ ) {
1005 			FontInfo *info = fontInfos[i];
1006 			//cerr << "\t" << info->path << endl;
1007 			string s = rootDir + "/" + info->path;
1008 			info->font = TTF_OpenFont( s.c_str(), info->size );
1009 			TTF_SetFontStyle( info->font, info->style );
1010 			if ( !info->font ) {
1011 				fprintf( stderr, "Couldn't load %d pt font from %s: %s\n", info->size, s.c_str(), SDL_GetError() );
1012 				quit( 2 );
1013 			} else {
1014 				//cerr << "\t\tSuccess." << endl;
1015 				info->fontMgr = new FontMgr( info->font, info->shadowX, info->shadowY );
1016 			}
1017 		}
1018 		//cerr << "Done loading fonts." << endl;
1019 		font_initialized = true;
1020 	}
1021 }
1022 
sectionIntersects(int a1,int a2,int b1,int b2)1023 bool SDLHandler::sectionIntersects( int a1, int a2, int b1, int b2 ) {
1024 	return( ( ( a1 <= b1 && a2 > b1 ) || ( a1 >= b1 && a1 < b2 ) )
1025 	        ? true : false );
1026 }
1027 
intersects(SDL_Rect * a,SDL_Rect * b)1028 bool SDLHandler::intersects( SDL_Rect *a, SDL_Rect *b ) {
1029 	return( ( sectionIntersects( a->x, a->x + a->w, b->x, b->x + b->w ) &&
1030 	          sectionIntersects( a->y, a->y + a->h, b->y, b->y + b->h ) )
1031 	        ? true : false );
1032 }
1033 
intersects(int x,int y,int w,int h,int x2,int y2,int w2,int h2)1034 bool SDLHandler::intersects( int x, int y, int w, int h,
1035                              int x2, int y2, int w2, int h2 ) {
1036 	SDL_Rect ra = {
1037 		x, y, w, h
1038 	};
1039 	SDL_Rect rb = {
1040 		x2, y2, w2, h2
1041 	};
1042 	return intersects( &ra, &rb );
1043 }
1044 
drawTooltip(float xpos2,float ypos2,float zpos2,float zrot,float yrot,char * message,float r,float g,float b,float zoom)1045 void SDLHandler::drawTooltip( float xpos2, float ypos2, float zpos2,
1046                               float zrot, float yrot,
1047                               char *message,
1048                               float r, float g, float b,
1049                               float zoom ) {
1050 	setFontType( Constants::SCOURGE_MONO_FONT );
1051 
1052 	int w = 0;
1053 	vector<int> widths;
1054 	vector<string> lines = Util::Tokenize<vector<string> >( message, "|" );
1055 	for ( vector<string>::iterator i = lines.begin(); i != lines.end(); i++ ) {
1056 		int ww = textWidth( i->c_str() ) + 10;
1057 		widths.push_back( ww );
1058 		if ( w < ww )
1059 			w = ww;
1060 	}
1061 
1062 	//int w = textWidth( message ) + 10;
1063 	//int w = strlen( message ) * 8 + 4;
1064 	int h = 12 * lines.size() + 5;
1065 	int x = -2;
1066 	int y = -14;
1067 
1068 	// only for widget tooltips: see if it hangs off the screen
1069 	bool right = false;
1070 	if ( zrot == 0 && yrot == 0 ) {
1071 		// do gluProject b/c parent window coordinates aren't part of xpos2.
1072 		GLdouble screenx, screeny, screenz;
1073 		double projection[16];
1074 		double modelview[16];
1075 		GLint viewport[4];
1076 		glGetDoublev( GL_PROJECTION_MATRIX, projection );
1077 		glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
1078 		glGetIntegerv( GL_VIEWPORT, viewport );
1079 		int res = gluProject( xpos2 + w + x, 0, 0,
1080 		                      modelview,
1081 		                      projection,
1082 		                      viewport,
1083 		                      &screenx, &screeny, &screenz );
1084 		if ( res && screenx > getScreenWidth() ) {
1085 			xpos2 -= ( w + x );
1086 			right = true;
1087 		}
1088 	}
1089 
1090 	// for widget tooltips only (hence the check for zrot/yrot)
1091 	if ( zrot == 0 && yrot == 0 && xpos2 + w + x > screen->w ) {
1092 
1093 	}
1094 
1095 	glPushMatrix();
1096 	glTranslatef( xpos2, ypos2 - ( y + h - 20 ), zpos2 );
1097 	glRotatef( zrot, 0.0f, 0.0f, 1.0f );
1098 	glRotatef( yrot, 1.0f, 0.0f, 0.0f );
1099 
1100 	glScalef( zoom, zoom, zoom );
1101 
1102 	glDisable( GL_DEPTH_TEST );
1103 	glDisable( GL_CULL_FACE );
1104 	glEnable( GL_BLEND );
1105 	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1106 
1107 	//glColor4f( 0, 0.15f, 0.05f, 0.5 );
1108 	glColor4f( r, g, b, 0.8f );
1109 	glBegin( GL_TRIANGLE_STRIP );
1110 	glVertex2f( x, y );
1111 	glVertex2f( x + w, y );
1112 	glVertex2f( x, y + h );
1113 	glVertex2f( x + w, y + h );
1114 	glEnd();
1115 	glBegin( GL_TRIANGLES );
1116 	if ( right ) {
1117 		glVertex2f( x + w, y + h - 5 );
1118 		glVertex2f( x + w + 5, y + h + 5 );
1119 		glVertex2f( x + w - 5, y + h );
1120 	} else {
1121 		glVertex2f( x, y + h - 5 );
1122 		glVertex2f( x - 5, y + h + 5 );
1123 		glVertex2f( x + 5, y + h );
1124 	}
1125 	glEnd();
1126 	glDisable( GL_BLEND );
1127 
1128 	//glColor4f( 0, 0.4f, 0.15f, 0.5 );
1129 	for ( int i = 0; i < 2; i++ ) {
1130 		if ( !i ) {
1131 			glLineWidth( 3.0f );
1132 			glColor4f( 0, 0, 0, 0 );
1133 		} else {
1134 			glLineWidth( 1.0f );
1135 			glColor4f( r + 0.35f, g + 0.35f, b + 0.35f, 0.8f );
1136 		}
1137 		glBegin( GL_LINE_LOOP );
1138 		if ( right ) {
1139 			glVertex2f( x + w, y );
1140 			glVertex2f( x, y  );
1141 			glVertex2f( x, y + h  );
1142 			glVertex2f( x + w - 5, y + h  );
1143 			glVertex2f( x + w + 5, y + h + 5  );
1144 			glVertex2f( x + w, y + h - 5  );
1145 		} else {
1146 			glVertex2f( x + w, y );
1147 			glVertex2f( x, y  );
1148 			glVertex2f( x, y + h - 5 );
1149 			glVertex2f( x - 5, y + h + 5 );
1150 			glVertex2f( x + 5, y + h );
1151 			glVertex2f( x + w, y + h );
1152 		}
1153 		glEnd();
1154 	}
1155 
1156 	glColor4f( 1, 1, 1, 1 );
1157 	for ( unsigned int i = 0; i < lines.size(); i++ ) {
1158 		int ww = widths[ i ];
1159 		int x = static_cast<int>( ( w - ww ) / 2.0f ) + 5;
1160 		texPrint( x, i * 12, "%s", lines[i].c_str() );
1161 	}
1162 	//texPrint( 0, 0, "%s", message );
1163 	setFontType( Constants::SCOURGE_DEFAULT_FONT );
1164 	glPopMatrix();
1165 }
1166 
testDrawView()1167 void SDLHandler::testDrawView() {
1168 	/* Clear The Screen And The Depth Buffer */
1169 	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1170 
1171 	/* Move Right 3 Units */
1172 	glLoadIdentity( );
1173 	glTranslatef( 1.5f, 0.0f, -6.0f );
1174 
1175 	/* Rotate The Quad On The X axis ( NEW ) */
1176 	glRotatef( rquad, 1.0f, 0.0f, 0.0f );
1177 
1178 	/* Set The Color To Blue One Time Only */
1179 	glColor3f( 0.5f, 0.5f, 1.0f );
1180 
1181 	glBegin( GL_QUADS );                 /* Draw A Quad                      */
1182 	glColor3f(   0.0f,  1.0f,  0.0f ); /* Set The Color To Green           */
1183 	glVertex3f(  1.0f,  1.0f, -1.0f ); /* Top Right Of The Quad (Top)      */
1184 	glVertex3f( -1.0f,  1.0f, -1.0f ); /* Top Left Of The Quad (Top)       */
1185 	glVertex3f( -1.0f,  1.0f,  1.0f ); /* Bottom Left Of The Quad (Top)    */
1186 	glVertex3f(  1.0f,  1.0f,  1.0f ); /* Bottom Right Of The Quad (Top)   */
1187 
1188 	glColor3f(   1.0f,  0.5f,  0.0f ); /* Set The Color To Orange          */
1189 	glVertex3f(  1.0f, -1.0f,  1.0f ); /* Top Right Of The Quad (Botm)     */
1190 	glVertex3f( -1.0f, -1.0f,  1.0f ); /* Top Left Of The Quad (Botm)      */
1191 	glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Botm)   */
1192 	glVertex3f(  1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Botm)  */
1193 
1194 	glColor3f(   1.0f,  0.0f,  0.0f ); /* Set The Color To Red             */
1195 	glVertex3f(  1.0f,  1.0f,  1.0f ); /* Top Right Of The Quad (Front)    */
1196 	glVertex3f( -1.0f,  1.0f,  1.0f ); /* Top Left Of The Quad (Front)     */
1197 	glVertex3f( -1.0f, -1.0f,  1.0f ); /* Bottom Left Of The Quad (Front)  */
1198 	glVertex3f(  1.0f, -1.0f,  1.0f ); /* Bottom Right Of The Quad (Front) */
1199 
1200 	glColor3f(   1.0f,  1.0f,  0.0f ); /* Set The Color To Yellow          */
1201 	glVertex3f(  1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Back)   */
1202 	glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Back)  */
1203 	glVertex3f( -1.0f,  1.0f, -1.0f ); /* Top Right Of The Quad (Back)     */
1204 	glVertex3f(  1.0f,  1.0f, -1.0f ); /* Top Left Of The Quad (Back)      */
1205 
1206 	glColor3f(   0.0f,  0.0f,  1.0f ); /* Set The Color To Blue            */
1207 	glVertex3f( -1.0f,  1.0f,  1.0f ); /* Top Right Of The Quad (Left)     */
1208 	glVertex3f( -1.0f,  1.0f, -1.0f ); /* Top Left Of The Quad (Left)      */
1209 	glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Left)   */
1210 	glVertex3f( -1.0f, -1.0f,  1.0f ); /* Bottom Right Of The Quad (Left)  */
1211 
1212 	glColor3f(   1.0f,  0.0f,  1.0f ); /* Set The Color To Violet          */
1213 	glVertex3f(  1.0f,  1.0f, -1.0f ); /* Top Right Of The Quad (Right)    */
1214 	glVertex3f(  1.0f,  1.0f,  1.0f ); /* Top Left Of The Quad (Right)     */
1215 	glVertex3f(  1.0f, -1.0f,  1.0f ); /* Bottom Left Of The Quad (Right)  */
1216 	glVertex3f(  1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Right) */
1217 	glEnd( );                            /* Done Drawing The Quad            */
1218 
1219 	/* Move Left 1.5 Units And Into The Screen 6.0 */
1220 	glLoadIdentity();
1221 	glTranslatef( 0.5f, 0.0f, -8.0f );
1222 
1223 	/* Rotate The Triangle On The Y axis ( NEW ) */
1224 	glRotatef( rtri, 0.0f, 1.0f, 0.0f );
1225 
1226 	glBegin( GL_TRIANGLES );             /* Drawing Using Triangles       */
1227 	glColor3f(   1.0f,  0.0f,  0.0f ); /* Red                           */
1228 	glVertex3f(  0.0f,  1.0f,  0.0f ); /* Top Of Triangle (Front)       */
1229 	glColor3f(   0.0f,  1.0f,  0.0f ); /* Green                         */
1230 	glVertex3f( -1.0f, -1.0f,  1.0f ); /* Left Of Triangle (Front)      */
1231 	glColor3f(   0.0f,  0.0f,  1.0f ); /* Blue                          */
1232 	glVertex3f(  1.0f, -1.0f,  1.0f ); /* Right Of Triangle (Front)     */
1233 
1234 	glColor3f(   1.0f,  0.0f,  0.0f ); /* Red                           */
1235 	glVertex3f(  0.0f,  1.0f,  0.0f ); /* Top Of Triangle (Right)       */
1236 	glColor3f(   0.0f,  0.0f,  1.0f ); /* Blue                          */
1237 	glVertex3f(  1.0f, -1.0f,  1.0f ); /* Left Of Triangle (Right)      */
1238 	glColor3f(   0.0f,  1.0f,  0.0f ); /* Green                         */
1239 	glVertex3f(  1.0f, -1.0f, -1.0f ); /* Right Of Triangle (Right)     */
1240 
1241 	glColor3f(   1.0f,  0.0f,  0.0f ); /* Red                           */
1242 	glVertex3f(  0.0f,  1.0f,  0.0f ); /* Top Of Triangle (Back)        */
1243 	glColor3f(   0.0f,  1.0f,  0.0f ); /* Green                         */
1244 	glVertex3f(  1.0f, -1.0f, -1.0f ); /* Left Of Triangle (Back)       */
1245 	glColor3f(   0.0f,  0.0f,  1.0f ); /* Blue                          */
1246 	glVertex3f( -1.0f, -1.0f, -1.0f ); /* Right Of Triangle (Back)      */
1247 
1248 	glColor3f(   1.0f,  0.0f,  0.0f ); /* Red                           */
1249 	glVertex3f(  0.0f,  1.0f,  0.0f ); /* Top Of Triangle (Left)        */
1250 	glColor3f(   0.0f,  0.0f,  1.0f ); /* Blue                          */
1251 	glVertex3f( -1.0f, -1.0f, -1.0f ); /* Left Of Triangle (Left)       */
1252 	glColor3f(   0.0f,  1.0f,  0.0f ); /* Green                         */
1253 	glVertex3f( -1.0f, -1.0f,  1.0f ); /* Right Of Triangle (Left)      */
1254 	glEnd( );                            /* Finished Drawing The Triangle */
1255 
1256 	/* Increase The Rotation Variable For The Triangle ( NEW ) */
1257 	rtri  += 0.2f;
1258 	/* Decrease The Rotation Variable For The Quad     ( NEW ) */
1259 	rquad -= 0.15f;
1260 }
1261 
getHighlightTexture()1262 Texture const& SDLHandler::getHighlightTexture() {
1263 	return gameAdapter->getHighlightTexture();
1264 }
1265 
getGuiTexture()1266 Texture const& SDLHandler::getGuiTexture() {
1267 	return gameAdapter->getGuiTexture();
1268 }
1269 
getGuiTexture2()1270 Texture const& SDLHandler::getGuiTexture2() {
1271 	return gameAdapter->getGuiTexture2();
1272 }
1273 
loadSystemTexture(char * line)1274 Texture const& SDLHandler::loadSystemTexture( char *line ) {
1275 	return gameAdapter->loadSystemTexture( line );
1276 }
1277 
allWindowsClosed()1278 void SDLHandler::allWindowsClosed() {
1279 	/*
1280 	if( gameAdapter->getSession()->getParty() &&
1281 	    gameAdapter->getSession()->getParty()->getPartySize() > 0 ) {
1282 	  gameAdapter->getSession()->getParty()->toggleRound( false );
1283 	}
1284 	*/
1285 }
1286 
setCursorMode(int n,bool useTimer)1287 void SDLHandler::setCursorMode( int n, bool useTimer ) {
1288 	cursorMode = n;
1289 	if ( cursorMode == Constants::CURSOR_FORBIDDEN && useTimer ) {
1290 		forbiddenTimer = SDL_GetTicks();
1291 	}
1292 }
1293 
setUpdate(char * message,int n,int total)1294 void SDLHandler::setUpdate( char *message, int n, int total ) {
1295 	if ( screenView->setUpdate( message, n, total ) ) {
1296 		processEventsAndRepaint();
1297 	}
1298 }
1299 
playSound(const std::string & file,int panning)1300 void SDLHandler::playSound( const std::string& file, int panning ) {
1301 	gameAdapter->getSession()->getSound()->playSound( file, panning );
1302 }
1303 
setContinueAt(char * func,int timeout)1304 void SDLHandler::setContinueAt( char *func, int timeout ) {
1305 	this->continueFunc = func;
1306 	this->continueTimeout = timeout;
1307 	this->continueStart = SDL_GetTicks();
1308 }
1309