ref: 6d241d506fbce2d0b6a69f19f83b34bdda0ac6af
dir: /src/wipeout/ui.c/
#include "../render.h" #include "../utils.h" #include "ui.h" #include "image.h" typedef struct { vec2i_t offset; uint16_t width; } glyph_t; typedef struct { uint16_t texture; uint16_t height; glyph_t glyphs[40]; } char_set_t; int ui_scale = 2; char_set_t char_set[UI_SIZE_MAX] = { [UI_SIZE_16] = { .texture = 0, .height = 16, .glyphs = { {{ 0, 0}, 25}, {{ 25, 0}, 24}, {{ 49, 0}, 17}, {{ 66, 0}, 24}, {{ 90, 0}, 24}, {{114, 0}, 17}, {{131, 0}, 25}, {{156, 0}, 18}, {{174, 0}, 7}, {{181, 0}, 17}, {{ 0, 16}, 17}, {{ 17, 16}, 17}, {{ 34, 16}, 28}, {{ 62, 16}, 17}, {{ 79, 16}, 24}, {{103, 16}, 24}, {{127, 16}, 26}, {{153, 16}, 24}, {{177, 16}, 18}, {{195, 16}, 17}, {{ 0, 32}, 17}, {{ 17, 32}, 17}, {{ 34, 32}, 29}, {{ 63, 32}, 24}, {{ 87, 32}, 17}, {{104, 32}, 18}, {{122, 32}, 24}, {{146, 32}, 10}, {{156, 32}, 18}, {{174, 32}, 17}, {{191, 32}, 18}, {{ 0, 48}, 18}, {{ 18, 48}, 18}, {{ 36, 48}, 18}, {{ 54, 48}, 22}, {{ 76, 48}, 25}, {{101, 48}, 7}, {{108, 48}, 7}, {{198, 0}, 0}, {{198, 0}, 0} } }, [UI_SIZE_12] = { .texture = 0, .height = 12, .glyphs = { {{ 0, 0}, 19}, {{ 19, 0}, 19}, {{ 38, 0}, 14}, {{ 52, 0}, 19}, {{ 71, 0}, 19}, {{ 90, 0}, 13}, {{103, 0}, 19}, {{122, 0}, 14}, {{136, 0}, 6}, {{142, 0}, 13}, {{155, 0}, 14}, {{169, 0}, 14}, {{ 0, 12}, 22}, {{ 22, 12}, 14}, {{ 36, 12}, 19}, {{ 55, 12}, 18}, {{ 73, 12}, 20}, {{ 93, 12}, 19}, {{112, 12}, 15}, {{127, 12}, 14}, {{141, 12}, 13}, {{154, 12}, 13}, {{167, 12}, 22}, {{ 0, 24}, 19}, {{ 19, 24}, 13}, {{ 32, 24}, 14}, {{ 46, 24}, 19}, {{ 65, 24}, 8}, {{ 73, 24}, 15}, {{ 88, 24}, 13}, {{101, 24}, 14}, {{115, 24}, 15}, {{130, 24}, 14}, {{144, 24}, 15}, {{159, 24}, 18}, {{177, 24}, 19}, {{196, 24}, 5}, {{201, 24}, 5}, {{183, 0}, 0}, {{183, 0}, 0} } }, [UI_SIZE_8] = { .texture = 0, .height = 8, .glyphs = { {{ 0, 0}, 13}, {{ 13, 0}, 13}, {{ 26, 0}, 10}, {{ 36, 0}, 13}, {{ 49, 0}, 13}, {{ 62, 0}, 9}, {{ 71, 0}, 13}, {{ 84, 0}, 10}, {{ 94, 0}, 4}, {{ 98, 0}, 9}, {{107, 0}, 10}, {{117, 0}, 10}, {{127, 0}, 16}, {{143, 0}, 10}, {{153, 0}, 13}, {{166, 0}, 13}, {{179, 0}, 14}, {{ 0, 8}, 13}, {{ 13, 8}, 10}, {{ 23, 8}, 9}, {{ 32, 8}, 9}, {{ 41, 8}, 9}, {{ 50, 8}, 16}, {{ 66, 8}, 14}, {{ 80, 8}, 9}, {{ 89, 8}, 10}, {{ 99, 8}, 13}, {{112, 8}, 6}, {{118, 8}, 11}, {{129, 8}, 10}, {{139, 8}, 10}, {{149, 8}, 11}, {{160, 8}, 10}, {{170, 8}, 10}, {{180, 8}, 12}, {{192, 8}, 14}, {{206, 8}, 4}, {{210, 8}, 4}, {{193, 0}, 0}, {{193, 0}, 0} } }, }; uint16_t icon_textures[UI_ICON_MAX]; void ui_load() { texture_list_t tl = image_get_compressed_textures("wipeout/textures/drfonts.cmp"); char_set[UI_SIZE_16].texture = texture_from_list(tl, 0); char_set[UI_SIZE_12].texture = texture_from_list(tl, 1); char_set[UI_SIZE_8 ].texture = texture_from_list(tl, 2); icon_textures[UI_ICON_HAND] = texture_from_list(tl, 3); icon_textures[UI_ICON_CONFIRM] = texture_from_list(tl, 5); icon_textures[UI_ICON_CANCEL] = texture_from_list(tl, 6); icon_textures[UI_ICON_END] = texture_from_list(tl, 7); icon_textures[UI_ICON_DEL] = texture_from_list(tl, 8); icon_textures[UI_ICON_STAR] = texture_from_list(tl, 9); } int ui_get_scale() { return ui_scale; } void ui_set_scale(int scale) { ui_scale = scale; } vec2i_t ui_scaled(vec2i_t v) { return vec2i(v.x * ui_scale, v.y * ui_scale); } vec2i_t ui_scaled_screen() { return vec2i_mulf(render_size(), ui_scale); } vec2i_t ui_scaled_pos(ui_pos_t anchor, vec2i_t offset) { vec2i_t pos; vec2i_t screen_size = render_size(); if (flags_is(anchor, UI_POS_LEFT)) { pos.x = offset.x * ui_scale; } else if (flags_is(anchor, UI_POS_CENTER)) { pos.x = (screen_size.x >> 1) + offset.x * ui_scale; } else if (flags_is(anchor, UI_POS_RIGHT)) { pos.x = screen_size.x + offset.x * ui_scale; } if (flags_is(anchor, UI_POS_TOP)) { pos.y = offset.y * ui_scale; } else if (flags_is(anchor, UI_POS_MIDDLE)) { pos.y = (screen_size.y >> 1) + offset.y * ui_scale; } else if (flags_is(anchor, UI_POS_BOTTOM)) { pos.y = screen_size.y + offset.y * ui_scale; } return pos; } #define char_to_glyph_index(C) (C >= '0' && C <= '9' ? (C - '0' + 26) : C - 'A') int ui_char_width(char c, ui_text_size_t size) { if (c == ' ') { return 8; } return char_set[size].glyphs[char_to_glyph_index(c)].width; } int ui_text_width(const char *text, ui_text_size_t size) { int width = 0; char_set_t *cs = &char_set[size]; for (int i = 0; text[i] != 0; i++) { width += text[i] != ' ' ? cs->glyphs[char_to_glyph_index(text[i])].width : 8; } return width; } int ui_number_width(int num, ui_text_size_t size) { char text_buffer[16]; text_buffer[15] = '\0'; int i; for (i = 14; i > 0; i--) { text_buffer[i] = '0' + (num % 10); num = num / 10; if (num == 0) { break; } } return ui_text_width(text_buffer + i, size); } void ui_draw_time(float time, vec2i_t pos, ui_text_size_t size, rgba_t color) { int msec = time * 1000; int tenths = (msec / 100) % 10; int secs = (msec / 1000) % 60; int mins = msec / (60 * 1000); char text_buffer[8]; text_buffer[0] = '0' + (mins / 10) % 10; text_buffer[1] = '0' + mins % 10; text_buffer[2] = 'e'; // ":" text_buffer[3] = '0' + secs / 10; text_buffer[4] = '0' + secs % 10; text_buffer[5] = 'f'; // "." text_buffer[6] = '0' + tenths; text_buffer[7] = '\0'; ui_draw_text(text_buffer, pos, size, color); } void ui_draw_number(int num, vec2i_t pos, ui_text_size_t size, rgba_t color) { char text_buffer[16]; text_buffer[15] = '\0'; int i; for (i = 14; i > 0; i--) { text_buffer[i] = '0' + (num % 10); num = num / 10; if (num == 0) { break; } } ui_draw_text(text_buffer + i, pos, size, color); } void ui_draw_text(const char *text, vec2i_t pos, ui_text_size_t size, rgba_t color) { char_set_t *cs = &char_set[size]; for (int i = 0; text[i] != 0; i++) { if (text[i] != ' ') { glyph_t *glyph = &cs->glyphs[char_to_glyph_index(text[i])]; vec2i_t size = vec2i(glyph->width, cs->height); render_push_2d_tile(pos, glyph->offset, size, ui_scaled(size), color, cs->texture); pos.x += glyph->width * ui_scale; } else { pos.x += 8 * ui_scale; } } } void ui_draw_image(vec2i_t pos, uint16_t texture) { vec2i_t scaled_size = ui_scaled(render_texture_size(texture)); render_push_2d(pos, scaled_size, rgba(128, 128, 128, 255), texture); } void ui_draw_icon(ui_icon_type_t icon, vec2i_t pos, rgba_t color) { render_push_2d(pos, ui_scaled(render_texture_size(icon_textures[icon])), color, icon_textures[icon]); } void ui_draw_text_centered(const char *text, vec2i_t pos, ui_text_size_t size, rgba_t color) { pos.x -= (ui_text_width(text, size) * ui_scale) >> 1; ui_draw_text(text, pos, size, color); }