From 6d1660fcbd89f9937492b0c769b82d681cd1828a Mon Sep 17 00:00:00 2001 From: natinusala Date: Sat, 3 Oct 2020 17:06:03 +0200 Subject: [PATCH] ozone: add cursor wiggle animation --- menu/drivers/ozone/ozone.c | 88 ++++++++++++++++++++++++++++-- menu/drivers/ozone/ozone.h | 25 ++++++++- menu/drivers/ozone/ozone_display.c | 14 ++++- menu/drivers/ozone/ozone_sidebar.c | 32 +++++------ 4 files changed, 134 insertions(+), 25 deletions(-) diff --git a/menu/drivers/ozone/ozone.c b/menu/drivers/ozone/ozone.c index 61b6df5fc1..25c6561c26 100644 --- a/menu/drivers/ozone/ozone.c +++ b/menu/drivers/ozone/ozone.c @@ -3,7 +3,7 @@ * Copyright (C) 2014-2017 - Jean-André Santoni * Copyright (C) 2016-2019 - Brad Parker * Copyright (C) 2018 - Alfredo Monclús - * Copyright (C) 2018 - natinusala + * Copyright (C) 2018-2020 - natinusala * Copyright (C) 2019 - Patrick Scheurenbrand * * RetroArch is free software: you can redistribute it and/or modify it under the terms @@ -303,13 +303,13 @@ static enum menu_action ozone_parse_menu_entry_action( { /* If cursor is active, ensure we target * an on screen category */ - size_t selection = (ozone->cursor_mode) - ? ozone_get_onscreen_category_selection(ozone) + size_t selection = (ozone->cursor_mode) + ? ozone_get_onscreen_category_selection(ozone) : ozone->categories_selection_ptr; new_selection = (int)(selection + 1); - if (new_selection >= (int)(ozone->system_tab_end + if (new_selection >= (int)(ozone->system_tab_end + horizontal_list_size + 1)) new_selection = 0; @@ -360,6 +360,8 @@ static enum menu_action ozone_parse_menu_entry_action( if (ozone->cursor_in_sidebar) { new_action = MENU_ACTION_ACCESSIBILITY_SPEAK_TITLE; + ozone_start_cursor_wiggle(ozone, MENU_ACTION_LEFT); + break; } else if (ozone->depth > 1) @@ -374,7 +376,11 @@ static enum menu_action ozone_parse_menu_entry_action( if (!ozone->cursor_in_sidebar) { if (ozone->depth == 1) + { new_action = MENU_ACTION_NOOP; + ozone_start_cursor_wiggle(ozone, MENU_ACTION_RIGHT); + } + break; } @@ -607,6 +613,8 @@ static void *ozone_init(void **userdata, bool video_is_threaded) ozone->num_search_terms_old = 0; + ozone->cursor_wiggle_state.wiggling = false; + ozone->thumbnail_path_data = gfx_thumbnail_path_init(); if (!ozone->thumbnail_path_data) goto error; @@ -1175,6 +1183,8 @@ static void ozone_context_reset(void *data, bool is_threaded) ozone->messagebox_state = false; ozone->messagebox_state_old = false; + ozone->cursor_wiggle_state.wiggling = false; + /* Animations */ ozone->animations.cursor_alpha = 1.0f; ozone->animations.scroll_y = 0.0f; @@ -3957,6 +3967,76 @@ void ozone_toggle_metadata_override(ozone_handle_t *ozone) gfx_animation_push(&animation_entry); } +void ozone_start_cursor_wiggle(ozone_handle_t* ozone, enum menu_action direction) +{ + /* Don't start another wiggle animation on top of another */ + if (!ozone || ozone->cursor_wiggle_state.wiggling) + return; + + /* Don't allow wiggling in invalid directions */ + if (!( + direction == MENU_ACTION_UP || + direction == MENU_ACTION_DOWN || + direction == MENU_ACTION_LEFT || + direction == MENU_ACTION_RIGHT + )) + return; + + /* Start wiggling */ + ozone->cursor_wiggle_state.start_time = menu_driver_get_current_time() / 1000; + ozone->cursor_wiggle_state.direction = direction; + ozone->cursor_wiggle_state.amplitude = rand() % 15 + 10; + ozone->cursor_wiggle_state.wiggling = true; +} + +static int ozone_wiggle(ozone_handle_t* ozone, float t) +{ + float a = ozone->cursor_wiggle_state.amplitude; + + /* Damped sine wave */ + float w = 0.8f; /* period */ + float c = 0.35f; /* damp factor */ + return roundf(a * exp(-(c * t)) * sin(w * t)); +} + +void ozone_apply_cursor_wiggle_offset(ozone_handle_t* ozone, int* x, size_t* y) +{ + retro_time_t cur_time; + retro_time_t t; + + /* Don't do anything if we are not wiggling */ + if (!ozone || !ozone->cursor_wiggle_state.wiggling) + return; + + cur_time = menu_driver_get_current_time() / 1000; + t = (cur_time - ozone->cursor_wiggle_state.start_time) / 10; + + /* Has the animation ended? */ + if (t >= OZONE_WIGGLE_DURATION) + { + ozone->cursor_wiggle_state.wiggling = false; + return; + } + + /* Change cursor position depending on wiggle direction */ + switch (ozone->cursor_wiggle_state.direction) + { + case MENU_ACTION_RIGHT: + *x += ozone_wiggle(ozone, t); + break; + case MENU_ACTION_LEFT: + *x -= ozone_wiggle(ozone, t); + break; + case MENU_ACTION_DOWN: + *y += ozone_wiggle(ozone, t); + break; + case MENU_ACTION_UP: + *y -= ozone_wiggle(ozone, t); + break; + default: + break; + } +} menu_ctx_driver_t menu_ctx_ozone = { NULL, /* set_texture */ diff --git a/menu/drivers/ozone/ozone.h b/menu/drivers/ozone/ozone.h index 6ea6c04094..733385d3c3 100644 --- a/menu/drivers/ozone/ozone.h +++ b/menu/drivers/ozone/ozone.h @@ -1,5 +1,5 @@ /* RetroArch - A frontend for libretro. - * Copyright (C) 2018 - natinusala + * Copyright (C) 2018-2020 - natinusala * Copyright (C) 2019 - Patrick Scheurenbrand * * RetroArch is free software: you can redistribute it and/or modify it under the terms @@ -295,6 +295,14 @@ struct ozone_handle bool is_file_list; bool is_quick_menu; bool first_frame; + + struct + { + retro_time_t start_time; + float amplitude; + enum menu_action direction; + bool wiggling; + } cursor_wiggle_state; }; /* If you change this struct, also @@ -394,7 +402,6 @@ static INLINE unsigned ozone_count_lines(const char *str) return lines; } - void ozone_update_content_metadata(ozone_handle_t *ozone); void ozone_font_flush( @@ -403,4 +410,18 @@ void ozone_font_flush( void ozone_toggle_metadata_override(ozone_handle_t *ozone); +#define OZONE_WIGGLE_DURATION 15 + +/** + * Starts the cursor wiggle animation in the given direction + * Use ozone_get_cursor_wiggle_offset to read the animation + * once it has started + */ +void ozone_start_cursor_wiggle(ozone_handle_t* ozone, enum menu_action direction); + +/** + * Changes x and y to the current offset of the cursor wiggle animation + */ +void ozone_apply_cursor_wiggle_offset(ozone_handle_t* ozone, int* x, size_t* y); + #endif diff --git a/menu/drivers/ozone/ozone_display.c b/menu/drivers/ozone/ozone_display.c index d5ebbbd667..e8815f5c01 100644 --- a/menu/drivers/ozone/ozone_display.c +++ b/menu/drivers/ozone/ozone_display.c @@ -3,7 +3,7 @@ * Copyright (C) 2014-2017 - Jean-André Santoni * Copyright (C) 2016-2019 - Brad Parker * Copyright (C) 2018 - Alfredo Monclús - * Copyright (C) 2018 - natinusala + * Copyright (C) 2018-2020 - natinusala * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- @@ -260,16 +260,24 @@ void ozone_draw_cursor( unsigned width, unsigned height, size_t y, float alpha) { + int new_x = x_offset; + size_t new_y = y; + + /* Apply wiggle animation if needed */ + if (ozone->cursor_wiggle_state.wiggling) + ozone_apply_cursor_wiggle_offset(ozone, &new_x, &new_y); + + /* Draw the cursor */ if (ozone->has_all_assets) ozone_draw_cursor_slice(ozone, userdata, video_width, video_height, - x_offset, width, height, y, alpha); + new_x, width, height, new_y, alpha); else ozone_draw_cursor_fallback(ozone, userdata, video_width, video_height, - x_offset, width, height, y, alpha); + new_x, width, height, new_y, alpha); } void ozone_draw_icon( diff --git a/menu/drivers/ozone/ozone_sidebar.c b/menu/drivers/ozone/ozone_sidebar.c index 5400b7f766..87da649e9a 100644 --- a/menu/drivers/ozone/ozone_sidebar.c +++ b/menu/drivers/ozone/ozone_sidebar.c @@ -3,7 +3,7 @@ * Copyright (C) 2014-2017 - Jean-André Santoni * Copyright (C) 2016-2019 - Brad Parker * Copyright (C) 2018 - Alfredo Monclús - * Copyright (C) 2018 - natinusala + * Copyright (C) 2018-2020 - natinusala * Copyright (C) 2019 - Patrick Scheurenbrand * * RetroArch is free software: you can redistribute it and/or modify it under the terms @@ -128,19 +128,19 @@ static void ozone_sidebar_collapse_end(void *userdata) static float ozone_sidebar_get_scroll_y( ozone_handle_t *ozone, unsigned video_height) { - float scroll_y = + float scroll_y = ozone->animations.scroll_y_sidebar; - float selected_position_y = + float selected_position_y = ozone_get_selected_sidebar_y_position(ozone); - float current_selection_middle_onscreen = - ozone->dimensions.header_height - + ozone->dimensions.spacer_1px - + ozone->animations.scroll_y_sidebar - + selected_position_y + float current_selection_middle_onscreen = + ozone->dimensions.header_height + + ozone->dimensions.spacer_1px + + ozone->animations.scroll_y_sidebar + + selected_position_y + ozone->dimensions.sidebar_entry_height / 2.0f; - float bottom_boundary = - (float)video_height - - (ozone->dimensions.header_height + ozone->dimensions.spacer_1px) + float bottom_boundary = + (float)video_height + - (ozone->dimensions.header_height + ozone->dimensions.spacer_1px) - ozone->dimensions.footer_height; float entries_middle = (float)video_height / 2.0f; float entries_height = ozone_get_sidebar_height(ozone); @@ -171,7 +171,7 @@ void ozone_draw_sidebar( unsigned i, sidebar_height; gfx_animation_ctx_ticker_t ticker; gfx_animation_ctx_ticker_smooth_t ticker_smooth; - static const char* const + static const char* const ticker_spacer = OZONE_TICKER_SPACER; unsigned ticker_x_offset = 0; settings_t *settings = config_get_ptr(); @@ -305,10 +305,10 @@ void ozone_draw_sidebar( video_width, video_height, ozone->sidebar_offset + ozone->dimensions.sidebar_padding_horizontal + ozone->dimensions.spacer_3px, - entry_width - ozone->dimensions.spacer_5px, - ozone->dimensions.sidebar_entry_height + ozone->dimensions.spacer_1px, - selection_old_y + ozone->animations.scroll_y_sidebar, - 1-ozone->animations.cursor_alpha); + entry_width - ozone->dimensions.spacer_5px, + ozone->dimensions.sidebar_entry_height + ozone->dimensions.spacer_1px, + selection_old_y + ozone->animations.scroll_y_sidebar, + 1-ozone->animations.cursor_alpha); /* Menu tabs */ y = ozone->dimensions.header_height + ozone->dimensions.spacer_1px + ozone->dimensions.sidebar_padding_vertical;