2018-11-22 15:45:52 +01:00
/* RetroArch - A frontend for libretro.
* Copyright ( C ) 2014 - 2017 - Jean - André Santoni
2019-04-11 17:35:13 +02:00
* Copyright ( C ) 2015 - 2018 - Andre Leiradella
2020-03-09 14:18:29 +01:00
* Copyright ( C ) 2018 - 2020 - natinusala
2018-11-22 15:45:52 +01:00
*
* 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 -
* ation , either version 3 of the License , or ( at your option ) any later version .
*
* RetroArch is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE . See the GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along with RetroArch .
* If not , see < http : //www.gnu.org/licenses/>.
*/
2020-01-12 21:46:28 +01:00
# include <retro_miscellaneous.h>
# include <lists/file_list.h>
# include <queues/fifo_queue.h>
# include <file/file_path.h>
# include <streams/file_stream.h>
# include <string/stdstring.h>
2020-02-15 01:54:44 +01:00
# include <retro_math.h>
2020-01-12 21:46:28 +01:00
2020-02-28 08:49:00 -07:00
# ifdef HAVE_THREADS
# include <rthreads/rthreads.h>
# define SLOCK_LOCK(x) slock_lock(x)
# define SLOCK_UNLOCK(x) slock_unlock(x)
# else
# define SLOCK_LOCK(x)
# define SLOCK_UNLOCK(x)
# endif
2020-02-17 01:54:07 +01:00
# include "gfx_widgets.h"
# include "gfx_display.h"
# include "font_driver.h"
2018-11-22 15:45:52 +01:00
2020-02-17 01:54:07 +01:00
# include "../msg_hash.h"
2018-11-22 15:45:52 +01:00
2020-02-17 01:54:07 +01:00
# include "../tasks/task_content.h"
2018-11-22 15:45:52 +01:00
2020-02-23 10:38:27 -07:00
# ifdef HAVE_CHEEVOS
# include "../cheevos-new/badges.h"
# endif
2019-04-11 16:46:29 +02:00
/* TODO: Fix context reset freezing everything in place (probably kills animations when it shouldn't anymore) */
2019-02-21 10:23:21 +01:00
static float msg_queue_background [ 16 ] = COLOR_HEX_TO_FLOAT ( 0x3A3A3A , 1.0f ) ;
static float msg_queue_info [ 16 ] = COLOR_HEX_TO_FLOAT ( 0x12ACF8 , 1.0f ) ;
/* TODO: Colors for warning, error and success */
2019-05-21 17:22:02 +02:00
static float msg_queue_task_progress_1 [ 16 ] = COLOR_HEX_TO_FLOAT ( 0x397869 , 1.0f ) ; /* Color of first progress bar in a task message */
static float msg_queue_task_progress_2 [ 16 ] = COLOR_HEX_TO_FLOAT ( 0x317198 , 1.0f ) ; /* Color of second progress bar in a task message (for multiple tasks with same message) */
2019-02-21 10:23:21 +01:00
2020-01-19 06:04:37 +01:00
#if 0
2019-02-21 10:23:21 +01:00
static float color_task_progress_bar [ 16 ] = COLOR_HEX_TO_FLOAT ( 0x22B14C , 1.0f ) ;
2020-01-19 06:04:37 +01:00
# endif
2019-02-21 10:23:21 +01:00
static float volume_bar_background [ 16 ] = COLOR_HEX_TO_FLOAT ( 0x1A1A1A , 1.0f ) ;
static float volume_bar_normal [ 16 ] = COLOR_HEX_TO_FLOAT ( 0x198AC6 , 1.0f ) ;
static float volume_bar_loud [ 16 ] = COLOR_HEX_TO_FLOAT ( 0xF5DD19 , 1.0f ) ;
static float volume_bar_loudest [ 16 ] = COLOR_HEX_TO_FLOAT ( 0xC23B22 , 1.0f ) ;
2020-02-23 11:03:38 +01:00
static uint64_t gfx_widgets_frame_count = 0 ;
2019-02-21 10:23:21 +01:00
/* Font data */
2020-02-23 11:03:38 +01:00
static font_data_t * font_regular = NULL ;
static font_data_t * font_bold = NULL ;
2019-02-21 10:23:21 +01:00
2020-03-09 19:35:49 +01:00
font_data_t * gfx_widgets_get_font_regular ( void )
2020-03-09 14:18:29 +01:00
{
return font_regular ;
}
2020-03-09 19:35:49 +01:00
font_data_t * gfx_widgets_get_font_bold ( void )
2020-03-09 14:18:29 +01:00
{
return font_bold ;
}
2019-02-21 10:23:21 +01:00
static video_font_raster_block_t font_raster_regular ;
static video_font_raster_block_t font_raster_bold ;
2020-02-17 01:43:40 +01:00
static float gfx_widgets_pure_white [ 16 ] = {
2019-02-21 10:23:21 +01:00
1.00 , 1.00 , 1.00 , 1.00 ,
1.00 , 1.00 , 1.00 , 1.00 ,
1.00 , 1.00 , 1.00 , 1.00 ,
1.00 , 1.00 , 1.00 , 1.00 ,
} ;
2020-03-09 14:18:29 +01:00
float * gfx_widgets_get_pure_white ( void )
{
return gfx_widgets_pure_white ;
}
2019-09-23 09:22:35 +02:00
/* FPS */
2020-02-23 11:03:38 +01:00
static char gfx_widgets_fps_text [ 255 ] = { 0 } ;
2019-09-23 09:22:35 +02:00
2020-02-16 18:11:50 +01:00
# ifdef HAVE_CHEEVOS
2019-04-11 16:46:29 +02:00
/* Achievement notification */
2020-02-28 08:49:00 -07:00
typedef struct cheevo_popup
{
char * title ;
uintptr_t badge ;
} cheevo_popup ;
# define CHEEVO_QUEUE_SIZE 8
static cheevo_popup cheevo_popup_queue [ CHEEVO_QUEUE_SIZE ] ;
static int cheevo_popup_queue_read_index = - 1 ;
static int cheevo_popup_queue_write_index = 0 ;
# ifdef HAVE_THREADS
slock_t * cheevo_popup_queue_lock = NULL ;
# endif
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
static float cheevo_unfold = 0.0f ;
2020-02-16 18:24:45 +01:00
static gfx_timer_t cheevo_timer ;
2019-04-11 16:46:29 +02:00
static float cheevo_y = 0.0f ;
static unsigned cheevo_width = 0 ;
static unsigned cheevo_height = 0 ;
2020-02-28 08:49:00 -07:00
static void gfx_widgets_start_achievement_notification ( void ) ;
2020-02-16 18:11:50 +01:00
# endif
2019-04-11 16:46:29 +02:00
2020-02-17 00:42:49 +01:00
# ifdef HAVE_MENU
2019-02-21 10:23:21 +01:00
/* Load content animation */
# define ANIMATION_LOAD_CONTENT_DURATION 333
# define LOAD_CONTENT_ANIMATION_INITIAL_ICON_SIZE 320
# define LOAD_CONTENT_ANIMATION_TARGET_ICON_SIZE 240
static bool load_content_animation_running = false ;
static char * load_content_animation_content_name = NULL ;
static char * load_content_animation_playlist_name = NULL ;
2020-02-17 21:28:42 +01:00
static uintptr_t load_content_animation_icon = 0 ;
2019-02-21 10:23:21 +01:00
static float load_content_animation_icon_color [ 16 ] ;
static float load_content_animation_icon_size ;
static float load_content_animation_icon_alpha ;
static float load_content_animation_fade_alpha ;
static float load_content_animation_final_fade_alpha ;
2020-02-16 18:24:45 +01:00
static gfx_timer_t load_content_animation_end_timer ;
2019-02-21 10:23:21 +01:00
2020-02-17 00:42:49 +01:00
static unsigned load_content_animation_icon_size_initial ;
static unsigned load_content_animation_icon_size_target ;
# endif
2020-02-17 01:43:40 +01:00
static float gfx_widgets_backdrop_orig [ 16 ] = {
2019-02-21 10:23:21 +01:00
0.00 , 0.00 , 0.00 , 0.75 ,
0.00 , 0.00 , 0.00 , 0.75 ,
0.00 , 0.00 , 0.00 , 0.75 ,
0.00 , 0.00 , 0.00 , 0.75 ,
} ;
2020-03-09 14:18:29 +01:00
float * gfx_widgets_get_backdrop_orig ( void )
{
return gfx_widgets_backdrop_orig ;
}
2020-02-17 01:43:40 +01:00
static float gfx_widgets_backdrop [ 16 ] = {
2019-02-21 10:23:21 +01:00
0.00 , 0.00 , 0.00 , 0.75 ,
0.00 , 0.00 , 0.00 , 0.75 ,
0.00 , 0.00 , 0.00 , 0.75 ,
0.00 , 0.00 , 0.00 , 0.75 ,
} ;
/* Messages queue */
typedef struct menu_widget_msg
{
char * msg ;
char * msg_new ;
float msg_transition_animation ;
unsigned msg_len ;
unsigned duration ;
unsigned text_height ;
float offset_y ;
float alpha ;
2020-02-23 11:03:38 +01:00
/* Is it currently doing the fade out animation ? */
bool dying ;
/* Has the timer expired ? if so, should be set to dying */
bool expired ;
2019-02-21 10:23:21 +01:00
unsigned width ;
2020-02-16 18:24:45 +01:00
gfx_timer_t expiration_timer ;
2019-02-21 10:23:21 +01:00
bool expiration_timer_started ;
retro_task_t * task_ptr ;
2020-02-23 11:03:38 +01:00
/* Used to detect title change */
char * task_title_ptr ;
/* How many tasks have used this notification? */
uint8_t task_count ;
2019-02-21 10:23:21 +01:00
int8_t task_progress ;
bool task_finished ;
bool task_error ;
bool task_cancelled ;
uint32_t task_ident ;
2020-02-23 11:03:38 +01:00
/* Unfold animation */
bool unfolded ;
2019-02-21 10:23:21 +01:00
bool unfolding ;
float unfold ;
float hourglass_rotation ;
2020-02-16 18:24:45 +01:00
gfx_timer_t hourglass_timer ;
2019-02-21 10:23:21 +01:00
} menu_widget_msg_t ;
2020-02-23 11:03:38 +01:00
static fifo_buffer_t * msg_queue = NULL ;
static file_list_t * current_msgs = NULL ;
static unsigned msg_queue_kill = 0 ;
2019-02-21 10:23:21 +01:00
2020-02-23 11:03:38 +01:00
/* Count of messages bound to a task in current_msgs */
static unsigned msg_queue_tasks_count = 0 ;
2019-02-21 10:23:21 +01:00
/* TODO: Don't display icons if assets are missing */
2020-02-17 21:28:42 +01:00
static uintptr_t msg_queue_icon = 0 ;
static uintptr_t msg_queue_icon_outline = 0 ;
static uintptr_t msg_queue_icon_rect = 0 ;
2019-02-21 10:23:21 +01:00
static bool msg_queue_has_icons = false ;
2020-03-09 14:18:29 +01:00
extern gfx_animation_ctx_tag gfx_widgets_generic_tag ;
gfx_animation_ctx_tag gfx_widgets_get_generic_tag ( void )
{
return gfx_widgets_generic_tag ;
}
2019-08-15 14:56:38 +02:00
2020-02-23 11:03:38 +01:00
/* There can only be one message animation at a time to
* avoid confusing users */
2020-02-16 18:29:34 +01:00
static bool widgets_moving = false ;
2019-02-21 10:23:21 +01:00
/* Icons */
2020-02-17 01:43:40 +01:00
enum gfx_widgets_icon
2019-02-21 10:23:21 +01:00
{
MENU_WIDGETS_ICON_VOLUME_MED = 0 ,
MENU_WIDGETS_ICON_VOLUME_MAX ,
MENU_WIDGETS_ICON_VOLUME_MIN ,
MENU_WIDGETS_ICON_VOLUME_MUTE ,
MENU_WIDGETS_ICON_PAUSED ,
MENU_WIDGETS_ICON_FAST_FORWARD ,
MENU_WIDGETS_ICON_REWIND ,
MENU_WIDGETS_ICON_SLOW_MOTION ,
MENU_WIDGETS_ICON_HOURGLASS ,
MENU_WIDGETS_ICON_CHECK ,
MENU_WIDGETS_ICON_INFO ,
2019-04-11 16:46:29 +02:00
MENU_WIDGETS_ICON_ACHIEVEMENT ,
2019-05-04 15:58:32 +02:00
MENU_WIDGETS_ICON_LAST
2019-02-21 10:23:21 +01:00
} ;
2020-02-17 01:43:40 +01:00
static const char * gfx_widgets_icons_names [ MENU_WIDGETS_ICON_LAST ] = {
2019-02-21 10:23:21 +01:00
" menu_volume_med.png " ,
" menu_volume_max.png " ,
" menu_volume_min.png " ,
" menu_volume_mute.png " ,
" menu_pause.png " ,
" menu_frameskip.png " ,
" menu_rewind.png " ,
" resume.png " ,
" menu_hourglass.png " ,
" menu_check.png " ,
2019-04-11 16:46:29 +02:00
" menu_info.png " ,
" menu_achievements.png "
2019-02-21 10:23:21 +01:00
} ;
2020-02-23 11:03:38 +01:00
static uintptr_t gfx_widgets_icons_textures [
MENU_WIDGETS_ICON_LAST ] = { 0 } ;
2019-02-21 10:23:21 +01:00
/* Volume */
2020-02-16 18:29:34 +01:00
static float volume_db = 0.0f ;
static float volume_percent = 1.0f ;
static gfx_timer_t volume_timer = 0.0f ;
2019-02-21 10:23:21 +01:00
2020-02-16 18:29:34 +01:00
static float volume_alpha = 0.0f ;
static float volume_text_alpha = 0.0f ;
static gfx_animation_ctx_tag volume_tag = ( uintptr_t ) & volume_alpha ;
static bool volume_mute = false ;
2019-02-21 10:23:21 +01:00
2020-02-23 11:03:38 +01:00
# ifdef HAVE_TRANSLATE
2019-10-23 14:15:14 -07:00
/* AI Service Overlay */
2020-02-17 21:28:42 +01:00
static int ai_service_overlay_state = 0 ;
static unsigned ai_service_overlay_width = 0 ;
static unsigned ai_service_overlay_height = 0 ;
static uintptr_t ai_service_overlay_texture = 0 ;
2020-02-23 11:03:38 +01:00
# endif
2019-10-23 14:15:14 -07:00
2019-05-04 23:21:17 +02:00
/* Generic message */
2020-02-16 18:29:34 +01:00
static gfx_timer_t generic_message_timer ;
2020-02-23 11:03:38 +01:00
static float generic_message_alpha = 0.0f ;
static char generic_message [ 256 ] = { ' \0 ' } ;
2019-05-11 17:24:00 +02:00
/* Libretro message */
2020-02-16 18:29:34 +01:00
static gfx_timer_t libretro_message_timer ;
2020-02-23 11:03:38 +01:00
static char libretro_message [ 512 ] = { ' \0 ' } ;
2019-05-04 23:21:17 +02:00
2019-02-21 10:23:21 +01:00
/* Metrics */
2020-02-13 17:26:16 +00:00
# define BASE_FONT_SIZE 32.0f
2020-02-23 11:03:38 +01:00
static float libretro_message_alpha = 0.0f ;
static float last_scale_factor = 0.0f ;
static float msg_queue_text_scale_factor = 0.0f ;
2020-02-16 18:29:34 +01:00
static float widget_font_size = 0.0f ;
2020-02-23 11:03:38 +01:00
2020-03-09 14:18:29 +01:00
float gfx_widgets_get_font_size ( void )
{
return widget_font_size ;
}
2020-02-16 18:29:34 +01:00
static unsigned simple_widget_padding = 0 ;
static unsigned simple_widget_height = 0 ;
static unsigned glyph_width = 0 ;
2019-02-21 10:23:21 +01:00
2020-03-09 14:18:29 +01:00
unsigned gfx_widgets_get_padding ( void )
{
return simple_widget_padding ;
}
unsigned gfx_widgets_get_height ( void )
{
return simple_widget_height ;
}
unsigned gfx_widgets_get_glyph_width ( void )
{
return glyph_width ;
}
2020-02-23 11:03:38 +01:00
static unsigned libretro_message_width = 0 ;
2019-02-21 10:23:21 +01:00
static unsigned msg_queue_height ;
static unsigned msg_queue_icon_size_x ;
static unsigned msg_queue_icon_size_y ;
static unsigned msg_queue_spacing ;
static unsigned msg_queue_glyph_width ;
static unsigned msg_queue_rect_start_x ;
static unsigned msg_queue_internal_icon_size ;
static unsigned msg_queue_internal_icon_offset ;
static unsigned msg_queue_icon_offset_y ;
static unsigned msg_queue_scissor_start_x ;
2020-02-04 16:07:06 +00:00
static unsigned msg_queue_default_rect_width_menu_alive ;
2019-02-21 10:23:21 +01:00
static unsigned msg_queue_default_rect_width ;
static unsigned msg_queue_task_text_start_x ;
static unsigned msg_queue_regular_padding_x ;
static unsigned msg_queue_regular_text_start ;
static unsigned msg_queue_regular_text_base_y ;
static unsigned msg_queue_task_rect_start_x ;
static unsigned msg_queue_task_hourglass_x ;
2020-02-16 18:29:34 +01:00
/* Used for both generic and libretro messages */
static unsigned generic_message_height ;
2019-05-11 17:24:00 +02:00
2020-03-03 17:07:27 +00:00
static unsigned volume_widget_width ;
static unsigned volume_widget_height ;
2020-02-23 11:03:38 +01:00
static unsigned divider_width_1px = 1 ;
2020-02-13 17:26:16 +00:00
2020-02-23 11:03:38 +01:00
static unsigned last_video_width = 0 ;
static unsigned last_video_height = 0 ;
2020-02-13 17:26:16 +00:00
2020-03-09 10:32:12 +01:00
/* Widgets list */
const static gfx_widget_t * const widgets [ ] = {
& gfx_widget_screenshot
} ;
static const size_t widgets_len = sizeof ( widgets ) / sizeof ( widgets [ 0 ] ) ;
2019-02-21 10:23:21 +01:00
static void msg_widget_msg_transition_animation_done ( void * userdata )
{
2020-02-23 11:03:38 +01:00
menu_widget_msg_t * msg = ( menu_widget_msg_t * ) userdata ;
2019-02-21 10:23:21 +01:00
2020-01-08 14:19:10 +00:00
if ( msg - > msg )
free ( msg - > msg ) ;
msg - > msg = NULL ;
if ( msg - > msg_new )
msg - > msg = strdup ( msg - > msg_new ) ;
2019-02-21 10:23:21 +01:00
msg - > msg_transition_animation = 0.0f ;
}
2020-02-17 01:43:40 +01:00
void gfx_widgets_msg_queue_push (
2019-06-18 01:23:23 +02:00
retro_task_t * task , const char * msg ,
2019-02-21 10:23:21 +01:00
unsigned duration ,
char * title ,
2019-06-18 01:23:23 +02:00
enum message_queue_icon icon ,
enum message_queue_category category ,
2020-02-17 16:07:37 +01:00
unsigned prio , bool flush ,
bool menu_is_alive )
2019-02-21 10:23:21 +01:00
{
menu_widget_msg_t * msg_widget = NULL ;
if ( fifo_write_avail ( msg_queue ) > 0 )
{
/* Get current msg if it exists */
2019-05-04 14:07:09 +02:00
if ( task & & task - > frontend_userdata )
2019-02-21 10:23:21 +01:00
{
2020-02-23 11:03:38 +01:00
msg_widget = ( menu_widget_msg_t * ) task - > frontend_userdata ;
2020-02-16 18:29:34 +01:00
/* msg_widgets can be passed between tasks */
msg_widget - > task_ptr = task ;
2019-02-21 10:23:21 +01:00
}
/* Spawn a new notification */
2019-05-04 14:07:09 +02:00
if ( ! msg_widget )
2019-02-21 10:23:21 +01:00
{
2019-05-04 14:07:09 +02:00
const char * title = msg ;
2019-02-21 10:23:21 +01:00
2019-05-04 14:07:09 +02:00
msg_widget = ( menu_widget_msg_t * ) calloc ( 1 , sizeof ( * msg_widget ) ) ;
2019-02-21 10:23:21 +01:00
2019-06-18 01:23:23 +02:00
if ( task )
2019-05-04 14:07:09 +02:00
title = task - > title ;
2019-02-21 10:23:21 +01:00
msg_widget - > duration = duration ;
msg_widget - > offset_y = 0 ;
msg_widget - > alpha = 1.0f ;
msg_widget - > dying = false ;
msg_widget - > expired = false ;
msg_widget - > expiration_timer = 0 ;
msg_widget - > task_ptr = task ;
msg_widget - > expiration_timer_started = false ;
msg_widget - > msg_new = NULL ;
msg_widget - > msg_transition_animation = 0.0f ;
msg_widget - > text_height = 0 ;
if ( msg_queue_has_icons )
{
msg_widget - > unfolded = false ;
msg_widget - > unfolding = false ;
msg_widget - > unfold = 0.0f ;
}
else
{
msg_widget - > unfolded = true ;
msg_widget - > unfolding = false ;
msg_widget - > unfold = 1.0f ;
}
if ( task )
{
2019-04-30 10:01:07 +02:00
msg_widget - > msg = strdup ( title ) ;
2019-12-23 17:34:44 +00:00
msg_widget - > msg_new = strdup ( title ) ;
2019-06-22 13:44:10 +02:00
msg_widget - > msg_len = ( unsigned ) strlen ( title ) ;
2019-02-21 10:23:21 +01:00
2020-03-05 16:32:15 +01:00
msg_widget - > task_error = ! string_is_empty ( task - > error ) ;
2019-04-30 10:01:07 +02:00
msg_widget - > task_cancelled = task - > cancelled ;
msg_widget - > task_finished = task - > finished ;
msg_widget - > task_progress = task - > progress ;
msg_widget - > task_ident = task - > ident ;
msg_widget - > task_title_ptr = task - > title ;
msg_widget - > task_count = 1 ;
msg_widget - > unfolded = true ;
2019-02-21 10:23:21 +01:00
2020-02-16 18:29:34 +01:00
msg_widget - > width = font_driver_get_message_width (
font_regular , title , msg_widget - > msg_len ,
msg_queue_text_scale_factor ) + simple_widget_padding / 2 ;
2019-02-21 10:23:21 +01:00
2019-04-30 10:01:07 +02:00
task - > frontend_userdata = msg_widget ;
2019-02-21 10:23:21 +01:00
2019-04-30 10:01:07 +02:00
msg_widget - > hourglass_rotation = 0 ;
2019-02-21 10:23:21 +01:00
}
else
{
/* Compute rect width, wrap if necessary */
2020-02-16 18:29:34 +01:00
/* Single line text > two lines text > two lines
* text with expanded width */
2019-06-22 13:44:10 +02:00
unsigned title_length = ( unsigned ) strlen ( title ) ;
2019-02-21 10:23:21 +01:00
char * msg = strdup ( title ) ;
2020-02-17 16:07:37 +01:00
unsigned width = menu_is_alive
2020-02-16 18:29:34 +01:00
? msg_queue_default_rect_width_menu_alive
: msg_queue_default_rect_width ;
unsigned text_width = font_driver_get_message_width (
font_regular , title , title_length , msg_queue_text_scale_factor ) ;
msg_widget - > text_height = msg_queue_text_scale_factor
* widget_font_size ;
2019-02-21 10:23:21 +01:00
/* Text is too wide, split it into two lines */
if ( text_width > width )
{
2020-02-04 16:07:06 +00:00
/* If the second line is too short, the widget may
* look unappealing - ensure that second line is at
* least 25 % of the total width */
if ( ( text_width - ( text_width > > 2 ) ) < width )
width = text_width - ( text_width > > 2 ) ;
2019-02-21 10:23:21 +01:00
2020-02-16 18:29:34 +01:00
word_wrap ( msg , msg , ( title_length * width ) / text_width ,
false , 2 ) ;
2019-02-21 10:23:21 +01:00
msg_widget - > text_height * = 2.5f ;
}
else
{
width = text_width ;
msg_widget - > text_height * = 1.35f ;
}
msg_widget - > msg = msg ;
2019-06-22 13:44:10 +02:00
msg_widget - > msg_len = ( unsigned ) strlen ( msg ) ;
2019-02-21 10:23:21 +01:00
msg_widget - > width = width + simple_widget_padding / 2 ;
}
fifo_write ( msg_queue , & msg_widget , sizeof ( msg_widget ) ) ;
}
/* Update task info */
else
{
if ( msg_widget - > expiration_timer_started )
{
2020-02-16 18:24:45 +01:00
gfx_timer_kill ( & msg_widget - > expiration_timer ) ;
2019-02-21 10:23:21 +01:00
msg_widget - > expiration_timer_started = false ;
}
2019-12-23 17:34:44 +00:00
if ( ! string_is_equal ( task - > title , msg_widget - > msg_new ) )
2019-02-21 10:23:21 +01:00
{
2019-06-22 13:44:10 +02:00
unsigned len = ( unsigned ) strlen ( task - > title ) ;
2020-02-16 18:29:34 +01:00
unsigned new_width = font_driver_get_message_width (
font_regular , task - > title , len , msg_queue_text_scale_factor ) ;
2019-02-21 10:23:21 +01:00
if ( msg_widget - > msg_new )
2019-05-11 06:26:40 +02:00
{
2019-02-21 10:23:21 +01:00
free ( msg_widget - > msg_new ) ;
2019-05-11 06:26:40 +02:00
msg_widget - > msg_new = NULL ;
}
2019-02-21 10:23:21 +01:00
msg_widget - > msg_new = strdup ( task - > title ) ;
msg_widget - > msg_len = len ;
msg_widget - > task_title_ptr = task - > title ;
msg_widget - > msg_transition_animation = 0 ;
2019-04-30 13:22:05 +02:00
if ( ! task - > alternative_look )
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2019-04-30 13:22:05 +02:00
2019-07-24 19:30:17 +02:00
entry . easing_enum = EASING_OUT_QUAD ;
2020-02-23 11:03:38 +01:00
entry . tag = ( uintptr_t ) msg_widget ;
2019-07-24 19:30:17 +02:00
entry . duration = MSG_QUEUE_ANIMATION_DURATION * 2 ;
entry . target_value = msg_queue_height / 2.0f ;
entry . subject = & msg_widget - > msg_transition_animation ;
entry . cb = msg_widget_msg_transition_animation_done ;
entry . userdata = msg_widget ;
2019-04-30 10:01:07 +02:00
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-04-30 13:22:05 +02:00
}
else
{
msg_widget_msg_transition_animation_done ( msg_widget ) ;
}
2019-02-21 10:23:21 +01:00
msg_widget - > task_count + + ;
2019-06-26 09:45:51 +02:00
msg_widget - > width = new_width ;
2019-02-21 10:23:21 +01:00
}
2020-03-05 16:32:15 +01:00
msg_widget - > task_error = ! string_is_empty ( task - > error ) ;
2019-02-21 10:23:21 +01:00
msg_widget - > task_cancelled = task - > cancelled ;
msg_widget - > task_finished = task - > finished ;
msg_widget - > task_progress = task - > progress ;
}
}
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_unfold_end ( void * userdata )
2019-02-21 10:23:21 +01:00
{
2020-02-23 11:03:38 +01:00
menu_widget_msg_t * unfold = ( menu_widget_msg_t * ) userdata ;
2019-02-21 10:23:21 +01:00
2020-02-23 11:03:38 +01:00
unfold - > unfolding = false ;
widgets_moving = false ;
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_move_end ( void * userdata )
2019-02-21 10:23:21 +01:00
{
if ( userdata )
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2020-02-23 11:03:38 +01:00
menu_widget_msg_t * unfold = ( menu_widget_msg_t * ) userdata ;
2019-02-21 10:23:21 +01:00
2020-02-17 01:43:40 +01:00
entry . cb = gfx_widgets_unfold_end ;
2019-02-21 10:23:21 +01:00
entry . duration = MSG_QUEUE_ANIMATION_DURATION ;
entry . easing_enum = EASING_OUT_QUAD ;
entry . subject = & unfold - > unfold ;
2020-02-23 11:03:38 +01:00
entry . tag = ( uintptr_t ) unfold ;
2019-02-21 10:23:21 +01:00
entry . target_value = 1.0f ;
entry . userdata = unfold ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-02-21 10:23:21 +01:00
unfold - > unfolded = true ;
unfold - > unfolding = true ;
}
else
widgets_moving = false ;
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_msg_queue_expired ( void * userdata )
2019-02-21 10:23:21 +01:00
{
2020-02-23 11:03:38 +01:00
menu_widget_msg_t * msg = ( menu_widget_msg_t * ) userdata ;
2019-02-21 10:23:21 +01:00
if ( msg & & ! msg - > expired )
msg - > expired = true ;
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_msg_queue_move ( void )
2019-02-21 10:23:21 +01:00
{
int i ;
float y = 0 ;
2020-02-16 18:11:50 +01:00
/* there should always be one and only one unfolded message */
menu_widget_msg_t * unfold = NULL ;
2019-02-21 10:23:21 +01:00
if ( current_msgs - > size = = 0 )
return ;
2019-06-24 15:03:58 +02:00
for ( i = ( int ) ( current_msgs - > size - 1 ) ; i > = 0 ; i - - )
2019-02-21 10:23:21 +01:00
{
2019-04-21 00:31:31 +02:00
menu_widget_msg_t * msg = ( menu_widget_msg_t * )
2020-02-23 11:13:48 +01:00
current_msgs - > list [ i ] . userdata ;
2019-02-21 10:23:21 +01:00
if ( ! msg | | msg - > dying )
continue ;
y + = msg_queue_height / ( msg - > task_ptr ? 2 : 1 ) + msg_queue_spacing ;
if ( ! msg - > unfolded )
unfold = msg ;
if ( msg - > offset_y ! = y )
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2019-02-21 10:23:21 +01:00
2020-02-17 01:43:40 +01:00
entry . cb = ( i = = 0 ) ? gfx_widgets_move_end : NULL ;
2019-02-21 10:23:21 +01:00
entry . duration = MSG_QUEUE_ANIMATION_DURATION ;
entry . easing_enum = EASING_OUT_QUAD ;
entry . subject = & msg - > offset_y ;
2020-02-23 11:03:38 +01:00
entry . tag = ( uintptr_t ) msg ;
2019-02-21 10:23:21 +01:00
entry . target_value = y ;
2019-07-24 19:30:17 +02:00
entry . userdata = unfold ;
2019-02-21 10:23:21 +01:00
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-02-21 10:23:21 +01:00
widgets_moving = true ;
}
}
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_msg_queue_free ( menu_widget_msg_t * msg , bool touch_list )
2019-02-21 10:23:21 +01:00
{
2019-05-04 14:48:33 +02:00
size_t i ;
2020-02-23 11:03:38 +01:00
gfx_animation_ctx_tag tag = ( uintptr_t ) msg ;
2019-02-21 10:23:21 +01:00
if ( msg - > task_ptr )
2019-05-11 06:26:40 +02:00
{
/* remove the reference the task has of ourself
only if the task is not finished already
( finished tasks are freed before the widget ) */
if ( ! msg - > task_finished & & ! msg - > task_error & & ! msg - > task_cancelled )
msg - > task_ptr - > frontend_userdata = NULL ;
/* update tasks count */
2019-02-21 10:23:21 +01:00
msg_queue_tasks_count - - ;
2019-05-11 06:26:40 +02:00
}
2019-02-21 10:23:21 +01:00
/* Kill all animations */
2020-02-16 18:24:45 +01:00
gfx_timer_kill ( & msg - > hourglass_timer ) ;
2020-02-16 14:01:34 +01:00
gfx_animation_kill_by_tag ( & tag ) ;
2019-02-21 10:23:21 +01:00
2019-07-24 19:30:17 +02:00
/* Kill all timers */
if ( msg - > expiration_timer_started )
2020-02-16 18:24:45 +01:00
gfx_timer_kill ( & msg - > expiration_timer ) ;
2019-07-24 19:30:17 +02:00
2019-02-21 10:23:21 +01:00
/* Free it */
if ( msg - > msg )
free ( msg - > msg ) ;
2019-12-23 17:34:44 +00:00
if ( msg - > msg_new )
free ( msg - > msg_new ) ;
2019-02-21 10:23:21 +01:00
/* Remove it from the list */
if ( touch_list )
{
file_list_free_userdata ( current_msgs , msg_queue_kill ) ;
for ( i = msg_queue_kill ; i < current_msgs - > size - 1 ; i + + )
current_msgs - > list [ i ] = current_msgs - > list [ i + 1 ] ;
current_msgs - > size - - ;
}
widgets_moving = false ;
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_msg_queue_kill_end ( void * userdata )
2019-02-21 10:23:21 +01:00
{
2019-04-21 00:31:31 +02:00
menu_widget_msg_t * msg = ( menu_widget_msg_t * )
2020-02-23 11:13:48 +01:00
current_msgs - > list [ msg_queue_kill ] . userdata ;
2019-02-21 10:23:21 +01:00
if ( ! msg )
return ;
2020-02-17 01:43:40 +01:00
gfx_widgets_msg_queue_free ( msg , true ) ;
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_msg_queue_kill ( unsigned idx )
2019-02-21 10:23:21 +01:00
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2019-04-21 00:31:31 +02:00
menu_widget_msg_t * msg = ( menu_widget_msg_t * )
2020-02-23 11:13:48 +01:00
current_msgs - > list [ idx ] . userdata ;
2019-02-21 10:23:21 +01:00
if ( ! msg )
return ;
widgets_moving = true ;
msg - > dying = true ;
msg_queue_kill = idx ;
/* Drop down */
entry . cb = NULL ;
entry . duration = MSG_QUEUE_ANIMATION_DURATION ;
entry . easing_enum = EASING_OUT_QUAD ;
2020-02-23 11:03:38 +01:00
entry . tag = ( uintptr_t ) msg ;
2019-02-21 10:23:21 +01:00
entry . userdata = NULL ;
entry . subject = & msg - > offset_y ;
entry . target_value = msg - > offset_y - msg_queue_height / 4 ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-02-21 10:23:21 +01:00
/* Fade out */
2020-02-17 01:43:40 +01:00
entry . cb = gfx_widgets_msg_queue_kill_end ;
2019-02-21 10:23:21 +01:00
entry . subject = & msg - > alpha ;
entry . target_value = 0.0f ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-02-21 10:23:21 +01:00
/* Move all messages back to their correct position */
2020-02-17 01:43:40 +01:00
gfx_widgets_msg_queue_move ( ) ;
2019-02-21 10:23:21 +01:00
}
2020-03-09 14:18:29 +01:00
void gfx_widgets_draw_icon (
2020-03-09 00:18:38 +01:00
void * userdata ,
unsigned video_width ,
unsigned video_height ,
2019-02-21 10:23:21 +01:00
unsigned icon_width ,
unsigned icon_height ,
uintptr_t texture ,
float x , float y ,
unsigned width , unsigned height ,
float rotation , float scale_factor ,
float * color )
{
2020-02-16 15:10:07 +01:00
gfx_display_ctx_rotate_draw_t rotate_draw ;
gfx_display_ctx_draw_t draw ;
2019-02-21 10:23:21 +01:00
struct video_coords coords ;
math_matrix_4x4 mymat ;
if ( ! texture )
return ;
rotate_draw . matrix = & mymat ;
rotate_draw . rotation = rotation ;
rotate_draw . scale_x = scale_factor ;
rotate_draw . scale_y = scale_factor ;
rotate_draw . scale_z = 1 ;
rotate_draw . scale_enable = true ;
2020-03-09 00:18:38 +01:00
gfx_display_rotate_z ( & rotate_draw , userdata ) ;
2019-02-21 10:23:21 +01:00
coords . vertices = 4 ;
coords . vertex = NULL ;
coords . tex_coord = NULL ;
coords . lut_tex_coord = NULL ;
coords . color = color ;
draw . x = x ;
draw . y = height - y - icon_height ;
draw . width = icon_width ;
draw . height = icon_height ;
draw . scale_factor = scale_factor ;
draw . rotation = rotation ;
draw . coords = & coords ;
draw . matrix_data = & mymat ;
draw . texture = texture ;
2020-02-16 15:10:07 +01:00
draw . prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP ;
2019-02-21 10:23:21 +01:00
draw . pipeline . id = 0 ;
2020-03-09 00:18:38 +01:00
gfx_display_draw ( & draw , userdata ,
video_width , video_height ) ;
2019-02-21 10:23:21 +01:00
}
2020-02-23 11:03:38 +01:00
# ifdef HAVE_TRANSLATE
2020-02-17 01:43:40 +01:00
static void gfx_widgets_draw_icon_blend (
2020-03-09 00:25:28 +01:00
void * userdata ,
unsigned video_width ,
unsigned video_height ,
2019-10-23 14:15:14 -07:00
unsigned icon_width ,
unsigned icon_height ,
uintptr_t texture ,
float x , float y ,
unsigned width , unsigned height ,
float rotation , float scale_factor ,
float * color )
{
2020-02-16 15:10:07 +01:00
gfx_display_ctx_rotate_draw_t rotate_draw ;
gfx_display_ctx_draw_t draw ;
2019-10-23 14:15:14 -07:00
struct video_coords coords ;
math_matrix_4x4 mymat ;
if ( ! texture )
return ;
rotate_draw . matrix = & mymat ;
rotate_draw . rotation = rotation ;
rotate_draw . scale_x = scale_factor ;
rotate_draw . scale_y = scale_factor ;
rotate_draw . scale_z = 1 ;
rotate_draw . scale_enable = true ;
2020-03-09 00:18:38 +01:00
gfx_display_rotate_z ( & rotate_draw , userdata ) ;
2019-10-23 14:15:14 -07:00
coords . vertices = 4 ;
coords . vertex = NULL ;
coords . tex_coord = NULL ;
coords . lut_tex_coord = NULL ;
coords . color = color ;
draw . x = x ;
draw . y = height - y - icon_height ;
draw . width = icon_width ;
draw . height = icon_height ;
draw . scale_factor = scale_factor ;
draw . rotation = rotation ;
draw . coords = & coords ;
draw . matrix_data = & mymat ;
draw . texture = texture ;
2020-02-16 15:10:07 +01:00
draw . prim_type = GFX_DISPLAY_PRIM_TRIANGLESTRIP ;
2019-10-23 14:15:14 -07:00
draw . pipeline . id = 0 ;
2020-03-09 00:18:38 +01:00
gfx_display_draw_blend ( & draw , userdata ,
video_width , video_height ) ;
2019-10-23 14:15:14 -07:00
}
2020-02-23 11:03:38 +01:00
# endif
2019-10-23 14:15:14 -07:00
2020-03-09 14:18:29 +01:00
float gfx_widgets_get_thumbnail_scale_factor (
2020-02-23 11:03:38 +01:00
const float dst_width , const float dst_height ,
2019-02-21 10:23:21 +01:00
const float image_width , const float image_height )
{
2020-02-23 11:03:38 +01:00
float dst_ratio = dst_width / dst_height ;
2019-02-21 10:23:21 +01:00
float image_ratio = image_width / image_height ;
2020-02-23 11:03:38 +01:00
if ( dst_ratio > image_ratio )
return ( dst_height / image_height ) ;
return ( dst_width / image_width ) ;
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_start_msg_expiration_timer ( menu_widget_msg_t * msg_widget , unsigned duration )
2019-02-21 10:23:21 +01:00
{
2020-02-16 18:24:45 +01:00
gfx_timer_ctx_entry_t timer ;
2019-02-21 10:23:21 +01:00
if ( msg_widget - > expiration_timer_started )
return ;
2020-02-17 01:43:40 +01:00
timer . cb = gfx_widgets_msg_queue_expired ;
2019-02-21 10:23:21 +01:00
timer . duration = duration ;
timer . userdata = msg_widget ;
2020-02-16 18:24:45 +01:00
gfx_timer_start ( & msg_widget - > expiration_timer , & timer ) ;
2019-02-21 10:23:21 +01:00
msg_widget - > expiration_timer_started = true ;
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_hourglass_tick ( void * userdata ) ;
2019-02-21 10:23:21 +01:00
2020-02-17 01:43:40 +01:00
static void gfx_widgets_hourglass_end ( void * userdata )
2019-02-21 10:23:21 +01:00
{
2020-02-16 18:24:45 +01:00
gfx_timer_ctx_entry_t timer ;
2020-02-23 11:03:38 +01:00
menu_widget_msg_t * msg = ( menu_widget_msg_t * ) userdata ;
2019-02-21 10:23:21 +01:00
msg - > hourglass_rotation = 0.0f ;
2020-02-17 01:43:40 +01:00
timer . cb = gfx_widgets_hourglass_tick ;
2019-05-04 14:07:09 +02:00
timer . duration = HOURGLASS_INTERVAL ;
timer . userdata = msg ;
2019-02-21 10:23:21 +01:00
2020-02-16 18:24:45 +01:00
gfx_timer_start ( & msg - > hourglass_timer , & timer ) ;
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_hourglass_tick ( void * userdata )
2019-02-21 10:23:21 +01:00
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2020-02-23 11:03:38 +01:00
menu_widget_msg_t * msg = ( menu_widget_msg_t * ) userdata ;
gfx_animation_ctx_tag tag = ( uintptr_t ) msg ;
2019-02-21 10:23:21 +01:00
2019-07-24 19:30:17 +02:00
entry . easing_enum = EASING_OUT_QUAD ;
entry . tag = tag ;
entry . duration = HOURGLASS_DURATION ;
2020-02-15 01:54:44 +01:00
entry . target_value = - ( 2 * M_PI ) ;
2019-07-24 19:30:17 +02:00
entry . subject = & msg - > hourglass_rotation ;
2020-02-17 01:43:40 +01:00
entry . cb = gfx_widgets_hourglass_end ;
2019-07-24 19:30:17 +02:00
entry . userdata = msg ;
2019-02-21 10:23:21 +01:00
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-02-21 10:23:21 +01:00
}
2020-02-13 17:26:16 +00:00
/* Forward declaration */
2020-02-17 01:43:40 +01:00
static void gfx_widgets_layout (
2020-02-13 17:26:16 +00:00
bool is_threaded , const char * dir_assets , char * font_path ) ;
2020-02-17 00:42:49 +01:00
# ifdef HAVE_MENU
2020-02-17 21:28:42 +01:00
bool menu_driver_get_load_content_animation_data (
uintptr_t * icon , char * * playlist_name ) ;
2020-02-17 00:42:49 +01:00
# endif
2020-02-13 17:26:16 +00:00
2020-02-17 01:43:40 +01:00
void gfx_widgets_iterate (
2020-03-04 17:07:49 +00:00
unsigned width , unsigned height , bool fullscreen ,
2020-02-16 23:38:24 +01:00
const char * dir_assets , char * font_path ,
bool is_threaded )
2019-02-21 10:23:21 +01:00
{
2019-05-04 14:48:33 +02:00
size_t i ;
2019-02-21 10:23:21 +01:00
2020-02-13 17:26:16 +00:00
/* Check whether screen dimensions or menu scale
* factor have changed */
2020-03-04 17:07:49 +00:00
float scale_factor = ( gfx_display_get_driver_id ( ) = = MENU_DRIVER_ID_XMB ) ?
gfx_display_get_widget_pixel_scale ( width , height , fullscreen ) :
gfx_display_get_widget_dpi_scale ( width , height , fullscreen ) ;
2020-02-13 17:26:16 +00:00
if ( ( scale_factor ! = last_scale_factor ) | |
2020-02-23 11:03:38 +01:00
( width ! = last_video_width ) | |
2020-02-13 17:26:16 +00:00
( height ! = last_video_height ) )
{
last_scale_factor = scale_factor ;
last_video_width = width ;
last_video_height = height ;
/* Note: We don't need a full context reset here
* > Just rescale layout , and reset frame time counter */
2020-02-17 01:43:40 +01:00
gfx_widgets_layout ( is_threaded , dir_assets , font_path ) ;
2020-02-13 17:26:16 +00:00
video_driver_monitor_reset ( ) ;
}
2020-03-09 10:32:12 +01:00
for ( i = 0 ; i < widgets_len ; i + + )
{
const gfx_widget_t * widget = widgets [ i ] ;
2020-03-09 14:18:29 +01:00
if ( widget - > iterate )
2020-03-09 10:32:12 +01:00
widget - > iterate ( width , height , fullscreen , dir_assets , font_path , is_threaded ) ;
}
2019-02-21 10:23:21 +01:00
/* Messages queue */
/* Consume one message if available */
2020-03-09 10:32:12 +01:00
if ( ( fifo_read_avail ( msg_queue ) > 0 )
2020-02-16 23:38:24 +01:00
& & ! widgets_moving
& & ( current_msgs - > size < MSG_QUEUE_ONSCREEN_MAX ) )
2019-02-21 10:23:21 +01:00
{
menu_widget_msg_t * msg_widget ;
fifo_read ( msg_queue , & msg_widget , sizeof ( msg_widget ) ) ;
/* Task messages always appear from the bottom of the screen */
if ( msg_queue_tasks_count = = 0 | | msg_widget - > task_ptr )
{
file_list_append ( current_msgs ,
NULL ,
NULL ,
0 ,
0 ,
0
) ;
2020-02-16 23:38:24 +01:00
file_list_set_userdata ( current_msgs ,
current_msgs - > size - 1 , msg_widget ) ;
2019-02-21 10:23:21 +01:00
}
/* Regular messages are always above tasks */
else
{
2019-06-22 14:52:29 +02:00
unsigned idx = ( unsigned ) ( current_msgs - > size - msg_queue_tasks_count ) ;
2019-02-21 10:23:21 +01:00
file_list_insert ( current_msgs ,
NULL ,
NULL ,
0 ,
0 ,
0 ,
idx
) ;
file_list_set_userdata ( current_msgs , idx , msg_widget ) ;
}
/* Start expiration timer if not associated to a task */
2019-08-15 15:17:01 +02:00
if ( ! msg_widget - > task_ptr )
2019-02-21 10:23:21 +01:00
{
2020-02-17 01:43:40 +01:00
gfx_widgets_start_msg_expiration_timer (
2020-02-16 23:38:24 +01:00
msg_widget , MSG_QUEUE_ANIMATION_DURATION * 2
+ msg_widget - > duration ) ;
2019-02-21 10:23:21 +01:00
}
/* Else, start hourglass animation timer */
else
{
msg_queue_tasks_count + + ;
2020-02-17 01:43:40 +01:00
gfx_widgets_hourglass_end ( msg_widget ) ;
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
gfx_widgets_msg_queue_move ( ) ;
2019-02-21 10:23:21 +01:00
}
/* Kill first expired message */
/* Start expiration timer of dead tasks */
for ( i = 0 ; i < current_msgs - > size ; i + + )
{
2020-02-23 11:13:48 +01:00
menu_widget_msg_t * msg = ( menu_widget_msg_t * )
current_msgs - > list [ i ] . userdata ;
2019-02-21 10:23:21 +01:00
if ( ! msg )
continue ;
2019-08-15 15:17:01 +02:00
if ( msg - > task_ptr & & ( msg - > task_finished | | msg - > task_cancelled ) )
2020-02-17 01:43:40 +01:00
gfx_widgets_start_msg_expiration_timer ( msg , TASK_FINISHED_DURATION ) ;
2019-02-21 10:23:21 +01:00
if ( msg - > expired & & ! widgets_moving )
{
2020-02-17 01:43:40 +01:00
gfx_widgets_msg_queue_kill ( ( unsigned ) i ) ;
2019-02-21 10:23:21 +01:00
break ;
}
}
}
2020-03-09 00:25:28 +01:00
static int gfx_widgets_draw_indicator (
void * userdata ,
unsigned video_width ,
unsigned video_height ,
2020-02-17 21:28:42 +01:00
uintptr_t icon , int y , int top_right_x_advance ,
2019-02-21 10:23:21 +01:00
enum msg_hash_enums msg )
{
unsigned width ;
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_backdrop_orig , DEFAULT_BACKDROP ) ;
2019-02-21 10:23:21 +01:00
if ( icon )
{
unsigned height = simple_widget_height * 2 ;
width = height ;
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
2019-02-21 10:23:21 +01:00
top_right_x_advance - width , y ,
width , height ,
2020-03-07 21:18:12 +01:00
video_width , video_height ,
2020-02-17 01:43:40 +01:00
gfx_widgets_backdrop_orig
2019-02-21 10:23:21 +01:00
) ;
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_pure_white , 1.0f ) ;
2019-02-21 10:23:21 +01:00
2020-03-09 00:18:38 +01:00
gfx_display_blend_begin ( userdata ) ;
gfx_widgets_draw_icon (
userdata ,
video_width ,
video_height ,
width , height ,
icon , top_right_x_advance - width , y ,
video_width , video_height ,
0 , 1 , gfx_widgets_pure_white
) ;
gfx_display_blend_end ( userdata ) ;
2019-02-21 10:23:21 +01:00
}
else
{
2020-01-12 21:11:26 +01:00
unsigned height = simple_widget_height ;
const char * txt = msg_hash_to_str ( msg ) ;
2019-06-22 13:44:10 +02:00
width = font_driver_get_message_width ( font_regular , txt , ( unsigned ) strlen ( txt ) , 1 ) + simple_widget_padding * 2 ;
2019-02-21 10:23:21 +01:00
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
top_right_x_advance - width , y ,
width , height ,
video_width , video_height ,
gfx_widgets_backdrop_orig
2019-02-21 10:23:21 +01:00
) ;
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular ,
2019-02-21 10:23:21 +01:00
txt ,
2020-02-13 17:26:16 +00:00
top_right_x_advance - width + simple_widget_padding , widget_font_size + simple_widget_padding / 4 ,
2020-03-07 21:18:12 +01:00
video_width , video_height ,
2019-02-21 10:23:21 +01:00
0xFFFFFFFF , TEXT_ALIGN_LEFT ,
1.0f ,
false , 0 , false
) ;
}
return width ;
}
2020-03-09 00:25:28 +01:00
static void gfx_widgets_draw_task_msg (
menu_widget_msg_t * msg ,
void * userdata ,
unsigned video_width ,
unsigned video_height )
2019-02-21 10:23:21 +01:00
{
unsigned text_color ;
unsigned bar_width ;
unsigned rect_x ;
unsigned rect_y ;
unsigned rect_width ;
unsigned rect_height ;
float * msg_queue_current_background ;
float * msg_queue_current_bar ;
2020-01-08 14:19:10 +00:00
bool draw_msg_new = false ;
2019-02-21 10:23:21 +01:00
unsigned task_percentage_offset = 0 ;
char task_percentage [ 256 ] = { 0 } ;
2020-01-08 14:19:10 +00:00
if ( msg - > msg_new )
draw_msg_new = ! string_is_equal ( msg - > msg_new , msg - > msg ) ;
2019-02-21 10:23:21 +01:00
task_percentage_offset = glyph_width * ( msg - > task_error ? 12 : 5 ) + simple_widget_padding * 1.25f ; /*11 = strlen("Task failed")+1 */
if ( msg - > task_finished )
{
if ( msg - > task_error )
2019-09-17 06:34:00 +02:00
strlcpy ( task_percentage , " Task failed " , sizeof ( task_percentage ) ) ;
2019-02-21 10:23:21 +01:00
else
2019-09-17 06:34:00 +02:00
strlcpy ( task_percentage , " " , sizeof ( task_percentage ) ) ;
2019-02-21 10:23:21 +01:00
}
else if ( msg - > task_progress > = 0 & & msg - > task_progress < = 100 )
2019-09-17 06:34:00 +02:00
snprintf ( task_percentage , sizeof ( task_percentage ) ,
" %i%% " , msg - > task_progress ) ;
2019-02-21 10:23:21 +01:00
rect_width = simple_widget_padding + msg - > width + task_percentage_offset ;
bar_width = rect_width * msg - > task_progress / 100.0f ;
text_color = COLOR_TEXT_ALPHA ( 0xFFFFFF00 , ( unsigned ) ( msg - > alpha * 255.0f ) ) ;
/* Rect */
if ( msg - > task_finished )
if ( msg - > task_count = = 1 )
msg_queue_current_background = msg_queue_task_progress_1 ;
else
msg_queue_current_background = msg_queue_task_progress_2 ;
else
if ( msg - > task_count = = 1 )
msg_queue_current_background = msg_queue_background ;
else
msg_queue_current_background = msg_queue_task_progress_1 ;
rect_x = msg_queue_rect_start_x - msg_queue_icon_size_x ;
2020-03-07 21:18:12 +01:00
rect_y = video_height - msg - > offset_y ;
2019-02-21 10:23:21 +01:00
rect_height = msg_queue_height / 2 ;
2020-02-16 15:10:07 +01:00
gfx_display_set_alpha ( msg_queue_current_background , msg - > alpha ) ;
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
rect_x , rect_y ,
rect_width , rect_height ,
video_width , video_height ,
msg_queue_current_background
) ;
2019-02-21 10:23:21 +01:00
/* Progress bar */
if ( ! msg - > task_finished & & msg - > task_progress > = 0 & & msg - > task_progress < = 100 )
{
if ( msg - > task_count = = 1 )
msg_queue_current_bar = msg_queue_task_progress_1 ;
else
msg_queue_current_bar = msg_queue_task_progress_2 ;
2020-02-16 15:10:07 +01:00
gfx_display_set_alpha ( msg_queue_current_bar , 1.0f ) ;
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
msg_queue_task_rect_start_x , video_height - msg - > offset_y ,
bar_width , rect_height ,
video_width , video_height ,
msg_queue_current_bar
) ;
2019-02-21 10:23:21 +01:00
}
/* Icon */
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_pure_white , msg - > alpha ) ;
2020-03-09 00:18:38 +01:00
gfx_display_blend_begin ( userdata ) ;
gfx_widgets_draw_icon (
userdata ,
video_width ,
video_height ,
msg_queue_height / 2 ,
msg_queue_height / 2 ,
gfx_widgets_icons_textures [ msg - > task_finished ? MENU_WIDGETS_ICON_CHECK : MENU_WIDGETS_ICON_HOURGLASS ] ,
msg_queue_task_hourglass_x ,
video_height - msg - > offset_y ,
video_width ,
video_height ,
msg - > task_finished ? 0 : msg - > hourglass_rotation ,
1 , gfx_widgets_pure_white ) ;
gfx_display_blend_end ( userdata ) ;
2019-02-21 10:23:21 +01:00
/* Text */
2020-01-08 14:19:10 +00:00
if ( draw_msg_new )
2019-02-21 10:23:21 +01:00
{
2020-03-07 21:18:12 +01:00
font_driver_flush ( video_width , video_height , font_regular ) ;
2019-02-21 10:23:21 +01:00
font_raster_regular . carr . coords . vertices = 0 ;
2020-03-09 00:18:38 +01:00
gfx_display_scissor_begin ( userdata ,
video_width , video_height ,
2020-03-08 22:58:17 +01:00
rect_x , rect_y , rect_width , rect_height ) ;
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular ,
2019-02-21 10:23:21 +01:00
msg - > msg_new ,
msg_queue_task_text_start_x ,
2020-03-07 21:18:12 +01:00
video_height - msg - > offset_y + msg_queue_text_scale_factor * widget_font_size + msg_queue_height / 4 - widget_font_size / 2.25f - msg_queue_height / 2 + msg - > msg_transition_animation ,
video_width , video_height ,
2019-02-21 10:23:21 +01:00
text_color ,
TEXT_ALIGN_LEFT ,
msg_queue_text_scale_factor ,
false ,
0 ,
true
) ;
}
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular ,
2019-02-21 10:23:21 +01:00
msg - > msg ,
msg_queue_task_text_start_x ,
2020-03-07 21:18:12 +01:00
video_height - msg - > offset_y + msg_queue_text_scale_factor * widget_font_size + msg_queue_height / 4 - widget_font_size / 2.25f + msg - > msg_transition_animation ,
video_width , video_height ,
2019-02-21 10:23:21 +01:00
text_color ,
TEXT_ALIGN_LEFT ,
msg_queue_text_scale_factor ,
false ,
0 ,
true
) ;
2020-01-08 14:19:10 +00:00
if ( draw_msg_new )
2019-02-21 10:23:21 +01:00
{
2020-03-07 21:18:12 +01:00
font_driver_flush ( video_width , video_height , font_regular ) ;
2019-02-21 10:23:21 +01:00
font_raster_regular . carr . coords . vertices = 0 ;
2020-03-09 00:18:38 +01:00
gfx_display_scissor_end ( userdata ,
2020-03-08 22:58:17 +01:00
video_width , video_height ) ;
2019-02-21 10:23:21 +01:00
}
/* Progress text */
text_color = COLOR_TEXT_ALPHA ( 0xFFFFFF00 , ( unsigned ) ( msg - > alpha / 2 * 255.0f ) ) ;
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular ,
2019-02-21 10:23:21 +01:00
task_percentage ,
msg_queue_rect_start_x - msg_queue_icon_size_x + rect_width - msg_queue_glyph_width ,
2020-03-07 21:18:12 +01:00
video_height - msg - > offset_y + msg_queue_text_scale_factor * widget_font_size + msg_queue_height / 4 - widget_font_size / 2.25f ,
video_width , video_height ,
2019-02-21 10:23:21 +01:00
text_color ,
TEXT_ALIGN_RIGHT ,
msg_queue_text_scale_factor ,
false ,
0 ,
true
) ;
}
2020-03-09 00:25:28 +01:00
static void gfx_widgets_draw_regular_msg (
menu_widget_msg_t * msg ,
void * userdata ,
unsigned video_width ,
unsigned video_height )
2019-02-21 10:23:21 +01:00
{
unsigned bar_width ;
unsigned text_color ;
2020-03-07 21:18:12 +01:00
uintptr_t icon = 0 ;
2019-02-21 10:23:21 +01:00
if ( ! icon )
2020-02-17 01:43:40 +01:00
icon = gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_INFO ] ; /* TODO: Real icon logic here */
2019-02-21 10:23:21 +01:00
/* Icon */
2020-02-16 15:10:07 +01:00
gfx_display_set_alpha ( msg_queue_info , msg - > alpha ) ;
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_pure_white , msg - > alpha ) ;
2020-02-16 15:10:07 +01:00
gfx_display_set_alpha ( msg_queue_background , msg - > alpha ) ;
2019-02-21 10:23:21 +01:00
if ( ! msg - > unfolded | | msg - > unfolding )
{
2020-03-07 21:18:12 +01:00
font_driver_flush ( video_width , video_height , font_regular ) ;
font_driver_flush ( video_width , video_height , font_bold ) ;
2019-02-21 10:23:21 +01:00
font_raster_regular . carr . coords . vertices = 0 ;
font_raster_bold . carr . coords . vertices = 0 ;
2020-03-09 00:18:38 +01:00
gfx_display_scissor_begin ( userdata ,
video_width , video_height ,
2020-03-08 22:58:17 +01:00
msg_queue_scissor_start_x , 0 ,
( msg_queue_scissor_start_x + msg - > width - simple_widget_padding * 2 ) * msg - > unfold , video_height ) ;
2019-02-21 10:23:21 +01:00
}
if ( msg_queue_has_icons )
{
2020-03-09 00:18:38 +01:00
gfx_display_blend_begin ( userdata ) ;
2019-02-21 10:23:21 +01:00
/* (int) cast is to be consistent with the rect drawing and prevent alignment
* issues , don ' t remove it */
2020-03-09 00:18:38 +01:00
gfx_widgets_draw_icon (
userdata ,
video_width ,
video_height ,
msg_queue_icon_size_x , msg_queue_icon_size_y ,
msg_queue_icon_rect , msg_queue_spacing , ( int ) ( video_height - msg - > offset_y - msg_queue_icon_offset_y ) ,
video_width , video_height ,
0 , 1 , msg_queue_background ) ;
2019-02-21 10:23:21 +01:00
2020-03-09 00:18:38 +01:00
gfx_display_blend_end ( userdata ) ;
2019-02-21 10:23:21 +01:00
}
/* Background */
bar_width = simple_widget_padding + msg - > width ;
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
msg_queue_rect_start_x , video_height - msg - > offset_y ,
bar_width , msg_queue_height ,
video_width , video_height ,
msg_queue_background
) ;
2019-02-21 10:23:21 +01:00
/* Text */
text_color = COLOR_TEXT_ALPHA ( 0xFFFFFF00 , ( unsigned ) ( msg - > alpha * 255.0f ) ) ;
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular ,
2019-02-21 10:23:21 +01:00
msg - > msg ,
msg_queue_regular_text_start - ( ( 1.0f - msg - > unfold ) * msg - > width / 2 ) ,
2020-03-07 21:18:12 +01:00
video_height - msg - > offset_y + msg_queue_regular_text_base_y - msg - > text_height / 2 ,
video_width , video_height ,
2019-02-21 10:23:21 +01:00
text_color ,
TEXT_ALIGN_LEFT ,
msg_queue_text_scale_factor , false , 0 , true
) ;
if ( ! msg - > unfolded | | msg - > unfolding )
{
2020-03-07 21:18:12 +01:00
font_driver_flush ( video_width , video_height , font_regular ) ;
font_driver_flush ( video_width , video_height , font_bold ) ;
2019-02-21 10:23:21 +01:00
font_raster_regular . carr . coords . vertices = 0 ;
font_raster_bold . carr . coords . vertices = 0 ;
2020-03-09 00:18:38 +01:00
gfx_display_scissor_end ( userdata ,
2020-03-08 22:58:17 +01:00
video_width , video_height ) ;
2019-02-21 10:23:21 +01:00
}
if ( msg_queue_has_icons )
{
2020-03-09 00:18:38 +01:00
gfx_display_blend_begin ( userdata ) ;
2019-02-21 10:23:21 +01:00
2020-03-09 00:18:38 +01:00
gfx_widgets_draw_icon (
userdata ,
video_width ,
video_height ,
msg_queue_icon_size_x , msg_queue_icon_size_y ,
msg_queue_icon , msg_queue_spacing , video_height
- msg - > offset_y - msg_queue_icon_offset_y ,
video_width , video_height ,
0 , 1 , msg_queue_info ) ;
2019-02-21 10:23:21 +01:00
2020-03-09 00:18:38 +01:00
gfx_widgets_draw_icon (
userdata ,
video_width ,
video_height ,
msg_queue_icon_size_x , msg_queue_icon_size_y ,
msg_queue_icon_outline , msg_queue_spacing , video_height - msg - > offset_y - msg_queue_icon_offset_y ,
video_width , video_height ,
0 , 1 , gfx_widgets_pure_white ) ;
2019-02-21 10:23:21 +01:00
2020-03-09 00:18:38 +01:00
gfx_widgets_draw_icon (
userdata ,
video_width ,
video_height ,
msg_queue_internal_icon_size , msg_queue_internal_icon_size ,
icon , msg_queue_spacing + msg_queue_internal_icon_offset ,
video_height - msg - > offset_y - msg_queue_icon_offset_y + msg_queue_internal_icon_offset ,
video_width , video_height ,
0 , 1 , gfx_widgets_pure_white ) ;
2019-04-11 16:46:29 +02:00
2020-03-09 00:18:38 +01:00
gfx_display_blend_end ( userdata ) ;
2019-02-21 10:23:21 +01:00
}
}
2020-03-09 00:25:28 +01:00
static void gfx_widgets_draw_backdrop (
void * userdata ,
unsigned video_width ,
unsigned video_height ,
float alpha )
2019-02-21 10:23:21 +01:00
{
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_backdrop , alpha ) ;
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height , 0 , 0 ,
2020-03-07 21:18:12 +01:00
video_width , video_height , video_width , video_height ,
gfx_widgets_backdrop ) ;
2019-02-21 10:23:21 +01:00
}
2020-03-09 00:25:28 +01:00
static void gfx_widgets_draw_load_content_animation (
void * userdata ,
unsigned video_width ,
unsigned video_height )
2019-02-21 10:23:21 +01:00
{
2020-02-17 00:42:49 +01:00
# ifdef HAVE_MENU
2020-02-13 17:26:16 +00:00
/* TODO: change metrics? */
2020-03-07 21:18:12 +01:00
int icon_size = ( int ) load_content_animation_icon_size ;
uint32_t text_alpha = load_content_animation_fade_alpha * 255.0f ;
uint32_t text_color = COLOR_TEXT_ALPHA ( 0xB8B8B800 , text_alpha ) ;
unsigned text_offset = - 25 * last_scale_factor * load_content_animation_fade_alpha ;
float * icon_color = load_content_animation_icon_color ;
2019-02-21 10:23:21 +01:00
/* Fade out */
2020-03-09 00:25:28 +01:00
gfx_widgets_draw_backdrop ( userdata ,
video_width , video_height , load_content_animation_fade_alpha ) ;
2019-02-21 10:23:21 +01:00
/* Icon */
2020-02-16 15:10:07 +01:00
gfx_display_set_alpha ( icon_color , load_content_animation_icon_alpha ) ;
2020-03-09 00:18:38 +01:00
gfx_display_blend_begin ( userdata ) ;
gfx_widgets_draw_icon (
userdata ,
video_width ,
video_height ,
icon_size ,
icon_size , load_content_animation_icon ,
video_width / 2 - icon_size / 2 ,
video_height / 2 - icon_size / 2 ,
video_width ,
video_height ,
0 , 1 , icon_color
) ;
gfx_display_blend_end ( userdata ) ;
2019-02-21 10:23:21 +01:00
/* Text */
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_bold ,
2019-02-21 10:23:21 +01:00
load_content_animation_content_name ,
2020-03-07 21:18:12 +01:00
video_width / 2 ,
video_height / 2 + ( 175 + 25 ) * last_scale_factor + text_offset ,
video_width ,
video_height ,
2019-02-21 10:23:21 +01:00
text_color ,
TEXT_ALIGN_CENTER ,
1 ,
false ,
0 ,
false
) ;
/* Flush text layer */
2020-03-07 21:18:12 +01:00
font_driver_flush ( video_width , video_height , font_regular ) ;
font_driver_flush ( video_width , video_height , font_bold ) ;
2019-02-21 10:23:21 +01:00
font_raster_regular . carr . coords . vertices = 0 ;
font_raster_bold . carr . coords . vertices = 0 ;
/* Everything disappears */
2020-03-09 00:25:28 +01:00
gfx_widgets_draw_backdrop ( userdata ,
video_width , video_height ,
2020-02-17 00:42:49 +01:00
load_content_animation_final_fade_alpha ) ;
# endif
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
void gfx_widgets_frame ( void * data )
2019-02-21 10:23:21 +01:00
{
2019-05-04 14:48:33 +02:00
size_t i ;
2020-01-12 21:46:28 +01:00
video_frame_info_t * video_info = ( video_frame_info_t * ) data ;
2020-03-07 23:12:02 +01:00
bool framecount_show = video_info - > framecount_show ;
bool memory_show = video_info - > memory_show ;
2020-03-08 23:56:22 +01:00
void * userdata = video_info - > userdata ;
2020-03-07 21:18:12 +01:00
unsigned video_width = video_info - > width ;
unsigned video_height = video_info - > height ;
2020-03-07 23:12:02 +01:00
bool widgets_is_paused = video_info - > widgets_is_paused ;
bool fps_show = video_info - > fps_show ;
bool widgets_is_fastforwarding = video_info - > widgets_is_fast_forwarding ;
bool widgets_is_rewinding = video_info - > widgets_is_rewinding ;
bool runloop_is_slowmotion = video_info - > runloop_is_slowmotion ;
2020-03-07 21:18:12 +01:00
int top_right_x_advance = video_width ;
2020-01-12 21:46:28 +01:00
int scissor_me_timbers = 0 ;
2019-02-21 10:23:21 +01:00
2020-02-17 01:43:40 +01:00
gfx_widgets_frame_count + + ;
2019-02-21 10:23:21 +01:00
2020-03-07 21:18:12 +01:00
gfx_display_set_viewport ( video_width , video_height ) ;
2019-02-21 10:23:21 +01:00
/* Font setup */
font_driver_bind_block ( font_regular , & font_raster_regular ) ;
font_driver_bind_block ( font_bold , & font_raster_bold ) ;
font_raster_regular . carr . coords . vertices = 0 ;
font_raster_bold . carr . coords . vertices = 0 ;
2020-02-23 11:03:38 +01:00
# ifdef HAVE_TRANSLATE
2019-10-23 14:15:14 -07:00
/* AI Service overlay */
if ( ai_service_overlay_state > 0 )
{
float outline_color [ 16 ] = {
0.00 , 1.00 , 0.00 , 1.00 ,
0.00 , 1.00 , 0.00 , 1.00 ,
0.00 , 1.00 , 0.00 , 1.00 ,
0.00 , 1.00 , 0.00 , 1.00 ,
} ;
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_pure_white , 1.0f ) ;
2019-10-23 14:15:14 -07:00
2020-03-09 00:25:28 +01:00
gfx_widgets_draw_icon_blend (
userdata ,
video_width ,
video_height ,
video_width , video_height ,
ai_service_overlay_texture ,
0 , 0 ,
video_width , video_height ,
0 , 1 , gfx_widgets_pure_white
) ;
2019-10-23 14:15:14 -07:00
/* top line */
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
0 , 0 ,
video_width , divider_width_1px ,
video_width , video_height ,
outline_color
) ;
2019-10-23 14:15:14 -07:00
/* bottom line */
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
0 , video_height - divider_width_1px ,
video_width , divider_width_1px ,
video_width , video_height ,
outline_color
) ;
2019-10-23 14:15:14 -07:00
/* left line */
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width ,
video_height ,
0 , 0 ,
divider_width_1px , video_height ,
video_width , video_height ,
outline_color
) ;
2019-10-23 14:15:14 -07:00
/* right line */
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
video_width - divider_width_1px , 0 ,
divider_width_1px , video_height ,
video_width , video_height ,
outline_color
) ;
2019-10-23 14:15:14 -07:00
if ( ai_service_overlay_state = = 2 )
ai_service_overlay_state = 3 ;
}
2020-02-23 11:03:38 +01:00
# endif
2019-10-23 14:15:14 -07:00
2019-05-11 17:24:00 +02:00
/* Libretro message */
if ( libretro_message_alpha > 0.0f )
{
unsigned text_color = COLOR_TEXT_ALPHA ( 0xffffffff , ( unsigned ) ( libretro_message_alpha * 255.0f ) ) ;
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_backdrop_orig , libretro_message_alpha ) ;
2019-05-11 17:24:00 +02:00
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
0 , video_height - generic_message_height ,
libretro_message_width , generic_message_height ,
video_width , video_height ,
gfx_widgets_backdrop_orig ) ;
2019-05-11 17:24:00 +02:00
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular , libretro_message ,
2019-05-11 17:24:00 +02:00
simple_widget_padding ,
2020-03-07 21:18:12 +01:00
video_height - generic_message_height / 2 + widget_font_size / 4 ,
video_width , video_height ,
2019-05-11 17:24:00 +02:00
text_color , TEXT_ALIGN_LEFT ,
1 , false , 0 , false ) ;
}
2019-05-04 23:21:17 +02:00
/* Generic message */
if ( generic_message_alpha > 0.0f )
{
unsigned text_color = COLOR_TEXT_ALPHA ( 0xffffffff , ( unsigned ) ( generic_message_alpha * 255.0f ) ) ;
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_backdrop_orig , generic_message_alpha ) ;
2019-05-04 23:21:17 +02:00
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
0 , video_height - generic_message_height ,
video_width , generic_message_height ,
video_width , video_height ,
gfx_widgets_backdrop_orig ) ;
2019-05-04 23:21:17 +02:00
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular , generic_message ,
2020-03-07 21:18:12 +01:00
video_width / 2 ,
video_height - generic_message_height / 2 + widget_font_size / 4 ,
video_width , video_height ,
2019-05-04 23:21:17 +02:00
text_color , TEXT_ALIGN_CENTER ,
1 , false , 0 , false ) ;
}
2020-02-16 18:11:50 +01:00
# ifdef HAVE_CHEEVOS
2019-04-11 16:46:29 +02:00
/* Achievement notification */
2020-02-28 08:49:00 -07:00
if ( cheevo_popup_queue_read_index > = 0 & & cheevo_popup_queue [ cheevo_popup_queue_read_index ] . title )
2019-04-11 16:46:29 +02:00
{
2020-02-28 08:49:00 -07:00
SLOCK_LOCK ( cheevo_popup_queue_lock ) ;
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
if ( cheevo_popup_queue [ cheevo_popup_queue_read_index ] . title )
2019-04-11 16:46:29 +02:00
{
2020-02-28 08:49:00 -07:00
unsigned unfold_offet = ( ( 1.0f - cheevo_unfold ) * cheevo_width / 2 ) ;
gfx_display_set_alpha ( gfx_widgets_backdrop_orig , DEFAULT_BACKDROP ) ;
gfx_display_set_alpha ( gfx_widgets_pure_white , 1.0f ) ;
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
/* Default icon */
if ( ! cheevo_popup_queue [ cheevo_popup_queue_read_index ] . badge )
2019-04-11 16:46:29 +02:00
{
2020-02-28 08:49:00 -07:00
/* Backdrop */
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
0 , ( int ) cheevo_y ,
cheevo_height , cheevo_height ,
video_width , video_height ,
gfx_widgets_backdrop_orig ) ;
2020-02-28 08:49:00 -07:00
/* Icon */
if ( gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_ACHIEVEMENT ] )
{
2020-03-09 00:18:38 +01:00
gfx_display_blend_begin ( userdata ) ;
gfx_widgets_draw_icon (
userdata ,
video_width ,
video_height ,
cheevo_height , cheevo_height ,
gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_ACHIEVEMENT ] , 0 , cheevo_y ,
video_width , video_height , 0 , 1 , gfx_widgets_pure_white ) ;
gfx_display_blend_end ( userdata ) ;
2020-02-28 08:49:00 -07:00
}
2019-04-11 16:46:29 +02:00
}
2020-02-28 08:49:00 -07:00
/* Badge */
else
{
2020-03-09 00:18:38 +01:00
gfx_widgets_draw_icon (
userdata ,
video_width ,
video_height ,
cheevo_height , cheevo_height ,
cheevo_popup_queue [ cheevo_popup_queue_read_index ] . badge ,
0 ,
cheevo_y ,
video_width , video_height , 0 , 1 , gfx_widgets_pure_white ) ;
2020-02-28 08:49:00 -07:00
}
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
/* I _think_ cheevo_unfold changes in another thread */
scissor_me_timbers = ( fabs ( cheevo_unfold - 1.0f ) > 0.01 ) ;
if ( scissor_me_timbers )
2020-03-09 00:18:38 +01:00
gfx_display_scissor_begin ( userdata ,
video_width ,
video_height ,
2020-03-08 22:58:17 +01:00
cheevo_height , 0 ,
( unsigned ) ( ( float ) ( cheevo_width ) * cheevo_unfold ) ,
cheevo_height ) ;
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
/* Backdrop */
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width , video_height ,
cheevo_height , ( int ) cheevo_y ,
cheevo_width , cheevo_height ,
video_width , video_height ,
gfx_widgets_backdrop_orig ) ;
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
/* Title */
gfx_display_draw_text ( font_regular ,
msg_hash_to_str ( MSG_ACHIEVEMENT_UNLOCKED ) ,
cheevo_height + simple_widget_padding - unfold_offet ,
widget_font_size * 1.9f + cheevo_y ,
2020-03-07 21:18:12 +01:00
video_width , video_height ,
2020-02-28 08:49:00 -07:00
TEXT_COLOR_FAINT ,
TEXT_ALIGN_LEFT ,
1 , false , 0 , true
) ;
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
/* Title */
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
/* TODO: is a ticker necessary ? */
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
gfx_display_draw_text ( font_regular ,
cheevo_popup_queue [ cheevo_popup_queue_read_index ] . title ,
cheevo_height + simple_widget_padding - unfold_offet , widget_font_size * 2.9f + cheevo_y ,
2020-03-07 21:18:12 +01:00
video_width , video_height ,
2020-02-28 08:49:00 -07:00
TEXT_COLOR_INFO ,
TEXT_ALIGN_LEFT ,
1 , false , 0 , true
) ;
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
if ( scissor_me_timbers )
{
2020-03-07 21:18:12 +01:00
font_driver_flush ( video_width , video_height , font_regular ) ;
2020-02-28 08:49:00 -07:00
font_raster_regular . carr . coords . vertices = 0 ;
2020-03-09 00:18:38 +01:00
gfx_display_scissor_end ( userdata ,
2020-03-08 22:58:17 +01:00
video_width , video_height ) ;
2020-02-28 08:49:00 -07:00
}
2019-04-11 16:46:29 +02:00
}
2020-02-28 08:49:00 -07:00
SLOCK_UNLOCK ( cheevo_popup_queue_lock ) ;
2019-04-11 16:46:29 +02:00
}
2020-02-16 18:11:50 +01:00
# endif
2019-04-11 16:46:29 +02:00
2019-02-21 10:23:21 +01:00
/* Volume */
if ( volume_alpha > 0.0f )
{
char msg [ 255 ] ;
char percentage_msg [ 255 ] ;
2020-02-17 21:28:42 +01:00
uintptr_t volume_icon = 0 ;
2020-03-03 17:07:27 +00:00
unsigned icon_size = gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_VOLUME_MED ] ? volume_widget_height : simple_widget_padding ;
2019-02-21 10:23:21 +01:00
unsigned text_color = COLOR_TEXT_ALPHA ( 0xffffffff , ( unsigned ) ( volume_text_alpha * 255.0f ) ) ;
2020-02-15 17:25:20 +01:00
unsigned text_color_db = COLOR_TEXT_ALPHA ( TEXT_COLOR_FAINT , ( unsigned ) ( volume_text_alpha * 255.0f ) ) ;
2019-02-21 10:23:21 +01:00
2020-01-12 21:11:26 +01:00
unsigned bar_x = icon_size ;
2020-02-13 17:26:16 +00:00
unsigned bar_height = widget_font_size / 2 ;
2020-03-03 17:07:27 +00:00
unsigned bar_width = volume_widget_width - bar_x - simple_widget_padding ;
unsigned bar_y = volume_widget_height / 2 + bar_height / 2 ;
2019-02-21 10:23:21 +01:00
2020-01-12 21:11:26 +01:00
float * bar_background = NULL ;
float * bar_foreground = NULL ;
float bar_percentage = 0.0f ;
2019-02-21 10:23:21 +01:00
2020-03-03 17:07:27 +00:00
unsigned volume_text_y = bar_y - ( widget_font_size / 3 ) ;
2019-02-21 10:23:21 +01:00
if ( volume_mute )
2020-02-17 01:43:40 +01:00
volume_icon = gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_VOLUME_MUTE ] ;
2019-02-21 10:23:21 +01:00
else if ( volume_percent < = 1.0f )
{
if ( volume_percent < = 0.5f )
2020-02-17 01:43:40 +01:00
volume_icon = gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_VOLUME_MIN ] ;
2019-02-21 10:23:21 +01:00
else
2020-02-17 01:43:40 +01:00
volume_icon = gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_VOLUME_MED ] ;
2019-02-21 10:23:21 +01:00
bar_background = volume_bar_background ;
bar_foreground = volume_bar_normal ;
bar_percentage = volume_percent ;
}
else if ( volume_percent > 1.0f & & volume_percent < = 2.0f )
{
2020-02-17 01:43:40 +01:00
volume_icon = gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_VOLUME_MAX ] ;
2019-02-21 10:23:21 +01:00
bar_background = volume_bar_normal ;
bar_foreground = volume_bar_loud ;
bar_percentage = volume_percent - 1.0f ;
}
else
{
2020-02-17 01:43:40 +01:00
volume_icon = gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_VOLUME_MAX ] ;
2019-02-21 10:23:21 +01:00
bar_background = volume_bar_loud ;
bar_foreground = volume_bar_loudest ;
bar_percentage = volume_percent - 2.0f ;
}
if ( bar_percentage > 1.0f )
bar_percentage = 1.0f ;
/* Backdrop */
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_backdrop_orig , volume_alpha ) ;
2019-02-21 10:23:21 +01:00
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width ,
video_height ,
0 , 0 ,
volume_widget_width ,
volume_widget_height ,
video_width ,
video_height ,
gfx_widgets_backdrop_orig
) ;
2019-02-21 10:23:21 +01:00
/* Icon */
if ( volume_icon )
{
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_pure_white , volume_text_alpha ) ;
2019-02-21 10:23:21 +01:00
2020-03-09 00:18:38 +01:00
gfx_display_blend_begin ( userdata ) ;
gfx_widgets_draw_icon (
userdata ,
video_width ,
video_height ,
icon_size , icon_size ,
volume_icon ,
0 , 0 ,
video_width , video_height ,
0 , 1 , gfx_widgets_pure_white
) ;
gfx_display_blend_end ( userdata ) ;
2019-02-21 10:23:21 +01:00
}
if ( volume_mute )
{
2020-02-17 01:43:40 +01:00
if ( ! gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_VOLUME_MUTE ] )
2019-02-21 10:23:21 +01:00
{
const char * text = msg_hash_to_str ( MSG_AUDIO_MUTED ) ;
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular ,
2019-02-21 10:23:21 +01:00
text ,
2020-03-03 17:07:27 +00:00
volume_widget_width / 2 , volume_widget_height / 2 + widget_font_size / 3 ,
2020-03-07 21:18:12 +01:00
video_width , video_height ,
2019-02-21 10:23:21 +01:00
text_color , TEXT_ALIGN_CENTER ,
2020-03-03 17:07:27 +00:00
1 , false , 0 , true
2019-02-21 10:23:21 +01:00
) ;
}
}
else
{
/* Bar */
2020-02-16 15:10:07 +01:00
gfx_display_set_alpha ( bar_background , volume_text_alpha ) ;
gfx_display_set_alpha ( bar_foreground , volume_text_alpha ) ;
2019-02-21 10:23:21 +01:00
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width ,
video_height ,
bar_x + bar_percentage * bar_width , bar_y ,
bar_width - bar_percentage * bar_width , bar_height ,
video_width , video_height ,
bar_background
) ;
gfx_display_draw_quad ( userdata ,
video_width ,
video_height ,
bar_x , bar_y ,
bar_percentage * bar_width , bar_height ,
video_width , video_height ,
bar_foreground
) ;
2019-02-21 10:23:21 +01:00
/* Text */
snprintf ( msg , sizeof ( msg ) , ( volume_db > = 0 ? " +%.1f dB " : " %.1f dB " ) ,
volume_db ) ;
snprintf ( percentage_msg , sizeof ( percentage_msg ) , " %d%% " ,
( int ) ( volume_percent * 100.0f ) ) ;
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular ,
2019-05-11 06:26:40 +02:00
msg ,
2020-03-03 17:07:27 +00:00
volume_widget_width - simple_widget_padding , volume_text_y ,
2020-03-07 21:18:12 +01:00
video_width , video_height ,
2019-02-21 10:23:21 +01:00
text_color_db ,
TEXT_ALIGN_RIGHT ,
1 , false , 0 , false
) ;
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular ,
2019-02-21 10:23:21 +01:00
percentage_msg ,
2020-03-03 17:07:27 +00:00
icon_size , volume_text_y ,
2020-03-07 21:18:12 +01:00
video_width , video_height ,
2019-02-21 10:23:21 +01:00
text_color ,
TEXT_ALIGN_LEFT ,
1 , false , 0 , false
) ;
}
}
/* Draw all messages */
for ( i = 0 ; i < current_msgs - > size ; i + + )
{
2020-02-23 11:13:48 +01:00
menu_widget_msg_t * msg = ( menu_widget_msg_t * ) current_msgs - > list [ i ] . userdata ;
2019-02-21 10:23:21 +01:00
if ( ! msg )
continue ;
if ( msg - > task_ptr )
2020-03-09 00:25:28 +01:00
gfx_widgets_draw_task_msg ( msg , userdata ,
video_width , video_height ) ;
2019-02-21 10:23:21 +01:00
else
2020-03-09 00:25:28 +01:00
gfx_widgets_draw_regular_msg ( msg , userdata ,
video_width , video_height ) ;
2019-02-21 10:23:21 +01:00
}
/* FPS Counter */
2020-03-07 23:12:02 +01:00
if ( fps_show
| | framecount_show
| | memory_show
2019-09-22 03:21:36 +02:00
)
2019-02-21 10:23:21 +01:00
{
2020-02-17 01:43:40 +01:00
const char * text = * gfx_widgets_fps_text = = ' \0 ' ? " N/A " : gfx_widgets_fps_text ;
2019-02-21 10:23:21 +01:00
2019-08-15 15:13:07 +02:00
int text_width = font_driver_get_message_width ( font_regular , text , ( unsigned ) strlen ( text ) , 1.0f ) ;
int total_width = text_width + simple_widget_padding * 2 ;
2019-02-21 10:23:21 +01:00
2020-02-14 17:10:39 +00:00
int fps_text_x = top_right_x_advance - simple_widget_padding - text_width ;
/* Ensure that left hand side of text does
* not bleed off the edge of the screen */
fps_text_x = ( fps_text_x < 0 ) ? 0 : fps_text_x ;
2020-02-17 01:43:40 +01:00
gfx_display_set_alpha ( gfx_widgets_backdrop_orig , DEFAULT_BACKDROP ) ;
2019-02-21 10:23:21 +01:00
2020-03-08 23:56:22 +01:00
gfx_display_draw_quad ( userdata ,
video_width ,
video_height ,
top_right_x_advance - total_width , 0 ,
total_width , simple_widget_height ,
video_width , video_height ,
gfx_widgets_backdrop_orig
) ;
2019-02-21 10:23:21 +01:00
2020-02-16 15:10:07 +01:00
gfx_display_draw_text ( font_regular ,
2019-02-21 10:23:21 +01:00
text ,
2020-02-14 17:10:39 +00:00
fps_text_x , widget_font_size + simple_widget_padding / 4 ,
2020-03-07 21:18:12 +01:00
video_width , video_height ,
2019-02-21 10:23:21 +01:00
0xFFFFFFFF ,
TEXT_ALIGN_LEFT ,
1 , false , 0 , true
) ;
}
/* Indicators */
2020-03-07 23:12:02 +01:00
if ( widgets_is_paused )
2020-03-09 00:25:28 +01:00
top_right_x_advance - = gfx_widgets_draw_indicator (
userdata ,
video_width ,
video_height ,
gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_PAUSED ] , ( fps_show ? simple_widget_height : 0 ) , top_right_x_advance ,
MSG_PAUSED ) ;
2019-02-21 10:23:21 +01:00
2020-03-07 23:12:02 +01:00
if ( widgets_is_fastforwarding )
2020-03-09 00:25:28 +01:00
top_right_x_advance - = gfx_widgets_draw_indicator (
userdata ,
video_width ,
video_height ,
gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_FAST_FORWARD ] , ( fps_show ? simple_widget_height : 0 ) , top_right_x_advance ,
MSG_PAUSED ) ;
2019-02-21 10:23:21 +01:00
2020-03-07 23:12:02 +01:00
if ( widgets_is_rewinding )
2020-03-09 00:25:28 +01:00
top_right_x_advance - = gfx_widgets_draw_indicator (
userdata ,
video_width ,
video_height ,
gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_REWIND ] , ( fps_show ? simple_widget_height : 0 ) , top_right_x_advance ,
MSG_REWINDING ) ;
2019-02-21 10:23:21 +01:00
2020-03-07 23:12:02 +01:00
if ( runloop_is_slowmotion )
2020-03-09 00:25:28 +01:00
top_right_x_advance - = gfx_widgets_draw_indicator (
userdata ,
video_width ,
video_height ,
gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_SLOW_MOTION ] , ( fps_show ? simple_widget_height : 0 ) , top_right_x_advance ,
MSG_SLOW_MOTION ) ;
2019-02-21 10:23:21 +01:00
2020-03-09 10:32:12 +01:00
for ( i = 0 ; i < widgets_len ; i + + )
{
const gfx_widget_t * widget = widgets [ i ] ;
2020-03-09 14:18:29 +01:00
if ( widget - > frame )
2020-03-09 10:32:12 +01:00
widget - > frame ( data ) ;
}
2020-02-17 00:42:49 +01:00
# ifdef HAVE_MENU
2019-02-21 10:23:21 +01:00
/* Load content animation */
if ( load_content_animation_running )
2020-03-09 00:25:28 +01:00
gfx_widgets_draw_load_content_animation ( userdata ,
video_width , video_height ) ;
2019-02-21 10:23:21 +01:00
else
2020-02-17 00:42:49 +01:00
# endif
2019-02-21 10:23:21 +01:00
{
2020-03-07 21:18:12 +01:00
font_driver_flush ( video_width , video_height , font_regular ) ;
font_driver_flush ( video_width , video_height , font_bold ) ;
2019-02-21 10:23:21 +01:00
font_raster_regular . carr . coords . vertices = 0 ;
font_raster_bold . carr . coords . vertices = 0 ;
}
2020-03-07 21:18:12 +01:00
gfx_display_unset_viewport ( video_width , video_height ) ;
2019-02-21 10:23:21 +01:00
}
2020-03-04 17:07:49 +00:00
bool gfx_widgets_init ( bool video_is_threaded , bool fullscreen )
2019-02-21 10:23:21 +01:00
{
2020-03-09 10:32:12 +01:00
size_t i ;
2020-02-16 15:10:07 +01:00
if ( ! gfx_display_init_first_driver ( video_is_threaded ) )
2019-08-15 14:20:51 +02:00
goto error ;
2019-02-21 10:23:21 +01:00
2020-02-17 01:43:40 +01:00
gfx_widgets_frame_count = 0 ;
2019-02-21 10:23:21 +01:00
2020-03-09 10:32:12 +01:00
for ( i = 0 ; i < widgets_len ; i + + )
{
const gfx_widget_t * widget = widgets [ i ] ;
if ( widget - > init )
widget - > init ( video_is_threaded , fullscreen ) ;
}
2019-02-21 10:23:21 +01:00
msg_queue = fifo_new ( MSG_QUEUE_PENDING_MAX * sizeof ( menu_widget_msg_t * ) ) ;
if ( ! msg_queue )
2019-08-15 14:20:51 +02:00
goto error ;
2019-02-21 10:23:21 +01:00
current_msgs = ( file_list_t * ) calloc ( 1 , sizeof ( file_list_t ) ) ;
if ( ! current_msgs )
2019-08-15 14:20:51 +02:00
goto error ;
2019-02-21 10:23:21 +01:00
2019-05-11 06:26:40 +02:00
if ( ! file_list_reserve ( current_msgs , MSG_QUEUE_ONSCREEN_MAX ) )
2019-08-15 14:20:51 +02:00
goto error ;
2019-05-11 06:26:40 +02:00
2020-02-13 17:26:16 +00:00
/* Initialise scaling parameters
* NOTE - special cases :
* > Ozone has a capped scale factor
* > XMB uses pixel based scaling - all other drivers
* use DPI based scaling */
video_driver_get_size ( & last_video_width , & last_video_height ) ;
2020-03-04 17:07:49 +00:00
last_scale_factor = ( gfx_display_get_driver_id ( ) = = MENU_DRIVER_ID_XMB ) ?
gfx_display_get_widget_pixel_scale ( last_video_width , last_video_height , fullscreen ) :
gfx_display_get_widget_dpi_scale ( last_video_width , last_video_height , fullscreen ) ;
2020-02-13 17:26:16 +00:00
2019-08-15 14:20:51 +02:00
return true ;
error :
return false ;
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_layout (
2020-02-13 17:26:16 +00:00
bool is_threaded , const char * dir_assets , char * font_path )
2019-02-21 10:23:21 +01:00
{
2020-03-09 10:32:12 +01:00
size_t i ;
2020-02-13 17:26:16 +00:00
int font_height = 0 ;
2020-03-03 17:07:27 +00:00
/* Base font size must be determined first
* > Note that size must be at least 2 ,
* otherwise gfx_display_font_file ( ) will
* generate a heap - buffer - overflow */
2020-02-14 17:10:39 +00:00
widget_font_size = BASE_FONT_SIZE * last_scale_factor ;
2020-03-03 17:07:27 +00:00
widget_font_size = ( widget_font_size > 2.0f ) ? widget_font_size : 2.0f ;
2019-02-21 10:23:21 +01:00
2020-02-13 17:26:16 +00:00
/* Initialise fonts */
2019-02-21 10:23:21 +01:00
2020-02-13 17:26:16 +00:00
/* > Free existing */
if ( font_regular )
2019-02-21 10:23:21 +01:00
{
2020-02-16 15:10:07 +01:00
gfx_display_font_free ( font_regular ) ;
2020-02-13 17:26:16 +00:00
font_regular = NULL ;
}
if ( font_bold )
{
2020-02-16 15:10:07 +01:00
gfx_display_font_free ( font_bold ) ;
2020-02-13 17:26:16 +00:00
font_bold = NULL ;
2019-02-21 10:23:21 +01:00
}
2020-02-13 17:26:16 +00:00
/* > Create new */
if ( string_is_empty ( font_path ) )
{
char ozone_path [ PATH_MAX_LENGTH ] ;
char font_path [ PATH_MAX_LENGTH ] ;
2019-02-21 10:23:21 +01:00
2020-02-13 17:26:16 +00:00
ozone_path [ 0 ] = ' \0 ' ;
font_path [ 0 ] = ' \0 ' ;
2019-02-21 10:23:21 +01:00
2020-02-13 17:26:16 +00:00
/* Base path */
fill_pathname_join ( ozone_path , dir_assets , " ozone " , sizeof ( ozone_path ) ) ;
2019-02-21 10:23:21 +01:00
2020-02-13 17:26:16 +00:00
/* Create regular font */
2019-02-21 10:23:21 +01:00
fill_pathname_join ( font_path , ozone_path , " regular.ttf " , sizeof ( font_path ) ) ;
2020-02-16 15:10:07 +01:00
font_regular = gfx_display_font_file ( font_path , widget_font_size , is_threaded ) ;
2019-02-21 10:23:21 +01:00
2020-02-13 17:26:16 +00:00
/* Create bold font */
2019-02-21 10:23:21 +01:00
fill_pathname_join ( font_path , ozone_path , " bold.ttf " , sizeof ( font_path ) ) ;
2020-02-16 15:10:07 +01:00
font_bold = gfx_display_font_file ( font_path , widget_font_size , is_threaded ) ;
2019-02-21 10:23:21 +01:00
}
else
{
2020-02-13 17:26:16 +00:00
/* Load fonts from user-supplied path */
2020-02-16 15:10:07 +01:00
font_regular = gfx_display_font_file ( font_path , widget_font_size , is_threaded ) ;
font_bold = gfx_display_font_file ( font_path , widget_font_size , is_threaded ) ;
2019-02-21 10:23:21 +01:00
}
2020-02-13 17:26:16 +00:00
/* > Get actual font size */
font_height = font_driver_get_line_height ( font_regular , 1.0f ) ;
if ( font_height > 0 )
widget_font_size = ( float ) font_height ;
/* Calculate dimensions */
simple_widget_padding = widget_font_size * 2.0f / 3.0f ;
simple_widget_height = widget_font_size + simple_widget_padding ;
2020-01-12 21:11:26 +01:00
glyph_width = font_driver_get_message_width ( font_regular , " a " , 1 , 1 ) ;
2019-02-21 10:23:21 +01:00
2020-02-13 17:26:16 +00:00
msg_queue_height = widget_font_size * 2.5f ;
2019-02-21 10:23:21 +01:00
if ( msg_queue_has_icons )
{
msg_queue_icon_size_y = msg_queue_height * 1.2347826087f ; /* original image is 280x284 */
msg_queue_icon_size_x = 0.98591549295f * msg_queue_icon_size_y ;
}
else
{
msg_queue_icon_size_x = 0 ;
msg_queue_icon_size_y = 0 ;
}
msg_queue_text_scale_factor = 0.69f ;
msg_queue_spacing = msg_queue_height / 3 ;
msg_queue_glyph_width = glyph_width * msg_queue_text_scale_factor ;
msg_queue_rect_start_x = msg_queue_spacing + msg_queue_icon_size_x ;
msg_queue_internal_icon_size = msg_queue_icon_size_y ;
msg_queue_internal_icon_offset = ( msg_queue_icon_size_y - msg_queue_internal_icon_size ) / 2 ;
msg_queue_icon_offset_y = ( msg_queue_icon_size_y - msg_queue_height ) / 2 ;
msg_queue_scissor_start_x = msg_queue_spacing + msg_queue_icon_size_x - ( msg_queue_icon_size_x * 0.28928571428f ) ;
if ( msg_queue_has_icons )
msg_queue_regular_padding_x = simple_widget_padding / 2 ;
else
msg_queue_regular_padding_x = simple_widget_padding ;
msg_queue_task_rect_start_x = msg_queue_rect_start_x - msg_queue_icon_size_x ;
msg_queue_task_text_start_x = msg_queue_task_rect_start_x + msg_queue_height / 2 ;
2020-02-17 01:43:40 +01:00
if ( ! gfx_widgets_icons_textures [ MENU_WIDGETS_ICON_HOURGLASS ] )
2019-02-21 10:23:21 +01:00
msg_queue_task_text_start_x - = msg_queue_glyph_width * 2 ;
msg_queue_regular_text_start = msg_queue_rect_start_x + msg_queue_regular_padding_x ;
2020-02-13 17:26:16 +00:00
msg_queue_regular_text_base_y = widget_font_size * msg_queue_text_scale_factor + msg_queue_height / 2 ;
2019-02-21 10:23:21 +01:00
msg_queue_task_hourglass_x = msg_queue_rect_start_x - msg_queue_icon_size_x ;
2019-05-04 23:21:17 +02:00
2020-02-13 17:26:16 +00:00
generic_message_height = widget_font_size * 2 ;
2020-02-04 16:07:06 +00:00
msg_queue_default_rect_width_menu_alive = msg_queue_glyph_width * 40 ;
2020-02-13 17:26:16 +00:00
msg_queue_default_rect_width = last_video_width - msg_queue_regular_text_start - ( 2 * simple_widget_padding ) ;
2020-02-17 00:42:49 +01:00
# ifdef HAVE_MENU
2020-02-14 17:10:39 +00:00
load_content_animation_icon_size_initial = LOAD_CONTENT_ANIMATION_INITIAL_ICON_SIZE * last_scale_factor ;
load_content_animation_icon_size_target = LOAD_CONTENT_ANIMATION_TARGET_ICON_SIZE * last_scale_factor ;
2020-02-17 00:42:49 +01:00
# endif
2020-02-13 17:26:16 +00:00
2020-03-03 17:07:27 +00:00
volume_widget_height = widget_font_size * 4 ;
volume_widget_width = volume_widget_height * 4 ;
/* Volume widget cannot exceed screen width
* > If it does , scale it down */
if ( volume_widget_width > last_video_width )
{
volume_widget_width = last_video_width ;
volume_widget_height = volume_widget_width / 4 ;
}
2020-02-23 11:03:38 +01:00
divider_width_1px = 1 ;
if ( last_scale_factor > 1.0f )
divider_width_1px = ( unsigned ) ( last_scale_factor + 0.5f ) ;
2020-03-09 10:32:12 +01:00
for ( i = 0 ; i < widgets_len ; i + + )
{
const gfx_widget_t * widget = widgets [ i ] ;
2020-03-09 14:18:29 +01:00
if ( widget - > layout )
2020-03-09 10:32:12 +01:00
widget - > layout ( is_threaded , dir_assets , font_path ) ;
}
2020-02-13 17:26:16 +00:00
}
2020-02-17 01:43:40 +01:00
void gfx_widgets_context_reset ( bool is_threaded ,
2020-03-04 17:07:49 +00:00
unsigned width , unsigned height , bool fullscreen ,
2020-02-13 17:26:16 +00:00
const char * dir_assets , char * font_path )
{
2020-03-09 10:32:12 +01:00
size_t i ;
2020-02-13 17:26:16 +00:00
char xmb_path [ PATH_MAX_LENGTH ] ;
char monochrome_png_path [ PATH_MAX_LENGTH ] ;
2020-02-17 01:43:40 +01:00
char gfx_widgets_path [ PATH_MAX_LENGTH ] ;
2020-02-13 17:26:16 +00:00
char theme_path [ PATH_MAX_LENGTH ] ;
xmb_path [ 0 ] = ' \0 ' ;
monochrome_png_path [ 0 ] = ' \0 ' ;
2020-02-17 01:43:40 +01:00
gfx_widgets_path [ 0 ] = ' \0 ' ;
2020-02-13 17:26:16 +00:00
theme_path [ 0 ] = ' \0 ' ;
/* Textures paths */
fill_pathname_join (
2020-02-17 01:43:40 +01:00
gfx_widgets_path ,
2020-02-13 17:26:16 +00:00
dir_assets ,
" menu_widgets " ,
2020-02-17 01:43:40 +01:00
sizeof ( gfx_widgets_path )
2020-02-13 17:26:16 +00:00
) ;
fill_pathname_join (
xmb_path ,
dir_assets ,
" xmb " ,
sizeof ( xmb_path )
) ;
/* Monochrome */
fill_pathname_join (
theme_path ,
xmb_path ,
" monochrome " ,
sizeof ( theme_path )
) ;
fill_pathname_join (
monochrome_png_path ,
theme_path ,
" png " ,
sizeof ( monochrome_png_path )
) ;
/* Load textures */
/* Icons */
for ( i = 0 ; i < MENU_WIDGETS_ICON_LAST ; i + + )
{
2020-02-17 01:43:40 +01:00
gfx_display_reset_textures_list ( gfx_widgets_icons_names [ i ] , monochrome_png_path , & gfx_widgets_icons_textures [ i ] , TEXTURE_FILTER_MIPMAP_LINEAR , NULL , NULL ) ;
2020-02-13 17:26:16 +00:00
}
/* Message queue */
2020-02-17 01:43:40 +01:00
gfx_display_reset_textures_list ( " msg_queue_icon.png " , gfx_widgets_path , & msg_queue_icon , TEXTURE_FILTER_LINEAR , NULL , NULL ) ;
gfx_display_reset_textures_list ( " msg_queue_icon_outline.png " , gfx_widgets_path , & msg_queue_icon_outline , TEXTURE_FILTER_LINEAR , NULL , NULL ) ;
gfx_display_reset_textures_list ( " msg_queue_icon_rect.png " , gfx_widgets_path , & msg_queue_icon_rect , TEXTURE_FILTER_NEAREST , NULL , NULL ) ;
2020-02-13 17:26:16 +00:00
msg_queue_has_icons = msg_queue_icon & & msg_queue_icon_outline & & msg_queue_icon_rect ;
2020-03-09 10:32:12 +01:00
for ( i = 0 ; i < widgets_len ; i + + )
{
const gfx_widget_t * widget = widgets [ i ] ;
2020-03-09 14:18:29 +01:00
if ( widget - > context_reset )
2020-03-09 10:32:12 +01:00
widget - > context_reset ( is_threaded , width , height , fullscreen , dir_assets , font_path ) ;
}
2020-02-13 17:26:16 +00:00
/* Update scaling/dimensions */
last_video_width = width ;
last_video_height = height ;
2020-03-04 17:07:49 +00:00
last_scale_factor = ( gfx_display_get_driver_id ( ) = = MENU_DRIVER_ID_XMB ) ?
gfx_display_get_widget_pixel_scale ( last_video_width , last_video_height , fullscreen ) :
gfx_display_get_widget_dpi_scale ( last_video_width , last_video_height , fullscreen ) ;
2020-02-13 17:26:16 +00:00
2020-02-23 11:03:38 +01:00
gfx_widgets_layout ( is_threaded , dir_assets , font_path ) ;
2020-02-13 17:26:16 +00:00
video_driver_monitor_reset ( ) ;
2019-02-21 10:23:21 +01:00
}
2020-02-17 16:35:19 +01:00
static void gfx_widgets_context_destroy ( void )
2019-02-21 10:23:21 +01:00
{
2020-03-09 10:32:12 +01:00
size_t i ;
for ( i = 0 ; i < widgets_len ; i + + )
{
const gfx_widget_t * widget = widgets [ i ] ;
2020-03-09 14:18:29 +01:00
if ( widget - > context_destroy )
2020-03-09 10:32:12 +01:00
widget - > context_destroy ( ) ;
}
2019-02-21 10:23:21 +01:00
/* TODO: Dismiss onscreen notifications that have been freed */
/* Textures */
for ( i = 0 ; i < MENU_WIDGETS_ICON_LAST ; i + + )
2020-02-17 01:43:40 +01:00
video_driver_texture_unload ( & gfx_widgets_icons_textures [ i ] ) ;
2019-02-21 10:23:21 +01:00
video_driver_texture_unload ( & msg_queue_icon ) ;
video_driver_texture_unload ( & msg_queue_icon_outline ) ;
video_driver_texture_unload ( & msg_queue_icon_rect ) ;
2020-02-17 20:49:37 +01:00
msg_queue_icon = 0 ;
msg_queue_icon_outline = 0 ;
msg_queue_icon_rect = 0 ;
2019-02-21 10:23:21 +01:00
/* Fonts */
2020-02-13 17:26:16 +00:00
if ( font_regular )
2020-02-16 15:10:07 +01:00
gfx_display_font_free ( font_regular ) ;
2020-02-13 17:26:16 +00:00
if ( font_bold )
2020-02-16 15:10:07 +01:00
gfx_display_font_free ( font_bold ) ;
2019-02-21 10:23:21 +01:00
font_regular = NULL ;
2020-02-17 16:35:19 +01:00
font_bold = NULL ;
2019-02-21 10:23:21 +01:00
}
2020-02-16 18:11:50 +01:00
# ifdef HAVE_CHEEVOS
2020-02-28 08:49:00 -07:00
static void gfx_widgets_achievement_free_current ( void )
{
if ( cheevo_popup_queue [ cheevo_popup_queue_read_index ] . title )
{
free ( cheevo_popup_queue [ cheevo_popup_queue_read_index ] . title ) ;
cheevo_popup_queue [ cheevo_popup_queue_read_index ] . title = NULL ;
}
if ( cheevo_popup_queue [ cheevo_popup_queue_read_index ] . badge )
{
video_driver_texture_unload ( & cheevo_popup_queue [ cheevo_popup_queue_read_index ] . badge ) ;
cheevo_popup_queue [ cheevo_popup_queue_read_index ] . badge = 0 ;
}
cheevo_popup_queue_read_index = ( cheevo_popup_queue_read_index + 1 ) % CHEEVO_QUEUE_SIZE ;
}
static void gfx_widgets_achievement_next ( void * userdata )
2019-04-11 16:46:29 +02:00
{
2020-02-28 08:49:00 -07:00
SLOCK_LOCK ( cheevo_popup_queue_lock ) ;
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
gfx_widgets_achievement_free_current ( ) ;
/* start the next popup (if present) */
if ( cheevo_popup_queue [ cheevo_popup_queue_read_index ] . title )
gfx_widgets_start_achievement_notification ( ) ;
SLOCK_UNLOCK ( cheevo_popup_queue_lock ) ;
2019-04-11 16:46:29 +02:00
}
2020-02-16 18:11:50 +01:00
# endif
2019-04-11 16:46:29 +02:00
2020-02-17 01:43:40 +01:00
void gfx_widgets_free ( void )
2019-02-21 10:23:21 +01:00
{
2019-05-04 14:48:33 +02:00
size_t i ;
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_tag libretro_tag ;
2019-02-21 10:23:21 +01:00
2020-02-17 16:35:19 +01:00
gfx_widgets_context_destroy ( ) ;
2020-03-09 10:32:12 +01:00
for ( i = 0 ; i < widgets_len ; i + + )
{
const gfx_widget_t * widget = widgets [ i ] ;
2020-03-09 14:18:29 +01:00
if ( widget - > free )
2020-03-09 10:32:12 +01:00
widget - > free ( ) ;
}
2019-02-21 10:23:21 +01:00
/* Kill any pending animation */
2020-02-16 14:01:34 +01:00
gfx_animation_kill_by_tag ( & volume_tag ) ;
2020-02-17 01:43:40 +01:00
gfx_animation_kill_by_tag ( & gfx_widgets_generic_tag ) ;
2019-02-21 10:23:21 +01:00
/* Purge everything from the fifo */
if ( msg_queue )
{
while ( fifo_read_avail ( msg_queue ) > 0 )
{
menu_widget_msg_t * msg_widget ;
fifo_read ( msg_queue , & msg_widget , sizeof ( msg_widget ) ) ;
2020-02-17 01:43:40 +01:00
gfx_widgets_msg_queue_free ( msg_widget , false ) ;
2019-02-21 10:23:21 +01:00
free ( msg_widget ) ;
}
fifo_free ( msg_queue ) ;
}
2020-02-17 20:49:37 +01:00
msg_queue = NULL ;
2019-02-21 10:23:21 +01:00
/* Purge everything from the list */
2019-04-11 16:46:29 +02:00
if ( current_msgs )
2019-02-21 10:23:21 +01:00
{
for ( i = 0 ; i < current_msgs - > size ; i + + )
{
2019-04-21 00:31:31 +02:00
menu_widget_msg_t * msg = ( menu_widget_msg_t * )
2020-02-23 11:13:48 +01:00
current_msgs - > list [ i ] . userdata ;
2019-02-21 10:23:21 +01:00
2020-02-17 01:43:40 +01:00
gfx_widgets_msg_queue_free ( msg , false ) ;
2019-02-21 10:23:21 +01:00
}
file_list_free ( current_msgs ) ;
}
2020-02-17 20:49:37 +01:00
current_msgs = NULL ;
2019-02-21 10:23:21 +01:00
2019-05-11 06:26:40 +02:00
msg_queue_tasks_count = 0 ;
2020-02-16 18:11:50 +01:00
# ifdef HAVE_CHEEVOS
2019-04-11 16:46:29 +02:00
/* Achievement notification */
2020-02-28 08:49:00 -07:00
if ( cheevo_popup_queue_read_index > = 0 )
{
SLOCK_LOCK ( cheevo_popup_queue_lock ) ;
while ( cheevo_popup_queue [ cheevo_popup_queue_read_index ] . title )
gfx_widgets_achievement_free_current ( ) ;
SLOCK_UNLOCK ( cheevo_popup_queue_lock ) ;
}
2020-02-16 18:11:50 +01:00
# endif
2019-04-11 16:46:29 +02:00
2019-02-21 10:23:21 +01:00
/* Font */
video_coord_array_free ( & font_raster_regular . carr ) ;
video_coord_array_free ( & font_raster_bold . carr ) ;
font_driver_bind_block ( NULL , NULL ) ;
2019-05-11 06:26:40 +02:00
/* Reset state of all other widgets */
/* Generic message*/
2020-02-17 20:49:37 +01:00
generic_message_alpha = 0.0f ;
2019-05-11 17:24:00 +02:00
/* Libretro message */
2020-02-17 20:49:37 +01:00
libretro_tag = ( uintptr_t ) & libretro_message_timer ;
2019-05-11 17:24:00 +02:00
libretro_message_alpha = 0.0f ;
2020-02-16 18:24:45 +01:00
gfx_timer_kill ( & libretro_message_timer ) ;
2020-02-16 14:01:34 +01:00
gfx_animation_kill_by_tag ( & libretro_tag ) ;
2019-05-11 06:26:40 +02:00
2019-10-23 14:15:14 -07:00
/* AI Service overlay */
/* ... */
2019-05-11 06:26:40 +02:00
/* Volume */
2020-02-17 20:49:37 +01:00
volume_alpha = 0.0f ;
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_volume_timer_end ( void * userdata )
2019-02-21 10:23:21 +01:00
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2019-02-21 10:23:21 +01:00
entry . cb = NULL ;
entry . duration = MSG_QUEUE_ANIMATION_DURATION ;
entry . easing_enum = EASING_OUT_QUAD ;
entry . subject = & volume_alpha ;
entry . tag = volume_tag ;
entry . target_value = 0.0f ;
entry . userdata = NULL ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-02-21 10:23:21 +01:00
entry . subject = & volume_text_alpha ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
void gfx_widgets_volume_update_and_show ( float new_volume , bool mute )
2019-02-21 10:23:21 +01:00
{
2020-02-16 18:24:45 +01:00
gfx_timer_ctx_entry_t entry ;
2019-02-21 10:23:21 +01:00
2020-02-16 14:01:34 +01:00
gfx_animation_kill_by_tag ( & volume_tag ) ;
2019-02-21 10:23:21 +01:00
volume_db = new_volume ;
volume_percent = pow ( 10 , new_volume / 20 ) ;
volume_alpha = DEFAULT_BACKDROP ;
volume_text_alpha = 1.0f ;
volume_mute = mute ;
2020-02-17 01:43:40 +01:00
entry . cb = gfx_widgets_volume_timer_end ;
2019-02-21 10:23:21 +01:00
entry . duration = VOLUME_DURATION ;
entry . userdata = NULL ;
2020-02-16 18:24:45 +01:00
gfx_timer_start ( & volume_timer , & entry ) ;
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
bool gfx_widgets_set_fps_text ( const char * new_fps_text )
2019-09-23 09:22:35 +02:00
{
2020-02-17 01:43:40 +01:00
strlcpy ( gfx_widgets_fps_text ,
new_fps_text , sizeof ( gfx_widgets_fps_text ) ) ;
2019-09-23 09:22:35 +02:00
return true ;
}
2020-02-23 11:03:38 +01:00
# ifdef HAVE_TRANSLATE
2020-02-17 01:43:40 +01:00
int gfx_widgets_ai_service_overlay_get_state ( void )
2019-10-23 14:15:14 -07:00
{
return ai_service_overlay_state ;
}
2020-02-17 01:43:40 +01:00
bool gfx_widgets_ai_service_overlay_set_state ( int state )
2019-10-23 14:15:14 -07:00
{
ai_service_overlay_state = state ;
return true ;
}
2020-02-17 01:43:40 +01:00
bool gfx_widgets_ai_service_overlay_load (
2019-10-23 14:15:14 -07:00
char * buffer , unsigned buffer_len , enum image_type_enum image_type )
{
if ( ai_service_overlay_state = = 0 )
{
2020-02-16 23:34:49 +01:00
bool res = gfx_display_reset_textures_list_buffer (
2019-10-23 14:15:14 -07:00
& ai_service_overlay_texture ,
TEXTURE_FILTER_MIPMAP_LINEAR ,
( void * ) buffer , buffer_len , image_type ,
& ai_service_overlay_width , & ai_service_overlay_height ) ;
if ( res )
ai_service_overlay_state = 1 ;
return res ;
}
return true ;
}
2020-02-17 01:43:40 +01:00
void gfx_widgets_ai_service_overlay_unload ( void )
2019-10-23 14:15:14 -07:00
{
if ( ai_service_overlay_state = = 1 )
{
video_driver_texture_unload ( & ai_service_overlay_texture ) ;
2020-02-17 20:49:37 +01:00
ai_service_overlay_texture = 0 ;
ai_service_overlay_state = 0 ;
2019-10-23 14:15:14 -07:00
}
}
2020-02-23 11:03:38 +01:00
# endif
2019-10-23 14:15:14 -07:00
2020-02-17 01:43:40 +01:00
static void gfx_widgets_end_load_content_animation ( void * userdata )
2019-02-21 10:23:21 +01:00
{
2019-04-21 00:31:31 +02:00
#if 0
task_load_content_resume ( ) ; /* TODO: Restore that */
# endif
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
void gfx_widgets_cleanup_load_content_animation ( void )
2019-02-21 10:23:21 +01:00
{
2020-02-17 00:42:49 +01:00
# ifdef HAVE_MENU
2019-02-21 10:23:21 +01:00
load_content_animation_running = false ;
free ( load_content_animation_content_name ) ;
2020-02-17 00:42:49 +01:00
# endif
2019-02-21 10:23:21 +01:00
}
2020-02-17 01:43:40 +01:00
void gfx_widgets_start_load_content_animation ( const char * content_name , bool remove_extension )
2019-02-21 10:23:21 +01:00
{
2020-02-17 00:42:49 +01:00
# ifdef HAVE_MENU
2019-02-21 10:23:21 +01:00
/* TODO: finish the animation based on design, correct all timings */
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2020-02-16 18:24:45 +01:00
gfx_timer_ctx_entry_t timer_entry ;
2019-02-21 10:23:21 +01:00
int i ;
float icon_color [ 16 ] = COLOR_HEX_TO_FLOAT ( 0x0473C9 , 1.0f ) ; /* TODO: random color */
unsigned timing = 0 ;
/* Prepare data */
load_content_animation_icon = 0 ;
/* Abort animation if we don't have an icon */
if ( ! menu_driver_get_load_content_animation_data ( & load_content_animation_icon ,
& load_content_animation_playlist_name ) | | ! load_content_animation_icon )
{
2020-02-17 01:43:40 +01:00
gfx_widgets_end_load_content_animation ( NULL ) ;
2019-02-21 10:23:21 +01:00
return ;
}
load_content_animation_content_name = strdup ( content_name ) ;
if ( remove_extension )
path_remove_extension ( load_content_animation_content_name ) ;
/* Reset animation state */
2020-02-13 17:26:16 +00:00
load_content_animation_icon_size = load_content_animation_icon_size_initial ;
2019-02-21 10:23:21 +01:00
load_content_animation_icon_alpha = 0.0f ;
load_content_animation_fade_alpha = 0.0f ;
load_content_animation_final_fade_alpha = 0.0f ;
memcpy ( load_content_animation_icon_color , icon_color , sizeof ( load_content_animation_icon_color ) ) ;
/* Setup the animation */
entry . cb = NULL ;
entry . easing_enum = EASING_OUT_QUAD ;
2020-02-17 01:43:40 +01:00
entry . tag = gfx_widgets_generic_tag ;
2019-02-21 10:23:21 +01:00
entry . userdata = NULL ;
/* Stage one: icon animation */
/* Position */
entry . duration = ANIMATION_LOAD_CONTENT_DURATION ;
entry . subject = & load_content_animation_icon_size ;
2020-02-13 17:26:16 +00:00
entry . target_value = load_content_animation_icon_size_target ;
2019-02-21 10:23:21 +01:00
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-02-21 10:23:21 +01:00
/* Alpha */
entry . subject = & load_content_animation_icon_alpha ;
entry . target_value = 1.0f ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-02-21 10:23:21 +01:00
timing + = entry . duration ;
/* Stage two: backdrop + text */
entry . duration = ANIMATION_LOAD_CONTENT_DURATION * 1.5 ;
entry . subject = & load_content_animation_fade_alpha ;
entry . target_value = 1.0f ;
2020-02-16 14:01:34 +01:00
gfx_animation_push_delayed ( timing , & entry ) ;
2019-02-21 10:23:21 +01:00
timing + = entry . duration ;
/* Stage three: wait then color transition */
timing + = ANIMATION_LOAD_CONTENT_DURATION * 1.5 ;
entry . duration = ANIMATION_LOAD_CONTENT_DURATION * 3 ;
for ( i = 0 ; i < 16 ; i + + )
{
if ( i = = 3 | | i = = 7 | | i = = 11 | | i = = 15 )
continue ;
entry . subject = & load_content_animation_icon_color [ i ] ;
2020-02-17 01:43:40 +01:00
entry . target_value = gfx_widgets_pure_white [ i ] ;
2019-02-21 10:23:21 +01:00
2020-02-16 14:01:34 +01:00
gfx_animation_push_delayed ( timing , & entry ) ;
2019-02-21 10:23:21 +01:00
}
timing + = entry . duration ;
/* Stage four: wait then make everything disappear */
timing + = ANIMATION_LOAD_CONTENT_DURATION * 2 ;
entry . duration = ANIMATION_LOAD_CONTENT_DURATION * 1.5 ;
entry . subject = & load_content_animation_final_fade_alpha ;
entry . target_value = 1.0f ;
2020-02-16 14:01:34 +01:00
gfx_animation_push_delayed ( timing , & entry ) ;
2019-02-21 10:23:21 +01:00
timing + = entry . duration ;
/* Setup end */
2020-02-17 01:43:40 +01:00
timer_entry . cb = gfx_widgets_end_load_content_animation ;
2019-02-21 10:23:21 +01:00
timer_entry . duration = timing ;
timer_entry . userdata = NULL ;
2020-02-16 18:24:45 +01:00
gfx_timer_start ( & load_content_animation_end_timer , & timer_entry ) ;
2019-02-21 10:23:21 +01:00
/* Draw all the things */
load_content_animation_running = true ;
2020-02-17 00:42:49 +01:00
# endif
2019-02-21 10:23:21 +01:00
}
2020-02-16 18:11:50 +01:00
# ifdef HAVE_CHEEVOS
2020-02-17 01:43:40 +01:00
static void gfx_widgets_achievement_dismiss ( void * userdata )
2019-04-11 16:46:29 +02:00
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2019-04-11 16:46:29 +02:00
/* Slide up animation */
2020-02-28 08:49:00 -07:00
entry . cb = gfx_widgets_achievement_next ;
2019-04-11 16:46:29 +02:00
entry . duration = MSG_QUEUE_ANIMATION_DURATION ;
entry . easing_enum = EASING_OUT_QUAD ;
entry . subject = & cheevo_y ;
2020-02-17 01:43:40 +01:00
entry . tag = gfx_widgets_generic_tag ;
2019-04-11 16:46:29 +02:00
entry . target_value = ( float ) ( - ( int ) ( cheevo_height ) ) ;
entry . userdata = NULL ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-04-11 16:46:29 +02:00
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_achievement_fold ( void * userdata )
2019-04-11 16:46:29 +02:00
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2019-04-11 16:46:29 +02:00
/* Fold */
2020-02-17 01:43:40 +01:00
entry . cb = gfx_widgets_achievement_dismiss ;
2019-04-11 16:46:29 +02:00
entry . duration = MSG_QUEUE_ANIMATION_DURATION ;
entry . easing_enum = EASING_OUT_QUAD ;
entry . subject = & cheevo_unfold ;
2020-02-17 01:43:40 +01:00
entry . tag = gfx_widgets_generic_tag ;
2019-04-11 16:46:29 +02:00
entry . target_value = 0.0f ;
entry . userdata = NULL ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-04-11 16:46:29 +02:00
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_achievement_unfold ( void * userdata )
2019-04-11 16:46:29 +02:00
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2020-02-16 18:24:45 +01:00
gfx_timer_ctx_entry_t timer ;
2019-04-11 16:46:29 +02:00
/* Unfold */
entry . cb = NULL ;
entry . duration = MSG_QUEUE_ANIMATION_DURATION ;
entry . easing_enum = EASING_OUT_QUAD ;
entry . subject = & cheevo_unfold ;
2020-02-17 01:43:40 +01:00
entry . tag = gfx_widgets_generic_tag ;
2019-04-11 16:46:29 +02:00
entry . target_value = 1.0f ;
entry . userdata = NULL ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-04-11 16:46:29 +02:00
/* Wait before dismissing */
2020-02-17 01:43:40 +01:00
timer . cb = gfx_widgets_achievement_fold ;
2019-04-11 16:46:29 +02:00
timer . duration = MSG_QUEUE_ANIMATION_DURATION + CHEEVO_NOTIFICATION_DURATION ;
timer . userdata = NULL ;
2020-02-16 18:24:45 +01:00
gfx_timer_start ( & cheevo_timer , & timer ) ;
2019-04-11 16:46:29 +02:00
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_start_achievement_notification ( void )
2019-04-11 16:46:29 +02:00
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
2020-02-13 17:26:16 +00:00
cheevo_height = widget_font_size * 4 ;
2020-01-12 21:11:26 +01:00
cheevo_width = MAX (
2019-04-11 16:46:29 +02:00
font_driver_get_message_width ( font_regular , msg_hash_to_str ( MSG_ACHIEVEMENT_UNLOCKED ) , 0 , 1 ) ,
2020-02-28 08:49:00 -07:00
font_driver_get_message_width ( font_regular , cheevo_popup_queue [ cheevo_popup_queue_read_index ] . title , 0 , 1 )
2019-04-11 16:46:29 +02:00
) ;
2020-01-12 21:11:26 +01:00
cheevo_width + = simple_widget_padding * 2 ;
cheevo_y = ( float ) ( - ( int ) cheevo_height ) ;
cheevo_unfold = 0.0f ;
2019-04-11 16:46:29 +02:00
/* Slide down animation */
2020-02-17 01:43:40 +01:00
entry . cb = gfx_widgets_achievement_unfold ;
2019-04-11 16:46:29 +02:00
entry . duration = MSG_QUEUE_ANIMATION_DURATION ;
entry . easing_enum = EASING_OUT_QUAD ;
entry . subject = & cheevo_y ;
2020-02-17 01:43:40 +01:00
entry . tag = gfx_widgets_generic_tag ;
2019-04-11 16:46:29 +02:00
entry . target_value = 0.0f ;
entry . userdata = NULL ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-04-11 16:46:29 +02:00
}
2020-02-17 01:43:40 +01:00
void gfx_widgets_push_achievement ( const char * title , const char * badge )
2019-04-11 16:46:29 +02:00
{
2020-02-28 08:49:00 -07:00
int start_notification = 1 ;
if ( cheevo_popup_queue_read_index < 0 )
{
/* queue uninitialized */
memset ( & cheevo_popup_queue , 0 , sizeof ( cheevo_popup_queue ) ) ;
cheevo_popup_queue_read_index = 0 ;
# ifdef HAVE_THREADS
cheevo_popup_queue_lock = slock_new ( ) ;
# endif
}
SLOCK_LOCK ( cheevo_popup_queue_lock ) ;
if ( cheevo_popup_queue_write_index = = cheevo_popup_queue_read_index )
{
if ( cheevo_popup_queue [ cheevo_popup_queue_write_index ] . title )
{
/* queue full */
SLOCK_UNLOCK ( cheevo_popup_queue_lock ) ;
return ;
}
/* queue empty */
}
else
{
/* notification already being displayed */
start_notification = 0 ;
}
cheevo_popup_queue [ cheevo_popup_queue_write_index ] . badge = cheevos_get_badge_texture ( badge , 0 ) ;
cheevo_popup_queue [ cheevo_popup_queue_write_index ] . title = strdup ( title ) ;
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
cheevo_popup_queue_write_index = ( cheevo_popup_queue_write_index + 1 ) % CHEEVO_QUEUE_SIZE ;
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
if ( start_notification )
gfx_widgets_start_achievement_notification ( ) ;
2019-04-11 16:46:29 +02:00
2020-02-28 08:49:00 -07:00
SLOCK_UNLOCK ( cheevo_popup_queue_lock ) ;
2019-04-11 16:46:29 +02:00
}
2020-02-16 18:11:50 +01:00
# endif
2019-04-11 16:46:29 +02:00
2020-02-17 01:43:40 +01:00
static void gfx_widgets_generic_message_fadeout ( void * userdata )
2019-05-04 23:21:17 +02:00
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
gfx_animation_ctx_tag tag = ( uintptr_t ) & generic_message_timer ;
2019-05-04 23:21:17 +02:00
/* Start fade out animation */
entry . cb = NULL ;
entry . duration = MSG_QUEUE_ANIMATION_DURATION ;
entry . easing_enum = EASING_OUT_QUAD ;
entry . subject = & generic_message_alpha ;
entry . tag = tag ;
entry . target_value = 0.0f ;
entry . userdata = NULL ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-05-04 23:21:17 +02:00
}
2020-02-17 01:43:40 +01:00
void gfx_widgets_set_message ( char * msg )
2019-05-04 23:21:17 +02:00
{
2020-02-16 18:24:45 +01:00
gfx_timer_ctx_entry_t timer ;
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_tag tag = ( uintptr_t ) & generic_message_timer ;
2019-05-04 23:21:17 +02:00
2020-02-23 11:03:38 +01:00
strlcpy ( generic_message , msg , sizeof ( generic_message ) ) ;
2019-05-04 23:21:17 +02:00
generic_message_alpha = DEFAULT_BACKDROP ;
/* Kill and restart the timer / animation */
2020-02-16 18:24:45 +01:00
gfx_timer_kill ( & generic_message_timer ) ;
2020-02-16 14:01:34 +01:00
gfx_animation_kill_by_tag ( & tag ) ;
2019-05-04 23:21:17 +02:00
2020-02-17 01:43:40 +01:00
timer . cb = gfx_widgets_generic_message_fadeout ;
2019-05-04 23:21:17 +02:00
timer . duration = GENERIC_MESSAGE_DURATION ;
timer . userdata = NULL ;
2020-02-16 18:24:45 +01:00
gfx_timer_start ( & generic_message_timer , & timer ) ;
2019-05-04 23:21:17 +02:00
}
2020-02-17 01:43:40 +01:00
static void gfx_widgets_libretro_message_fadeout ( void * userdata )
2019-05-11 17:24:00 +02:00
{
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_entry_t entry ;
gfx_animation_ctx_tag tag = ( uintptr_t ) & libretro_message_timer ;
2019-05-11 17:24:00 +02:00
/* Start fade out animation */
entry . cb = NULL ;
entry . duration = MSG_QUEUE_ANIMATION_DURATION ;
entry . easing_enum = EASING_OUT_QUAD ;
entry . subject = & libretro_message_alpha ;
entry . tag = tag ;
entry . target_value = 0.0f ;
entry . userdata = NULL ;
2020-02-16 14:01:34 +01:00
gfx_animation_push ( & entry ) ;
2019-05-11 17:24:00 +02:00
}
2020-02-17 01:43:40 +01:00
void gfx_widgets_set_libretro_message ( const char * msg , unsigned duration )
2019-05-11 17:24:00 +02:00
{
2020-02-16 18:24:45 +01:00
gfx_timer_ctx_entry_t timer ;
2020-02-16 14:01:34 +01:00
gfx_animation_ctx_tag tag = ( uintptr_t ) & libretro_message_timer ;
2019-05-11 17:24:00 +02:00
2020-02-23 11:03:38 +01:00
strlcpy ( libretro_message , msg , sizeof ( libretro_message ) ) ;
2020-03-09 14:18:29 +01:00
2019-05-11 17:24:00 +02:00
libretro_message_alpha = DEFAULT_BACKDROP ;
/* Kill and restart the timer / animation */
2020-02-16 18:24:45 +01:00
gfx_timer_kill ( & libretro_message_timer ) ;
2020-02-16 14:01:34 +01:00
gfx_animation_kill_by_tag ( & tag ) ;
2019-05-11 17:24:00 +02:00
2020-02-17 01:43:40 +01:00
timer . cb = gfx_widgets_libretro_message_fadeout ;
2019-05-11 17:24:00 +02:00
timer . duration = duration ;
timer . userdata = NULL ;
2020-02-16 18:24:45 +01:00
gfx_timer_start ( & libretro_message_timer , & timer ) ;
2019-05-11 17:24:00 +02:00
/* Compute text width */
2019-06-22 14:52:29 +02:00
libretro_message_width = font_driver_get_message_width ( font_regular , msg , ( unsigned ) strlen ( msg ) , 1 ) + simple_widget_padding * 2 ;
2019-05-11 17:24:00 +02:00
}