mirror of
https://github.com/libretro/RetroArch
synced 2025-03-30 07:20:36 +00:00
Add optional widget-based 'load content' launch feedback animation
This commit is contained in:
parent
4319379d57
commit
506aa0a36c
@ -906,7 +906,8 @@ ifeq ($(HAVE_GFX_WIDGETS), 1)
|
||||
gfx/widgets/gfx_widget_volume.o \
|
||||
gfx/widgets/gfx_widget_generic_message.o \
|
||||
gfx/widgets/gfx_widget_libretro_message.o \
|
||||
gfx/widgets/gfx_widget_progress_message.o
|
||||
gfx/widgets/gfx_widget_progress_message.o \
|
||||
gfx/widgets/gfx_widget_load_content_animation.o
|
||||
ifeq ($(HAVE_CHEEVOS), 1)
|
||||
OBJ += gfx/widgets/gfx_widget_achievement_popup.o
|
||||
endif
|
||||
|
@ -767,6 +767,10 @@ static const bool audio_enable_menu_bgm = false;
|
||||
#define DEFAULT_MENU_ENABLE_WIDGETS false
|
||||
#endif
|
||||
|
||||
/* Display an animation when loading content
|
||||
* > Currently implemented only as a widget */
|
||||
#define DEFAULT_MENU_SHOW_LOAD_CONTENT_ANIMATION DEFAULT_MENU_ENABLE_WIDGETS
|
||||
|
||||
/* Output samplerate. */
|
||||
#ifdef GEKKO
|
||||
#define DEFAULT_OUTPUT_RATE 32000
|
||||
|
@ -1472,6 +1472,7 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
SETTING_BOOL("core_set_supports_no_game_enable", &settings->bools.set_supports_no_game_enable, true, true, false);
|
||||
SETTING_BOOL("audio_enable", &settings->bools.audio_enable, true, DEFAULT_AUDIO_ENABLE, false);
|
||||
SETTING_BOOL("menu_enable_widgets", &settings->bools.menu_enable_widgets, true, DEFAULT_MENU_ENABLE_WIDGETS, false);
|
||||
SETTING_BOOL("menu_show_load_content_animation", &settings->bools.menu_show_load_content_animation, true, DEFAULT_MENU_SHOW_LOAD_CONTENT_ANIMATION, false);
|
||||
SETTING_BOOL("menu_widget_scale_auto", &settings->bools.menu_widget_scale_auto, true, DEFAULT_MENU_WIDGET_SCALE_AUTO, false);
|
||||
SETTING_BOOL("audio_enable_menu", &settings->bools.audio_enable_menu, true, audio_enable_menu, false);
|
||||
SETTING_BOOL("audio_enable_menu_ok", &settings->bools.audio_enable_menu_ok, true, audio_enable_menu_ok, false);
|
||||
|
@ -158,6 +158,7 @@ typedef struct settings
|
||||
/* Menu */
|
||||
bool filter_by_current_core;
|
||||
bool menu_enable_widgets;
|
||||
bool menu_show_load_content_animation;
|
||||
bool menu_widget_scale_auto;
|
||||
bool menu_show_start_screen;
|
||||
bool menu_pause_libretro;
|
||||
|
@ -44,13 +44,6 @@
|
||||
|
||||
#define MSG_QUEUE_FONT_SIZE (BASE_FONT_SIZE * 0.69f)
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
#define ANIMATION_LOAD_CONTENT_DURATION 333
|
||||
|
||||
#define LOAD_CONTENT_ANIMATION_INITIAL_ICON_SIZE 320
|
||||
#define LOAD_CONTENT_ANIMATION_TARGET_ICON_SIZE 240
|
||||
#endif
|
||||
|
||||
/* TODO/FIXME - global state - perhaps move outside this file */
|
||||
static float msg_queue_background[16] =
|
||||
COLOR_HEX_TO_FLOAT(0x3A3A3A, 1.0f);
|
||||
@ -108,10 +101,6 @@ static const char
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
#ifdef HAVE_MENU
|
||||
bool menu_driver_get_load_content_animation_data(
|
||||
uintptr_t *icon, char **playlist_name);
|
||||
#endif
|
||||
static void gfx_widgets_context_reset(
|
||||
dispgfx_widget_t *p_dispwidget,
|
||||
bool is_threaded,
|
||||
@ -205,7 +194,8 @@ const static gfx_widget_t* const widgets[] = {
|
||||
#endif
|
||||
&gfx_widget_generic_message,
|
||||
&gfx_widget_libretro_message,
|
||||
&gfx_widget_progress_message
|
||||
&gfx_widget_progress_message,
|
||||
&gfx_widget_load_content_animation
|
||||
};
|
||||
|
||||
static void msg_widget_msg_transition_animation_done(void *userdata)
|
||||
@ -622,7 +612,6 @@ void gfx_widgets_draw_icon(
|
||||
unsigned icon_height,
|
||||
uintptr_t texture,
|
||||
float x, float y,
|
||||
unsigned width, unsigned height,
|
||||
float rotation, float scale_factor,
|
||||
float *color)
|
||||
{
|
||||
@ -650,7 +639,7 @@ void gfx_widgets_draw_icon(
|
||||
coords.color = color;
|
||||
|
||||
draw.x = x;
|
||||
draw.y = height - y - icon_height;
|
||||
draw.y = video_height - y - icon_height;
|
||||
draw.width = icon_width;
|
||||
draw.height = icon_height;
|
||||
draw.scale_factor = scale_factor;
|
||||
@ -674,7 +663,6 @@ static void gfx_widgets_draw_icon_blend(
|
||||
unsigned icon_height,
|
||||
uintptr_t texture,
|
||||
float x, float y,
|
||||
unsigned width, unsigned height,
|
||||
float rotation, float scale_factor,
|
||||
float *color)
|
||||
{
|
||||
@ -702,7 +690,7 @@ static void gfx_widgets_draw_icon_blend(
|
||||
coords.color = color;
|
||||
|
||||
draw.x = x;
|
||||
draw.y = height - y - icon_height;
|
||||
draw.y = video_height - y - icon_height;
|
||||
draw.width = icon_width;
|
||||
draw.height = icon_height;
|
||||
draw.scale_factor = scale_factor;
|
||||
@ -976,7 +964,6 @@ static int gfx_widgets_draw_indicator(
|
||||
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);
|
||||
@ -1116,8 +1103,6 @@ static void gfx_widgets_draw_task_msg(
|
||||
: MENU_WIDGETS_ICON_HOURGLASS],
|
||||
p_dispwidget->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);
|
||||
@ -1230,7 +1215,6 @@ static void gfx_widgets_draw_regular_msg(
|
||||
p_dispwidget->msg_queue_icon_rect,
|
||||
p_dispwidget->msg_queue_spacing,
|
||||
(int)(video_height - msg->offset_y - p_dispwidget->msg_queue_icon_offset_y),
|
||||
video_width, video_height,
|
||||
0, 1, msg_queue_background);
|
||||
|
||||
gfx_display_blend_end(userdata);
|
||||
@ -1287,7 +1271,6 @@ static void gfx_widgets_draw_regular_msg(
|
||||
p_dispwidget->msg_queue_icon,
|
||||
p_dispwidget->msg_queue_spacing, video_height
|
||||
- msg->offset_y - p_dispwidget->msg_queue_icon_offset_y,
|
||||
video_width, video_height,
|
||||
0, 1, msg_queue_info);
|
||||
|
||||
gfx_widgets_draw_icon(
|
||||
@ -1299,7 +1282,6 @@ static void gfx_widgets_draw_regular_msg(
|
||||
p_dispwidget->msg_queue_icon_outline,
|
||||
p_dispwidget->msg_queue_spacing,
|
||||
video_height - msg->offset_y - p_dispwidget->msg_queue_icon_offset_y,
|
||||
video_width, video_height,
|
||||
0, 1, gfx_widgets_pure_white);
|
||||
|
||||
gfx_widgets_draw_icon(
|
||||
@ -1309,95 +1291,12 @@ static void gfx_widgets_draw_regular_msg(
|
||||
p_dispwidget->msg_queue_internal_icon_size, p_dispwidget->msg_queue_internal_icon_size,
|
||||
icon, p_dispwidget->msg_queue_spacing + p_dispwidget->msg_queue_internal_icon_offset,
|
||||
video_height - msg->offset_y - p_dispwidget->msg_queue_icon_offset_y + p_dispwidget->msg_queue_internal_icon_offset,
|
||||
video_width, video_height,
|
||||
0, 1, gfx_widgets_pure_white);
|
||||
|
||||
gfx_display_blend_end(userdata);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
static void gfx_widgets_draw_backdrop(
|
||||
void *userdata,
|
||||
unsigned video_width,
|
||||
unsigned video_height,
|
||||
float alpha)
|
||||
{
|
||||
gfx_display_set_alpha(gfx_widgets_backdrop, alpha);
|
||||
gfx_display_draw_quad(userdata,
|
||||
video_width, video_height, 0, 0,
|
||||
video_width, video_height, video_width, video_height,
|
||||
gfx_widgets_backdrop);
|
||||
}
|
||||
|
||||
static void gfx_widgets_draw_load_content_animation(
|
||||
dispgfx_widget_t *p_dispwidget,
|
||||
void *userdata,
|
||||
unsigned video_width,
|
||||
unsigned video_height)
|
||||
{
|
||||
/* TODO: change metrics? */
|
||||
int icon_size = (int)p_dispwidget->load_content_animation_icon_size;
|
||||
uint32_t text_alpha = p_dispwidget->load_content_animation_fade_alpha * 255.0f;
|
||||
uint32_t text_color = COLOR_TEXT_ALPHA(0xB8B8B800, text_alpha);
|
||||
unsigned text_offset = -25 * p_dispwidget->last_scale_factor *
|
||||
p_dispwidget->load_content_animation_fade_alpha;
|
||||
float *icon_color = p_dispwidget->load_content_animation_icon_color;
|
||||
|
||||
/* Fade out */
|
||||
gfx_widgets_draw_backdrop(userdata,
|
||||
video_width, video_height,
|
||||
p_dispwidget->load_content_animation_fade_alpha);
|
||||
|
||||
/* Icon */
|
||||
gfx_display_set_alpha(icon_color,
|
||||
p_dispwidget->load_content_animation_icon_alpha);
|
||||
gfx_display_blend_begin(userdata);
|
||||
gfx_widgets_draw_icon(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
icon_size,
|
||||
icon_size,
|
||||
p_dispwidget->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);
|
||||
|
||||
/* Text
|
||||
* TODO/FIXME: Check vertical alignment - where is
|
||||
* this text actually meant to go...? */
|
||||
gfx_widgets_draw_text(&p_dispwidget->gfx_widget_fonts.bold,
|
||||
p_dispwidget->load_content_animation_content_name,
|
||||
video_width / 2,
|
||||
video_height / 2 + (175 + 25) * p_dispwidget->last_scale_factor
|
||||
+ text_offset
|
||||
+ p_dispwidget->gfx_widget_fonts.bold.line_centre_offset,
|
||||
video_width,
|
||||
video_height,
|
||||
text_color,
|
||||
TEXT_ALIGN_CENTER,
|
||||
false);
|
||||
|
||||
/* Flush text layer */
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.regular);
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.bold);
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.msg_queue);
|
||||
|
||||
/* Everything disappears */
|
||||
gfx_widgets_draw_backdrop(userdata,
|
||||
video_width, video_height,
|
||||
p_dispwidget->load_content_animation_final_fade_alpha);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void INLINE gfx_widgets_font_bind(gfx_widget_font_data_t *font_data)
|
||||
{
|
||||
font_driver_bind_block(font_data->font, &font_data->raster_block);
|
||||
@ -1458,8 +1357,6 @@ void gfx_widgets_frame(void *data)
|
||||
p_dispwidget->ai_service_overlay_texture,
|
||||
0,
|
||||
0,
|
||||
video_width,
|
||||
video_height,
|
||||
0,
|
||||
1,
|
||||
gfx_widgets_pure_white
|
||||
@ -1648,24 +1545,13 @@ void gfx_widgets_frame(void *data)
|
||||
SLOCK_UNLOCK(p_dispwidget->current_msgs_lock);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
/* Load content animation */
|
||||
if (p_dispwidget->load_content_animation_running)
|
||||
gfx_widgets_draw_load_content_animation(
|
||||
p_dispwidget,
|
||||
userdata,
|
||||
video_width,
|
||||
video_height);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.regular);
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.bold);
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.msg_queue);
|
||||
}
|
||||
/* Ensure all text is flushed */
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.regular);
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.bold);
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.msg_queue);
|
||||
|
||||
/* Unbind fonts */
|
||||
gfx_widgets_font_unbind(&p_dispwidget->gfx_widget_fonts.regular);
|
||||
@ -1878,15 +1764,6 @@ static void gfx_widgets_layout(
|
||||
p_dispwidget->msg_queue_default_rect_width = p_dispwidget->last_video_width
|
||||
- p_dispwidget->msg_queue_regular_text_start - (2 * p_dispwidget->simple_widget_padding);
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
p_dispwidget->load_content_animation_icon_size_initial =
|
||||
LOAD_CONTENT_ANIMATION_INITIAL_ICON_SIZE *
|
||||
p_dispwidget->last_scale_factor;
|
||||
p_dispwidget->load_content_animation_icon_size_target =
|
||||
LOAD_CONTENT_ANIMATION_TARGET_ICON_SIZE *
|
||||
p_dispwidget->last_scale_factor;
|
||||
#endif
|
||||
|
||||
p_dispwidget->divider_width_1px = 1;
|
||||
if (p_dispwidget->last_scale_factor > 1.0f)
|
||||
p_dispwidget->divider_width_1px = (unsigned)(p_dispwidget->last_scale_factor + 0.5f);
|
||||
@ -2188,132 +2065,3 @@ void gfx_widgets_ai_service_overlay_unload(dispgfx_widget_t *p_dispwidget)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
static void gfx_widgets_end_load_content_animation(void *userdata)
|
||||
{
|
||||
#if 0
|
||||
task_load_content_resume(); /* TODO: Restore that */
|
||||
#endif
|
||||
}
|
||||
|
||||
void gfx_widgets_cleanup_load_content_animation(void)
|
||||
{
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
p_dispwidget->load_content_animation_running = false;
|
||||
if (p_dispwidget->load_content_animation_content_name)
|
||||
free(p_dispwidget->load_content_animation_content_name);
|
||||
p_dispwidget->load_content_animation_content_name = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void gfx_widgets_start_load_content_animation(
|
||||
const char *content_name, bool remove_extension)
|
||||
{
|
||||
#ifdef HAVE_MENU
|
||||
/* TODO: finish the animation based on design, correct all timings */
|
||||
int i;
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
gfx_timer_ctx_entry_t timer_entry;
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
float icon_color[16] =
|
||||
COLOR_HEX_TO_FLOAT(0x0473C9, 1.0f); /* TODO: random color */
|
||||
unsigned timing = 0;
|
||||
|
||||
/* Prepare data */
|
||||
p_dispwidget->load_content_animation_icon = 0;
|
||||
|
||||
/* Abort animation if we don't have an icon */
|
||||
if (!menu_driver_get_load_content_animation_data(
|
||||
&p_dispwidget->load_content_animation_icon,
|
||||
&p_dispwidget->load_content_animation_playlist_name) ||
|
||||
!p_dispwidget->load_content_animation_icon)
|
||||
{
|
||||
gfx_widgets_end_load_content_animation(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
p_dispwidget->load_content_animation_content_name = strdup(content_name);
|
||||
|
||||
if (remove_extension)
|
||||
path_remove_extension(p_dispwidget->load_content_animation_content_name);
|
||||
|
||||
/* Reset animation state */
|
||||
p_dispwidget->load_content_animation_icon_size = p_dispwidget->load_content_animation_icon_size_initial;
|
||||
p_dispwidget->load_content_animation_icon_alpha = 0.0f;
|
||||
p_dispwidget->load_content_animation_fade_alpha = 0.0f;
|
||||
p_dispwidget->load_content_animation_final_fade_alpha = 0.0f;
|
||||
|
||||
memcpy(p_dispwidget->load_content_animation_icon_color, icon_color, sizeof(p_dispwidget->load_content_animation_icon_color));
|
||||
|
||||
/* Setup the animation */
|
||||
entry.cb = NULL;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.tag = p_dispwidget->gfx_widgets_generic_tag;
|
||||
entry.userdata = NULL;
|
||||
|
||||
/* Stage one: icon animation */
|
||||
/* Position */
|
||||
entry.duration = ANIMATION_LOAD_CONTENT_DURATION;
|
||||
entry.subject = &p_dispwidget->load_content_animation_icon_size;
|
||||
entry.target_value = p_dispwidget->load_content_animation_icon_size_target;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
|
||||
/* Alpha */
|
||||
entry.subject = &p_dispwidget->load_content_animation_icon_alpha;
|
||||
entry.target_value = 1.0f;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
timing += entry.duration;
|
||||
|
||||
/* Stage two: backdrop + text */
|
||||
entry.duration = ANIMATION_LOAD_CONTENT_DURATION*1.5;
|
||||
entry.subject = &p_dispwidget->load_content_animation_fade_alpha;
|
||||
entry.target_value = 1.0f;
|
||||
|
||||
gfx_animation_push_delayed(timing, &entry);
|
||||
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 = &p_dispwidget->load_content_animation_icon_color[i];
|
||||
entry.target_value = gfx_widgets_pure_white[i];
|
||||
|
||||
gfx_animation_push_delayed(timing, &entry);
|
||||
}
|
||||
|
||||
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 =
|
||||
&p_dispwidget->load_content_animation_final_fade_alpha;
|
||||
entry.target_value = 1.0f;
|
||||
|
||||
gfx_animation_push_delayed(timing, &entry);
|
||||
timing += entry.duration;
|
||||
|
||||
/* Setup end */
|
||||
timer_entry.cb = gfx_widgets_end_load_content_animation;
|
||||
timer_entry.duration = timing;
|
||||
timer_entry.userdata = NULL;
|
||||
|
||||
gfx_timer_start(
|
||||
&p_dispwidget->load_content_animation_end_timer,
|
||||
&timer_entry);
|
||||
|
||||
/* Draw all the things */
|
||||
p_dispwidget->load_content_animation_running = true;
|
||||
#endif
|
||||
}
|
||||
|
@ -146,25 +146,11 @@ typedef struct dispgfx_widget
|
||||
bool widgets_moving;
|
||||
bool widgets_inited;
|
||||
bool msg_queue_has_icons;
|
||||
#ifdef HAVE_MENU
|
||||
bool load_content_animation_running;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TRANSLATE
|
||||
int ai_service_overlay_state;
|
||||
#endif
|
||||
#ifdef HAVE_MENU
|
||||
float load_content_animation_icon_color[16];
|
||||
float load_content_animation_icon_size;
|
||||
float load_content_animation_icon_alpha;
|
||||
float load_content_animation_fade_alpha;
|
||||
float load_content_animation_final_fade_alpha;
|
||||
#endif
|
||||
float last_scale_factor;
|
||||
#ifdef HAVE_MENU
|
||||
unsigned load_content_animation_icon_size_initial;
|
||||
unsigned load_content_animation_icon_size_target;
|
||||
#endif
|
||||
#ifdef HAVE_TRANSLATE
|
||||
unsigned ai_service_overlay_width;
|
||||
unsigned ai_service_overlay_height;
|
||||
@ -201,9 +187,6 @@ typedef struct dispgfx_widget
|
||||
|
||||
uint64_t gfx_widgets_frame_count;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
uintptr_t load_content_animation_icon;
|
||||
#endif
|
||||
#ifdef HAVE_TRANSLATE
|
||||
uintptr_t ai_service_overlay_texture;
|
||||
#endif
|
||||
@ -214,13 +197,6 @@ typedef struct dispgfx_widget
|
||||
MENU_WIDGETS_ICON_LAST];
|
||||
|
||||
char gfx_widgets_fps_text[255];
|
||||
#ifdef HAVE_MENU
|
||||
char *load_content_animation_content_name;
|
||||
char *load_content_animation_playlist_name;
|
||||
#endif
|
||||
#ifdef HAVE_MENU
|
||||
gfx_timer_t load_content_animation_end_timer;
|
||||
#endif
|
||||
uintptr_t gfx_widgets_generic_tag;
|
||||
gfx_widget_fonts_t gfx_widget_fonts;
|
||||
fifo_buffer_t *msg_queue;
|
||||
@ -313,7 +289,6 @@ void gfx_widgets_draw_icon(
|
||||
unsigned icon_height,
|
||||
uintptr_t texture,
|
||||
float x, float y,
|
||||
unsigned width, unsigned height,
|
||||
float rotation, float scale_factor,
|
||||
float *color);
|
||||
|
||||
@ -372,11 +347,6 @@ bool gfx_widgets_ai_service_overlay_load(
|
||||
void gfx_widgets_ai_service_overlay_unload(dispgfx_widget_t *p_dispwidget);
|
||||
#endif
|
||||
|
||||
void gfx_widgets_start_load_content_animation(
|
||||
const char *content_name, bool remove_extension);
|
||||
|
||||
void gfx_widgets_cleanup_load_content_animation(void);
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
void gfx_widgets_push_achievement(const char *title, const char *badge);
|
||||
#endif
|
||||
@ -394,6 +364,9 @@ void gfx_widget_set_progress_message(void *data,
|
||||
const char *message, unsigned duration,
|
||||
unsigned priority, int8_t progress);
|
||||
|
||||
/* Warning: not thread safe! */
|
||||
bool gfx_widget_start_load_content_animation(void);
|
||||
|
||||
/* All the functions below should be called in
|
||||
* the video driver - once they are all added, set
|
||||
* enable_menu_widgets to true for that driver */
|
||||
@ -410,6 +383,7 @@ extern const gfx_widget_t gfx_widget_volume;
|
||||
extern const gfx_widget_t gfx_widget_generic_message;
|
||||
extern const gfx_widget_t gfx_widget_libretro_message;
|
||||
extern const gfx_widget_t gfx_widget_progress_message;
|
||||
extern const gfx_widget_t gfx_widget_load_content_animation;
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
extern const gfx_widget_t gfx_widget_achievement_popup;
|
||||
|
@ -144,7 +144,7 @@ static void gfx_widget_achievement_popup_frame(void* data, void* userdata)
|
||||
p_dispwidget->gfx_widgets_icons_textures[MENU_WIDGETS_ICON_ACHIEVEMENT],
|
||||
0,
|
||||
state->y,
|
||||
video_width, video_height, 0, 1, gfx_widgets_get_pure_white());
|
||||
0, 1, gfx_widgets_get_pure_white());
|
||||
gfx_display_blend_end(video_info->userdata);
|
||||
}
|
||||
}
|
||||
@ -160,8 +160,6 @@ static void gfx_widget_achievement_popup_frame(void* data, void* userdata)
|
||||
state->queue[state->queue_read_index].badge,
|
||||
0,
|
||||
state->y,
|
||||
video_width,
|
||||
video_height,
|
||||
0,
|
||||
1,
|
||||
gfx_widgets_get_pure_white());
|
||||
|
989
gfx/widgets/gfx_widget_load_content_animation.c
Normal file
989
gfx/widgets/gfx_widget_load_content_animation.c
Normal file
@ -0,0 +1,989 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2014-2017 - Jean-André Santoni
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
* Copyright (C) 2018-2020 - natinusala
|
||||
* Copyright (C) 2019-2020 - James Leaver
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include <string/stdstring.h>
|
||||
#include <file/file_path.h>
|
||||
|
||||
#include "../gfx_widgets.h"
|
||||
#include "../gfx_animation.h"
|
||||
#include "../gfx_display.h"
|
||||
#include "../../retroarch.h"
|
||||
#include "../../core_info.h"
|
||||
#include "../../playlist.h"
|
||||
#include "../../paths.h"
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
#include "../../menu/menu_driver.h"
|
||||
#endif
|
||||
|
||||
#define LOAD_CONTENT_ANIMATION_FADE_IN_DURATION 466.0f
|
||||
#define LOAD_CONTENT_ANIMATION_SLIDE_DURATION 666.0f
|
||||
#define LOAD_CONTENT_ANIMATION_WAIT_DURATION 1000.0f
|
||||
#define LOAD_CONTENT_ANIMATION_FADE_OUT_DURATION 433.0f
|
||||
|
||||
/* Widget state */
|
||||
|
||||
enum gfx_widget_load_content_animation_status
|
||||
{
|
||||
GFX_WIDGET_LOAD_CONTENT_IDLE = 0,
|
||||
GFX_WIDGET_LOAD_CONTENT_BEGIN,
|
||||
GFX_WIDGET_LOAD_CONTENT_FADE_IN,
|
||||
GFX_WIDGET_LOAD_CONTENT_SLIDE,
|
||||
GFX_WIDGET_LOAD_CONTENT_WAIT,
|
||||
GFX_WIDGET_LOAD_CONTENT_FADE_OUT
|
||||
};
|
||||
|
||||
struct gfx_widget_load_content_animation_state
|
||||
{
|
||||
enum gfx_widget_load_content_animation_status status;
|
||||
gfx_timer_t timer;
|
||||
float alpha;
|
||||
float slide_offset;
|
||||
|
||||
char content_name[512];
|
||||
char system_name[512];
|
||||
char icon_directory[PATH_MAX_LENGTH];
|
||||
char icon_file[PATH_MAX_LENGTH];
|
||||
|
||||
uintptr_t icon_texture;
|
||||
bool has_icon;
|
||||
|
||||
unsigned content_name_width;
|
||||
unsigned system_name_width;
|
||||
|
||||
unsigned bg_width;
|
||||
unsigned bg_height;
|
||||
float bg_x;
|
||||
float bg_y;
|
||||
|
||||
unsigned bg_shadow_height;
|
||||
float bg_shadow_top_y;
|
||||
float bg_shadow_bottom_y;
|
||||
|
||||
unsigned margin_shadow_width;
|
||||
float margin_shadow_left_x;
|
||||
float margin_shadow_right_x;
|
||||
|
||||
unsigned icon_size;
|
||||
float icon_x_start;
|
||||
float icon_x_end;
|
||||
float icon_y;
|
||||
|
||||
float text_x_start;
|
||||
float text_x_end;
|
||||
float content_name_y;
|
||||
float system_name_y;
|
||||
|
||||
float bg_alpha;
|
||||
float bg_underlay_alpha;
|
||||
float bg_shadow_alpha;
|
||||
|
||||
float bg_color[16];
|
||||
float bg_underlay_color[16];
|
||||
float bg_shadow_top_color[16];
|
||||
float bg_shadow_bottom_color[16];
|
||||
float margin_shadow_left_color[16];
|
||||
float margin_shadow_right_color[16];
|
||||
float icon_color[16];
|
||||
|
||||
unsigned content_name_color;
|
||||
unsigned system_name_color;
|
||||
};
|
||||
|
||||
typedef struct gfx_widget_load_content_animation_state gfx_widget_load_content_animation_state_t;
|
||||
|
||||
static gfx_widget_load_content_animation_state_t p_w_load_content_animation_st = {
|
||||
|
||||
GFX_WIDGET_LOAD_CONTENT_IDLE, /* status */
|
||||
0.0f, /* timer */
|
||||
0.0f, /* alpha */
|
||||
0.0f, /* slide_offset */
|
||||
|
||||
{'\0'}, /* content_name */
|
||||
{'\0'}, /* system_name */
|
||||
{'\0'}, /* icon_directory */
|
||||
{'\0'}, /* icon_file */
|
||||
|
||||
0, /* icon_texture */
|
||||
false, /* has_icon */
|
||||
|
||||
0, /* content_name_width */
|
||||
0, /* system_name_width */
|
||||
|
||||
0, /* bg_width */
|
||||
0, /* bg_height */
|
||||
0.0f, /* bg_x */
|
||||
0.0f, /* bg_y */
|
||||
|
||||
0, /* bg_shadow_height */
|
||||
0.0f, /* bg_shadow_top_y */
|
||||
0.0f, /* bg_shadow_bottom_y */
|
||||
|
||||
0, /* margin_shadow_width */
|
||||
0.0f, /* margin_shadow_left_x */
|
||||
0.0f, /* margin_shadow_right_x */
|
||||
|
||||
0, /* icon_size */
|
||||
0.0f, /* icon_x_start */
|
||||
0.0f, /* icon_x_end */
|
||||
0.0f, /* icon_y */
|
||||
|
||||
0.0f, /* text_x_start */
|
||||
0.0f, /* text_x_end */
|
||||
0.0f, /* content_name_y */
|
||||
0.0f, /* system_name_y */
|
||||
|
||||
0.95f, /* bg_alpha */
|
||||
0.5f, /* bg_underlay_alpha */
|
||||
0.4f, /* bg_shadow_alpha */
|
||||
|
||||
COLOR_HEX_TO_FLOAT(0x000000, 1.0f), /* bg_color */
|
||||
COLOR_HEX_TO_FLOAT(0x505050, 1.0f), /* bg_underlay_color */
|
||||
COLOR_HEX_TO_FLOAT(0x000000, 0.0f), /* bg_shadow_top_color */
|
||||
COLOR_HEX_TO_FLOAT(0x000000, 0.0f), /* bg_shadow_bottom_color */
|
||||
COLOR_HEX_TO_FLOAT(0x000000, 0.0f), /* margin_shadow_left_color */
|
||||
COLOR_HEX_TO_FLOAT(0x000000, 0.0f), /* margin_shadow_right_color */
|
||||
COLOR_HEX_TO_FLOAT(0xE0E0E0, 1.0f), /* icon_color */
|
||||
|
||||
0xE0E0E0FF, /* content_name_color */
|
||||
0xCFCFCFFF, /* system_name_color */
|
||||
};
|
||||
|
||||
gfx_widget_load_content_animation_state_t *gfx_widget_load_content_animation_get_ptr(void)
|
||||
{
|
||||
return &p_w_load_content_animation_st;
|
||||
}
|
||||
|
||||
/* Utilities */
|
||||
|
||||
static void gfx_widget_load_content_animation_reset(void)
|
||||
{
|
||||
gfx_widget_load_content_animation_state_t *state = gfx_widget_load_content_animation_get_ptr();
|
||||
uintptr_t alpha_tag = (uintptr_t)&state->alpha;
|
||||
uintptr_t slide_offset_tag = (uintptr_t)&state->slide_offset;
|
||||
|
||||
/* Kill any existing timers/animations */
|
||||
gfx_timer_kill(&state->timer);
|
||||
gfx_animation_kill_by_tag(&alpha_tag);
|
||||
gfx_animation_kill_by_tag(&slide_offset_tag);
|
||||
|
||||
/* Reset pertinent state parameters */
|
||||
state->status = GFX_WIDGET_LOAD_CONTENT_IDLE;
|
||||
state->alpha = 0.0f;
|
||||
state->slide_offset = 0.0f;
|
||||
state->content_name[0] = '\0';
|
||||
state->system_name[0] = '\0';
|
||||
state->icon_file[0] = '\0';
|
||||
state->has_icon = false;
|
||||
state->content_name_width = 0;
|
||||
state->system_name_width = 0;
|
||||
|
||||
/* Unload any icon texture */
|
||||
if (state->icon_texture)
|
||||
{
|
||||
video_driver_texture_unload(&state->icon_texture);
|
||||
state->icon_texture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_widget_load_content_animation_load_icon(void)
|
||||
{
|
||||
gfx_widget_load_content_animation_state_t *state = gfx_widget_load_content_animation_get_ptr();
|
||||
|
||||
/* In all cases, unload any existing icon texture */
|
||||
if (state->icon_texture)
|
||||
{
|
||||
video_driver_texture_unload(&state->icon_texture);
|
||||
state->icon_texture = 0;
|
||||
}
|
||||
|
||||
/* If widget has a valid icon set, load it */
|
||||
if (state->has_icon)
|
||||
gfx_display_reset_textures_list(
|
||||
state->icon_file, state->icon_directory,
|
||||
&state->icon_texture,
|
||||
TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
static void gfx_widget_load_content_animation_fade_out_cb(void *userdata)
|
||||
{
|
||||
/* Animation is complete - reset widget */
|
||||
gfx_widget_load_content_animation_reset();
|
||||
}
|
||||
|
||||
static void gfx_widget_load_content_animation_wait_cb(void *userdata)
|
||||
{
|
||||
gfx_widget_load_content_animation_state_t *state = (gfx_widget_load_content_animation_state_t*)userdata;
|
||||
uintptr_t alpha_tag = (uintptr_t)&state->alpha;
|
||||
gfx_animation_ctx_entry_t animation_entry;
|
||||
|
||||
/* Trigger fade out animation */
|
||||
state->alpha = 1.0f;
|
||||
|
||||
animation_entry.easing_enum = EASING_OUT_QUAD;
|
||||
animation_entry.tag = alpha_tag;
|
||||
animation_entry.duration = LOAD_CONTENT_ANIMATION_FADE_OUT_DURATION;
|
||||
animation_entry.target_value = 0.0f;
|
||||
animation_entry.subject = &state->alpha;
|
||||
animation_entry.cb = gfx_widget_load_content_animation_fade_out_cb;
|
||||
animation_entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&animation_entry);
|
||||
state->status = GFX_WIDGET_LOAD_CONTENT_FADE_OUT;
|
||||
}
|
||||
|
||||
static void gfx_widget_load_content_animation_slide_cb(void *userdata)
|
||||
{
|
||||
gfx_widget_load_content_animation_state_t *state = (gfx_widget_load_content_animation_state_t*)userdata;
|
||||
gfx_timer_ctx_entry_t timer;
|
||||
|
||||
/* Start wait timer */
|
||||
timer.duration = LOAD_CONTENT_ANIMATION_WAIT_DURATION;
|
||||
timer.cb = gfx_widget_load_content_animation_wait_cb;
|
||||
timer.userdata = state;
|
||||
|
||||
gfx_timer_start(&state->timer, &timer);
|
||||
state->status = GFX_WIDGET_LOAD_CONTENT_WAIT;
|
||||
}
|
||||
|
||||
static void gfx_widget_load_content_animation_fade_in_cb(void *userdata)
|
||||
{
|
||||
gfx_widget_load_content_animation_state_t *state = (gfx_widget_load_content_animation_state_t*)userdata;
|
||||
uintptr_t slide_offset_tag = (uintptr_t)&state->slide_offset;
|
||||
gfx_animation_ctx_entry_t animation_entry;
|
||||
|
||||
/* Trigger slide animation */
|
||||
state->slide_offset = 0.0f;
|
||||
|
||||
animation_entry.easing_enum = EASING_IN_OUT_QUAD;
|
||||
animation_entry.tag = slide_offset_tag;
|
||||
animation_entry.duration = LOAD_CONTENT_ANIMATION_SLIDE_DURATION;
|
||||
animation_entry.target_value = 1.0f;
|
||||
animation_entry.subject = &state->slide_offset;
|
||||
animation_entry.cb = gfx_widget_load_content_animation_slide_cb;
|
||||
animation_entry.userdata = state;
|
||||
|
||||
gfx_animation_push(&animation_entry);
|
||||
state->status = GFX_WIDGET_LOAD_CONTENT_SLIDE;
|
||||
}
|
||||
|
||||
/* Widget interface */
|
||||
|
||||
bool gfx_widget_start_load_content_animation(void)
|
||||
{
|
||||
gfx_widget_load_content_animation_state_t *state = gfx_widget_load_content_animation_get_ptr();
|
||||
|
||||
const char *content_path = path_get(RARCH_PATH_CONTENT);
|
||||
const char *core_path = path_get(RARCH_PATH_CORE);
|
||||
playlist_t *playlist = playlist_get_cached();
|
||||
|
||||
bool playlist_entry_found = false;
|
||||
bool has_content = false;
|
||||
bool has_system = false;
|
||||
bool has_db_name = false;
|
||||
|
||||
core_info_ctx_find_t core_info_finder;
|
||||
char icon_path[PATH_MAX_LENGTH];
|
||||
|
||||
icon_path[0] = '\0';
|
||||
|
||||
/* To ensure we leave the widget in a well defined
|
||||
* state, perform a reset before parsing variables */
|
||||
gfx_widget_load_content_animation_reset();
|
||||
|
||||
/* Sanity check - we require both content and
|
||||
* core path
|
||||
* > Note that we would prefer to enable the load
|
||||
* content animation for 'content-less' cores as
|
||||
* well, but allowing no content would mean we
|
||||
* trigger a false positive every time the dummy
|
||||
* core is started (this higher level behaviour is
|
||||
* deeply ingrained in RetroArch, and too difficult
|
||||
* to change...) */
|
||||
if (string_is_empty(content_path) ||
|
||||
string_is_empty(core_path) ||
|
||||
string_is_equal(core_path, "builtin"))
|
||||
return false;
|
||||
|
||||
/* Check core validity */
|
||||
core_info_finder.inf = NULL;
|
||||
core_info_finder.path = core_path;
|
||||
|
||||
if (!core_info_find(&core_info_finder))
|
||||
return false;
|
||||
|
||||
core_path = core_info_finder.inf->path;
|
||||
|
||||
/* Parse content path
|
||||
* > If we have a cached playlist, attempt to find
|
||||
* the entry label for the current content */
|
||||
if (playlist)
|
||||
{
|
||||
const struct playlist_entry *entry = NULL;
|
||||
#ifdef HAVE_MENU
|
||||
menu_handle_t *menu = menu_driver_get_ptr();
|
||||
|
||||
/* If we have an active menu, playlist entry
|
||||
* index can be obtained directly */
|
||||
if (menu)
|
||||
{
|
||||
if (playlist_index_is_valid(
|
||||
playlist, menu->rpl_entry_selection_ptr,
|
||||
content_path, core_path))
|
||||
playlist_get_index(
|
||||
playlist, menu->rpl_entry_selection_ptr,
|
||||
&entry);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* No menu - have to search playlist... */
|
||||
playlist_get_index_by_path(playlist, content_path,
|
||||
&entry);
|
||||
|
||||
if (entry &&
|
||||
!string_is_empty(entry->core_path))
|
||||
{
|
||||
const char *entry_core_file = path_basename(entry->core_path);
|
||||
|
||||
/* Check whether core matches... */
|
||||
if (string_is_empty(entry_core_file) ||
|
||||
!string_starts_with_size(
|
||||
entry_core_file,
|
||||
core_info_finder.inf->core_file_id.str,
|
||||
core_info_finder.inf->core_file_id.len))
|
||||
entry = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* If playlist entry is valid, extract all
|
||||
* available information */
|
||||
if (entry)
|
||||
{
|
||||
playlist_entry_found = true;
|
||||
|
||||
/* Get entry label */
|
||||
if (!string_is_empty(entry->label))
|
||||
{
|
||||
strlcpy(state->content_name, entry->label,
|
||||
sizeof(state->content_name));
|
||||
has_content = true;
|
||||
}
|
||||
|
||||
/* Get entry db_name, */
|
||||
if (!string_is_empty(entry->db_name))
|
||||
{
|
||||
strlcpy(state->system_name, entry->db_name,
|
||||
sizeof(state->system_name));
|
||||
path_remove_extension(state->system_name);
|
||||
|
||||
has_system = true;
|
||||
has_db_name = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If content was found in playlist but the entry
|
||||
* did not have a db_name, use playlist name itself
|
||||
* as the system name */
|
||||
if (playlist_entry_found && !has_system)
|
||||
{
|
||||
const char *playlist_path = playlist_get_conf_path(playlist);
|
||||
|
||||
if (!string_is_empty(playlist_path))
|
||||
{
|
||||
fill_pathname_base_noext(state->system_name, playlist_path,
|
||||
sizeof(state->system_name));
|
||||
|
||||
/* Exclude history and favourites playlists */
|
||||
if (string_is_equal(state->system_name, "history") ||
|
||||
string_is_equal(state->system_name, "favorites") ||
|
||||
string_ends_with_size(state->system_name, "_history",
|
||||
strlen(state->system_name), STRLEN_CONST("_history")))
|
||||
state->system_name[0] = '\0';
|
||||
|
||||
/* Check whether a valid system name was found */
|
||||
if (!string_is_empty(state->system_name))
|
||||
{
|
||||
has_system = true;
|
||||
has_db_name = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we haven't yet set the content name,
|
||||
* use content file name as a fallback */
|
||||
if (!has_content)
|
||||
fill_pathname_base_noext(state->content_name, content_path,
|
||||
sizeof(state->content_name));
|
||||
|
||||
/* Check whether system name has been set */
|
||||
if (!has_system)
|
||||
{
|
||||
/* Use core display name, if available */
|
||||
if (!string_is_empty(core_info_finder.inf->display_name))
|
||||
strlcpy(state->system_name, core_info_finder.inf->display_name,
|
||||
sizeof(state->system_name));
|
||||
/* Otherwise, just use 'RetroArch' as a fallback */
|
||||
else
|
||||
strlcpy(state->system_name, "RetroArch",
|
||||
sizeof(state->system_name));
|
||||
}
|
||||
|
||||
/* > Content name has been determined
|
||||
* > System name has been determined
|
||||
* All that remains is the icon */
|
||||
|
||||
/* Get icon filename
|
||||
* > Use db_name, if available */
|
||||
if (has_db_name)
|
||||
{
|
||||
strlcpy(state->icon_file, state->system_name,
|
||||
sizeof(state->icon_file));
|
||||
strlcat(state->icon_file, ".png",
|
||||
sizeof(state->icon_file));
|
||||
|
||||
fill_pathname_join(icon_path,
|
||||
state->icon_directory, state->icon_file,
|
||||
sizeof(icon_path));
|
||||
|
||||
state->has_icon = path_is_valid(icon_path);
|
||||
}
|
||||
|
||||
/* > If db_name is unavailable (or was extracted
|
||||
* from a playlist with non-standard naming),
|
||||
* try to extract a valid system from the core
|
||||
* itself */
|
||||
if (!state->has_icon)
|
||||
{
|
||||
const char *core_db_name = NULL;
|
||||
struct string_list *databases_list =
|
||||
core_info_finder.inf->databases_list;
|
||||
|
||||
/* We can only use the core db_name if the
|
||||
* core is associated with exactly one database */
|
||||
if (databases_list &&
|
||||
(databases_list->size == 1))
|
||||
core_db_name = databases_list->elems[0].data;
|
||||
|
||||
if (!string_is_empty(core_db_name) &&
|
||||
!string_is_equal(core_db_name, state->system_name))
|
||||
{
|
||||
state->icon_file[0] = '\0';
|
||||
icon_path[0] = '\0';
|
||||
|
||||
strlcpy(state->icon_file, core_db_name,
|
||||
sizeof(state->icon_file));
|
||||
strlcat(state->icon_file, ".png",
|
||||
sizeof(state->icon_file));
|
||||
|
||||
fill_pathname_join(icon_path,
|
||||
state->icon_directory, state->icon_file,
|
||||
sizeof(icon_path));
|
||||
|
||||
state->has_icon = path_is_valid(icon_path);
|
||||
}
|
||||
}
|
||||
|
||||
/* > If no system-specific icon is available,
|
||||
* use default 'retroarch' icon as a fallback */
|
||||
if (!state->has_icon)
|
||||
{
|
||||
state->icon_file[0] = '\0';
|
||||
icon_path[0] = '\0';
|
||||
|
||||
strlcpy(state->icon_file, "retroarch.png",
|
||||
sizeof(state->icon_file));
|
||||
|
||||
fill_pathname_join(icon_path,
|
||||
state->icon_directory, state->icon_file,
|
||||
sizeof(icon_path));
|
||||
|
||||
state->has_icon = path_is_valid(icon_path);
|
||||
}
|
||||
|
||||
/* All parameters are initialised
|
||||
* > Signal that animation should begin */
|
||||
state->status = GFX_WIDGET_LOAD_CONTENT_BEGIN;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Widget layout() */
|
||||
|
||||
static void gfx_widget_load_content_animation_layout(
|
||||
void *data,
|
||||
bool is_threaded, const char *dir_assets, char *font_path)
|
||||
{
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)data;
|
||||
gfx_widget_load_content_animation_state_t *state = gfx_widget_load_content_animation_get_ptr();
|
||||
|
||||
unsigned last_video_width = gfx_widgets_get_last_video_width(p_dispwidget);
|
||||
unsigned last_video_height = gfx_widgets_get_last_video_height(p_dispwidget);
|
||||
unsigned widget_padding = gfx_widgets_get_padding(p_dispwidget);
|
||||
|
||||
gfx_widget_font_data_t *font_regular = gfx_widgets_get_font_regular(p_dispwidget);
|
||||
gfx_widget_font_data_t *font_bold = gfx_widgets_get_font_bold(p_dispwidget);
|
||||
|
||||
/* Icon layout */
|
||||
state->icon_size = (unsigned)((((float)font_regular->line_height +
|
||||
(float)font_bold->line_height) * 1.6f) + 0.5f);
|
||||
state->icon_x_start = (float)(last_video_width - state->icon_size) * 0.5f;
|
||||
state->icon_y = (float)(last_video_height - state->icon_size) * 0.5f;
|
||||
/* > Note: cannot determine state->icon_x_end
|
||||
* until text strings are set */
|
||||
|
||||
/* Background layout */
|
||||
state->bg_width = last_video_width;
|
||||
state->bg_height = state->icon_size + (widget_padding * 2);
|
||||
state->bg_x = 0.0f;
|
||||
state->bg_y = (float)(last_video_height - state->bg_height) * 0.5f;
|
||||
|
||||
/* Background shadow layout */
|
||||
state->bg_shadow_height = (unsigned)((float)state->bg_height * 0.3f);
|
||||
state->bg_shadow_top_y = state->bg_y - (float)state->bg_shadow_height;
|
||||
state->bg_shadow_bottom_y = state->bg_y + (float)state->bg_height;
|
||||
|
||||
/* Margin shadow layout */
|
||||
state->margin_shadow_width = widget_padding;
|
||||
state->margin_shadow_left_x = 0.0f;
|
||||
state->margin_shadow_right_x = (float)(last_video_width - widget_padding);
|
||||
|
||||
/* Text layout */
|
||||
state->text_x_start = state->icon_x_start +
|
||||
(float)(state->icon_size + widget_padding);
|
||||
state->content_name_y = state->icon_y +
|
||||
((float)state->icon_size * 0.3f) +
|
||||
(float)font_bold->line_centre_offset;
|
||||
state->system_name_y = state->icon_y +
|
||||
((float)state->icon_size * 0.7f) +
|
||||
(float)font_regular->line_centre_offset;
|
||||
/* > Note: cannot determine state->text_x_end
|
||||
* until text strings are set */
|
||||
}
|
||||
|
||||
/* Widget iterate() */
|
||||
|
||||
static void gfx_widget_load_content_animation_iterate(void *user_data,
|
||||
unsigned width, unsigned height, bool fullscreen,
|
||||
const char *dir_assets, char *font_path,
|
||||
bool is_threaded)
|
||||
{
|
||||
gfx_widget_load_content_animation_state_t *state = gfx_widget_load_content_animation_get_ptr();
|
||||
|
||||
if (state->status == GFX_WIDGET_LOAD_CONTENT_BEGIN)
|
||||
{
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)user_data;
|
||||
|
||||
unsigned last_video_width = gfx_widgets_get_last_video_width(p_dispwidget);
|
||||
unsigned widget_padding = gfx_widgets_get_padding(p_dispwidget);
|
||||
|
||||
gfx_widget_font_data_t *font_regular = gfx_widgets_get_font_regular(p_dispwidget);
|
||||
gfx_widget_font_data_t *font_bold = gfx_widgets_get_font_bold(p_dispwidget);
|
||||
|
||||
uintptr_t alpha_tag = (uintptr_t)&state->alpha;
|
||||
|
||||
int content_name_width;
|
||||
int system_name_width;
|
||||
int text_width;
|
||||
int icon_x_end;
|
||||
int text_x_end;
|
||||
gfx_animation_ctx_entry_t animation_entry;
|
||||
|
||||
/* Load icon texture */
|
||||
gfx_widget_load_content_animation_load_icon();
|
||||
|
||||
/* Get overall text width */
|
||||
content_name_width = font_driver_get_message_width(
|
||||
font_bold->font, state->content_name,
|
||||
(unsigned)strlen(state->content_name), 1.0f);
|
||||
system_name_width = font_driver_get_message_width(
|
||||
font_regular->font, state->system_name,
|
||||
(unsigned)strlen(state->system_name), 1.0f);
|
||||
|
||||
state->content_name_width = (content_name_width > 0) ?
|
||||
(unsigned)content_name_width : 0;
|
||||
state->system_name_width = (system_name_width > 0) ?
|
||||
(unsigned)system_name_width : 0;
|
||||
|
||||
text_width = (state->content_name_width > state->system_name_width) ?
|
||||
(int)state->content_name_width : (int)state->system_name_width;
|
||||
|
||||
/* Now we have the text width, can determine
|
||||
* final icon/text x draw positions */
|
||||
state->icon_x_end = ((int)last_video_width - text_width -
|
||||
(int)state->icon_size - (3 * (int)widget_padding)) >> 1;
|
||||
state->icon_x_end = state->icon_x_end < (int)widget_padding ?
|
||||
widget_padding : state->icon_x_end;
|
||||
|
||||
state->text_x_end = state->icon_x_end +
|
||||
(float)(state->icon_size + widget_padding);
|
||||
|
||||
/* Trigger fade in animation */
|
||||
state->alpha = 0.0f;
|
||||
|
||||
animation_entry.easing_enum = EASING_OUT_QUAD;
|
||||
animation_entry.tag = alpha_tag;
|
||||
animation_entry.duration = LOAD_CONTENT_ANIMATION_FADE_IN_DURATION;
|
||||
animation_entry.target_value = 1.0f;
|
||||
animation_entry.subject = &state->alpha;
|
||||
animation_entry.cb = gfx_widget_load_content_animation_fade_in_cb;
|
||||
animation_entry.userdata = state;
|
||||
|
||||
gfx_animation_push(&animation_entry);
|
||||
state->status = GFX_WIDGET_LOAD_CONTENT_FADE_IN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Widget frame() */
|
||||
|
||||
static void gfx_widget_load_content_animation_frame(void *data, void *user_data)
|
||||
{
|
||||
gfx_widget_load_content_animation_state_t *state = gfx_widget_load_content_animation_get_ptr();
|
||||
|
||||
if (state->status != GFX_WIDGET_LOAD_CONTENT_IDLE)
|
||||
{
|
||||
video_frame_info_t *video_info = (video_frame_info_t*)data;
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)user_data;
|
||||
|
||||
unsigned video_width = video_info->width;
|
||||
unsigned video_height = video_info->height;
|
||||
void *userdata = video_info->userdata;
|
||||
|
||||
gfx_widget_font_data_t *font_regular = gfx_widgets_get_font_regular(p_dispwidget);
|
||||
gfx_widget_font_data_t *font_bold = gfx_widgets_get_font_bold(p_dispwidget);
|
||||
size_t msg_queue_size = gfx_widgets_get_msg_queue_size(p_dispwidget);
|
||||
|
||||
float bg_alpha;
|
||||
float icon_alpha;
|
||||
float text_alpha;
|
||||
|
||||
float icon_x;
|
||||
float text_x;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
/* Draw nothing if menu is currently active */
|
||||
if (menu_driver_is_alive())
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Determine status-dependent opacity/position
|
||||
* values */
|
||||
switch (state->status)
|
||||
{
|
||||
case GFX_WIDGET_LOAD_CONTENT_FADE_IN:
|
||||
bg_alpha = 1.0f;
|
||||
icon_alpha = state->alpha;
|
||||
text_alpha = 0.0f;
|
||||
icon_x = state->icon_x_start;
|
||||
text_x = state->text_x_start;
|
||||
break;
|
||||
case GFX_WIDGET_LOAD_CONTENT_SLIDE:
|
||||
bg_alpha = 1.0f;
|
||||
icon_alpha = 1.0f;
|
||||
/* Use 'slide_offset' as the alpha value
|
||||
* > Saves having to trigger two animations */
|
||||
text_alpha = state->slide_offset;
|
||||
icon_x = state->icon_x_start + (state->slide_offset *
|
||||
(state->icon_x_end - state->icon_x_start));
|
||||
text_x = state->text_x_start + (state->slide_offset *
|
||||
(state->text_x_end - state->text_x_start));
|
||||
break;
|
||||
case GFX_WIDGET_LOAD_CONTENT_WAIT:
|
||||
bg_alpha = 1.0f;
|
||||
icon_alpha = 1.0f;
|
||||
text_alpha = 1.0f;
|
||||
icon_x = state->icon_x_end;
|
||||
text_x = state->text_x_end;
|
||||
break;
|
||||
case GFX_WIDGET_LOAD_CONTENT_FADE_OUT:
|
||||
bg_alpha = state->alpha;
|
||||
icon_alpha = state->alpha;
|
||||
text_alpha = state->alpha;
|
||||
icon_x = state->icon_x_end;
|
||||
text_x = state->text_x_end;
|
||||
break;
|
||||
case GFX_WIDGET_LOAD_CONTENT_BEGIN:
|
||||
default:
|
||||
bg_alpha = 1.0f;
|
||||
icon_alpha = 0.0f;
|
||||
text_alpha = 0.0f;
|
||||
icon_x = state->icon_x_start;
|
||||
text_x = state->text_x_start;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Draw background */
|
||||
if (bg_alpha > 0.0f)
|
||||
{
|
||||
/* > Set opacity */
|
||||
state->bg_shadow_top_color[3] = bg_alpha * state->bg_shadow_alpha;
|
||||
state->bg_shadow_top_color[7] = bg_alpha * state->bg_shadow_alpha;
|
||||
state->bg_shadow_bottom_color[11] = bg_alpha * state->bg_shadow_alpha;
|
||||
state->bg_shadow_bottom_color[15] = bg_alpha * state->bg_shadow_alpha;
|
||||
|
||||
gfx_display_set_alpha(state->bg_color, bg_alpha * state->bg_alpha);
|
||||
gfx_display_set_alpha(state->bg_underlay_color,
|
||||
bg_alpha * state->bg_underlay_alpha);
|
||||
|
||||
/* > Background underlay */
|
||||
gfx_display_draw_quad(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
0,
|
||||
0,
|
||||
video_width,
|
||||
video_height,
|
||||
video_width,
|
||||
video_height,
|
||||
state->bg_underlay_color);
|
||||
|
||||
/* > Background shadow */
|
||||
gfx_display_draw_quad(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->bg_x,
|
||||
state->bg_shadow_top_y,
|
||||
state->bg_width,
|
||||
state->bg_shadow_height,
|
||||
video_width,
|
||||
video_height,
|
||||
state->bg_shadow_top_color);
|
||||
|
||||
gfx_display_draw_quad(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->bg_x,
|
||||
state->bg_shadow_bottom_y,
|
||||
state->bg_width,
|
||||
state->bg_shadow_height,
|
||||
video_width,
|
||||
video_height,
|
||||
state->bg_shadow_bottom_color);
|
||||
|
||||
/* > Background */
|
||||
gfx_display_draw_quad(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->bg_x,
|
||||
state->bg_y,
|
||||
state->bg_width,
|
||||
state->bg_height,
|
||||
video_width,
|
||||
video_height,
|
||||
state->bg_color);
|
||||
}
|
||||
|
||||
/* Draw icon */
|
||||
if (icon_alpha > 0.0f)
|
||||
{
|
||||
gfx_display_set_alpha(state->icon_color, icon_alpha);
|
||||
|
||||
if (state->icon_texture)
|
||||
{
|
||||
gfx_display_blend_begin(userdata);
|
||||
|
||||
gfx_widgets_draw_icon(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->icon_size,
|
||||
state->icon_size,
|
||||
state->icon_texture,
|
||||
icon_x,
|
||||
state->icon_y,
|
||||
0.0f,
|
||||
1.0f,
|
||||
state->icon_color);
|
||||
|
||||
gfx_display_blend_end(userdata);
|
||||
}
|
||||
/* If there is no icon, draw a placeholder
|
||||
* (otherwise layout will look terrible...) */
|
||||
else
|
||||
gfx_display_draw_quad(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
icon_x,
|
||||
state->icon_y,
|
||||
state->icon_size,
|
||||
state->icon_size,
|
||||
video_width,
|
||||
video_height,
|
||||
state->icon_color);
|
||||
}
|
||||
|
||||
/* Draw text */
|
||||
if (text_alpha > 0.0f)
|
||||
{
|
||||
unsigned text_alpha_int = (unsigned)(text_alpha * 255.0f);
|
||||
|
||||
/* > Set opacity */
|
||||
state->content_name_color = COLOR_TEXT_ALPHA(state->content_name_color,
|
||||
text_alpha_int);
|
||||
state->system_name_color = COLOR_TEXT_ALPHA(state->system_name_color,
|
||||
text_alpha_int);
|
||||
|
||||
/* > Content name */
|
||||
gfx_widgets_draw_text(
|
||||
font_bold,
|
||||
state->content_name,
|
||||
text_x,
|
||||
state->content_name_y,
|
||||
video_width,
|
||||
video_height,
|
||||
state->content_name_color,
|
||||
TEXT_ALIGN_LEFT,
|
||||
true);
|
||||
|
||||
/* > System name */
|
||||
gfx_widgets_draw_text(
|
||||
font_regular,
|
||||
state->system_name,
|
||||
text_x,
|
||||
state->system_name_y,
|
||||
video_width,
|
||||
video_height,
|
||||
state->system_name_color,
|
||||
TEXT_ALIGN_LEFT,
|
||||
true);
|
||||
|
||||
/* If the message queue is active, must flush the
|
||||
* text here to avoid overlaps */
|
||||
if (msg_queue_size > 0)
|
||||
{
|
||||
gfx_widgets_flush_text(video_width, video_height, font_regular);
|
||||
gfx_widgets_flush_text(video_width, video_height, font_bold);
|
||||
}
|
||||
/* Must also flush text if it overlaps the edge of
|
||||
* the screen (otherwise it will bleed through the
|
||||
* 'margin' shadows) */
|
||||
else
|
||||
{
|
||||
if (state->system_name_width > video_width -
|
||||
(unsigned)text_x - state->margin_shadow_width)
|
||||
gfx_widgets_flush_text(video_width, video_height, font_regular);
|
||||
|
||||
if (state->content_name_width > video_width -
|
||||
(unsigned)text_x - state->margin_shadow_width)
|
||||
gfx_widgets_flush_text(video_width, video_height, font_bold);
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw 'margin' shadows
|
||||
* > This ensures rendered text is cleanly
|
||||
* truncated when it exceeds the width of
|
||||
* the screen */
|
||||
if (bg_alpha > 0.0f)
|
||||
{
|
||||
/* > Set opacity */
|
||||
state->margin_shadow_left_color[3] = bg_alpha;
|
||||
state->margin_shadow_left_color[11] = bg_alpha;
|
||||
state->margin_shadow_right_color[7] = bg_alpha;
|
||||
state->margin_shadow_right_color[15] = bg_alpha;
|
||||
|
||||
/* > Left */
|
||||
gfx_display_draw_quad(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->margin_shadow_left_x,
|
||||
state->bg_y,
|
||||
state->margin_shadow_width,
|
||||
state->bg_height,
|
||||
video_width,
|
||||
video_height,
|
||||
state->margin_shadow_left_color);
|
||||
|
||||
/* > Right */
|
||||
gfx_display_draw_quad(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->margin_shadow_right_x,
|
||||
state->bg_y,
|
||||
state->margin_shadow_width,
|
||||
state->bg_height,
|
||||
video_width,
|
||||
video_height,
|
||||
state->margin_shadow_right_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Widget context_reset() */
|
||||
|
||||
static void gfx_widget_load_content_animation_context_reset(
|
||||
bool is_threaded,
|
||||
unsigned width, unsigned height, bool fullscreen,
|
||||
const char *dir_assets, char *font_path,
|
||||
char* menu_png_path,
|
||||
char* widgets_png_path)
|
||||
{
|
||||
gfx_widget_load_content_animation_state_t *state = gfx_widget_load_content_animation_get_ptr();
|
||||
|
||||
/* Cache icon directory */
|
||||
if (string_is_empty(menu_png_path))
|
||||
state->icon_directory[0] = '\0';
|
||||
else
|
||||
strlcpy(state->icon_directory, menu_png_path,
|
||||
sizeof(state->icon_directory));
|
||||
|
||||
/* Reload icon texture */
|
||||
gfx_widget_load_content_animation_load_icon();
|
||||
}
|
||||
|
||||
/* Widget context_destroy() */
|
||||
|
||||
static void gfx_widget_load_content_animation_context_destroy(void)
|
||||
{
|
||||
gfx_widget_load_content_animation_state_t *state = gfx_widget_load_content_animation_get_ptr();
|
||||
|
||||
/* Unload any icon texture */
|
||||
if (state->icon_texture)
|
||||
{
|
||||
video_driver_texture_unload(&state->icon_texture);
|
||||
state->icon_texture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Widget free() */
|
||||
|
||||
static void gfx_widget_load_content_animation_free(void)
|
||||
{
|
||||
gfx_widget_load_content_animation_reset();
|
||||
}
|
||||
|
||||
/* Widget definition */
|
||||
|
||||
const gfx_widget_t gfx_widget_load_content_animation = {
|
||||
NULL, /* init */
|
||||
gfx_widget_load_content_animation_free,
|
||||
gfx_widget_load_content_animation_context_reset,
|
||||
gfx_widget_load_content_animation_context_destroy,
|
||||
gfx_widget_load_content_animation_layout,
|
||||
gfx_widget_load_content_animation_iterate,
|
||||
gfx_widget_load_content_animation_frame
|
||||
};
|
@ -189,7 +189,6 @@ static void gfx_widget_screenshot_frame(void* data, void *user_data)
|
||||
state->thumbnail_height,
|
||||
state->texture,
|
||||
0, state->y,
|
||||
video_width, video_height,
|
||||
0, 1, pure_white
|
||||
);
|
||||
|
||||
|
@ -196,7 +196,6 @@ static void gfx_widget_volume_frame(void* data, void *user_data)
|
||||
icon_size, icon_size,
|
||||
volume_icon,
|
||||
0, 0,
|
||||
video_width, video_height,
|
||||
0, 1, pure_white
|
||||
);
|
||||
gfx_display_blend_end(userdata);
|
||||
|
@ -1307,6 +1307,7 @@ MENU
|
||||
#ifdef HAVE_CHEEVOS
|
||||
#include "../gfx/widgets/gfx_widget_achievement_popup.c"
|
||||
#endif
|
||||
#include "../gfx/widgets/gfx_widget_load_content_animation.c"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
@ -4300,6 +4300,10 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_MENU_WIDGETS_ENABLE,
|
||||
"menu_widgets_enable"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_MENU_SHOW_LOAD_CONTENT_ANIMATION,
|
||||
"menu_show_load_content_animation"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VIDEO_SHADERS_ENABLE,
|
||||
"video_shader_enable"
|
||||
|
@ -3380,6 +3380,14 @@ MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MEMORY_SHOW,
|
||||
"Displays the used and total amount of memory on the system."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CONTENT_ANIMATION,
|
||||
"\"Load Content\" Startup Notification"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_MENU_SHOW_LOAD_CONTENT_ANIMATION,
|
||||
"Show a brief launch feedback animation when loading content."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_FONT_PATH,
|
||||
"Notification Font"
|
||||
|
@ -375,6 +375,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_quit_retroarch, MENU_
|
||||
#endif
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_restart_retroarch, MENU_ENUM_SUBLABEL_RESTART_RETROARCH)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_widgets, MENU_ENUM_SUBLABEL_MENU_WIDGETS_ENABLE)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_show_load_content_animation, MENU_ENUM_SUBLABEL_MENU_SHOW_LOAD_CONTENT_ANIMATION)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_window_width, MENU_ENUM_SUBLABEL_VIDEO_WINDOW_WIDTH)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_window_height, MENU_ENUM_SUBLABEL_VIDEO_WINDOW_HEIGHT)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_fullscreen_x, MENU_ENUM_SUBLABEL_VIDEO_FULLSCREEN_X)
|
||||
@ -2971,6 +2972,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_MENU_WIDGETS_ENABLE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_widgets);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_MENU_SHOW_LOAD_CONTENT_ANIMATION:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_show_load_content_animation);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_RESTART_RETROARCH:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_restart_retroarch);
|
||||
break;
|
||||
|
@ -9811,6 +9811,5 @@ menu_ctx_driver_t menu_ctx_mui = {
|
||||
NULL, /* update_savestate_thumbnail_image */
|
||||
materialui_pointer_down,
|
||||
materialui_pointer_up,
|
||||
NULL, /* get_load_content_animation_data */
|
||||
materialui_menu_entry_action
|
||||
};
|
||||
|
@ -2954,28 +2954,6 @@ static int ozone_list_bind_init(menu_file_list_cbs_t *cbs,
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GFX_WIDGETS
|
||||
static bool ozone_get_load_content_animation_data(void *userdata, uintptr_t *icon, char **playlist_name)
|
||||
{
|
||||
ozone_handle_t *ozone = (ozone_handle_t*) userdata;
|
||||
|
||||
if (ozone->categories_selection_ptr > ozone->system_tab_end)
|
||||
{
|
||||
ozone_node_t *node = (ozone_node_t*) file_list_get_userdata_at_offset(ozone->horizontal_list, ozone->categories_selection_ptr - ozone->system_tab_end-1);
|
||||
|
||||
*icon = node->icon;
|
||||
*playlist_name = node->console_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
*icon = ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_QUICKMENU];
|
||||
*playlist_name = "RetroArch";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool INLINE ozone_metadata_override_available(ozone_handle_t *ozone)
|
||||
{
|
||||
/* Ugly construct...
|
||||
@ -3891,10 +3869,5 @@ menu_ctx_driver_t menu_ctx_ozone = {
|
||||
NULL, /* update_savestate_thumbnail_image */
|
||||
NULL, /* pointer_down */
|
||||
ozone_pointer_up,
|
||||
#ifdef HAVE_GFX_WIDGETS
|
||||
ozone_get_load_content_animation_data,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
ozone_menu_entry_action
|
||||
};
|
||||
|
@ -5495,6 +5495,5 @@ menu_ctx_driver_t menu_ctx_rgui = {
|
||||
NULL, /* update_savestate_thumbnail_image */
|
||||
NULL, /* pointer_down */
|
||||
rgui_pointer_up,
|
||||
NULL, /* get_load_content_animation_data */
|
||||
rgui_menu_entry_action
|
||||
};
|
||||
|
@ -4515,6 +4515,5 @@ menu_ctx_driver_t menu_ctx_stripes = {
|
||||
stripes_update_savestate_thumbnail_image,
|
||||
NULL, /* pointer_down */
|
||||
stripes_pointer_up, /* pointer_up */
|
||||
NULL, /* get_load_content_animation_data */
|
||||
generic_menu_entry_action
|
||||
};
|
||||
|
@ -7003,28 +7003,6 @@ static int xmb_menu_entry_action(
|
||||
return generic_menu_entry_action(userdata, entry, i, new_action);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GFX_WIDGETS
|
||||
static bool xmb_get_load_content_animation_data(void *userdata, uintptr_t *icon, char **playlist_name)
|
||||
{
|
||||
xmb_handle_t *xmb = (xmb_handle_t*) userdata;
|
||||
|
||||
if (xmb->categories_selection_ptr > xmb->system_tab_end)
|
||||
{
|
||||
xmb_node_t *node = (xmb_node_t*) file_list_get_userdata_at_offset(xmb->horizontal_list, xmb->categories_selection_ptr - xmb->system_tab_end-1);
|
||||
|
||||
*icon = node->icon;
|
||||
*playlist_name = xmb->title_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
*icon = xmb->textures.list[XMB_TEXTURE_QUICKMENU];
|
||||
*playlist_name = "RetroArch";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
menu_ctx_driver_t menu_ctx_xmb = {
|
||||
NULL,
|
||||
xmb_messagebox,
|
||||
@ -7070,10 +7048,5 @@ menu_ctx_driver_t menu_ctx_xmb = {
|
||||
xmb_update_savestate_thumbnail_image,
|
||||
NULL, /* pointer_down */
|
||||
xmb_pointer_up,
|
||||
#ifdef HAVE_GFX_WIDGETS
|
||||
xmb_get_load_content_animation_data,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
xmb_menu_entry_action
|
||||
};
|
||||
|
@ -7455,6 +7455,7 @@ unsigned menu_displaylist_build_list(
|
||||
{MENU_ENUM_LABEL_FRAMECOUNT_SHOW, PARSE_ONLY_BOOL, false },
|
||||
{MENU_ENUM_LABEL_STATISTICS_SHOW, PARSE_ONLY_BOOL, false },
|
||||
{MENU_ENUM_LABEL_MEMORY_SHOW, PARSE_ONLY_BOOL, false },
|
||||
{MENU_ENUM_LABEL_MENU_SHOW_LOAD_CONTENT_ANIMATION, PARSE_ONLY_BOOL, false },
|
||||
{MENU_ENUM_LABEL_VIDEO_FONT_PATH, PARSE_ONLY_PATH, false },
|
||||
{MENU_ENUM_LABEL_VIDEO_FONT_SIZE, PARSE_ONLY_FLOAT, false },
|
||||
{MENU_ENUM_LABEL_VIDEO_MESSAGE_POS_X, PARSE_ONLY_FLOAT, false },
|
||||
@ -7508,6 +7509,12 @@ unsigned menu_displaylist_build_list(
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
case MENU_ENUM_LABEL_MENU_SHOW_LOAD_CONTENT_ANIMATION:
|
||||
#ifdef HAVE_GFX_WIDGETS
|
||||
if (menu_enable_widgets)
|
||||
build_list[i].checked = true;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
if (video_font_enable)
|
||||
build_list[i].checked = true;
|
||||
|
@ -295,7 +295,6 @@ typedef struct menu_ctx_driver
|
||||
enum menu_input_pointer_gesture gesture,
|
||||
menu_file_list_cbs_t *cbs,
|
||||
menu_entry_t *entry, unsigned action);
|
||||
bool (*get_load_content_animation_data)(void *userdata, uintptr_t *icon, char **playlist_name);
|
||||
/* This will be invoked whenever a menu entry action
|
||||
* (menu_entry_action()) is performed */
|
||||
int (*entry_action)(void *userdata, menu_entry_t *entry, size_t i, enum menu_action action);
|
||||
@ -421,9 +420,6 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data);
|
||||
|
||||
void menu_driver_frame(bool menu_is_alive, video_frame_info_t *video_info);
|
||||
|
||||
bool menu_driver_get_load_content_animation_data(
|
||||
uintptr_t *icon, char **playlist_name);
|
||||
|
||||
bool menu_driver_iterate(menu_ctx_iterate_t *iterate,
|
||||
retro_time_t current_time);
|
||||
|
||||
|
@ -13385,6 +13385,24 @@ static bool setting_append_list(
|
||||
general_write_handler,
|
||||
general_read_handler,
|
||||
SD_FLAG_NONE);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_bool_action_left_with_refresh;
|
||||
(*list)[list_info->index - 1].action_left = &setting_bool_action_left_with_refresh;
|
||||
(*list)[list_info->index - 1].action_right = &setting_bool_action_right_with_refresh;
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.menu_show_load_content_animation,
|
||||
MENU_ENUM_LABEL_MENU_SHOW_LOAD_CONTENT_ANIMATION,
|
||||
MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CONTENT_ANIMATION,
|
||||
DEFAULT_MENU_SHOW_LOAD_CONTENT_ANIMATION,
|
||||
MENU_ENUM_LABEL_VALUE_OFF,
|
||||
MENU_ENUM_LABEL_VALUE_ON,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler,
|
||||
SD_FLAG_NONE);
|
||||
#endif
|
||||
|
||||
if (string_is_equal(settings->arrays.menu_driver, "xmb") || string_is_equal(settings->arrays.menu_driver, "ozone"))
|
||||
|
@ -2558,6 +2558,8 @@ enum msg_hash_enums
|
||||
#endif
|
||||
|
||||
MENU_LABEL(MENU_WIDGETS_ENABLE),
|
||||
MENU_LABEL(MENU_SHOW_LOAD_CONTENT_ANIMATION),
|
||||
|
||||
MENU_LABEL(SELECT_FILE),
|
||||
MENU_LABEL(SELECT_FROM_PLAYLIST),
|
||||
|
||||
|
11
retroarch.c
11
retroarch.c
@ -4824,7 +4824,6 @@ static menu_ctx_driver_t menu_ctx_null = {
|
||||
NULL, /* update_savestate_thumbnail_image */
|
||||
NULL, /* pointer_down */
|
||||
NULL, /* pointer_up */
|
||||
NULL, /* get_load_content_animation_data */
|
||||
NULL /* entry_action */
|
||||
};
|
||||
|
||||
@ -6457,16 +6456,6 @@ void menu_driver_frame(bool menu_is_alive, video_frame_info_t *video_info)
|
||||
p_rarch->menu_driver_ctx->frame(p_rarch->menu_userdata, video_info);
|
||||
}
|
||||
|
||||
bool menu_driver_get_load_content_animation_data(
|
||||
uintptr_t *icon, char **playlist_name)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
return p_rarch->menu_driver_ctx
|
||||
&& p_rarch->menu_driver_ctx->get_load_content_animation_data
|
||||
&& p_rarch->menu_driver_ctx->get_load_content_animation_data(
|
||||
p_rarch->menu_userdata, icon, playlist_name);
|
||||
}
|
||||
|
||||
/* Time format strings with AM-PM designation require special
|
||||
* handling due to platform dependence */
|
||||
static void strftime_am_pm(char* ptr, size_t maxsize, const char* format,
|
||||
|
@ -551,7 +551,7 @@ static void content_load_init_wrap(
|
||||
* Returns: false (0) if retroarch_main_init failed,
|
||||
* otherwise true (1).
|
||||
**/
|
||||
static bool content_load(content_ctx_info_t *info,
|
||||
static bool content_load(content_ctx_info_t *info,
|
||||
content_state_t *p_content)
|
||||
{
|
||||
unsigned i = 0;
|
||||
@ -610,6 +610,26 @@ static bool content_load(content_ctx_info_t *info,
|
||||
content_clear_subsystem();
|
||||
}
|
||||
|
||||
#ifdef HAVE_GFX_WIDGETS
|
||||
/* If retroarch_main_init() returned true, we
|
||||
* can safely trigger a load content animation */
|
||||
if (gfx_widgets_ready())
|
||||
{
|
||||
/* Note: Have to read settings value here
|
||||
* (It will be invalid if we try to read
|
||||
* it earlier...) */
|
||||
#ifdef HAVE_CONFIGFILE
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool show_load_content_animation = settings && settings->bools.menu_show_load_content_animation;
|
||||
#else
|
||||
bool show_load_content_animation = false;
|
||||
#endif
|
||||
|
||||
if (show_load_content_animation)
|
||||
gfx_widget_start_load_content_animation();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
|
||||
menu_shader_manager_init();
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user