1 /*
2 * Tux Racer
3 * Copyright (C) 1999-2001 Jasmin F. Patry
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #include "tuxracer.h"
21 #include "event_select.h"
22 #include "ui_mgr.h"
23 #include "ui_theme.h"
24 #include "button.h"
25 #include "listbox.h"
26 #include "loop.h"
27 #include "render_util.h"
28 #include "audio.h"
29 #include "gl_util.h"
30 #include "keyboard.h"
31 #include "multiplayer.h"
32 #include "course_load.h"
33 #include "fonts.h"
34 #include "textures.h"
35 #include "course_mgr.h"
36 #include "save.h"
37 #include "ui_snow.h"
38 #include "joystick.h"
39
40 static listbox_t *event_listbox = NULL;
41 static listbox_t *cup_listbox = NULL;
42 static button_t *back_btn = NULL;
43 static button_t *continue_btn = NULL;
44 static list_elem_t cur_event = NULL;
45 static event_data_t *event_data = NULL;
46 static list_elem_t cur_cup = NULL;
47
event_list_elem_to_string_func(list_elem_data_t elem)48 static char* event_list_elem_to_string_func( list_elem_data_t elem )
49 {
50 return get_event_name( (event_data_t*) elem );
51 }
52
cup_list_elem_to_string_func(list_elem_data_t elem)53 static char* cup_list_elem_to_string_func( list_elem_data_t elem )
54 {
55 return get_cup_name( (cup_data_t*) elem );
56 }
57
58
59 /*---------------------------------------------------------------------------*/
60 /*!
61 Updates the enabled states of the buttons
62 \author jfpatry
63 \date Created: 2000-09-24
64 \date Modified: 2000-09-24
65 */
update_button_enabled_states()66 static void update_button_enabled_states( )
67 {
68 if ( continue_btn == NULL ) {
69 return;
70 }
71
72 if ( is_cup_complete( event_data, cur_cup ) ||
73 is_cup_first_incomplete_cup( event_data, cur_cup ) )
74 {
75 button_set_enabled( continue_btn, True );
76 } else {
77 button_set_enabled( continue_btn, False );
78 }
79 }
80
81
set_cur_cup_to_first_incomplete(event_data_t * event_data,list_t cup_list)82 static void set_cur_cup_to_first_incomplete( event_data_t *event_data,
83 list_t cup_list )
84 {
85 cur_cup = get_last_complete_cup_for_event( event_data );
86
87 if ( cur_cup == NULL ) {
88 cur_cup = get_list_head( cup_list );
89 } else if ( cur_cup != get_list_tail( cup_list ) ) {
90 cur_cup = get_next_list_elem( cup_list, cur_cup );
91 }
92 }
93
event_listbox_item_change_cb(listbox_t * listbox,void * userdata)94 static void event_listbox_item_change_cb( listbox_t *listbox, void *userdata )
95 {
96 list_elem_t cur_event;
97 list_t cup_list;
98
99 check_assertion( userdata == NULL, "userdata is not null" );
100
101 cur_event = listbox_get_current_item( listbox );
102 event_data = (event_data_t*) get_list_elem_data( cur_event );
103
104 cup_list = get_event_cup_list( event_data );
105 listbox_set_item_list( cup_listbox, cup_list,
106 cup_list_elem_to_string_func );
107
108 set_cur_cup_to_first_incomplete( event_data, cup_list );
109
110 listbox_set_current_item( cup_listbox, cur_cup );
111
112 update_button_enabled_states();
113
114 ui_set_dirty();
115 }
116
cup_listbox_item_change_cb(listbox_t * listbox,void * userdata)117 static void cup_listbox_item_change_cb( listbox_t *listbox, void *userdata )
118 {
119 check_assertion( userdata == NULL, "userdata is not null" );
120
121 cur_cup = listbox_get_current_item( listbox );
122
123 update_button_enabled_states();
124 }
125
back_click_cb(button_t * button,void * userdata)126 static void back_click_cb( button_t *button, void *userdata )
127 {
128 check_assertion( userdata == NULL, "userdata is not null" );
129
130 set_game_mode( GAME_TYPE_SELECT );
131
132 ui_set_dirty();
133 }
134
continue_click_cb(button_t * button,void * userdata)135 static void continue_click_cb( button_t *button, void *userdata )
136 {
137 cup_data_t *cup_data;
138 player_data_t *plyr = get_player_data( local_player() );
139
140 check_assertion( userdata == NULL, "userdata is not null" );
141
142 cur_event = listbox_get_current_item( event_listbox );
143 event_data = (event_data_t*) get_list_elem_data( cur_event );
144
145 cur_cup = listbox_get_current_item( cup_listbox );
146 cup_data = (cup_data_t*) get_list_elem_data( cur_cup );
147
148 g_game.current_event = get_event_name( event_data );
149 g_game.current_cup = get_cup_name( cup_data );
150
151 plyr->lives = INIT_NUM_LIVES;
152
153 set_game_mode( RACE_SELECT );
154
155 ui_set_dirty();
156 }
157
set_widget_positions_and_draw_decorations()158 static void set_widget_positions_and_draw_decorations()
159 {
160 int w = getparam_x_resolution();
161 int h = getparam_y_resolution();
162 int box_width, box_height, box_max_y;
163 int x_org, y_org;
164 char *string;
165 font_t *font;
166 int text_width, asc, desc;
167 list_t cup_list;
168 GLuint texobj;
169
170 /* set the dimensions of the box in which all widgets should fit */
171 box_width = 460;
172 box_height = 310;
173 box_max_y = h - 128;
174
175 x_org = w/2 - box_width/2;
176 y_org = h/2 - box_height/2;
177 if ( y_org + box_height > box_max_y ) {
178 y_org = box_max_y - box_height;
179 }
180
181 button_set_position(
182 back_btn,
183 make_point2d( x_org + 131 - button_get_width( back_btn )/2.0,
184 42 ) );
185
186 button_set_position(
187 continue_btn,
188 make_point2d( x_org + 329 - button_get_width( continue_btn )/2.0,
189 42 ) );
190
191 listbox_set_position(
192 cup_listbox,
193 make_point2d( x_org + 52,
194 y_org + 103 ) );
195
196 listbox_set_position(
197 event_listbox,
198 make_point2d( x_org + 52,
199 y_org + 193 ) );
200
201 /*
202 * Draw other stuff
203 */
204
205 /* Event & cup icons */
206 if ( !get_texture_binding( get_event_icon_texture_binding( event_data ),
207 &texobj ) ) {
208 texobj = 0;
209 }
210
211 glBindTexture( GL_TEXTURE_2D, texobj );
212
213
214 glBegin( GL_QUADS );
215 {
216 point2d_t tll, tur;
217 point2d_t ll, ur;
218
219 ll = make_point2d( x_org, y_org + 193 );
220 ur = make_point2d( x_org + 44, y_org + 193 + 44 );
221 tll = make_point2d( 0, 0 );
222 tur = make_point2d( 44.0/64.0, 44.0/64.0 );
223
224 glTexCoord2f( tll.x, tll.y );
225 glVertex2f( ll.x, ll.y );
226
227 glTexCoord2f( tur.x, tll.y );
228 glVertex2f( ur.x, ll.y );
229
230 glTexCoord2f( tur.x, tur.y );
231 glVertex2f( ur.x, ur.y );
232
233 glTexCoord2f( tll.x, tur.y );
234 glVertex2f( ll.x, ur.y );
235 }
236 glEnd();
237
238 if ( !get_texture_binding(
239 get_cup_icon_texture_binding(
240 (cup_data_t*) get_list_elem_data( cur_cup ) ), &texobj ) )
241 {
242 texobj = 0;
243 }
244
245 glBindTexture( GL_TEXTURE_2D, texobj );
246
247 glBegin( GL_QUADS );
248 {
249 point2d_t tll, tur;
250 point2d_t ll, ur;
251
252 ll = make_point2d( x_org, y_org + 103 );
253 ur = make_point2d( x_org + 44, y_org + 103 + 44 );
254 tll = make_point2d( 0, 0 );
255 tur = make_point2d( 44.0/64.0, 44.0/64.0 );
256
257 glTexCoord2f( tll.x, tll.y );
258 glVertex2f( ll.x, ll.y );
259
260 glTexCoord2f( tur.x, tll.y );
261 glVertex2f( ur.x, ll.y );
262
263 glTexCoord2f( tur.x, tur.y );
264 glVertex2f( ur.x, ur.y );
265
266 glTexCoord2f( tll.x, tur.y );
267 glVertex2f( ll.x, ur.y );
268 }
269 glEnd();
270
271 if ( !get_font_binding( "menu_label", &font ) ) {
272 print_warning( IMPORTANT_WARNING,
273 "Couldn't get font for binding menu_label" );
274 } else {
275 bind_font_texture( font );
276 string = "Select event and cup";
277 get_font_metrics( font, string, &text_width, &asc, &desc );
278
279 glPushMatrix();
280 {
281 glTranslatef( x_org + box_width/2.0 - text_width/2.0,
282 y_org + 310 - asc,
283 0 );
284
285 draw_string( font, string );
286 }
287 glPopMatrix();
288 }
289
290 if ( !get_font_binding( "event_and_cup_label", &font ) ) {
291 print_warning( IMPORTANT_WARNING,
292 "Couldn't get font for binding menu_label" );
293 } else {
294 bind_font_texture( font );
295 string = "Event:";
296 get_font_metrics( font, string, &text_width, &asc, &desc );
297
298 glPushMatrix();
299 {
300 glTranslatef( x_org,
301 y_org + 193 + 44 + 5 + desc,
302 0 );
303
304 draw_string( font, string );
305 }
306 glPopMatrix();
307
308 string = "Cup:";
309
310 glPushMatrix();
311 {
312 glTranslatef( x_org,
313 y_org + 103 + 44 + 5 + desc,
314 0 );
315
316 draw_string( font, string );
317 }
318 glPopMatrix();
319 }
320
321 cur_event = listbox_get_current_item( event_listbox );
322 event_data = (event_data_t*) get_list_elem_data( cur_event );
323 cup_list = get_event_cup_list( event_data );
324 cur_cup = listbox_get_current_item( cup_listbox );
325
326 if ( is_cup_complete( event_data, cur_cup ) ) {
327 string = "You've won this cup!";
328 } else if ( is_cup_first_incomplete_cup( event_data, cur_cup ) ) {
329 string = "You must complete this cup next";
330 } else {
331 string = "You cannot enter this cup yet";
332 }
333
334 if ( !get_font_binding( "cup_status", &font ) ) {
335 print_warning( IMPORTANT_WARNING,
336 "Couldn't get font for binding cup_status" );
337 } else {
338 bind_font_texture( font );
339
340 get_font_metrics( font, string, &text_width, &asc, &desc );
341
342 glPushMatrix();
343 {
344 glTranslatef( x_org + box_width/2.0 - text_width/2.0,
345 y_org + 70,
346 0 );
347
348 draw_string( font, string );
349 }
350 glPopMatrix();
351 }
352 }
353
event_select_init(void)354 static void event_select_init(void)
355 {
356 list_t event_list = NULL;
357 list_t cup_list = NULL;
358 point2d_t dummy_pos = {0, 0};
359
360 winsys_set_display_func( main_loop );
361 winsys_set_idle_func( main_loop );
362 winsys_set_reshape_func( reshape );
363 winsys_set_mouse_func( ui_event_mouse_func );
364 winsys_set_motion_func( ui_event_motion_func );
365 winsys_set_passive_motion_func( ui_event_motion_func );
366
367 event_list = get_events_list();
368
369 if ( g_game.prev_mode != RACE_SELECT ) {
370 cur_event = get_list_head( event_list );
371 event_data = (event_data_t*)get_list_elem_data( cur_event );
372 cup_list = get_event_cup_list( event_data );
373
374 set_cur_cup_to_first_incomplete( event_data, cup_list );
375 } else {
376 event_data = (event_data_t*)get_list_elem_data( cur_event );
377 cup_list = get_event_cup_list( event_data );
378 }
379
380
381
382 /*
383 * Create widgets
384 */
385
386 /* back button */
387 back_btn = button_create( dummy_pos,
388 150, 40,
389 "button_label",
390 "Back" );
391 button_set_hilit_font_binding( back_btn, "button_label_hilit" );
392 button_set_visible( back_btn, True );
393 button_set_click_event_cb( back_btn, back_click_cb, NULL );
394
395 /* continue button */
396 continue_btn = button_create( dummy_pos,
397 150, 40,
398 "button_label",
399 "Continue" );
400 button_set_hilit_font_binding( continue_btn, "button_label_hilit" );
401 button_set_disabled_font_binding( continue_btn, "button_label_disabled" );
402 button_set_visible( continue_btn, True );
403 button_set_click_event_cb( continue_btn, continue_click_cb, NULL );
404
405 /* event listbox */
406 event_listbox = listbox_create( dummy_pos,
407 460 - 52, 44,
408 "listbox_item",
409 event_list,
410 event_list_elem_to_string_func );
411
412 listbox_set_current_item( event_listbox, cur_event );
413
414 listbox_set_item_change_event_cb( event_listbox,
415 event_listbox_item_change_cb,
416 NULL );
417
418 listbox_set_visible( event_listbox, True );
419
420 /* cup listbox */
421 cup_listbox = listbox_create( dummy_pos,
422 460 - 52, 44,
423 "listbox_item",
424 cup_list,
425 cup_list_elem_to_string_func );
426
427 listbox_set_current_item( cup_listbox, cur_cup );
428
429 listbox_set_item_change_event_cb( cup_listbox,
430 cup_listbox_item_change_cb,
431 NULL );
432
433 listbox_set_visible( cup_listbox, True );
434
435 update_button_enabled_states();
436
437 play_music( "start_screen" );
438 }
439
event_select_loop(scalar_t time_step)440 static void event_select_loop( scalar_t time_step )
441 {
442 check_gl_error();
443
444 update_audio();
445
446 set_gl_options( GUI );
447
448 clear_rendering_context();
449
450 ui_setup_display();
451
452 if (getparam_ui_snow()) {
453 update_ui_snow( time_step, False );
454 draw_ui_snow();
455 }
456
457 ui_draw_menu_decorations();
458
459 set_widget_positions_and_draw_decorations();
460
461 ui_draw();
462
463 reshape( getparam_x_resolution(), getparam_y_resolution() );
464
465 winsys_swap_buffers();
466 }
467
event_select_term(void)468 static void event_select_term(void)
469 {
470 button_delete( back_btn );
471 back_btn = NULL;
472
473 button_delete( continue_btn );
474 continue_btn = NULL;
475
476 listbox_delete( event_listbox );
477 event_listbox = NULL;
478
479 listbox_delete( cup_listbox );
480 cup_listbox = NULL;
481 }
482
START_KEYBOARD_CB(event_select_key_cb)483 START_KEYBOARD_CB( event_select_key_cb )
484 {
485 if ( release ) {
486 return;
487 }
488
489 if ( special ) {
490 switch( key ) {
491 case WSK_LEFT:
492 listbox_goto_prev_item( event_listbox );
493 break;
494 case WSK_RIGHT:
495 listbox_goto_next_item( event_listbox );
496 break;
497 case WSK_DOWN:
498 listbox_goto_next_item( cup_listbox );
499 break;
500 case WSK_UP:
501 listbox_goto_prev_item( cup_listbox );
502 break;
503 }
504 } else {
505 switch (key) {
506 case 13: /* Enter */
507 if ( continue_btn ) {
508 button_simulate_mouse_click( continue_btn );
509 ui_set_dirty();
510 }
511 break;
512 case 27: /* Esc */
513 if ( back_btn ) {
514 button_simulate_mouse_click( back_btn );
515 ui_set_dirty();
516 }
517 break;
518 }
519 }
520
521 ui_check_dirty();
522 }
523 END_KEYBOARD_CB
524
event_select_register()525 void event_select_register()
526 {
527 int status = 0;
528
529 status |=
530 add_keymap_entry( EVENT_SELECT,
531 DEFAULT_CALLBACK, NULL, NULL, event_select_key_cb );
532
533 check_assertion( status == 0,
534 "out of keymap entries" );
535
536 register_loop_funcs( EVENT_SELECT,
537 event_select_init,
538 event_select_loop,
539 event_select_term );
540 }
541
542
543
544 /* EOF */
545