/** * Render a button. * @param button * Button to render. * @param text * Optional text to render. */ void button_show(button_struct *button, const char *text) { SDL_Surface *texture; (void) button_need_redraw(button); if (button->pressed_forced) { button->pressed = 1; } texture = texture_surface(button_determine_texture(button)); surface_show(button->surface, button->x, button->y, NULL, texture); if (text) { const char *color, *color_shadow; int x, y; if (button->disabled) { color = COLOR_GRAY; color_shadow = COLOR_BLACK; } else if (button->mouse_over) { color = button->color_over; color_shadow = button->color_over_shadow; } else { color = button->color; color_shadow = button->color_shadow; } x = button->x; y = button->y; if (button->center) { x += texture->w / 2 - text_get_width(button->font, text, button->flags) / 2; y += texture->h / 2 - FONT_HEIGHT(button->font) / 2; } if (!color_shadow) { text_show(button->surface, button->font, text, x, y, color, button->flags, NULL); } else { text_show_shadow(button->surface, button->font, text, x, y - 2, color, color_shadow, button->flags, NULL); } } if (button->repeat_func && button->pressed && SDL_GetTicks() - button->pressed_ticks > button->pressed_repeat_ticks) { button->repeat_func(button); button->pressed_ticks = SDL_GetTicks(); button->pressed_repeat_ticks = 150; } button->redraw = 0; }
/** * Show one list. * @param list * List to show. * @param x * X position. * @param y * Y position. */ void list_show(list_struct *list, int x, int y) { uint32_t row, col; int w = 0, extra_width = 0; SDL_Rect box; if (!list) { return; } list->x = x; list->y = y; /* Draw a frame, if needed. */ if (list->draw_frame_func) { list->draw_frame_func(list); } /* Draw the column names. */ for (col = 0; col < list->cols; col++) { extra_width = 0; /* Center it? */ if (list->col_centered[col]) { extra_width = list->col_widths[col] / 2 - text_get_width(list->font, list->col_names[col], 0) / 2; } /* Actually draw the column name. */ if (list->col_names[col]) { text_show_shadow(list->surface, list->font, list->col_names[col], list->x + w + extra_width, list->y, list->focus ? COLOR_WHITE : COLOR_GRAY, COLOR_BLACK, 0, NULL); } w += list->col_widths[col] + list->col_spacings[col]; } /* Initialize default values for coloring rows. */ box.x = list->x + list->frame_offset; box.w = list->width; box.h = LIST_ROW_HEIGHT(list); if (list->scrollbar_enabled) { scrollbar_show(&list->scrollbar, list->surface, list->x + list->frame_offset + 1 + w, LIST_ROWS_START(list)); } /* Doing coloring of each row? */ if (list->row_color_func) { for (row = 0; row < list->max_rows; row++) { box.y = LIST_ROWS_START(list) + (row * LIST_ROW_HEIGHT(list)); list->row_color_func(list, row, box); } } /* Start printing out rows from the offset to the maximum. */ for (row = list->row_offset; row < list->rows; row++) { /* Stop if we reached maximum number of visible rows. */ if (LIST_ROW_OFFSET(row, list) == list->max_rows) { break; } if (list->row_selected_func && (row + 1) == list->row_selected) { /* Color selected row. */ box.y = LIST_ROWS_START(list) + (LIST_ROW_OFFSET(row, list) * LIST_ROW_HEIGHT(list)); list->row_selected_func(list, box); } else if (list->row_highlight_func && (row + 1) == list->row_highlighted) { /* Color highlighted row. */ box.y = LIST_ROWS_START(list) + (LIST_ROW_OFFSET(row, list) * LIST_ROW_HEIGHT(list)); list->row_highlight_func(list, box); } w = 0; /* Show all the columns. */ for (col = 0; col < list->cols; col++) { /* Is there any text to show? */ if (list->text[row][col] && list->font != NULL) { const char *text_color, *text_color_shadow; SDL_Rect text_rect; extra_width = 0; /* Center it. */ if (list->col_centered[col]) { extra_width = list->col_widths[col] / 2 - text_get_width(list->font, list->text[row][col], TEXT_WORD_WRAP) / 2; } text_color = list->focus ? COLOR_WHITE : COLOR_GRAY; text_color_shadow = COLOR_BLACK; if (list->text_color_hook) { list->text_color_hook(list, row, col, &text_color, &text_color_shadow); } /* Add width limit on the string. */ text_rect.x = list->x + w + extra_width; text_rect.y = LIST_ROWS_START(list) + (LIST_ROW_OFFSET(row, list) * LIST_ROW_HEIGHT(list)); text_rect.w = list->col_widths[col] + list->col_spacings[col]; text_rect.h = LIST_ROW_HEIGHT(list); /* Output the text. */ if (text_color_shadow) { text_show_shadow(list->surface, list->font, list->text[row][col], text_rect.x, text_rect.y, text_color, text_color_shadow, TEXT_WORD_WRAP | list->text_flags, &text_rect); } else if (text_color) { text_show(list->surface, list->font, list->text[row][col], text_rect.x, text_rect.y, text_color, TEXT_WORD_WRAP | list->text_flags, &text_rect); } } if (list->post_column_func) { list->post_column_func(list, row, col); } w += list->col_widths[col] + list->col_spacings[col]; } } }
/** * Show the main GUI after starting the client -- servers list, chat box, * connecting to server, etc. */ void intro_show(void) { SDL_Surface *texture; int x, y; size_t server_count; server_struct *node; char buf[MAX_BUF]; SDL_Rect box; sound_start_bg_music("intro.ogg", setting_get_int(OPT_CAT_SOUND, OPT_VOLUME_MUSIC), -1); texture = TEXTURE_CLIENT("intro"); /* Background */ surface_show(ScreenSurface, 0, 0, NULL, texture); textwin_show(ScreenSurface, texture->w, 1, ScreenSurface->w - texture->w - 2, ScreenSurface->h - 3); /* Calculate whether to show the eyes or not. Blinks every * EYES_BLINK_TIME ticks, then waits EYES_BLINK_DELAY ticks until * showing the eyes again. */ if (SDL_GetTicks() - eyes_blink_ticks >= (eyes_draw ? EYES_BLINK_TIME : EYES_BLINK_DELAY)) { eyes_blink_ticks = SDL_GetTicks(); eyes_draw++; } if (eyes_draw) { SDL_Rect src_box; src_box.x = 0; src_box.y = eyes_draw - 1; src_box.w = TEXTURE_CLIENT("eyes")->w; src_box.h = TEXTURE_CLIENT("eyes")->h; surface_show(ScreenSurface, texture->w - 90, 310 + src_box.y, &src_box, TEXTURE_CLIENT("eyes")); if (eyes_draw > 1) { eyes_draw++; if (eyes_draw > src_box.h) { eyes_draw = 1; } } } texture = TEXTURE_CLIENT("servers_bg"); x = 15; y = ScreenSurface->h - texture->h - 5; surface_show(ScreenSurface, x, y, NULL, texture); server_count = server_get_count(); /* Create the buttons. */ if (!list_servers) { button_create(&button_play); button_create(&button_refresh); button_create(&button_server); button_create(&button_settings); button_create(&button_update); button_create(&button_help); button_create(&button_credits); button_create(&button_quit); } /* List doesn't exist or the count changed? Create new list. */ if (!list_servers || last_server_count != server_count) { size_t i; /* Remove it if it exists already. */ if (list_servers) { list_remove(list_servers); } /* Create the servers list. */ list_servers = list_create(11, 3, 8); list_servers->handle_enter_func = list_handle_enter; list_servers->handle_esc_func = list_handle_esc; list_servers->text_color_hook = list_text_color; list_scrollbar_enable(list_servers); list_set_column(list_servers, 0, 295, 7, "Server", -1); list_set_column(list_servers, 1, 50, 9, "Port", 1); list_set_column(list_servers, 2, 46, 7, "Players", 1); /* Add the servers to the list. */ for (i = 0; i < server_count; i++) { node = server_get_id(i); list_add(list_servers, i, 0, node->name); snprintf(VS(buf), "%d", node->port_crypto == -1 ? node->port : node->port_crypto); list_add(list_servers, i, 1, buf); if (node->player >= 0) { snprintf(buf, sizeof(buf), "%d", node->player); } else { strcpy(buf, "-"); } list_add(list_servers, i, 2, buf); } /* Store the new count. */ last_server_count = server_count; } /* Actually draw the list. */ list_show(list_servers, x + 12, y + 8); node = server_get_id(list_servers->row_selected - 1); /* Do we have any selected server? If so, show its version and * description. */ if (node) { snprintf(buf, sizeof(buf), "Version: %s", node->version); text_show_shadow(ScreenSurface, FONT_ARIAL10, buf, x + 13, y + 185, COLOR_HGOLD, COLOR_BLACK, 0, NULL); box.w = 410; box.h = 48; text_show(ScreenSurface, FONT_ARIAL10, node->desc, x + 13, y + 197, COLOR_WHITE, TEXT_WORD_WRAP | TEXT_MARKUP, &box); } /* Show whether we are connecting to the metaserver or not. */ if (ms_connecting(-1)) { text_show_shadow(ScreenSurface, FONT_ARIAL10, "Connecting to metaserver, please wait...", x + 105, y + 8, COLOR_HGOLD, COLOR_BLACK, 0, NULL); } else { text_show_shadow(ScreenSurface, FONT_ARIAL10, "Select a secure server.", x + 196, y + 8, COLOR_GREEN, COLOR_BLACK, 0, NULL); } texture = TEXTURE_CLIENT("servers_bg_over"); surface_show(ScreenSurface, x, y, NULL, texture); x += texture->w + 20; texture = TEXTURE_CLIENT("news_bg"); surface_show(ScreenSurface, x, y, NULL, texture); box.w = texture->w; box.h = 0; text_show_shadow(ScreenSurface, FONT_SERIF12, "Game News", x, y + 10, COLOR_HGOLD, COLOR_BLACK, TEXT_ALIGN_CENTER, &box); /* No list yet, make one and start downloading the data. */ if (!list_news) { /* Start downloading. */ news_request = curl_request_create(clioption_settings.game_news_url, CURL_PKEY_TRUST_ULTIMATE); curl_request_start_get(news_request); list_news = list_create(18, 1, 8); list_news->focus = 0; list_news->handle_enter_func = list_handle_enter; list_news->handle_esc_func = list_handle_esc; list_set_column(list_news, 0, 150, 7, NULL, -1); list_set_font(list_news, FONT_ARIAL10); } /* Download in progress? */ if (news_request != NULL) { curl_state_t state = curl_request_get_state(news_request); /* Finished downloading, parse the data. */ if (state == CURL_STATE_OK) { char *body = curl_request_get_body(news_request, NULL); if (body != NULL) { uint32_t i = 0; char *cp = strtok(body, "\n"); while (cp != NULL) { list_add(list_news, i++, 0, cp); cp = strtok(NULL, "\n"); } } } /* Finished downloading or there was an error: clean up in either * case. */ if (state != CURL_STATE_INPROGRESS) { curl_request_free(news_request); news_request = NULL; } } /* Show the news list. */ list_show(list_news, x + 13, y + 10); button_play.x = button_refresh.x = button_server.x = button_settings.x = button_update.x = button_help.x = button_credits.x = button_quit.x = 489; y += 2; button_play.y = y + 10; button_show(&button_play, "Play"); button_refresh.y = y + 35; button_show(&button_refresh, "Refresh"); button_server.y = y + 60; button_show(&button_server, "Server"); button_settings.y = y + 86; button_show(&button_settings, "Settings"); button_update.y = y + 110; button_show(&button_update, "Update"); button_help.y = y + 135; button_show(&button_help, "Help"); button_credits.y = y + 160; button_show(&button_credits, "Credits"); button_quit.y = y + 224; button_show(&button_quit, "Quit"); if (clioption_settings.connect[0] && cpl.state < ST_STARTCONNECT) { size_t i; for (i = 0; i < server_count; i++) { node = server_get_id(i); if (strcasecmp(clioption_settings.connect[0], node->name) == 0) { list_servers->row_selected = i + 1; if (!clioption_settings.reconnect) { efree(clioption_settings.connect[0]); clioption_settings.connect[0] = NULL; } event_push_key_once(SDLK_RETURN, 0); break; } } } }