diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c index 7d1b6c5c49..92e4457f4a 100644 --- a/menu/drivers/materialui.c +++ b/menu/drivers/materialui.c @@ -568,7 +568,8 @@ static void materialui_render_messagebox(materialui_handle_t *mui, mui->textures.list[MUI_TEXTURE_KEY_HOVER], mui->font, video_info, - menu_event_get_osk_grid(), menu_event_get_osk_ptr()); + menu_event_get_osk_grid(), menu_event_get_osk_ptr(), + 0xffffffff); end: if (list) diff --git a/menu/drivers/ozone.c b/menu/drivers/ozone.c index b35db9b344..04077c79c4 100644 --- a/menu/drivers/ozone.c +++ b/menu/drivers/ozone.c @@ -50,6 +50,7 @@ #define ANIMATION_PUSH_ENTRY_DURATION 10 #define ANIMATION_CURSOR_DURATION 8 +#define ANIMATION_CURSOR_PULSE 30 #define ENTRIES_START_Y 127 @@ -71,12 +72,14 @@ static float ozone_backdrop[16] = { enum OZONE_TEXTURE { OZONE_TEXTURE_RETROARCH = 0, + OZONE_TEXTURE_CURSOR_BORDER, OZONE_TEXTURE_LAST }; static char *OZONE_TEXTURES_FILES[OZONE_TEXTURE_LAST] = { - "retroarch" + "retroarch", + "cursor_border" }; enum OZONE_THEME_TEXTURES { @@ -85,14 +88,19 @@ enum OZONE_THEME_TEXTURES { OZONE_THEME_TEXTURE_SWITCH, OZONE_THEME_TEXTURE_CHECK, + OZONE_THEME_TEXTURE_CURSOR_NO_BORDER, + OZONE_THEME_TEXTURE_CURSOR_STATIC, + OZONE_THEME_TEXTURE_LAST }; -static char* OZONE_THEME_TEXTURES_FILES[OZONE_THEME_TEXTURE_LAST] = { +static char *OZONE_THEME_TEXTURES_FILES[OZONE_THEME_TEXTURE_LAST] = { "button_a", "button_b", "switch", - "check" + "check", + "cursor_noborder", + "cursor_static" }; enum OZONE_TAB_TEXTURES { @@ -382,6 +390,12 @@ static float ozone_sidebar_gradient_bottom_dark[16] = { 0.2, 0.2, 0.2, 1.00, }; +static float ozone_border_0_light[16] = COLOR_HEX_TO_FLOAT(0x50EFD9, 1.00); +static float ozone_border_1_light[16] = COLOR_HEX_TO_FLOAT(0x0DB6D5, 1.00); + +static float ozone_border_0_dark[16] = COLOR_HEX_TO_FLOAT(0x198AC6, 1.00); +static float ozone_border_1_dark[16] = COLOR_HEX_TO_FLOAT(0x89F1F2, 1.00); + typedef struct ozone_theme { /* Background color */ @@ -410,6 +424,12 @@ typedef struct ozone_theme float *sidebar_top_gradient; float *sidebar_bottom_gradient; + /* + Fancy cursor colors + */ + float *cursor_border_0; + float *cursor_border_1; + menu_texture_item textures[OZONE_THEME_TEXTURE_LAST]; const char *name; @@ -435,6 +455,9 @@ ozone_theme_t ozone_theme_light = { ozone_sidebar_gradient_top_light, ozone_sidebar_gradient_bottom_light, + ozone_border_0_light, + ozone_border_1_light, + {0}, "light" @@ -460,6 +483,9 @@ ozone_theme_t ozone_theme_dark = { ozone_sidebar_gradient_top_dark, ozone_sidebar_gradient_bottom_dark, + ozone_border_0_dark, + ozone_border_1_dark, + {0}, "dark" @@ -473,7 +499,7 @@ ozone_theme_t *ozone_themes[] = { static unsigned ozone_themes_count = sizeof(ozone_themes) / sizeof(ozone_themes[0]); static unsigned last_color_theme = 0; static bool last_use_preferred_system_color_theme = false; -static ozone_theme_t *ozone_default_theme = &ozone_theme_light; +static ozone_theme_t *ozone_default_theme = &ozone_theme_light; /* also used as a tag for cursor animation */ typedef struct ozone_handle { @@ -552,6 +578,10 @@ typedef struct ozone_handle float entries_border[16]; float entries_icon[16]; float entries_checkmark[16]; + float cursor_alpha[16]; + + unsigned cursor_state; /* 0 -> 1 -> 0 -> 1 [...] */ + float cursor_border[16]; } theme_dynamic; bool need_compute; @@ -564,6 +594,7 @@ typedef struct ozone_handle bool want_horizontal_animation; char *pending_message; + bool has_all_assets; } ozone_handle_t; /* If you change this struct, also @@ -1342,11 +1373,12 @@ static void ozone_unload_theme_textures(ozone_handle_t *ozone) } } -static void ozone_reset_theme_textures(ozone_handle_t *ozone) +static bool ozone_reset_theme_textures(ozone_handle_t *ozone) { int i; int j; char theme_path[255]; + bool result = true; for (j = 0; j < ozone_themes_count; j++) { @@ -1365,10 +1397,76 @@ static void ozone_reset_theme_textures(ozone_handle_t *ozone) strlcpy(filename, OZONE_THEME_TEXTURES_FILES[i], sizeof(filename)); strlcat(filename, ".png", sizeof(filename)); - menu_display_reset_textures_list(filename, theme_path, &theme->textures[i], TEXTURE_FILTER_MIPMAP_LINEAR); + if (!menu_display_reset_textures_list(filename, theme_path, &theme->textures[i], TEXTURE_FILTER_MIPMAP_LINEAR)) + result = false; } } + return result; +} + +static void ozone_cursor_animation_cb(void *userdata); + +static void ozone_animate_cursor(ozone_handle_t *ozone, float *dst, float *target) +{ + menu_animation_ctx_entry_t entry; + int i; + + entry.easing_enum = EASING_OUT_QUAD; + entry.tag = (uintptr_t) &ozone_default_theme; + entry.duration = ANIMATION_CURSOR_PULSE; + entry.userdata = ozone; + + for (i = 0; i < 16; i++) + { + if (i == 3 || i == 7 || i == 11 || i == 15) + continue; + + if (i == 14) + entry.cb = ozone_cursor_animation_cb; + else + entry.cb = NULL; + + entry.subject = &dst[i]; + entry.target_value = target[i]; + + menu_animation_push(&entry); + } +} + +static void ozone_cursor_animation_cb(void *userdata) +{ + ozone_handle_t *ozone = (ozone_handle_t*) userdata; + + float *target = NULL; + + switch (ozone->theme_dynamic.cursor_state) + { + case 0: + target = ozone->theme->cursor_border_1; + break; + case 1: + target = ozone->theme->cursor_border_0; + break; + } + + ozone->theme_dynamic.cursor_state = (ozone->theme_dynamic.cursor_state + 1) % 2; + + ozone_animate_cursor(ozone, ozone->theme_dynamic.cursor_border, target); +} + +static void ozone_restart_cursor_animation(ozone_handle_t *ozone) +{ + menu_animation_ctx_tag tag = (uintptr_t) &ozone_default_theme; + + if (!ozone->has_all_assets) + return; + + ozone->theme_dynamic.cursor_state = 1; + memcpy(ozone->theme_dynamic.cursor_border, ozone->theme->cursor_border_0, sizeof(ozone->theme_dynamic.cursor_border)); + menu_animation_kill_by_tag(&tag); + + ozone_animate_cursor(ozone, ozone->theme_dynamic.cursor_border, ozone->theme->cursor_border_1); } static void ozone_set_color_theme(ozone_handle_t *ozone, unsigned color_theme) @@ -1395,6 +1493,9 @@ static void ozone_set_color_theme(ozone_handle_t *ozone, unsigned color_theme) memcpy(ozone->theme_dynamic.entries_border, ozone->theme->entries_border, sizeof(ozone->theme_dynamic.entries_border)); memcpy(ozone->theme_dynamic.entries_icon, ozone->theme->entries_icon, sizeof(ozone->theme_dynamic.entries_icon)); memcpy(ozone->theme_dynamic.entries_checkmark, ozone_pure_white, sizeof(ozone->theme_dynamic.entries_checkmark)); + memcpy(ozone->theme_dynamic.cursor_alpha, ozone_pure_white, sizeof(ozone->theme_dynamic.cursor_alpha)); + + ozone_restart_cursor_animation(ozone); last_color_theme = color_theme; } @@ -1592,6 +1693,8 @@ static void ozone_context_reset(void *data, bool is_threaded) if (ozone) { + ozone->has_all_assets = true; + /* Fonts init */ unsigned i; unsigned size; @@ -1607,6 +1710,18 @@ static void ozone_context_reset(void *data, bool is_threaded) fill_pathname_join(font_path, ozone->assets_path, "bold.ttf", sizeof(font_path)); ozone->fonts.title = menu_display_font_file(font_path, FONT_SIZE_TITLE, is_threaded); + if ( + !ozone->fonts.footer || + !ozone->fonts.entries_label || + !ozone->fonts.entries_sublabel || + !ozone->fonts.time || + !ozone->fonts.sidebar || + !ozone->fonts.title + ) + { + ozone->has_all_assets = false; + } + /* Naive font size */ ozone->title_font_glyph_width = FONT_SIZE_TITLE * 3/4; ozone->entry_font_glyph_width = FONT_SIZE_ENTRIES_LABEL * 3/4; @@ -1622,7 +1737,7 @@ static void ozone_context_reset(void *data, bool is_threaded) size = font_driver_get_message_width(ozone->fonts.entries_sublabel, "a", 1, 1); if (size) ozone->sublabel_font_glyph_width = size; - + /* Textures init */ for (i = 0; i < OZONE_TEXTURE_LAST; i++) { @@ -1630,7 +1745,8 @@ static void ozone_context_reset(void *data, bool is_threaded) strlcpy(filename, OZONE_TEXTURES_FILES[i], sizeof(filename)); strlcat(filename, ".png", sizeof(filename)); - menu_display_reset_textures_list(filename, ozone->png_path, &ozone->textures[i], TEXTURE_FILTER_MIPMAP_LINEAR); + if (!menu_display_reset_textures_list(filename, ozone->png_path, &ozone->textures[i], TEXTURE_FILTER_MIPMAP_LINEAR)) + ozone->has_all_assets = false; } /* Sidebar textures */ @@ -1640,15 +1756,18 @@ static void ozone_context_reset(void *data, bool is_threaded) strlcpy(filename, OZONE_TAB_TEXTURES_FILES[i], sizeof(filename)); strlcat(filename, ".png", sizeof(filename)); - menu_display_reset_textures_list(filename, ozone->tab_path, &ozone->tab_textures[i], TEXTURE_FILTER_MIPMAP_LINEAR); + if (!menu_display_reset_textures_list(filename, ozone->tab_path, &ozone->tab_textures[i], TEXTURE_FILTER_MIPMAP_LINEAR)) + ozone->has_all_assets = false; } /* Theme textures */ - ozone_reset_theme_textures(ozone); + if (!ozone_reset_theme_textures(ozone)) + ozone->has_all_assets = false; /* Icons textures init */ for (i = 0; i < OZONE_ENTRIES_ICONS_TEXTURE_LAST; i++) - menu_display_reset_textures_list(ozone_entries_icon_texture_path(ozone, i), ozone->icons_path, &ozone->icons_textures[i], TEXTURE_FILTER_MIPMAP_LINEAR); + if (!menu_display_reset_textures_list(ozone_entries_icon_texture_path(ozone, i), ozone->icons_path, &ozone->icons_textures[i], TEXTURE_FILTER_MIPMAP_LINEAR)) + ozone->has_all_assets = false; menu_display_allocate_white_texture(); @@ -1663,6 +1782,13 @@ static void ozone_context_reset(void *data, bool is_threaded) ozone->animations.cursor_alpha = 1.0f; ozone->animations.scroll_y = 0.0f; ozone->animations.list_alpha = 1.0f; + + /* Missing assets message */ + /* TODO Localize */ + if (!ozone->has_all_assets) + runloop_msg_queue_push("Some assets are missing - please update them", 1, 256, false); + + ozone_restart_cursor_animation(ozone); } } @@ -1710,6 +1836,9 @@ static void ozone_context_destroy(void *data) ozone->fonts.entries_label = NULL; ozone->fonts.entries_sublabel = NULL; ozone->fonts.sidebar = NULL; + + menu_animation_ctx_tag tag = (uintptr_t) &ozone_default_theme; + menu_animation_kill_by_tag(&tag); } static void *ozone_list_get_entry(void *data, @@ -2401,9 +2530,55 @@ static void ozone_draw_footer(ozone_handle_t *ozone, video_frame_info_t *video_i menu_display_blend_end(video_info); } -/* TODO Reduce sidebar width ? */ +/* TODO Fluid sidebar width ? */ -static void ozone_draw_cursor(ozone_handle_t *ozone, video_frame_info_t *video_info, int x_offset, unsigned entry_width, size_t y, float alpha) +static void ozone_draw_cursor_slice(ozone_handle_t *ozone, + video_frame_info_t *video_info, + int x_offset, + unsigned entry_width, + size_t y, float alpha) +{ + ozone_color_alpha(ozone->theme_dynamic.cursor_alpha, alpha); + ozone_color_alpha(ozone->theme_dynamic.cursor_border, alpha); + + menu_display_blend_begin(video_info); + + /* Cursor without border */ + menu_display_draw_texture_slice( + video_info, + x_offset - 14, + y + 8, + 80, 80, + entry_width + 3 + 28 - 4, + 72, + video_info->width, video_info->height, + ozone->theme_dynamic.cursor_alpha, + 20, 1.0, + ozone->theme->textures[OZONE_THEME_TEXTURE_CURSOR_NO_BORDER] + ); + + /* Tainted border */ + menu_display_draw_texture_slice( + video_info, + x_offset - 14, + y + 8, + 80, 80, + entry_width + 3 + 28 - 4, + 72, + video_info->width, video_info->height, + ozone->theme_dynamic.cursor_border, + 20, 1.0, + ozone->textures[OZONE_TEXTURE_CURSOR_BORDER] + ); + + menu_display_blend_end(video_info); +} + +static void ozone_draw_cursor_fallback(ozone_handle_t *ozone, + video_frame_info_t *video_info, + int x_offset, + unsigned entry_width, + size_t y, float alpha) { ozone_color_alpha(ozone->theme_dynamic.selection_border, alpha); ozone_color_alpha(ozone->theme_dynamic.selection, alpha); @@ -2418,6 +2593,18 @@ static void ozone_draw_cursor(ozone_handle_t *ozone, video_frame_info_t *video_i menu_display_draw_quad(video_info, x_offset + entry_width, y, 3, 70 - 10 - 3 - 6 - 4, video_info->width, video_info->height, ozone->theme_dynamic.selection_border); } +static void ozone_draw_cursor(ozone_handle_t *ozone, + video_frame_info_t *video_info, + int x_offset, + unsigned entry_width, + size_t y, float alpha) +{ + if (ozone->has_all_assets) + ozone_draw_cursor_slice(ozone, video_info, x_offset, entry_width, y, alpha); + else + ozone_draw_cursor_fallback(ozone, video_info, x_offset, entry_width, y, alpha); +} + static void ozone_draw_sidebar(ozone_handle_t *ozone, video_frame_info_t *video_info) { size_t y; @@ -2455,7 +2642,7 @@ static void ozone_draw_sidebar(ozone_handle_t *ozone, video_frame_info_t *video_ if (ozone->cursor_in_sidebar) ozone_draw_cursor(ozone, video_info, ozone->sidebar_offset + 41, 408-81, selection_y-8, ozone->animations.cursor_alpha); - if (ozone->cursor_in_sidebar_old && ozone->categories_selection_ptr != ozone->categories_active_idx_old) + if (ozone->cursor_in_sidebar_old) ozone_draw_cursor(ozone, video_info, ozone->sidebar_offset + 41, 408-81, selection_old_y-8, 1-ozone->animations.cursor_alpha); /* Icons */ @@ -2635,12 +2822,13 @@ text_iterate: y += node->height; } - /* Cursor(s) layer */ + /* Cursor(s) layer - current */ if (!ozone->cursor_in_sidebar) ozone_draw_cursor(ozone, video_info, x_offset + 456, entry_width, selection_y + scroll_y, ozone->animations.cursor_alpha * alpha); - if (!ozone->cursor_in_sidebar_old && ozone->selection != ozone->selection_old) - ozone_draw_cursor(ozone, video_info, x_offset + 456, entry_width, old_selection_y + scroll_y, 1-ozone->animations.cursor_alpha * alpha); + /* Old*/ + if (!ozone->cursor_in_sidebar_old) + ozone_draw_cursor(ozone, video_info, x_offset + 456, entry_width, old_selection_y + scroll_y, (1-ozone->animations.cursor_alpha) * alpha); /* Icons + text */ y = ENTRIES_START_Y; @@ -2848,18 +3036,19 @@ static void ozone_draw_messagebox(ozone_handle_t *ozone, menu_display_blend_begin(video_info); - menu_display_draw_texture_slice( - video_info, - x - longest_width/2 - 48, - y + 16 - 48, - 256, 256, - longest_width + 48 * 2, - line_height * list->size + 48 * 2, - width, height, - ozone->theme->message_background, - 16, 1.0, - ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_DIALOG_SLICE] - ); + if (ozone->has_all_assets) /* avoid drawing a black box if there's no assets */ + menu_display_draw_texture_slice( + video_info, + x - longest_width/2 - 48, + y + 16 - 48, + 256, 256, + longest_width + 48 * 2, + line_height * list->size + 48 * 2, + width, height, + ozone->theme->message_background, + 16, 1.0, + ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_DIALOG_SLICE] + ); for (i = 0; i < list->size; i++) { @@ -2879,11 +3068,12 @@ static void ozone_draw_messagebox(ozone_handle_t *ozone, if (menu_input_dialog_get_display_kb()) menu_display_draw_keyboard( - ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_KEY_HOVER], + ozone->theme->textures[OZONE_THEME_TEXTURE_CURSOR_STATIC], ozone->fonts.footer, video_info, menu_event_get_osk_grid(), - menu_event_get_osk_ptr()); + menu_event_get_osk_ptr(), + ozone->theme->text_rgba); end: string_list_free(list); diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 686ff89714..089de09fe2 100755 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -922,7 +922,8 @@ static void xmb_render_messagebox_internal( xmb->font, video_info, menu_event_get_osk_grid(), - menu_event_get_osk_ptr()); + menu_event_get_osk_ptr(), + 0xffffffff); end: string_list_free(list); diff --git a/menu/menu_driver.c b/menu/menu_driver.c index 6d63093a01..503bfaee8c 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -1503,7 +1503,8 @@ void menu_display_draw_keyboard( uintptr_t hover_texture, const font_data_t *font, video_frame_info_t *video_info, - char *grid[], unsigned id) + char *grid[], unsigned id, + unsigned text_color) { unsigned i; int ptr_width, ptr_height; @@ -1537,7 +1538,8 @@ void menu_display_draw_keyboard( for (i = 0; i < 44; i++) { - int line_y = (i / 11) * height / 10.0; + int line_y = (i / 11) * height / 10.0; + unsigned color = 0xffffffff; if (i == id) { @@ -1553,13 +1555,15 @@ void menu_display_draw_keyboard( hover_texture); menu_display_blend_end(video_info); + + color = text_color; } menu_display_draw_text(font, grid[i], width/2.0 - (11*ptr_width)/2.0 + (i % 11) * ptr_width + ptr_width/2.0, height/2.0 + ptr_height + line_y + font->size / 3, - width, height, 0xffffffff, TEXT_ALIGN_CENTER, 1.0f, + width, height, color, TEXT_ALIGN_CENTER, 1.0f, false, 0); } } @@ -1600,7 +1604,7 @@ void menu_display_draw_text( video_driver_set_osd_msg(text, ¶ms, (void*)font); } -void menu_display_reset_textures_list( +bool menu_display_reset_textures_list( const char *texture_path, const char *iconpath, uintptr_t *item, enum texture_filter_type filter_type) { @@ -1616,14 +1620,16 @@ void menu_display_reset_textures_list( fill_pathname_join(texpath, iconpath, texture_path, sizeof(texpath)); if (string_is_empty(texpath) || !filestream_exists(texpath)) - return; + return false; if (!image_texture_load(&ti, texpath)) - return; + return false; video_driver_texture_load(&ti, filter_type, item); image_texture_free(&ti); + + return true; } bool menu_driver_is_binding_state(void) diff --git a/menu/menu_driver.h b/menu/menu_driver.h index 48d9e02c44..612ff33eb9 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -738,7 +738,8 @@ void menu_display_draw_keyboard( uintptr_t hover_texture, const font_data_t *font, video_frame_info_t *video_info, - char *grid[], unsigned id); + char *grid[], unsigned id, + unsigned text_color); void menu_display_draw_pipeline(menu_display_ctx_draw_t *draw, video_frame_info_t *video_info); @@ -819,7 +820,7 @@ font_data_t *menu_display_font( font_data_t *menu_display_font_file(char* fontpath, float font_size, bool is_threaded); -void menu_display_reset_textures_list( +bool menu_display_reset_textures_list( const char *texture_path, const char *iconpath, uintptr_t *item,