1 /***************************************************************************
2 
3     file        : racegl.cpp
4     created     : Sat Nov 16 18:22:00 CET 2002
5     copyright   : (C) 2002-2013 by Eric Espie, Bernhard Wymann
6     email       : eric.espie@torcs.org
7     version     : $Id: racegl.cpp,v 1.7.2.4 2013/09/01 10:24:23 berniw Exp $
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *   This program is free software; you can redistribute it and/or modify  *
14  *   it under the terms of the GNU General Public License as published by  *
15  *   the Free Software Foundation; either version 2 of the License, or     *
16  *   (at your option) any later version.                                   *
17  *                                                                         *
18  ***************************************************************************/
19 
20 /** @file
21 
22     @author	<a href=mailto:eric.espie@torcs.org>Eric Espie</a>
23     @version	$Id: racegl.cpp,v 1.7.2.4 2013/09/01 10:24:23 berniw Exp $
24 */
25 #include <stdlib.h>
26 #include <stdio.h>
27 
28 #include <tgfclient.h>
29 #include <raceman.h>
30 #include <robot.h>
31 
32 #include "racemain.h"
33 #include "raceinit.h"
34 #include "racestate.h"
35 #include "raceengine.h"
36 
37 #include "racegl.h"
38 
39 static void	*reScreenHandle = 0;
40 static void	*reHookHandle = 0;
41 static int	rePauseId;
42 static int	reMsgId;
43 static int	reBigMsgId;
44 
45 static float bgcolor[4] = {0.0, 0.0, 0.0, 0.0};
46 static float white[4]   = {1.0, 1.0, 1.0, 1.0};
47 static float red[4]     = {1.0, 0.0, 0.0, 1.0};
48 
49 static void
reDisplay(void)50 reDisplay(void)
51 {
52     ReStateManage();
53 }
54 
55 static void
reScreenActivate(void *)56 reScreenActivate(void * /* dummy */)
57 {
58     glutDisplayFunc(reDisplay);
59 
60     if ((ReInfo->s->_raceState & RM_RACE_PAUSED) == 0) {
61 	ReStart(); 			/* resynchro */
62     }
63     glutPostRedisplay();
64 }
65 
66 static void
ReBoardInfo(void *)67 ReBoardInfo(void * /* vboard */)
68 {
69     if (ReInfo->s->_raceState & RM_RACE_PAUSED) {
70 	ReInfo->s->_raceState &= ~RM_RACE_PAUSED;
71 	ReStart();
72 	GfuiVisibilitySet(reScreenHandle, rePauseId, 0);
73     } else {
74 	ReInfo->s->_raceState |= RM_RACE_PAUSED;
75 	ReStop();
76 	GfuiVisibilitySet(reScreenHandle, rePauseId, 1);
77     }
78 }
79 
80 static void
reSkipPreStart(void *)81 reSkipPreStart(void * /* dummy */)
82 {
83     if (ReInfo->s->currentTime < -1.0) {
84 	ReInfo->s->currentTime = -1.0;
85 	ReInfo->_reLastTime = -1.0;
86     }
87 }
88 
89 static void
reMovieCapture(void *)90 reMovieCapture(void * /* dummy */)
91 {
92    tRmMovieCapture	*capture = &(ReInfo->movieCapture);
93 
94     if (!capture->enabled || (ReInfo->_displayMode == RM_DISP_MODE_NONE)) {
95 	GfOut("Video Capture Mode Not Enabled\n");
96 	return;
97     }
98 
99     capture->state = 1 - capture->state;
100     if (capture->state) {
101 	GfOut("Video Capture Mode On\n");
102 	capture->currentFrame = 0;
103 	capture->currentCapture++;
104 	capture->lastFrame = GfTimeClock() - capture->deltaFrame;
105 	ReInfo->_displayMode = RM_DISP_MODE_CAPTURE;
106     } else {
107 	GfOut("Video Capture Mode Off\n");
108 	ReInfo->_displayMode = RM_DISP_MODE_NORMAL;
109 	ReStart();
110     }
111 
112 }
113 
114 
115 
116 static void
reAddKeys(void)117 reAddKeys(void)
118 {
119     GfuiAddSKey(reScreenHandle, GLUT_KEY_F1,        "Help", reScreenHandle, GfuiHelpScreen, NULL);
120     GfuiAddSKey(reScreenHandle, GLUT_KEY_F12,       "Screen Shot", NULL, GfuiScreenShot, NULL);
121 
122 
123     GfuiAddKey(reScreenHandle, '-', "Slow Time",         (void*)0, ReTimeMod, NULL);
124     GfuiAddKey(reScreenHandle, '+', "Accelerate Time",   (void*)1, ReTimeMod, NULL);
125     GfuiAddKey(reScreenHandle, '.', "Real Time",         (void*)2, ReTimeMod, NULL);
126     GfuiAddKey(reScreenHandle, 'p', "Pause Race",        (void*)0, ReBoardInfo, NULL);
127     GfuiAddKey(reScreenHandle, 27,  "Stop Current Race", (void*)RE_STATE_RACE_STOP, ReStateApply, NULL);
128     /* GfuiAddKey(reScreenHandle, 'q', "Exit of TORCS",     (void*)RE_STATE_EXIT, ReStateApply, NULL); */
129     GfuiAddKey(reScreenHandle, ' ', "Skip Pre Start",    (void*)0, reSkipPreStart, NULL);
130 #ifdef DEBUG
131     //GfuiAddKey(reScreenHandle, '0', "One step simulation",    (void*)1, reOneStep, NULL);
132 #endif
133     GfuiAddKey(reScreenHandle, 'c', "Movie Capture",      (void*)0, reMovieCapture, NULL);
134 
135 }
136 
137 
138 void
ReSetRaceMsg(const char * msg)139 ReSetRaceMsg(const char *msg)
140 {
141 	static char *curMsg = 0;
142 
143 	if (curMsg) free(curMsg);
144 
145 	if (msg) {
146 		curMsg = strdup(msg);
147 		GfuiLabelSetText(reScreenHandle, reMsgId, curMsg);
148 	} else {
149 		curMsg = 0;
150 		GfuiLabelSetText(reScreenHandle, reMsgId, "");
151 	}
152 }
153 
154 void
ReSetRaceBigMsg(const char * msg)155 ReSetRaceBigMsg(const char *msg)
156 {
157 	static char *curMsg = 0;
158 
159 	if (curMsg) free(curMsg);
160 
161 	if (msg) {
162 		curMsg = strdup(msg);
163 		GfuiLabelSetText(reScreenHandle, reBigMsgId, curMsg);
164 	} else {
165 		curMsg = 0;
166 		GfuiLabelSetText(reScreenHandle, reBigMsgId, "");
167 	}
168 }
169 
170 void *
ReScreenInit(void)171 ReScreenInit(void)
172 {
173 
174     ReScreenShutdown();
175 
176     reScreenHandle = GfuiScreenCreateEx(bgcolor, 0, reScreenActivate, 0, 0, 0);
177 
178     reAddKeys();
179 
180     reMsgId = GfuiLabelCreateEx(reScreenHandle,
181 				"",
182 				red,
183 				GFUI_FONT_LARGE_C,
184 				320,
185 				400,
186 				GFUI_ALIGN_HC_VB,
187 				42);
188 
189     rePauseId = GfuiLabelCreateEx(reScreenHandle,
190 				  "P A U S E",
191 				  red,
192 				  GFUI_FONT_BIG_C,
193 				  320,
194 				  420,
195 				  GFUI_ALIGN_HC_VB,
196 				  0);
197 
198     reBigMsgId = GfuiLabelCreateEx(reScreenHandle,
199 				   "",
200 				   red,
201 				   GFUI_FONT_BIG_C,
202 				   320,
203 				   360,
204 				   GFUI_ALIGN_HC_VB,
205 				   32);
206 
207     GfuiVisibilitySet(reScreenHandle, rePauseId, 0);
208 
209     return reScreenHandle;
210 }
211 
212 
213 void
ReScreenShutdown(void)214 ReScreenShutdown(void)
215 {
216     if (reScreenHandle) {
217 	GfuiScreenRelease(reScreenHandle);
218 	reScreenHandle = 0;
219     }
220 }
221 
222 
223 static void
reHookActivate(void *)224 reHookActivate(void * /* dummy */)
225 {
226     ReStateManage();
227 }
228 
229 void *
ReHookInit(void)230 ReHookInit(void)
231 {
232     if (reHookHandle) {
233 	return reHookHandle;
234     }
235 
236     reHookHandle = GfuiHookCreate(0, reHookActivate);
237 
238     return reHookHandle;
239 }
240 
241 
242 void
ReHookShutdown(void)243 ReHookShutdown(void)
244 {
245     if (reHookHandle) {
246 	GfuiHookRelease(reHookHandle);
247 	reHookHandle = 0;
248     }
249 }
250 
251 /**************************************************************************/
252 
253 /*
254  * Result only screen
255  */
256 #define LINES	21
257 
258 static float	*reColor[] = {white, red};
259 
260 static void	*reResScreenHdle = 0;
261 static int	reResTitleId;
262 static int	reResMsgId[LINES];
263 static int	reResMsgClr[LINES];
264 static char	*reResMsg[LINES];
265 static int	reCurLine;
266 
267 static void
reAddResKeys(void)268 reAddResKeys(void)
269 {
270     GfuiAddSKey(reResScreenHdle, GLUT_KEY_F1,  "Help", reScreenHandle, GfuiHelpScreen, NULL);
271     GfuiAddSKey(reResScreenHdle, GLUT_KEY_F12, "Screen Shot", NULL, GfuiScreenShot, NULL);
272 
273     GfuiAddKey(reResScreenHdle, 27,  "Stop Current Race", (void*)RE_STATE_RACE_STOP, ReStateApply, NULL);
274     /* GfuiAddKey(reResScreenHdle, 'q', "Exit of TORCS",     (void*)RE_STATE_EXIT, ReStateApply, NULL); */
275 }
276 
277 static void
reResScreenActivate(void *)278 reResScreenActivate(void * /* dummy */)
279 {
280     glutDisplayFunc(reDisplay);
281     GfuiDisplay();
282     glutPostRedisplay();
283 }
284 
285 
286 static void
reContDisplay(void)287 reContDisplay(void)
288 {
289     GfuiDisplay();
290     glutPostRedisplay();
291 }
292 
293 
294 static void
reResCont(void *)295 reResCont(void * /* dummy */)
296 {
297     ReStateManage();
298 }
299 
300 static void
reResScreenShutdown(void *)301 reResScreenShutdown(void * /* dummy */)
302 {
303     int		i;
304 
305     for (i = 1; i < LINES; i++) {
306 	FREEZ(reResMsg[i]);
307     }
308 }
309 
310 void *
ReResScreenInit(void)311 ReResScreenInit(void)
312 {
313 	int i;
314 	int y, dy;
315 	static const char *title[3] = {"Practice", "Qualifications", "Race"};
316 
317 	if (reResScreenHdle) {
318 		GfuiScreenRelease(reResScreenHdle);
319 	}
320 
321 	reResScreenHdle = GfuiScreenCreateEx(bgcolor, 0, reResScreenActivate, 0, reResScreenShutdown, 0);
322 
323 	GfuiTitleCreate(reResScreenHdle, title[ReInfo->s->_raceType], strlen(title[ReInfo->s->_raceType]));
324 
325 	const char* img = GfParmGetStr(ReInfo->params, RM_SECT_HEADER, RM_ATTR_RUNIMG, 0);
326 	if (img) {
327 		GfuiScreenAddBgImg(reResScreenHdle, img);
328 	}
329 
330 	reAddResKeys();
331 
332 	reResTitleId = GfuiLabelCreateEx(reResScreenHdle,
333 						"",
334 						red,
335 						GFUI_FONT_LARGE_C,
336 						320, 420,
337 						GFUI_ALIGN_HC_VB, 50);
338 
339 	y = 400;
340 	dy = 378 / LINES;
341 	for (i = 0; i < LINES; i++) {
342 		FREEZ(reResMsg[i]);
343 		reResMsgClr[i] = 0;
344 		reResMsgId[i] = GfuiLabelCreateEx(reResScreenHdle,
345 							"",
346 							white,
347 							GFUI_FONT_MEDIUM_C,
348 							20, y,
349 							GFUI_ALIGN_HL_VB, 120);
350 		y -= dy;
351 	}
352 
353 	reCurLine = 0;
354 	return reResScreenHdle;
355 }
356 
357 void
ReResScreenSetTitle(char * title)358 ReResScreenSetTitle(char *title)
359 {
360 	if (reResScreenHdle) {
361 		GfuiLabelSetText(reResScreenHdle, reResTitleId, title);
362 	}
363 }
364 
365 void
ReResScreenAddText(char * text)366 ReResScreenAddText(char *text)
367 {
368     int		i;
369 
370     if (reCurLine == LINES) {
371 	free(reResMsg[0]);
372 	for (i = 1; i < LINES; i++) {
373 	    reResMsg[i - 1] = reResMsg[i];
374 	    GfuiLabelSetText(reResScreenHdle, reResMsgId[i - 1], reResMsg[i]);
375 	}
376 	reCurLine--;
377     }
378     reResMsg[reCurLine] = strdup(text);
379     GfuiLabelSetText(reResScreenHdle, reResMsgId[reCurLine], reResMsg[reCurLine]);
380     reCurLine++;
381 }
382 
383 void
ReResScreenSetText(const char * text,int line,int clr)384 ReResScreenSetText(const char *text, int line, int clr)
385 {
386 	if (line < LINES) {
387 		FREEZ(reResMsg[line]);
388 		reResMsg[line] = strdup(text);
389 		if ((clr >= 0) && (clr < 2)) {
390 			reResMsgClr[line] = clr;
391 		} else {
392 			reResMsgClr[line] = 0;
393 		}
394 		GfuiLabelSetText(reResScreenHdle, reResMsgId[line], reResMsg[line]);
395 		GfuiLabelSetColor(reResScreenHdle, reResMsgId[line], reColor[reResMsgClr[line]]);
396 	}
397 }
398 
399 int
ReResGetLines(void)400 ReResGetLines(void)
401 {
402     return LINES;
403 }
404 
405 void
ReResEraseScreen(void)406 ReResEraseScreen(void)
407 {
408 	int i;
409 
410 	for (i = 0; i < LINES; i++) {
411 		ReResScreenSetText("", i, 0);
412 	}
413 }
414 
415 
416 void
ReResScreenRemoveText(int line)417 ReResScreenRemoveText(int line)
418 {
419     if (line < LINES) {
420 	FREEZ(reResMsg[line]);
421 	GfuiLabelSetText(reResScreenHdle, reResMsgId[line], "");
422     }
423 }
424 
425 void
ReResShowCont(void)426 ReResShowCont(void)
427 {
428 
429     GfuiButtonCreate(reResScreenHdle,
430 		     "Continue",
431 		     GFUI_FONT_LARGE_C,
432 		     320, 15, GFUI_BTNSZ,
433 		     GFUI_ALIGN_HC_VB,
434 		     0, 0, reResCont,
435 		     NULL, (tfuiCallback)NULL,
436 		     (tfuiCallback)NULL);
437     GfuiAddKey(reResScreenHdle, 13,  "Continue", 0, reResCont, NULL);
438     GfuiAddKey(reResScreenHdle, 27,  "Continue", 0, reResCont, NULL);
439 
440     glutDisplayFunc(reContDisplay);
441     glutPostRedisplay();
442 }
443 
444