/*! tux_open_courses Tcl callback \author jfpatry \date Created: 2000-09-19 \date Modified: 2000-09-19 */ static int open_courses_cb( ClientData cd, Tcl_Interp *ip, int argc, const char **argv ) { char *err_msg; const char **list = NULL; int num_courses; list_elem_t last_elem = NULL; list_elem_t last_speed_elem = NULL; list_elem_t last_score_elem = NULL; int i, j; char preview_file[100]; check_assertion( initialized, "course_mgr module not initialized" ); if ( argc != 2 ) { err_msg = "Wrong number of arguments"; goto bail_open_courses; } if ( Tcl_SplitList( ip, argv[1], &num_courses, &list ) == TCL_ERROR ) { err_msg = "Argument is not a list"; goto bail_open_courses; } /* Add items to end of list */ last_elem = get_list_tail( open_course_list ); last_speed_elem = get_list_tail( speed_course_list ); last_score_elem = get_list_tail( score_course_list ); for ( i=0; i<num_courses; i++ ) { open_course_data_t *data; data = create_open_course_data( ip, list[i], &err_msg ); #ifdef __ANDROID__ sprintf(preview_file, "courses/%s/preview.jpg", data->course); #else sprintf(preview_file, "%s/courses/%s/preview.jpg", getparam_data_dir(), data->course); #endif load_texture(data->course, preview_file, 1); bind_texture(data->course, data->course); if ( data == NULL ) { goto bail_open_courses; } last_elem = insert_list_elem( open_course_list, last_elem, (list_elem_data_t) data ); if(data->speed) { last_speed_elem = insert_list_elem( speed_course_list, last_speed_elem, (list_elem_data_t) data ); } if(data->score) { last_score_elem = insert_list_elem( score_course_list, last_score_elem, (list_elem_data_t) data ); } } Tcl_Free( (char*) list ); list = NULL; return TCL_OK; bail_open_courses: /* We'll leave the data that was successfully added in the list. */ Tcl_AppendResult( ip, "Error in call to tux_open_courses: ", err_msg, "\n", "Usage: tux_open_courses { list of open courses }", (NULL) ); return TCL_ERROR; }
/*! Sets the font binding to be used when the button is disabled \author jfpatry \date Created: 2000-09-17 \date Modified: 2000-09-17 */ void button_set_disabled_font_binding( button_t *button, char *binding ) { check_assertion( button != NULL, "button is NULL" ); button->disabled_font_binding = binding; }
bool_t load_texture( char *texname, char *filename, int repeatable ) { IMAGE *texImage; texture_node_t *tex; int max_texture_size; print_debug(DEBUG_TEXTURE, "Loading texture %s from file: %s", texname, filename); if ( initialized == False ) { check_assertion( 0, "texture module not initialized" ); } texImage = ImageLoad( filename ); if ( texImage == NULL ) { print_warning( IMPORTANT_WARNING, "couldn't load image %s", filename ); return False; } if (get_hash_entry( texture_table, texname, (hash_entry_t*)&tex )) { print_debug(DEBUG_TEXTURE, "Found texture %s with id: %d", texname, tex->texture_id); glDeleteTextures( 1, &(tex->texture_id) ); } else { tex = (texture_node_t*)malloc(sizeof(texture_node_t)); check_assertion( tex != NULL, "out of memory" ); tex->ref_count = 0; add_hash_entry( texture_table, texname, (hash_entry_t)tex ); } tex->repeatable = repeatable; glGenTextures( 1, &(tex->texture_id) ); glBindTexture( GL_TEXTURE_2D, tex->texture_id ); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); if ( repeatable ) { glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); } else { #ifndef __APPLE__DISABLED__ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); #endif } glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, get_min_filter() ); /* Check if we need to scale image */ glGetIntegerv( GL_MAX_TEXTURE_SIZE, &max_texture_size ); if ( texImage->sizeX > max_texture_size || texImage->sizeY > max_texture_size ) { #ifdef __APPLE__DISABLED__ abort(); //We don't support that yet #else char *newdata = (char*)malloc( texImage->sizeZ * max_texture_size * max_texture_size ); check_assertion( newdata != NULL, "out of memory" ); print_debug( DEBUG_TEXTURE, "Texture `%s' too large -- scaling to " "maximum allowed size", filename ); /* In the case of large- or small-aspect ratio textures, this could end up using *more* space... oh well. */ gluScaleImage( texImage->sizeZ == 3 ? GL_RGB : GL_RGBA, texImage->sizeX, texImage->sizeY, GL_UNSIGNED_BYTE, texImage->data, max_texture_size, max_texture_size, GL_UNSIGNED_BYTE, newdata ); free( texImage->data ); texImage->data = (unsigned char*) newdata; texImage->sizeX = max_texture_size; texImage->sizeY = max_texture_size; #endif } #ifndef __APPLE__ gluBuild2DMipmaps( GL_TEXTURE_2D, texImage->sizeZ, texImage->sizeX, texImage->sizeY, texImage->sizeZ == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, texImage->data ); #else glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D( GL_TEXTURE_2D, 0, texImage->sizeZ == 3 ? GL_RGB : GL_RGBA, texImage->sizeX, texImage->sizeY == 255 ? 256 : texImage->sizeY /* Work around for tree.png */, 0, texImage->sizeZ == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, texImage->data ); #endif free( texImage->data ); free( texImage ); TRDebugLog("%dx%d %d (%d)\n", texImage->sizeX, texImage->sizeY, texImage->sizeZ, glGetError()); return True; }
/*! Initializes the audio module. \author jfpatry \date Created: 2000-08-13 \date Modified: 2000-08-13 */ void init_audio() { int hz, channels, buffer; Uint16 format; check_assertion( !initialized_, "init_audio called twice" ); sound_contexts_ = create_hash_table(); music_contexts_ = create_hash_table(); initialized_ = True; /* * Init SDL Audio */ if ( getparam_no_audio() == False ) { if ( SDL_Init( SDL_INIT_AUDIO ) < 0 ) { handle_error( 1, "Couldn't initialize SDL: %s", SDL_GetError() ); } /* Open the audio device */ switch (getparam_audio_freq_mode()) { case 0: hz = 11025; break; case 1: hz = 22050; break; case 2: hz = 44100; break; default: hz = 22050; setparam_audio_freq_mode(1); } switch ( getparam_audio_format_mode() ) { case 0: format = AUDIO_U8; break; case 1: format = AUDIO_S16SYS; break; default: format = AUDIO_S16SYS; setparam_audio_format_mode( 1 ); } if ( getparam_audio_stereo() ) { channels = 2; } else { channels = 1; } buffer = getparam_audio_buffer_size(); if ( Mix_OpenAudio(hz, format, channels, buffer) < 0 ) { print_warning( 1, "Warning: Couldn't set %d Hz %d-bit audio\n" " Reason: %s\n", hz, getparam_audio_format_mode() == 0 ? 8 : 16, SDL_GetError()); } else { print_debug( DEBUG_SOUND, "Opened audio device at %d Hz %d-bit audio", hz, getparam_audio_format_mode() == 0 ? 8 : 16 ); } } }
void quit_click_cb( button_t *button, void *userdata ) { check_assertion( userdata == NULL, "userdata is not null" ); winsys_exit( 0 ); }
/*! Mode initialization function \author jfpatry \date Created: 2000-09-24 \date Modified: 2000-09-24 */ static void race_select_init(void) { listbox_list_elem_to_string_fptr_t conv_func = NULL; point2d_t dummy_pos = {0, 0}; int i; winsys_set_display_func( main_loop ); winsys_set_idle_func( main_loop ); winsys_set_reshape_func( reshape ); winsys_set_mouse_func( ui_event_mouse_func ); winsys_set_motion_func( ui_event_motion_func ); winsys_set_passive_motion_func( ui_event_motion_func ); plyr = get_player_data( local_player() ); /* Setup the race list */ if ( g_game.practicing ) { g_game.current_event = "__Practice_Event__"; g_game.current_cup = "__Practice_Cup__"; if(g_game.is_speed_only_mode) race_list = get_speed_courses_list(); else race_list = get_score_courses_list(); conv_func = get_name_from_open_course_data; cup_data = NULL; last_completed_race = NULL; event_data = NULL; } else { event_data = (event_data_t*) get_list_elem_data( get_event_by_name( g_game.current_event ) ); check_assertion( event_data != NULL, "Couldn't find current event." ); cup_data = (cup_data_t*) get_list_elem_data( get_event_cup_by_name( event_data, g_game.current_cup ) ); check_assertion( cup_data != NULL, "Couldn't find current cup." ); race_list = get_cup_race_list( cup_data ); conv_func = get_name_from_race_data; } /* Unless we're coming back from a race, initialize the race data to defaults. */ if ( g_game.prev_mode != GAME_OVER ) { /* Make sure we don't play previously loaded course */ cup_complete = False; /* Initialize the race data */ cur_elem = get_list_head( race_list ); if ( g_game.practicing ) { g_game.race.course = NULL; g_game.race.name = NULL; g_game.race.description = NULL; for (i=0; i<DIFFICULTY_NUM_LEVELS; i++) { g_game.race.herring_req[i] = 0; g_game.race.time_req[i] = 0; g_game.race.score_req[i] = 0; } g_game.race.mirrored = False; g_game.race.conditions = RACE_CONDITIONS_SUNNY; g_game.race.windy = False; g_game.race.snowing = False; } else { /* Not practicing */ race_data_t *data; data = (race_data_t*) get_list_elem_data( cur_elem ); g_game.race = *data; if ( is_cup_complete( event_data, get_event_cup_by_name( event_data, g_game.current_cup ) ) ) { cup_complete = True; last_completed_race = get_list_tail( race_list ); } else { cup_complete = False; last_completed_race = NULL; } } } else { /* Back from a race */ if ( !g_game.race_aborted ) { update_race_results(); } } back_btn = button_create( dummy_pos, 150, 40, "button_label", Localize("Back","") ); button_set_hilit_font_binding( back_btn, "button_label_hilit" ); button_set_visible( back_btn, True ); button_set_click_event_cb( back_btn, back_click_cb, NULL ); start_btn = button_create( dummy_pos, 150, 40, "button_label", Localize("Race!","") ); button_set_hilit_font_binding( start_btn, "button_label_hilit" ); button_set_disabled_font_binding( start_btn, "button_label_disabled" ); button_set_visible( start_btn, True ); button_set_click_event_cb( start_btn, start_click_cb, NULL ); #ifdef __APPLE__ race_listbox = listbox_create( dummy_pos, 300, 44, "course_name_label", race_list, conv_func ); #else race_listbox = listbox_create( dummy_pos, 460, 44, "listbox_item", race_list, conv_func ); #endif listbox_set_current_item( race_listbox, cur_elem ); listbox_set_item_change_event_cb( race_listbox, race_listbox_item_change_cb, NULL ); listbox_set_visible( race_listbox, True ); /* * Create text area */ #ifdef __APPLE__ desc_ta = textarea_create( dummy_pos, 170, 147, "race_description", "" ); #else desc_ta = textarea_create( dummy_pos, 312, 107, "race_description", "" ); #endif if ( g_game.practicing ) { open_course_data_t *data; data = (open_course_data_t*) get_list_elem_data( cur_elem ); textarea_set_text( desc_ta, data->description ); } else { race_data_t *data; data = (race_data_t*) get_list_elem_data( cur_elem ); textarea_set_text( desc_ta, data->description ); } textarea_set_visible( desc_ta, True ); /* * Create state buttons - only if practicing or if cup_complete */ if ( g_game.practicing || cup_complete ) { /* mirror */ mirror_ssbtn = ssbutton_create( dummy_pos, 32, 32, 2 ); ssbutton_set_state_image( mirror_ssbtn, 0, "mirror_button", make_point2d( 0.0/64.0, 32.0/64.0 ), make_point2d( 32.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state_image( mirror_ssbtn, 1, "mirror_button", make_point2d( 32.0/64.0, 32.0/64.0 ), make_point2d( 64.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state( mirror_ssbtn, (int)g_game.race.mirrored ); #ifdef __APPLE__ ssbutton_set_visible( mirror_ssbtn, False ); #else ssbutton_set_visible( mirror_ssbtn, True ); #endif /* conditions */ conditions_ssbtn = ssbutton_create( dummy_pos, 32, 32, 4 ); float border = 2.0; ssbutton_set_state_image( conditions_ssbtn, 0, "conditions_button", make_point2d( (0.0 + border)/64.0, (32.0 + border)/64.0 ), make_point2d( (32.0 - border)/64.0, (64.0 - border)/64.0 ), white ); ssbutton_set_state_image( conditions_ssbtn, 1, "conditions_button", make_point2d( (32.0 + border)/64.0, (0.0 + border)/64.0 ), make_point2d( (64.0 - border)/64.0, (32.0 - border)/64.0 ), white ); ssbutton_set_state_image( conditions_ssbtn, 2, "conditions_button", make_point2d( (32.0 + border)/64.0, (32.0 + border)/64.0 ), make_point2d( (64.0 - border)/64.0, (64.0 - border)/64.0 ), white ); ssbutton_set_state_image( conditions_ssbtn, 3, "conditions_button", make_point2d( (0.0 + border)/64.0, (0.0 + border)/64.0 ), make_point2d( (32.0 - border)/64.0, (32.0 - border)/64.0 ), white ); ssbutton_set_state( conditions_ssbtn, (int)g_game.race.conditions ); ssbutton_set_visible( conditions_ssbtn, True ); #ifdef __APPLE__ ssbutton_set_visible( conditions_ssbtn, False ); #else ssbutton_set_visible( conditions_ssbtn, True ); #endif /* wind */ wind_ssbtn = ssbutton_create( dummy_pos, 32, 32, 2 ); ssbutton_set_state_image( wind_ssbtn, 0, "wind_button", make_point2d( 0.0/64.0, 32.0/64.0 ), make_point2d( 32.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state_image( wind_ssbtn, 1, "wind_button", make_point2d( 32.0/64.0, 32.0/64.0 ), make_point2d( 64.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state( wind_ssbtn, (int)g_game.race.windy ); #ifdef __APPLE__ ssbutton_set_visible( wind_ssbtn, False ); #else ssbutton_set_visible( wind_ssbtn, True ); #endif /* snow */ snow_ssbtn = ssbutton_create( dummy_pos, 32, 32, 2 ); ssbutton_set_state_image( snow_ssbtn, 0, "snow_button", make_point2d( 0.0/64.0, 32.0/64.0 ), make_point2d( 32.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state_image( snow_ssbtn, 1, "snow_button", make_point2d( 32.0/64.0, 32.0/64.0 ), make_point2d( 64.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state( snow_ssbtn, (int)g_game.race.snowing ); #ifdef __APPLE__ ssbutton_set_visible( snow_ssbtn, False ); #else ssbutton_set_visible( snow_ssbtn, True ); #endif /* XXX snow button doesn't do anything, so disable for now */ ssbutton_set_enabled( snow_ssbtn, False ); /* Can't change conditions if in cup mode */ if ( !g_game.practicing ) { ssbutton_set_enabled( conditions_ssbtn, False ); ssbutton_set_enabled( wind_ssbtn, False ); ssbutton_set_enabled( snow_ssbtn, False ); ssbutton_set_enabled( mirror_ssbtn, False ); } } else { conditions_ssbtn = NULL; wind_ssbtn = NULL; snow_ssbtn = NULL; mirror_ssbtn = NULL; } update_race_data(); update_button_enabled_states(); play_music( "start_screen" ); }
void calc_normals(const char *course) { scalar_t *elevation; scalar_t courseWidth, courseLength; int nx, ny; int x,y; point_t p0, p1, p2; vector_t n, nml, v1, v2; char buff[BUFF_LEN]; sprintf( buff, "%s/courses/%s/normal.data", getparam_data_dir(), course ); get_course_dimensions( &courseWidth, &courseLength ); get_course_divisions( &nx, &ny ); if(nmls != (void*)-1 && nmls_fd != -1) { munmap(nmls, nmls_len); close(nmls_fd); } #if 0 else { free(nmls); } #endif struct stat buf; int exists = (stat(buff, &buf) == 0); if(exists) { nmls_fd = open(buff, O_RDONLY); if ( nmls_fd == -1) { handle_system_error( 1, "can't open file failed" ); } TRDebugLog("mapping to memory normal.data\n"); nmls_len = sizeof(vector_t)*nx*ny; nmls = mmap(NULL, nmls_len, PROT_READ, MAP_SHARED,nmls_fd, 0); if ( nmls == (void *)-1 ) { handle_system_error( 1, "read mmap failed" ); } } else { nmls_len = sizeof(vector_t)*nx*ny; #if TARGET_IPHONE_SIMULATOR nmls_fd = open(buff, O_RDWR | O_CREAT | O_TRUNC, 0644); if ( nmls_fd == -1) { handle_system_error( 1, "can't open file failed" ); } int result = lseek(nmls_fd, nmls_len-1, SEEK_SET); if (result == -1) { handle_system_error( 1, "can't write file failed" ); } result = write(nmls_fd, "", 1); if (result != 1) { handle_system_error( 1, "can't write file failed" ); } nmls = mmap(NULL, nmls_len, PROT_READ | PROT_WRITE, MAP_SHARED, nmls_fd, 0); if ( nmls == (void *)-1 ) { handle_system_error( 1, "write mmap failed" ); } TRDebugLog("Writing to normal.data\n"); #else # ifdef TR_DEBUG_MODE abort(); // This shouldn't be reached on simulator. Crash to indicate. # endif nmls = malloc(nmls_len); #endif elevation = get_course_elev_data(); for ( y=0; y<ny; y++) { for ( x=0; x<nx; x++) { nml = make_vector( 0., 0., 0. ); p0 = make_point( XCD(x), ELEV(x,y), ZCD(y) ); /* The terrain is meshed as follows: ... +-+-+-+-+ x<---+ |\|/|\|/| | ...+-+-+-+-+... V |/|\|/|\| y +-+-+-+-+ ... So there are two types of vertices: those surrounded by four triangles (x+y is odd), and those surrounded by eight (x+y is even). */ #define POINT(x,y) make_point( XCD(x), ELEV(x,y), ZCD(y) ) if ( (x + y) % 2 == 0 ) { if ( x > 0 && y > 0 ) { p1 = POINT(x, y-1); p2 = POINT(x-1,y-1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); p1 = POINT(x-1,y-1); p2 = POINT(x-1,y ); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x > 0 && y < ny-1 ) { p1 = POINT(x-1,y ); p2 = POINT(x-1,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); p1 = POINT(x-1,y+1); p2 = POINT(x ,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x < nx-1 && y > 0 ) { p1 = POINT(x+1,y ); p2 = POINT(x+1,y-1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); p1 = POINT(x+1,y-1); p2 = POINT(x ,y-1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x < nx-1 && y < ny-1 ) { p1 = POINT(x+1,y ); p2 = POINT(x+1,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v1, v2 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); p1 = POINT(x+1,y+1); p2 = POINT(x ,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v1, v2 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } } else { /* x + y is odd */ if ( x > 0 && y > 0 ) { p1 = POINT(x, y-1); p2 = POINT(x-1,y ); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x > 0 && y < ny-1 ) { p1 = POINT(x-1,y ); p2 = POINT(x ,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x < nx-1 && y > 0 ) { p1 = POINT(x+1,y ); p2 = POINT(x ,y-1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v2, v1 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } if ( x < nx-1 && y < ny-1 ) { p1 = POINT(x+1,y ); p2 = POINT(x ,y+1); v1 = subtract_points( p1, p0 ); v2 = subtract_points( p2, p0 ); n = cross_product( v1, v2 ); check_assertion( n.y > 0, "course normal points down" ); normalize_vector( &n ); nml = add_vectors( nml, n ); } } normalize_vector( &nml ); NORMAL(x,y) = nml; continue; } #undef POINT } #if TARGET_IPHONE_SIMULATOR munmap(nmls, nmls_len); close(nmls_fd); nmls_fd = open(buff, O_RDONLY); if (nmls_fd == -1) { handle_system_error( 1, "can't remount normal.data" ); } TRDebugLog("remounting to memory normal.data\n"); nmls_len = sizeof(vector_t)*nx*ny; nmls = mmap(NULL, nmls_len, PROT_READ, MAP_SHARED, nmls_fd, 0); if ( nmls == (void *)-1 ) { handle_system_error( 1, "remount mmap failed" ); } #endif } }
/*! Returns the visibility status of the specified listbox \return True iff listbox is visible \author jfpatry \date Created: 2000-09-17 \date Modified: 2000-09-17 */ bool_t listbox_is_visible( listbox_t *listbox ) { check_assertion( listbox != NULL, "listbox is NULL" ); return listbox->visible; }
/*! Returns the active state of the listbox \return Active state of listbox \author jfpatry \date Created: 2000-09-18 \date Modified: 2000-09-18 */ bool_t listbox_is_active( listbox_t *listbox ) { check_assertion( listbox != NULL, "listbox is NULL" ); return listbox->active; }
/*! Returns the width of the listbox \return The width of the listbox \author jfpatry \date Created: 2000-09-17 \date Modified: 2000-09-17 */ scalar_t listbox_get_width( listbox_t *listbox ) { check_assertion( listbox != NULL, "listbox is NULL" ); return listbox->w; }
/*! Returns the height of the listbox \return The height of the listbox \author jfpatry \date Created: 2000-09-17 \date Modified: 2000-09-17 */ scalar_t listbox_get_height( listbox_t *listbox ) { check_assertion( listbox != NULL, "listbox is NULL" ); return listbox->h; }
/*! Returns the listbox's current item \return The currently selected listbox item \author jfpatry \date Created: 2000-09-17 \date Modified: 2000-09-17 */ list_elem_t listbox_get_current_item( listbox_t *listbox ) { check_assertion( listbox != NULL, "listbox is NULL" ); return listbox->cur_item; }
/*! Creates a new listbox \return The new listbox object \author jfpatry \date Created: 2000-09-17 \date Modified: 2000-09-17 */ listbox_t* listbox_create( point2d_t pos, scalar_t w, scalar_t h, char *font_binding, list_t item_list, listbox_list_elem_to_string_fptr_t func ) { listbox_t *listbox; char *binding; point2d_t ll; point2d_t ur; listbox = (listbox_t*)malloc( sizeof(listbox_t) ); check_assertion( listbox != NULL, "out of memory" ); listbox->pos = pos; listbox->w = w; listbox->h = h; listbox->arrow_width = DEFAULT_ARROW_REGION_WIDTH; listbox->border_width = DEFAULT_BORDER_WIDTH; listbox->text_pad = DEFAULT_TEXT_PAD; listbox->arrow_vert_separation = DEFAULT_ARROW_VERT_SEPARATION; listbox->font_binding = font_binding; listbox->border_colour = ui_foreground_colour; listbox->background_colour = ui_background_colour; /* Create up arrow button */ listbox->up_button = button_create( make_point2d( 0, 0 ), /* position will be set later */ DEFAULT_ARROW_BUTTON_WIDTH, (mWidth>320)?DEFAULT_ARROW_BUTTON_HEIGHT:DEFAULT_ARROW_BUTTON_HEIGHT/2, NULL, NULL ); binding = "listbox_arrows"; ll = make_point2d( 0.0/64.0, 16.0/64.0 ); ur = make_point2d( 32.0/64.0, 32.0/64.0 ); button_set_image( listbox->up_button, binding, ll, ur, white ); ll = make_point2d( 32.0/64.0, 16.0/64.0 ); ur = make_point2d( 64.0/64.0, 32.0/64.0 ); button_set_disabled_image( listbox->up_button, binding, ll, ur, white ); ll = make_point2d( 32.0/64.0, 48.0/64.0 ); ur = make_point2d( 64.0/64.0, 64.0/64.0 ); button_set_hilit_image( listbox->up_button, binding, ll, ur, white ); ll = make_point2d( 0.0/64.0, 48.0/64.0 ); ur = make_point2d( 32.0/64.0, 64.0/64.0 ); button_set_clicked_image( listbox->up_button, binding, ll, ur, white ); button_set_click_event_cb( listbox->up_button, listbox_arrow_click_cb, listbox ); /* Create down arrow button */ listbox->down_button = button_create( make_point2d( 0, 0 ), /* position will be set later */ DEFAULT_ARROW_BUTTON_WIDTH, (mWidth>320)?DEFAULT_ARROW_BUTTON_HEIGHT:DEFAULT_ARROW_BUTTON_HEIGHT/2, NULL, NULL ); binding = "listbox_arrows"; ll = make_point2d( 0.0/64.0, 0.0/64.0 ); ur = make_point2d( 32.0/64.0, 16.0/64.0 ); button_set_image( listbox->down_button, binding, ll, ur, white ); ll = make_point2d( 32.0/64.0, 0.0/64.0 ); ur = make_point2d( 64.0/64.0, 16.0/64.0 ); button_set_disabled_image( listbox->down_button, binding, ll, ur, white ); ll = make_point2d( 32.0/64.0, 32.0/64.0 ); ur = make_point2d( 64.0/64.0, 48.0/64.0 ); button_set_hilit_image( listbox->down_button, binding, ll, ur, white ); ll = make_point2d( 0.0/64.0, 32.0/64.0 ); ur = make_point2d( 32.0/64.0, 48.0/64.0 ); button_set_clicked_image( listbox->down_button, binding, ll, ur, white ); button_set_click_event_cb( listbox->down_button, listbox_arrow_click_cb, listbox ); button_set_click_event_cb( listbox->down_button, listbox_arrow_click_cb, listbox ); listbox->item_change_cb = NULL; listbox->item_change_cb_userdata = NULL; listbox->item_list = item_list; listbox->cur_item = get_list_head( listbox->item_list ); listbox->label_gen_func = func; listbox->visible = False; listbox->active = False; update_button_enabled_states( listbox ); update_button_positions( listbox ); return listbox; }
/*! Callback to draws the listbox \return None \author jfpatry \date Created: 2000-09-17 \date Modified: 2000-09-17 */ static void listbox_draw_cb( void *widget ) { check_assertion( widget != NULL, "widget is NULL" ); listbox_draw( (listbox_t*) widget ); }
/*! Creates a race_data_t object from a Tcl string. \return New race_data_t object if successful, or NULL if error \author jfpatry \date Created: 2000-09-19 \date Modified: 2000-09-19 */ static race_data_t* create_race_data ( Tcl_Interp *ip, const char *string, char **err_msg ) { const char **argv = NULL; const char **orig_argv = NULL; int argc = 0; char *course = NULL; char *name = NULL; char *description = NULL; int herring_req[DIFFICULTY_NUM_LEVELS]; bool_t herring_req_init = False; scalar_t time_req[DIFFICULTY_NUM_LEVELS]; bool_t time_req_init = False; int score_req[DIFFICULTY_NUM_LEVELS]; bool_t score_req_init = False; bool_t mirrored = False; race_conditions_t conditions = RACE_CONDITIONS_SUNNY; bool_t windy = False; bool_t snowing = False; race_data_t *race_data = NULL; if ( Tcl_SplitList( ip, string, &argc, &argv ) == TCL_ERROR ) { *err_msg = "race data is not a list"; goto bail_race_data; } orig_argv = argv; while ( *argv != NULL ) { if ( strcmp( *argv, "-course" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -course in race data"; goto bail_race_data; } course = string_copy( *argv ); } else if ( strcmp( *argv, "-name" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -name in race data"; goto bail_race_data; } name = string_copy( *argv ); } else if ( strcmp( *argv, "-description" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -description in race data"; goto bail_race_data; } description = string_copy( *argv ); } else if ( strcmp( *argv, "-herring" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -herring in race data"; goto bail_race_data; } if ( get_tcl_int_tuple( ip, *argv, herring_req, sizeof(herring_req)/sizeof(herring_req[0]) ) == TCL_ERROR ) { *err_msg = "Value for -herring is not a list or has " "the wrong number of elements"; goto bail_race_data; } herring_req_init = True; } else if ( strcmp( *argv, "-time" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -time in race data" ; goto bail_race_data; } if ( get_tcl_tuple( ip, *argv, time_req, sizeof(time_req)/sizeof(time_req[0]) ) == TCL_ERROR ) { *err_msg = "Value for -time is not a list or hsa the " "wrong number of elements"; goto bail_race_data; } time_req_init = True; } else if ( strcmp( *argv, "-score" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -score in race data"; goto bail_race_data; } if ( get_tcl_int_tuple( ip, *argv, score_req, sizeof(score_req)/sizeof(score_req[0]) ) == TCL_ERROR ) { *err_msg = "Value for -score is not a list or has the " "wrong number of elements"; goto bail_race_data; } score_req_init = True; } else if ( strcmp( *argv, "-mirrored" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -mirrored in race data"; goto bail_race_data; } if ( string_cmp_no_case( *argv, "yes" ) == 0 ) { mirrored = True; } else { mirrored = False; } } else if ( strcmp( *argv, "-conditions" ) == 0 ) { int i; NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -conditions in race data"; goto bail_race_data; } for ( i=0; i<RACE_CONDITIONS_NUM_CONDITIONS; i++ ) { if ( string_cmp_no_case( race_condition_names[i], *argv ) == 0 ) { break; } } if ( i == RACE_CONDITIONS_NUM_CONDITIONS ) { *err_msg = "Invalid value for -conditions in race data"; goto bail_race_data; } conditions = (race_conditions_t)i; } else if ( strcmp( *argv, "-windy" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -windy in race data"; goto bail_race_data; } if ( string_cmp_no_case( *argv, "yes" ) == 0 ) { windy = True; } else { windy = False; } } else if ( strcmp( *argv, "-snowing" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -snowing in race data"; goto bail_race_data; } if ( string_cmp_no_case( *argv, "yes" ) == 0 ) { snowing = True; } else { snowing = False; } } else { sprintf( err_buff, "unrecognized option `%s' in race data", *argv ); *err_msg = err_buff; goto bail_race_data; } NEXT_ARG; } /* Check mandatory arguments */ if ( course == NULL ) { *err_msg = "No course specified in race data"; goto bail_race_data; } if ( !herring_req_init || !time_req_init || !score_req_init ) { *err_msg = "Must specify requirement for herring, time, and score."; goto bail_race_data; } /* Create new race_data_t object */ race_data = (race_data_t*) malloc( sizeof(race_data_t) ); check_assertion( race_data != NULL, "out of memory" ); race_data->course = course; race_data->name = name; race_data->description = description; memcpy( race_data->herring_req, herring_req, sizeof(herring_req) ); memcpy( race_data->time_req, time_req, sizeof(time_req) ); memcpy( race_data->score_req, score_req, sizeof(score_req) ); race_data->mirrored = mirrored; race_data->conditions = conditions; race_data->windy = windy; race_data->snowing = snowing; Tcl_Free( (char*) orig_argv ); return race_data; bail_race_data: if ( orig_argv ) { Tcl_Free( (char*) orig_argv ); } if ( course ) { free( course ); } if ( name ) { free( name ); } if ( description ) { free( description ); } if ( race_data ) { free( race_data ); } return NULL; }
path_searcht::resultt path_searcht::operator()( const goto_functionst &goto_functions) { locst locs(ns); var_mapt var_map(ns); locs.build(goto_functions); // this is the container for the history-forest path_symex_historyt history; queue.push_back(initial_state(var_map, locs, history)); // set up the statistics number_of_dropped_states=0; number_of_paths=0; number_of_VCCs=0; number_of_steps=0; number_of_feasible_paths=0; number_of_infeasible_paths=0; number_of_VCCs_after_simplification=0; number_of_failed_properties=0; number_of_locs=locs.size(); // stop the time start_time=current_time(); initialize_property_map(goto_functions); while(!queue.empty()) { number_of_steps++; // Pick a state from the queue, // according to some heuristic. // The state moves to the head of the queue. pick_state(); // move into temporary queue queuet tmp_queue; tmp_queue.splice( tmp_queue.begin(), queue, queue.begin(), ++queue.begin()); try { statet &state=tmp_queue.front(); // record we have seen it loc_data[state.get_pc().loc_number].visited=true; debug() << "Loc: #" << state.get_pc().loc_number << ", queue: " << queue.size() << ", depth: " << state.get_depth(); for(const auto & s : queue) debug() << ' ' << s.get_depth(); debug() << eom; if(drop_state(state)) { number_of_dropped_states++; number_of_paths++; continue; } if(!state.is_executable()) { number_of_paths++; continue; } if(eager_infeasibility && state.last_was_branch() && !is_feasible(state)) { number_of_infeasible_paths++; number_of_paths++; continue; } if(number_of_steps%1000==0) { status() << "Queue " << queue.size() << " thread " << state.get_current_thread() << '/' << state.threads.size() << " PC " << state.pc() << messaget::eom; } // an error, possibly? if(state.get_instruction()->is_assert()) { if(show_vcc) do_show_vcc(state); else { check_assertion(state); // all assertions failed? if(number_of_failed_properties==property_map.size()) break; } } // execute path_symex(state, tmp_queue); // put at head of main queue queue.splice(queue.begin(), tmp_queue); } catch(const std::string &e) { error() << e << eom; number_of_dropped_states++; } catch(const char *e) { error() << e << eom; number_of_dropped_states++; } catch(int) { number_of_dropped_states++; } } report_statistics(); return number_of_failed_properties==0?SAFE:UNSAFE; }
/*! Creates a cup_data_t object from a Tcl string. \return New cup_data_t object if successful, or NULL if error \author jfpatry \date Created: 2000-09-19 \date Modified: 2000-09-19 */ static cup_data_t* create_cup_data( Tcl_Interp *ip, const char *string, char **err_msg ) { const char **argv = NULL; const char **orig_argv = NULL; int argc = 0; char *name = NULL; char *icon = NULL; list_t race_list = NULL; list_elem_t last_race = NULL; const char **races = NULL; int num_races = 0; int i; cup_data_t *cup_data = NULL; if ( Tcl_SplitList( ip, string, &argc, &argv ) == TCL_ERROR ) { *err_msg = "cup data is not a list"; goto bail_cup_data; } orig_argv = argv; while ( *argv != NULL ) { if ( strcmp( *argv, "-name" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -name in cup data"; goto bail_cup_data; } name = string_copy( *argv ); } else if ( strcmp( *argv, "-icon" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -icon in cup data"; goto bail_cup_data; } icon = string_copy( *argv ); } else if ( strcmp( *argv, "-races" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg= "No data supplied for -races in cup data"; goto bail_cup_data; } race_list = create_list(); last_race = NULL; if ( Tcl_SplitList( ip, *argv, &num_races, &races ) == TCL_ERROR ) { *err_msg = "Race data is not a list in event data"; goto bail_cup_data; } for ( i=0; i<num_races; i++) { race_data_t *race_data; race_data = create_race_data( ip, races[i], err_msg ); if ( race_data == NULL ) { goto bail_cup_data; } last_race = insert_list_elem( race_list, last_race, (list_elem_data_t) race_data ); } Tcl_Free( (char*) races ); races = NULL; } else { sprintf( err_buff, "Unrecognized argument `%s'", *argv ); *err_msg = err_buff; goto bail_cup_data; } NEXT_ARG; } /* Make sure mandatory fields have been specified */ if ( name == NULL ) { *err_msg = "Must specify a name in cup data"; goto bail_cup_data; } if ( icon == NULL ) { *err_msg = "Must specify an icon texture in cup data"; goto bail_cup_data; } if ( race_list == NULL ) { *err_msg = "Must specify a race list in cup data"; goto bail_cup_data; } /* Create a new cup data object */ cup_data = (cup_data_t*) malloc( sizeof( cup_data_t ) ); check_assertion( cup_data != NULL, "out of memory" ); cup_data->name = name; cup_data->race_list = race_list; bind_texture( name, icon ); Tcl_Free( (char*) orig_argv ); argv = NULL; free( icon ); return cup_data; bail_cup_data: if ( orig_argv ) { Tcl_Free( (char*) orig_argv ); } if ( name ) { free( name ); } if ( icon ) { free( icon ); } if ( races ) { Tcl_Free( (char*) races ); } /* Clean out race list */ if ( race_list ) { last_race = get_list_tail( race_list ); while ( last_race != NULL ) { race_data_t *data; data = (race_data_t*) delete_list_elem( race_list, last_race ); free( data ); last_race = get_list_tail( race_list ); } del_list( race_list ); } if ( cup_data ) { free( cup_data ); } return NULL; }
float quadsquare::RecomputeError(const quadcornerdata& cd) // Recomputes the error values for this tree. Returns the // max error. // Also updates MinY & MaxY. { int i; int j; int t; int half = 1 << cd.Level; int whole = half << 1; float terrain_error; // Measure error of center and edge vertices. float maxerror = 0; // Compute error of center vert. float e; if (cd.ChildIndex & 1) { e = fabs(Vertex[0].Y - (cd.Verts[1].Y + cd.Verts[3].Y) * 0.5); } else { e = fabs(Vertex[0].Y - (cd.Verts[0].Y + cd.Verts[2].Y) * 0.5); } if (e > maxerror) maxerror = e; // Initial min/max. MaxY = Vertex[0].Y; MinY = Vertex[0].Y; // Check min/max of corners. for (i = 0; i < 4; i++) { float y = cd.Verts[i].Y; if (y < MinY) MinY = y; if (y > MaxY) MaxY = y; } // Edge verts. e = fabs(Vertex[1].Y - (cd.Verts[0].Y + cd.Verts[3].Y) * 0.5); if (e > maxerror) maxerror = e; Error[0] = e; e = fabs(Vertex[4].Y - (cd.Verts[2].Y + cd.Verts[3].Y) * 0.5); if (e > maxerror) maxerror = e; Error[1] = e; // Terrain edge checks if ( cd.Level == 0 && cd.xorg <= RowSize-1 && cd.zorg <= NumRows-1 ) { // Check South vertex int x = cd.xorg + half; int z = cd.zorg + whole; int idx = x + z * RowSize; bool different_terrains = false; terrain_error = 0.f; check_assertion( x >= 0, "x coordinate is negative" ); check_assertion( z >= 0, "z coordinate is negative" ); if ( x < RowSize && z < NumRows ) { if ( x < RowSize - 1 ) { if ( Terrain[idx] != Terrain[idx+1] ) { different_terrains = true; } } if ( z >= 1 ) { idx -= RowSize; if ( Terrain[idx] != Terrain[idx+1] ) { different_terrains = true; } } if ( different_terrains ) { ForceSouthVert = true; terrain_error = TERRAIN_ERROR_SCALE * whole * whole; } else { ForceSouthVert = false; } if ( terrain_error > Error[0] ) { Error[0] = terrain_error; } if ( Error[0] > maxerror ) { maxerror = Error[0]; } } // Check East vertex x = cd.xorg + whole; z = cd.zorg + half; idx = x + z * RowSize; terrain_error = 0; different_terrains = false; if ( x < RowSize && z < NumRows ) { if ( z >= 1 ) { if ( Terrain[idx] != Terrain[idx-RowSize] ) { different_terrains = true; } } if ( z >= 1 && x < RowSize - 1 ) { idx += 1; if ( Terrain[idx] != Terrain[idx-RowSize] ) { different_terrains = true; } } if ( different_terrains ) { ForceEastVert = true; terrain_error = TERRAIN_ERROR_SCALE * whole * whole; } else { ForceEastVert = false; } if ( terrain_error > Error[1] ) { Error[1] = terrain_error; } if ( Error[1] > maxerror ) { maxerror = Error[1]; } } } // Min/max of edge verts. for (i = 0; i < 4; i++) { float y = Vertex[1 + i].Y; if (y < MinY) MinY = y; if (y > MaxY) MaxY = y; } // Check child squares. for (i = 0; i < 4; i++) { quadcornerdata q; if (Child[i]) { SetupCornerData(&q, cd, i); Error[i+2] = Child[i]->RecomputeError(q); if (Child[i]->MinY < MinY) MinY = Child[i]->MinY; if (Child[i]->MaxY > MaxY) MaxY = Child[i]->MaxY; } else { // Compute difference between bilinear average at child center, and diagonal edge approximation. Error[i+2] = fabs((Vertex[0].Y + cd.Verts[i].Y) - (Vertex[i+1].Y + Vertex[((i+1)&3) + 1].Y)) * 0.25; } if (Error[i+2] > maxerror) maxerror = Error[i+2]; } // // Compute terrain_error // int terrain; int *terrain_count = new int[(int)NumTerrains]; for (t=0; t<NumTerrains; t++) { terrain_count[t] = 0; } for (i=cd.xorg; i<=cd.xorg+whole; i++) { for (j=cd.zorg; j<=cd.zorg+whole; j++) { if ( i < 0 || i >= RowSize || j < 0 || j >= NumRows ) { continue; } terrain = (int) Terrain[ i + RowSize*j ]; check_assertion( terrain >= 0 && terrain < NumTerrains, "Invalid terrain type" ); terrain_count[ terrain ] += 1; } } int max_count = 0; int max_type = 0; int total = 0; for (t=0; t<NumTerrains; t++) { if ( terrain_count[t] > max_count ) { max_count = terrain_count[t]; max_type = t; } total += terrain_count[t]; } delete [] terrain_count; /* Calculate a terrain error that varies between 0 and 1 */ if ( total > 0 ) { terrain_error = (1.0 - max_count / total); if ( NumTerrains > 1 ) { terrain_error *= NumTerrains / ( NumTerrains - 1.0 ); } } else { terrain_error = 0; } /* and scale it by the square area */ terrain_error *= whole * whole; /* and finally scale it so that it's comparable to height error */ terrain_error *= TERRAIN_ERROR_SCALE; if ( terrain_error > maxerror ) { maxerror = terrain_error; } if ( terrain_error > Error[0] ) { Error[0] = terrain_error; } if ( terrain_error > Error[1] ) { Error[1] = terrain_error; } // The error and MinY/MaxY values for this node and descendants are correct now. Dirty = false; return maxerror; }
/*! Sets the widget positions and draws other on-screen goo \author jfpatry \date Created: 2000-09-24 \date Modified: 2000-09-24 */ static void set_widget_positions_and_draw_decorations() { int w = getparam_x_resolution(); int h = getparam_y_resolution(); int box_width, box_height, box_max_y; int x_org, y_org; char *string; font_t *font; char *current_course; int text_width, asc, desc; GLuint texobj; /* set the dimensions of the box in which all widgets should fit */ #ifdef __APPLE__ box_width = w; box_height = 200 * mHeight / 320; box_max_y = h - 128 * mHeight / 320; x_org = 10 * mHeight / 320; y_org = box_height/2 * mHeight / 320; if ( y_org + box_height > box_max_y ) { y_org = box_max_y - box_height + 50 * mHeight / 320; } button_set_position( back_btn, make_point2d( 0, 0 ) ); button_set_position( start_btn, make_point2d( box_width - button_get_width( start_btn ), 0 ) ); listbox_set_position( race_listbox, make_point2d( 160 * mHeight / 320, box_height/2.0+40 * mHeight / 320 ) ); #ifdef __APPLE__ textarea_set_position( desc_ta, make_point2d( 1000, 1000 ) ); #else textarea_set_position( desc_ta, make_point2d( x_org, y_org + 66 * mHeight / 320 ) ); #endif if ( g_game.practicing || ( cup_complete && conditions_ssbtn && wind_ssbtn && snow_ssbtn && mirror_ssbtn ) ) { ssbutton_set_position( conditions_ssbtn, make_point2d( x_org + box_width - 4*36 + 4, y_org + 151 ) ); ssbutton_set_position( wind_ssbtn, make_point2d( x_org + box_width - 3*36 + 4 , y_org + 151 ) ); ssbutton_set_position( snow_ssbtn, make_point2d( x_org + box_width - 2*36 + 4, y_org + 151 ) ); ssbutton_set_position( mirror_ssbtn, make_point2d( x_org + box_width - 1*36 + 4, y_org + 151 ) ); #else box_width = 460; box_height = 310; box_max_y = h - 128; x_org = w/2 - box_width/2; y_org = h/2 - box_height/2; if ( y_org + box_height > box_max_y ) { y_org = box_max_y - box_height; } button_set_position( back_btn, make_point2d( x_org + 131 - button_get_width( back_btn )/2.0, 42 ) ); button_set_position( start_btn, make_point2d( x_org + 343 - button_get_width( start_btn )/2.0, 42 ) ); listbox_set_position( race_listbox, make_point2d( x_org, y_org + 221 ) ); textarea_set_position( desc_ta, make_point2d( x_org, y_org + 66 ) ); if ( g_game.practicing || ( cup_complete && conditions_ssbtn && wind_ssbtn && snow_ssbtn && mirror_ssbtn ) ) { ssbutton_set_position( conditions_ssbtn, make_point2d( x_org + box_width - 4*36 + 4, y_org + 181 ) ); ssbutton_set_position( wind_ssbtn, make_point2d( x_org + box_width - 3*36 + 4 , y_org + 181 ) ); ssbutton_set_position( snow_ssbtn, make_point2d( x_org + box_width - 2*36 + 4, y_org + 181 ) ); ssbutton_set_position( mirror_ssbtn, make_point2d( x_org + box_width - 1*36 + 4, y_org + 181 ) ); #endif } else { /* Draw tux life icons */ GLuint texobj; int i; glPushMatrix(); { #ifdef __APPLE__ glTranslatef( 10 * mHeight / 320, 60 * mHeight / 320, 0 ); #else glTranslatef( x_org + box_width - 4*36 + 4, y_org + 181, 0 ); #endif check_assertion( INIT_NUM_LIVES == 4, "Assumption about number of lives invalid -- " "need to recode this part" ); if ( !get_texture_binding( "tux_life", &texobj ) ) { texobj = 0; } glBindTexture( GL_TEXTURE_2D, texobj ); for ( i=0; i<4; i++ ) { point2d_t ll, ur; if ( plyr->lives > i ) { ll = make_point2d( 0, 0.5 ); ur = make_point2d( 1, 1 ); } else { ll = make_point2d( 0, 0 ); ur = make_point2d( 1, 0.5 ); } glBegin( GL_QUADS ); { glTexCoord2f( ll.x, ll.y ); glVertex2f( 0, 0 ); glTexCoord2f( ur.x, ll.y ); glVertex2f( 32 * mHeight / 320, 0 ); glTexCoord2f( ur.x, ur.y ); glVertex2f( 32 * mHeight / 320, 32 * mHeight / 320 ); glTexCoord2f( ll.x, ur.y ); glVertex2f( 0, 32 * mHeight / 320 ); } glEnd(); glTranslatef( 36 * mHeight / 320, 0, 0 ); } } glPopMatrix(); } #ifndef __APPLE__ // We don't care about that stuff /* Draw other stuff */ if ( !get_font_binding( "menu_label", &font ) ) { print_warning( IMPORTANT_WARNING, "Couldn't get font for binding menu_label" ); } else { bind_font_texture( font ); string = "Select a race"; get_font_metrics( font, string, &text_width, &asc, &desc ); glPushMatrix(); { glTranslatef( x_org + box_width/2.0 - text_width/2.0, y_org + 310 - asc, 0 ); draw_string( font, string ); } glPopMatrix(); } /* Draw text indicating race requirements (if race not completed), or results in race if race completed. */ draw_status_msg( x_org, y_org, box_width, box_height ); #else /* Draw text indicating race requirements (if race not completed), or results in race if race completed. */ draw_status_msg( x_org, y_org, box_width, box_height ); #endif /* Draw preview */ if ( g_game.practicing ) { list_elem_t elem; open_course_data_t *data; elem = listbox_get_current_item( race_listbox ); data = (open_course_data_t*) get_list_elem_data( elem ); current_course = data->course; } else { list_elem_t elem; race_data_t *data; elem = listbox_get_current_item( race_listbox ); data = (race_data_t*) get_list_elem_data( elem ); current_course = data->course; } glDisable( GL_TEXTURE_2D ); glColor4f( 0.0, 0.0, 0.0, 0.3 ); #ifdef __APPLE__ float margin = 4.f * mHeight / 320; float yoffset = 26 * mHeight / 320 + 30 * mHeight / 320; glBegin( GL_QUADS ); { glVertex2f( x_org, y_org + yoffset ); glVertex2f( x_org + 140 * mHeight / 320, y_org + yoffset ); glVertex2f( x_org + 140 * mHeight / 320, y_org + yoffset+107 * mHeight / 320 ); glVertex2f( x_org, y_org + yoffset+107 * mHeight / 320 ); } glEnd(); #else glBegin( GL_QUADS ); { glVertex2f( x_org+box_width-140, y_org+66 ); glVertex2f( x_org+box_width, y_org+66 ); glVertex2f( x_org+box_width, y_org+66+107 ); glVertex2f( x_org+box_width-140, y_org+66+107 ); } glEnd(); #endif glColor4f( 1.0, 1.0, 1.0, 1.0 ); glEnable( GL_TEXTURE_2D ); if ( !get_texture_binding( current_course, &texobj ) ) { if ( !get_texture_binding( "no_preview", &texobj ) ) { texobj = 0; } } glBindTexture( GL_TEXTURE_2D, texobj ); #ifdef __APPLE__ glBegin( GL_QUADS ); { glTexCoord2d( 0, 0); glVertex2f( x_org + margin, y_org + yoffset+margin ); glTexCoord2d( 1, 0); glVertex2f( x_org + 140 * mHeight / 320 - margin, y_org + yoffset+margin ); glTexCoord2d( 1, 1); glVertex2f( x_org + 140 * mHeight / 320 - margin, y_org + yoffset+margin+99 * mHeight / 320 ); glTexCoord2d( 0, 1); glVertex2f( x_org + margin, y_org + yoffset+margin+99 * mHeight / 320 ); } glEnd(); #else glBegin( GL_QUADS ); { glTexCoord2d( 0, 0); glVertex2f( x_org+box_width-136, y_org+70 ); glTexCoord2d( 1, 0); glVertex2f( x_org+box_width-4, y_org+70 ); glTexCoord2d( 1, 1); glVertex2f( x_org+box_width-4, y_org+70+99 ); glTexCoord2d( 0, 1); glVertex2f( x_org+box_width-136, y_org+70+99 ); } glEnd(); #endif } /*---------------------------------------------------------------------------*/ /*! Mode initialization function \author jfpatry \date Created: 2000-09-24 \date Modified: 2000-09-24 */ static void race_select_init(void) { listbox_list_elem_to_string_fptr_t conv_func = NULL; point2d_t dummy_pos = {0, 0}; int i; winsys_set_display_func( main_loop ); winsys_set_idle_func( main_loop ); winsys_set_reshape_func( reshape ); winsys_set_mouse_func( ui_event_mouse_func ); winsys_set_motion_func( ui_event_motion_func ); winsys_set_passive_motion_func( ui_event_motion_func ); plyr = get_player_data( local_player() ); /* Setup the race list */ if ( g_game.practicing ) { g_game.current_event = "__Practice_Event__"; g_game.current_cup = "__Practice_Cup__"; race_list = get_open_courses_list(); conv_func = get_name_from_open_course_data; cup_data = NULL; last_completed_race = NULL; event_data = NULL; } else { event_data = (event_data_t*) get_list_elem_data( get_event_by_name( g_game.current_event ) ); check_assertion( event_data != NULL, "Couldn't find current event." ); cup_data = (cup_data_t*) get_list_elem_data( get_event_cup_by_name( event_data, g_game.current_cup ) ); check_assertion( cup_data != NULL, "Couldn't find current cup." ); race_list = get_cup_race_list( cup_data ); conv_func = get_name_from_race_data; } /* Unless we're coming back from a race, initialize the race data to defaults. */ if ( g_game.prev_mode != GAME_OVER ) { /* Make sure we don't play previously loaded course */ cup_complete = False; /* Initialize the race data */ cur_elem = get_list_head( race_list ); if ( g_game.practicing ) { g_game.race.course = NULL; g_game.race.name = NULL; g_game.race.description = NULL; for (i=0; i<DIFFICULTY_NUM_LEVELS; i++) { g_game.race.herring_req[i] = 0; g_game.race.time_req[i] = 0; g_game.race.score_req[i] = 0; } g_game.race.mirrored = False; g_game.race.conditions = RACE_CONDITIONS_SUNNY; g_game.race.windy = False; g_game.race.snowing = False; } else { /* Not practicing */ race_data_t *data; data = (race_data_t*) get_list_elem_data( cur_elem ); g_game.race = *data; if ( is_cup_complete( event_data, get_event_cup_by_name( event_data, g_game.current_cup ) ) ) { cup_complete = True; last_completed_race = get_list_tail( race_list ); } else { cup_complete = False; last_completed_race = NULL; } } } else { /* Back from a race */ if ( !g_game.race_aborted ) { update_race_results(); } if (!g_game.practicing && !cup_complete) { if ( was_current_race_won() ) { update_for_won_race(); /* Advance to next race */ if ( cur_elem != get_list_tail( race_list ) ) { cur_elem = get_next_list_elem( race_list, cur_elem ); } } else { /* lost race */ plyr->lives -= 1; } print_debug( DEBUG_GAME_LOGIC, "Current lives: %d", plyr->lives ); } } back_btn = button_create( dummy_pos, 80 * mWidth / 480, 48 * mHeight / 320, "button_label", (mWidth>320)?"Back":"<< " ); button_set_hilit_font_binding( back_btn, "button_label_hilit" ); button_set_visible( back_btn, True ); button_set_click_event_cb( back_btn, back_click_cb, NULL ); start_btn = button_create( dummy_pos, 80 * mWidth / 480, 48 * mHeight / 320, "button_label", (mWidth>320)?"Race":" >>" ); button_set_hilit_font_binding( start_btn, "button_label_hilit" ); button_set_disabled_font_binding( start_btn, "button_label_disabled" ); button_set_visible( start_btn, True ); button_set_click_event_cb( start_btn, start_click_cb, NULL ); #ifdef __APPLE__ race_listbox = listbox_create( dummy_pos, mWidth - 170 * mHeight / 320, 44 * mHeight / 320, "course_name_label", race_list, conv_func ); #else race_listbox = listbox_create( dummy_pos, 460 * mHeight / 320, 44 * mHeight / 320, "listbox_item", race_list, conv_func ); #endif listbox_set_current_item( race_listbox, cur_elem ); listbox_set_item_change_event_cb( race_listbox, race_listbox_item_change_cb, NULL ); listbox_set_visible( race_listbox, True ); /* * Create text area */ #ifdef __APPLE__ desc_ta = textarea_create( dummy_pos, 150, 147, "race_description", "" ); #else desc_ta = textarea_create( dummy_pos, 312, 107, "race_description", "" ); #endif if ( g_game.practicing ) { open_course_data_t *data; data = (open_course_data_t*) get_list_elem_data( cur_elem ); textarea_set_text( desc_ta, data->description ); } else { race_data_t *data; data = (race_data_t*) get_list_elem_data( cur_elem ); textarea_set_text( desc_ta, data->description ); } textarea_set_visible( desc_ta, True ); /* * Create state buttons - only if practicing or if cup_complete */ if ( g_game.practicing || cup_complete ) { /* mirror */ mirror_ssbtn = ssbutton_create( dummy_pos, 32, 32, 2 ); ssbutton_set_state_image( mirror_ssbtn, 0, "mirror_button", make_point2d( 0.0/64.0, 32.0/64.0 ), make_point2d( 32.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state_image( mirror_ssbtn, 1, "mirror_button", make_point2d( 32.0/64.0, 32.0/64.0 ), make_point2d( 64.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state( mirror_ssbtn, (int)g_game.race.mirrored ); #ifdef __APPLE__ ssbutton_set_visible( mirror_ssbtn, False ); #else ssbutton_set_visible( mirror_ssbtn, True ); #endif /* conditions */ conditions_ssbtn = ssbutton_create( dummy_pos, 32, 32, 4 ); float border = 2.0; ssbutton_set_state_image( conditions_ssbtn, 0, "conditions_button", make_point2d( (0.0 + border)/64.0, (32.0 + border)/64.0 ), make_point2d( (32.0 - border)/64.0, (64.0 - border)/64.0 ), white ); ssbutton_set_state_image( conditions_ssbtn, 1, "conditions_button", make_point2d( (32.0 + border)/64.0, (0.0 + border)/64.0 ), make_point2d( (64.0 - border)/64.0, (32.0 - border)/64.0 ), white ); ssbutton_set_state_image( conditions_ssbtn, 2, "conditions_button", make_point2d( (32.0 + border)/64.0, (32.0 + border)/64.0 ), make_point2d( (64.0 - border)/64.0, (64.0 - border)/64.0 ), white ); ssbutton_set_state_image( conditions_ssbtn, 3, "conditions_button", make_point2d( (0.0 + border)/64.0, (0.0 + border)/64.0 ), make_point2d( (32.0 - border)/64.0, (32.0 - border)/64.0 ), white ); ssbutton_set_state( conditions_ssbtn, (int)g_game.race.conditions ); ssbutton_set_visible( conditions_ssbtn, True ); #ifdef __APPLE__ ssbutton_set_visible( conditions_ssbtn, False ); #else ssbutton_set_visible( conditions_ssbtn, True ); #endif /* wind */ wind_ssbtn = ssbutton_create( dummy_pos, 32, 32, 2 ); ssbutton_set_state_image( wind_ssbtn, 0, "wind_button", make_point2d( 0.0/64.0, 32.0/64.0 ), make_point2d( 32.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state_image( wind_ssbtn, 1, "wind_button", make_point2d( 32.0/64.0, 32.0/64.0 ), make_point2d( 64.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state( wind_ssbtn, (int)g_game.race.windy ); #ifdef __APPLE__ ssbutton_set_visible( wind_ssbtn, False ); #else ssbutton_set_visible( wind_ssbtn, True ); #endif /* snow */ snow_ssbtn = ssbutton_create( dummy_pos, 32, 32, 2 ); ssbutton_set_state_image( snow_ssbtn, 0, "snow_button", make_point2d( 0.0/64.0, 32.0/64.0 ), make_point2d( 32.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state_image( snow_ssbtn, 1, "snow_button", make_point2d( 32.0/64.0, 32.0/64.0 ), make_point2d( 64.0/64.0, 64.0/64.0 ), white ); ssbutton_set_state( snow_ssbtn, (int)g_game.race.snowing ); #ifdef __APPLE__ ssbutton_set_visible( snow_ssbtn, False ); #else ssbutton_set_visible( snow_ssbtn, True ); #endif /* XXX snow button doesn't do anything, so disable for now */ ssbutton_set_enabled( snow_ssbtn, False ); /* Can't change conditions if in cup mode */ if ( !g_game.practicing ) { ssbutton_set_enabled( conditions_ssbtn, False ); ssbutton_set_enabled( wind_ssbtn, False ); ssbutton_set_enabled( snow_ssbtn, False ); ssbutton_set_enabled( mirror_ssbtn, False ); } } else { conditions_ssbtn = NULL; wind_ssbtn = NULL; snow_ssbtn = NULL; mirror_ssbtn = NULL; } update_race_data(); update_button_enabled_states(); play_music( "start_screen" ); }
void quadsquare::UpdateAux(const quadcornerdata& cd, const float ViewerLocation[3], float CenterError, clip_result_t vis ) // Does the actual work of updating enabled states and tree growing/shrinking. { BlockUpdateCount++; //xxxxx check_assertion( vis != NotVisible, "Invalid visibility value" ); if ( vis != NoClip ) { vis = ClipSquare( cd ); if ( vis == NotVisible ) { return; } } // Make sure error values are current. if (Dirty) { RecomputeError(cd); } int half = 1 << cd.Level; int whole = half << 1; // See about enabling child verts. // East vert. if ( (EnabledFlags & 1) == 0 && VertexTest(cd.xorg + whole, Vertex[1].Y, cd.zorg + half, Error[0], ViewerLocation, cd.Level, East) == true ) { EnableEdgeVertex(0, false, cd); } // South vert. if ( (EnabledFlags & 8) == 0 && VertexTest(cd.xorg + half, Vertex[4].Y, cd.zorg + whole, Error[1], ViewerLocation, cd.Level, South) == true ) { EnableEdgeVertex(3, false, cd); } if (cd.Level > 0) { if ((EnabledFlags & 32) == 0) { if (BoxTest(cd.xorg, cd.zorg, half, MinY, MaxY, Error[3], ViewerLocation) == true) EnableChild(1, cd); // nw child.er } if ((EnabledFlags & 16) == 0) { if (BoxTest(cd.xorg + half, cd.zorg, half, MinY, MaxY, Error[2], ViewerLocation) == true) EnableChild(0, cd); // ne child. } if ((EnabledFlags & 64) == 0) { if (BoxTest(cd.xorg, cd.zorg + half, half, MinY, MaxY, Error[4], ViewerLocation) == true) EnableChild(2, cd); // sw child. } if ((EnabledFlags & 128) == 0) { if (BoxTest(cd.xorg + half, cd.zorg + half, half, MinY, MaxY, Error[5], ViewerLocation) == true) EnableChild(3, cd); // se child. } // Recurse into child quadrants as necessary. quadcornerdata q; if (EnabledFlags & 32) { SetupCornerData(&q, cd, 1); Child[1]->UpdateAux(q, ViewerLocation, Error[3], vis); } if (EnabledFlags & 16) { SetupCornerData(&q, cd, 0); Child[0]->UpdateAux(q, ViewerLocation, Error[2], vis); } if (EnabledFlags & 64) { SetupCornerData(&q, cd, 2); Child[2]->UpdateAux(q, ViewerLocation, Error[4], vis); } if (EnabledFlags & 128) { SetupCornerData(&q, cd, 3); Child[3]->UpdateAux(q, ViewerLocation, Error[5], vis); } } // Test for disabling. East, South, and center. if ( (EnabledFlags & 1) && SubEnabledCount[0] == 0 && VertexTest(cd.xorg + whole, Vertex[1].Y, cd.zorg + half, Error[0], ViewerLocation, cd.Level, East) == false) { EnabledFlags &= ~1; quadsquare* s = GetNeighbor(0, cd); if (s) s->EnabledFlags &= ~4; } if ( (EnabledFlags & 8) && SubEnabledCount[1] == 0 && VertexTest(cd.xorg + half, Vertex[4].Y, cd.zorg + whole, Error[1], ViewerLocation, cd.Level, South) == false) { EnabledFlags &= ~8; quadsquare* s = GetNeighbor(3, cd); if (s) s->EnabledFlags &= ~2; } if (EnabledFlags == 0 && cd.Parent != NULL && BoxTest(cd.xorg, cd.zorg, whole, MinY, MaxY, CenterError, ViewerLocation) == false) { // Disable ourself. cd.Parent->Square->NotifyChildDisable(*cd.Parent, cd.ChildIndex); // nb: possibly deletes 'this'. } }
void update_key_frame( player_data_t *plyr, scalar_t dt ) { int idx; scalar_t frac; point_t pos; scalar_t v; matrixgl_t cob_mat, rot_mat; char *root; char *lsh; char *rsh; char *lhp; char *rhp; char *lkn; char *rkn; char *lank; char *rank; char *head; char *neck; char *tail; root = get_tux_root_node(); lsh = get_tux_left_shoulder_joint(); rsh = get_tux_right_shoulder_joint(); lhp = get_tux_left_hip_joint(); rhp = get_tux_right_hip_joint(); lkn = get_tux_left_knee_joint(); rkn = get_tux_right_knee_joint(); lank = get_tux_left_ankle_joint(); rank = get_tux_right_ankle_joint(); head = get_tux_head(); neck = get_tux_neck(); tail = get_tux_tail_joint(); keyTime += dt; for (idx = 1; idx < numFrames; idx ++) { if ( keyTime < frames[idx].time ) break; } if ( idx == numFrames || numFrames == 0 ) { set_game_mode( RACING ); return; } reset_scene_node( root ); reset_scene_node( lsh ); reset_scene_node( rsh ); reset_scene_node( lhp ); reset_scene_node( rhp ); reset_scene_node( lkn ); reset_scene_node( rkn ); reset_scene_node( lank ); reset_scene_node( rank ); reset_scene_node( head ); reset_scene_node( neck ); reset_scene_node( tail ); check_assertion( idx > 0, "invalid keyframe index" ); if ( fabs( frames[idx-1].time - frames[idx].time ) < EPS ) { frac = 1.; } else { frac = (keyTime - frames[idx].time) / ( frames[idx-1].time - frames[idx].time ); } pos.x = interp( frac, frames[idx-1].pos.x, frames[idx].pos.x ); pos.z = interp( frac, frames[idx-1].pos.z, frames[idx].pos.z ); pos.y = interp( frac, frames[idx-1].pos.y, frames[idx].pos.y ); pos.y += find_y_coord( pos.x, pos.z ); set_tux_pos( plyr, pos ); make_identity_matrix( cob_mat ); v = interp( frac, frames[idx-1].yaw, frames[idx].yaw ); rotate_scene_node( root, 'y', v ); make_rotation_matrix( rot_mat, v, 'y' ); multiply_matrices( cob_mat, cob_mat, rot_mat ); v = interp( frac, frames[idx-1].pitch, frames[idx].pitch ); rotate_scene_node( root, 'x', v ); make_rotation_matrix( rot_mat, v, 'x' ); multiply_matrices( cob_mat, cob_mat, rot_mat ); v = interp( frac, frames[idx-1].l_shldr, frames[idx].l_shldr ); rotate_scene_node( lsh, 'z', v ); v = interp( frac, frames[idx-1].r_shldr, frames[idx].r_shldr ); rotate_scene_node( rsh, 'z', v ); v = interp( frac, frames[idx-1].l_hip, frames[idx].l_hip ); rotate_scene_node( lhp, 'z', v ); v = interp( frac, frames[idx-1].r_hip, frames[idx].r_hip ); rotate_scene_node( rhp, 'z', v ); /* Set orientation */ plyr->orientation = make_quaternion_from_matrix( cob_mat ); plyr->orientation_initialized = True; }
tex_font_metrics_t* load_tex_font_metrics( char *filename ) { tex_font_metrics_t *tfm = NULL; FILE *tfm_file = NULL; int i; char magic[4]; char *err_msg; int endian_check; bool_t swap_bytes; struct char_dims ch_dims; int num_chars; int texture_width, texture_height; char dummy; check_assertion( sizeof(int) == 4, "This architecture's integer size is != 4" ); check_assertion( sizeof(short) == 2, "This architecture's short integer size is != 2" ); check_assertion( sizeof(char) == 1, "This architecture's char size is != 1" ); /* Open file */ tfm_file = fopen( filename, "rb" ); if ( tfm_file == NULL ) { print_warning( MISSING_FILE_WARNING, "Couldn't open font metrics file %s", filename ); return NULL; } tfm = (tex_font_metrics_t*)malloc( sizeof(tex_font_metrics_t) ); check_assertion( tfm != NULL, "out of memory" ); /* Initialize tfm */ for (i=0; i<MAX_TEX_FONT_CHARS; i++) { tfm->char_data[i] = NULL; } /* Check magic number */ READ_BYTES( tfm_file, magic, sizeof(magic), False ); if ( strncmp( magic, "\377tfm", 4 ) != 0 ) { err_msg = "File is not a valid tfm file"; goto bail; } /* Check endian-ness */ READ_BYTES( tfm_file, &endian_check, sizeof(int), False ); if ( endian_check == 0x12345678 ) { swap_bytes = False; } else if ( endian_check == 0x78563412 ) { swap_bytes = True; } else { err_msg = "File is not a valid tfm file"; goto bail; } /* Read in texture_width, texture_height, max_ascent, max_descent */ READ_BYTES( tfm_file, &texture_width, sizeof(int), swap_bytes ); READ_BYTES( tfm_file, &texture_height, sizeof(int), swap_bytes ); READ_BYTES( tfm_file, &tfm->max_ascent, sizeof(int), swap_bytes ); READ_BYTES( tfm_file, &tfm->max_descent, sizeof(int), swap_bytes ); READ_BYTES( tfm_file, &num_chars, sizeof(int), swap_bytes ); for (i=0; i<num_chars; i++) { tfm_char_data_t *cd; scalar_t sstep = 0.5/texture_width; scalar_t tstep = 0.5/texture_height; READ_BYTES( tfm_file, &ch_dims.ch, sizeof(unsigned short), swap_bytes ); READ_BYTES( tfm_file, &ch_dims.w, sizeof(unsigned char), False ); READ_BYTES( tfm_file, &ch_dims.h, sizeof(unsigned char), False ); READ_BYTES( tfm_file, &ch_dims.x_offset, sizeof(char), False ); READ_BYTES( tfm_file, &ch_dims.y_offset, sizeof(char), False ); READ_BYTES( tfm_file, &ch_dims.kern_width, sizeof(char), False ); READ_BYTES( tfm_file, &dummy, sizeof(char), False ); READ_BYTES( tfm_file, &ch_dims.x_pixel, sizeof(short), swap_bytes ); READ_BYTES( tfm_file, &ch_dims.y_pixel, sizeof(short), swap_bytes ); if ( ch_dims.ch >= MAX_TEX_FONT_CHARS ) { err_msg = "Two-byte characters are not supported"; goto bail; } cd = ( tfm_char_data_t * ) malloc( sizeof( tfm_char_data_t ) ); check_assertion( cd != NULL, "out of memory" ); cd->ll = make_point2d( ch_dims.x_offset, ch_dims.y_offset ); cd->lr = make_point2d( cd->ll.x + ch_dims.w, cd->ll.y ); cd->ur = make_point2d( cd->lr.x, cd->lr.y + ch_dims.h ); cd->ul = make_point2d( cd->ur.x - ch_dims.w, cd->ur.y ); cd->tex_ll = make_point2d( ch_dims.x_pixel / (scalar_t)texture_width + sstep, ch_dims.y_pixel / (scalar_t)texture_height + tstep ); cd->tex_lr = make_point2d( cd->tex_ll.x + sstep + ch_dims.w / (scalar_t)texture_width, cd->tex_ll.y + tstep ); cd->tex_ur = make_point2d( cd->tex_lr.x + sstep, cd->tex_lr.y + tstep + ch_dims.h / (scalar_t)texture_height ); cd->tex_ul = make_point2d( cd->tex_ur.x + sstep - ch_dims.w / (scalar_t)texture_width, cd->tex_ur.y + tstep ); cd->kern_width = ch_dims.kern_width; tfm->char_data[ch_dims.ch] = cd; } fclose( tfm_file ); return tfm; bail: if ( tfm != NULL ) { for (i=0; i<MAX_TEX_FONT_CHARS; i++) { if ( tfm->char_data[i] != NULL ) { free( tfm->char_data[i] ); } } free( tfm ); } if ( tfm_file != NULL ) { fclose( tfm_file ); } print_warning( IMPORTANT_WARNING, "Error opening font metrics file `%s': %s\n", filename, err_msg ); return NULL; }
/* * Tcl callback to allow setting of game configuration variables from Tcl. */ static int set_param_cb ( ClientData cd, Tcl_Interp *ip, int argc, const char *argv[]) { int i; int tmp_int; int num_params; struct param *parm; if ( argc != 3 ) { Tcl_AppendResult(ip, argv[0], ": invalid number of arguments\n", "Usage: ", argv[0], " <parameter name> <value>", (char *)0 ); return TCL_ERROR; } /* Search for parameter */ parm = NULL; num_params = sizeof(Params)/sizeof(struct param); for (i=0; i<num_params; i++) { parm = (struct param*)&Params + i; if ( strcmp( parm->name, argv[1] ) == 0 ) { break; } } /* If can't find parameter, report error */ if ( parm == NULL || i == num_params ) { Tcl_AppendResult(ip, argv[0], ": invalid parameter `", argv[1], "'", (char *)0 ); return TCL_ERROR; } /* Set value of parameter */ switch ( parm->type ) { case PARAM_STRING: set_param_string( parm, argv[2] ); break; case PARAM_CHAR: if ( strlen( argv[2] ) > 1 ) { Tcl_AppendResult(ip, "\n", argv[0], ": value for `", argv[1], "' must be a single character", (char *)0 ); return TCL_ERROR; } set_param_char( parm, argv[2][0] ); break; case PARAM_INT: if ( Tcl_GetInt( ip, argv[2], &tmp_int ) != TCL_OK ) { Tcl_AppendResult(ip, "\n", argv[0], ": value for `", argv[1], "' must be an integer", (char *)0 ); return TCL_ERROR; } set_param_int( parm, tmp_int ); break; case PARAM_BOOL: if ( Tcl_GetBoolean( ip, argv[2], &tmp_int ) != TCL_OK ) { Tcl_AppendResult(ip, "\n", argv[0], ": value for `", argv[1], "' must be a boolean", (char *)0 ); return TCL_ERROR; } check_assertion( tmp_int == 0 || tmp_int == 1, "invalid boolean value" ); set_param_bool( parm, (bool_t) tmp_int ); break; default: code_not_reached(); } return TCL_OK; }
/*! tux_events Tcl callback Here's a sample call to tux_events: tux_events { { -name "Herring Run" -icon noicon -cups { { -name "Cup 1" -icon noicon -races { { -course path_of_daggers \ -description "nice long description" \ -herring { 15 20 25 30 } \ -time { 40.0 35.0 30.0 25.0 } \ -score { 0 0 0 0 } \ -mirrored yes -conditions cloudy \ -windy no -snowing no } { -course ingos_speedway \ -description "nice long description" \ -herring { 15 20 25 30 } \ -time { 40.0 35.0 30.0 25.0 } \ -score { 0 0 0 0 } \ -mirrored yes -conditions cloudy \ -windy no -snowing no } } -name "Cup 2" -icon noicon -races { { -course penguins_cant_fly \ -description "nice long description" \ -herring { 15 20 25 30 } \ -time { 40.0 35.0 30.0 25.0 } \ -score { 0 0 0 0 } \ -mirrored yes -conditions cloudy \ -windy no -snowing no } { -course ingos_speedway \ -description "nice long description" \ -herring { 15 20 25 30 } \ -time { 40.0 35.0 30.0 25.0 } \ -score { 0 0 0 0 } \ -mirrored yes -conditions cloudy \ -windy no -snowing no } } } } } } \return Tcl error code \author jfpatry \date Created: 2000-09-19 \date Modified: 2000-09-19 */ static int events_cb( ClientData cd, Tcl_Interp *ip, int argc, const char **argv ) { char *err_msg; const char **list = NULL; int num_events; list_elem_t last_event = NULL; int i; /* Make sure module has been initialized */ check_assertion( initialized, "course_mgr module not initialized" ); if ( argc != 2 ) { err_msg = "Incorrect number of arguments"; goto bail_events; } if ( Tcl_SplitList( ip, argv[1], &num_events, &list ) == TCL_ERROR ) { err_msg = "Argument is not a list"; goto bail_events; } /* We currently only allow tux_events to be called once */ last_event = get_list_tail( event_list ); if ( last_event != NULL ) { err_msg = "tux_events has already been called; it can only be called " "once."; goto bail_events; } for (i=0; i<num_events; i++) { event_data_t *data = create_event_data( ip, list[i], &err_msg ); if ( data == NULL ) { goto bail_events; } last_event = insert_list_elem( event_list, last_event, (list_elem_data_t) data ); } Tcl_Free( (char*) list ); list = NULL; return TCL_OK; bail_events: if ( list != NULL ) { Tcl_Free( (char*) list ); } /* Clean out event list */ if ( event_list != NULL ) { last_event = get_list_tail( event_list ); while ( last_event != NULL ) { event_data_t *data; data = (event_data_t*) delete_list_elem( event_list, last_event ); free( data ); last_event = get_list_tail( event_list ); } } Tcl_AppendResult( ip, "Error in call to tux_events: ", err_msg, "\n", "Usage: tux_events { list of event data }", (NULL) ); return TCL_ERROR; }
/*! Draws a button widget \return None \author jfpatry \date Created: 2000-09-18 \date Modified: 2000-09-18 */ void button_draw( button_t *button ) { GLuint texobj; texture_region_t *tex; point2d_t pos; scalar_t w, h; char *font_binding; check_assertion( button != NULL, "button is NULL" ); pos = button->pos; w = button->w; h = button->h; glEnable( GL_TEXTURE_2D ); tex = NULL; font_binding = NULL; if ( !button->enabled ) { if ( button->disabled_tex.binding ) { tex = &button->disabled_tex; } else if ( button->tex.binding ) { tex = &button->tex; } if ( button->disabled_font_binding ) { font_binding = button->disabled_font_binding; } else if ( button->font_binding ) { font_binding = button->font_binding; } } else if ( button->clicked ) { if ( button->clicked_tex.binding ) { tex = &button->clicked_tex; } else if ( button->hilit_tex.binding ) { tex = &button->hilit_tex; } else if ( button->tex.binding ) { tex = &button->tex; } if ( button->hilit_font_binding ) { font_binding = button->hilit_font_binding; } else if ( button->font_binding ) { font_binding = button->font_binding; } } else if ( button->focused ) { if ( button->hilit_tex.binding ) { tex = &button->hilit_tex; } else if ( button->tex.binding ) { tex = &button->tex; } if ( button->hilit_font_binding ) { font_binding = button->hilit_font_binding; } else if ( button->font_binding ) { font_binding = button->font_binding; } } else { if ( button->tex.binding ) { tex = &button->tex; } if ( button->font_binding ) { font_binding = button->font_binding; } } if ( tex != NULL ) { if ( !get_texture_binding( tex->binding, &texobj ) ) { print_warning( IMPORTANT_WARNING, "Couldnt get texture object for binding %s", tex->binding ); texobj = 0; } glBindTexture( GL_TEXTURE_2D, texobj ); glColor4dv( (scalar_t*) &tex->colour ); glBegin( GL_QUADS ); { glTexCoord2f( tex->ll.x, tex->ll.y ); glVertex3f( pos.x, pos.y, 0 ); glTexCoord2f( tex->ur.x, tex->ll.y ); glVertex3f( pos.x + w, pos.y, 0 ); glTexCoord2f( tex->ur.x, tex->ur.y ); glVertex3f( pos.x + w, pos.y + h, 0 ); glTexCoord2f( tex->ll.x, tex->ur.y ); glVertex3f( pos.x, pos.y + h, 0 ); } glEnd(); } if ( font_binding && button->label != NULL ) { font_t *font; int w, asc, desc; if (!get_font_binding( font_binding, &font )) { print_warning( IMPORTANT_WARNING, "Couldn't get font object for binding %s", font_binding ); font = NULL; } else { bind_font_texture( font ); get_font_metrics( font, button->label, &w, &asc, &desc ); glPushMatrix(); { glTranslatef( button->pos.x + button->w/2.0 - w/2.0, button->pos.y + button->h/2.0 - asc/2.0 + desc/2.0, 0.0 ); draw_string( font, button->label ); } glPopMatrix(); } } }
/*! Creates an open_course_data_t object from a Tcl string. \author jfpatry \date Created: 2000-09-21 \date Modified: 2000-09-21 */ open_course_data_t* create_open_course_data( Tcl_Interp *ip, const char *string, char **err_msg ) { const char **argv = NULL; const char **orig_argv = NULL; int argc = 0; char *course = NULL; char *name = NULL; char *description = NULL; race_conditions_t conditions = RACE_CONDITIONS_SUNNY; scalar_t par_time = 120; bool_t speed = True; bool_t score = True; open_course_data_t *open_course_data = NULL; if ( Tcl_SplitList( ip, string, &argc, &argv ) == TCL_ERROR ) { *err_msg = "open course data is not a list"; goto bail_open_course_data; } orig_argv = argv; while ( *argv != NULL ) { if ( strcmp( *argv, "-course" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -course in open course data"; goto bail_open_course_data; } course = string_copy( *argv ); } else if ( strcmp( *argv, "-name" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -name in open course data"; goto bail_open_course_data; } name = string_copy( *argv ); } else if ( strcmp( *argv, "-description" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -description in open course data"; goto bail_open_course_data; } description = string_copy( *argv ); } else if ( strcmp( *argv, "-par_time" ) == 0 ) { NEXT_ARG; if ( *argv == NULL ) { par_time = 120.0; print_warning( PEDANTIC_WARNING, "No data supplied for -par_time in open course " "data. Using %g seconds.", par_time ); } else if ( Tcl_GetDouble( ip, *argv, &par_time ) != TCL_OK ) { *err_msg = "Invalid value for -par_time in open course data"; goto bail_open_course_data; } } else if ( strcmp( *argv, "-conditions" ) == 0 ) { int i; NEXT_ARG; if ( *argv == NULL ) { *err_msg = "No data supplied for -conditions in open course data"; goto bail_open_course_data; } for ( i=0; i<RACE_CONDITIONS_NUM_CONDITIONS; i++ ) { if ( string_cmp_no_case( race_condition_names[i], *argv ) == 0 ) { break; } } if ( i == RACE_CONDITIONS_NUM_CONDITIONS ) { *err_msg = "Invalid value for -conditions in race data"; goto bail_open_course_data; } conditions = (race_conditions_t)i; } else if ( strcmp( *argv, "-no_speed" ) == 0 ) { speed = False; } else if ( strcmp( *argv, "-no_score" ) == 0 ) { score = False; } else { sprintf( err_buff, "unrecognized option `%s' in open course data", *argv ); *err_msg = err_buff; goto bail_open_course_data; } NEXT_ARG; } /* Check mandatory arguments */ if ( course == NULL ) { *err_msg = "No course specified in open course data"; goto bail_open_course_data; } if ( name == NULL ) { *err_msg = "No name specified in open course data"; goto bail_open_course_data; } /* Create new open_course_data_t object */ open_course_data = (open_course_data_t*) malloc( sizeof(open_course_data_t) ); check_assertion( open_course_data != NULL, "out of memory" ); open_course_data->course = course; open_course_data->name = name; open_course_data->description = description; open_course_data->par_time = par_time; open_course_data->conditions = conditions; open_course_data->speed = speed; open_course_data->score = score; Tcl_Free( (char*) orig_argv ); return open_course_data; bail_open_course_data: if ( orig_argv ) { Tcl_Free( (char*) orig_argv ); } if ( course ) { free( course ); } if ( name ) { free( name ); } if ( description ) { free( description ); } if ( open_course_data ) { free( open_course_data ); } return NULL; }
/*! Sets the button's position \return None \author jfpatry \date Created: 2000-09-17 \date Modified: 2000-09-17 */ void button_set_position( button_t *button, point2d_t pos ) { check_assertion( button != NULL, "button is NULL" ); button->pos = pos; }
/*! Fills \c buff with a string describing the current OS (including version) \return 0 on success, 1 if buffer too small, -1 if failed to determine OS version \author jfpatry \date Created: 2000-10-30 \date Modified: 2000-10-30 */ int get_os_version( char *buff, int size ) { #ifdef WIN32 /* Win32 Version */ /* See http://www.mvps.org/vb/index2.html?tips/getversionex.htm for a table mapping OSVERSIONINFOEX entries to Windows version */ char tmp_buff[BUFF_LEN]; int tmp_buff_size = BUFF_LEN; char *ptr = tmp_buff; int len; OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if ( !GetVersionEx( (OSVERSIONINFO *) &osvi) ) { return -1; } switch (osvi.dwPlatformId) { case VER_PLATFORM_WIN32_NT: /* Check for NT versus 2000 */ if ( osvi.dwMajorVersion <= 4 ) { if ( !append_to_buff( &ptr, &tmp_buff_size, "Microsoft Windows NT" ) ) { return -1; } } if ( osvi.dwMajorVersion == 5 ) { if ( !append_to_buff( &ptr, &tmp_buff_size, "Microsoft Windows 2000" ) ) { return -1; } } /* Display version, service pack (if any), and build number. */ len = snprintf(ptr, tmp_buff_size, " version %d.%d %s (Build %d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF); check_assertion( len >= 0, "tmp_buff too small" ); if ( len < 0 ) { return -1; } ptr += len; tmp_buff_size -= len; break; case VER_PLATFORM_WIN32_WINDOWS: if ((osvi.dwMajorVersion > 4) || ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion > 0))) { if ( osvi.dwMinorVersion <= 10 ) { if ( strcmp( osvi.szCSDVersion, "A" ) == 0 ) { if ( !append_to_buff( &ptr, &tmp_buff_size, "Microsoft Windows 98 SE") ) { return -1; } } else { if ( !append_to_buff( &ptr, &tmp_buff_size, "Microsoft Windows 98") ) { return -1; } } } else { if ( !append_to_buff( &ptr, &tmp_buff_size, "Microsoft Windows ME") ) { return -1; } } } else { if ( strcmp( osvi.szCSDVersion, "B" ) == 0 ) { if ( !append_to_buff( &ptr, &tmp_buff_size, "Microsoft Windows 95 OSR2") ) { return -1; } } else { if ( !append_to_buff( &ptr, &tmp_buff_size, "Microsoft Windows 95") ) { return -1; } } } /* Append Build */ len = snprintf(ptr, tmp_buff_size, " (Build %d)", osvi.dwBuildNumber & 0xFFFF); check_assertion( len >= 0, "tmp_buff too small" ); if ( len < 0 ) { return -1; } ptr += len; tmp_buff_size -= len; break; case VER_PLATFORM_WIN32s: if ( !append_to_buff( &ptr, &tmp_buff_size, "Microsoft Win32s") ) { return -1; } break; } len = snprintf( buff, size, "%s", tmp_buff ); if ( len < 0 ) { /* buffer too small */ buff[size-1] = (char)0; return 1; } return 0; #else /* Unix/Linux version */ struct utsname utsname; if ( uname( &utsname ) >= 0 ) { if ( strlen( utsname.sysname ) + strlen( utsname.release ) + strlen( utsname.version ) + 3 > size ) { if ( size > 0 ) { buff[0] = (char)0; } return 1; } sprintf( buff, "%s %s %s", utsname.sysname, utsname.release, utsname.version ); return 0; } else { /* uname failed */ return -1; } #endif /* WIN32 */ }