mirror of
https://github.com/libretro/RetroArch
synced 2025-03-05 19:13:45 +00:00
Merge pull request #10870 from Jamiras/gfx_widgets_achievements
gfx_widgets: move achievement popup widget into its own file
This commit is contained in:
commit
8098c5978f
@ -849,6 +849,9 @@ 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
|
||||
ifeq ($(HAVE_CHEEVOS), 1)
|
||||
OBJ += gfx/widgets/gfx_widget_achievement_popup.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_OVERLAY), 1)
|
||||
|
@ -32,10 +32,6 @@
|
||||
|
||||
#include "../tasks/task_content.h"
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
#include "../cheevos/badges.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#define SLOCK_LOCK(x) slock_lock(x)
|
||||
#define SLOCK_UNLOCK(x) slock_unlock(x)
|
||||
@ -112,10 +108,6 @@ static const char
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
#ifdef HAVE_CHEEVOS
|
||||
static void gfx_widgets_start_achievement_notification(
|
||||
dispgfx_widget_t *p_dispwidget);
|
||||
#endif
|
||||
#ifdef HAVE_MENU
|
||||
bool menu_driver_get_load_content_animation_data(
|
||||
uintptr_t *icon, char **playlist_name);
|
||||
@ -206,6 +198,9 @@ size_t gfx_widgets_get_msg_queue_size(void *data)
|
||||
const static gfx_widget_t* const widgets[] = {
|
||||
&gfx_widget_screenshot,
|
||||
&gfx_widget_volume,
|
||||
#ifdef HAVE_CHEEVOS
|
||||
&gfx_widget_achievement_popup,
|
||||
#endif
|
||||
&gfx_widget_generic_message,
|
||||
&gfx_widget_libretro_message
|
||||
};
|
||||
@ -1402,9 +1397,6 @@ static void INLINE gfx_widgets_font_unbind(gfx_widget_font_data_t *font_data)
|
||||
void gfx_widgets_frame(void *data)
|
||||
{
|
||||
size_t i;
|
||||
#ifdef HAVE_CHEEVOS
|
||||
int scissor_me_timbers = 0;
|
||||
#endif
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
video_frame_info_t *video_info = (video_frame_info_t*)data;
|
||||
bool framecount_show = video_info->framecount_show;
|
||||
@ -1506,143 +1498,6 @@ void gfx_widgets_frame(void *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
/* Achievement notification */
|
||||
if (p_dispwidget->cheevo_popup_queue_read_index >= 0 &&
|
||||
p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].title)
|
||||
{
|
||||
SLOCK_LOCK(p_dispwidget->cheevo_popup_queue_lock);
|
||||
|
||||
if (p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].title)
|
||||
{
|
||||
unsigned unfold_offet = ((1.0f - p_dispwidget->cheevo_unfold)
|
||||
* p_dispwidget->cheevo_width / 2);
|
||||
|
||||
gfx_display_set_alpha(gfx_widgets_backdrop_orig, DEFAULT_BACKDROP);
|
||||
gfx_display_set_alpha(gfx_widgets_pure_white, 1.0f);
|
||||
|
||||
/* Default icon */
|
||||
if (!p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].badge)
|
||||
{
|
||||
/* Backdrop */
|
||||
gfx_display_draw_quad(userdata,
|
||||
video_width, video_height,
|
||||
0, (int)p_dispwidget->cheevo_y,
|
||||
p_dispwidget->cheevo_height,
|
||||
p_dispwidget->cheevo_height,
|
||||
video_width, video_height,
|
||||
gfx_widgets_backdrop_orig);
|
||||
|
||||
/* Icon */
|
||||
if (p_dispwidget->gfx_widgets_icons_textures[
|
||||
MENU_WIDGETS_ICON_ACHIEVEMENT])
|
||||
{
|
||||
gfx_display_blend_begin(userdata);
|
||||
gfx_widgets_draw_icon(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
p_dispwidget->cheevo_height,
|
||||
p_dispwidget->cheevo_height,
|
||||
p_dispwidget->gfx_widgets_icons_textures[
|
||||
MENU_WIDGETS_ICON_ACHIEVEMENT],
|
||||
0,
|
||||
p_dispwidget->cheevo_y,
|
||||
video_width, video_height, 0, 1, gfx_widgets_pure_white);
|
||||
gfx_display_blend_end(userdata);
|
||||
}
|
||||
}
|
||||
/* Badge */
|
||||
else
|
||||
{
|
||||
gfx_widgets_draw_icon(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
p_dispwidget->cheevo_height,
|
||||
p_dispwidget->cheevo_height,
|
||||
p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].badge,
|
||||
0,
|
||||
p_dispwidget->cheevo_y,
|
||||
video_width,
|
||||
video_height,
|
||||
0,
|
||||
1,
|
||||
gfx_widgets_pure_white);
|
||||
}
|
||||
|
||||
/* I _think_ cheevo_unfold changes in another thread */
|
||||
scissor_me_timbers = (fabs(p_dispwidget->cheevo_unfold - 1.0f) > 0.01);
|
||||
if (scissor_me_timbers)
|
||||
gfx_display_scissor_begin(userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
p_dispwidget->cheevo_height,
|
||||
0,
|
||||
(unsigned)((float)(p_dispwidget->cheevo_width)
|
||||
* p_dispwidget->cheevo_unfold),
|
||||
p_dispwidget->cheevo_height);
|
||||
|
||||
/* Backdrop */
|
||||
gfx_display_draw_quad(
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
p_dispwidget->cheevo_height,
|
||||
(int)p_dispwidget->cheevo_y,
|
||||
p_dispwidget->cheevo_width,
|
||||
p_dispwidget->cheevo_height,
|
||||
video_width,
|
||||
video_height,
|
||||
gfx_widgets_backdrop_orig);
|
||||
|
||||
/* Title */
|
||||
gfx_widgets_draw_text(&p_dispwidget->gfx_widget_fonts.regular,
|
||||
msg_hash_to_str(MSG_ACHIEVEMENT_UNLOCKED),
|
||||
p_dispwidget->cheevo_height
|
||||
+ p_dispwidget->simple_widget_padding - unfold_offet,
|
||||
p_dispwidget->cheevo_y
|
||||
+ p_dispwidget->gfx_widget_fonts.regular.line_height
|
||||
+ p_dispwidget->gfx_widget_fonts.regular.line_ascender,
|
||||
video_width, video_height,
|
||||
TEXT_COLOR_FAINT,
|
||||
TEXT_ALIGN_LEFT,
|
||||
true);
|
||||
|
||||
/* Cheevo name */
|
||||
|
||||
/* TODO: is a ticker necessary ? */
|
||||
gfx_widgets_draw_text(&p_dispwidget->gfx_widget_fonts.regular,
|
||||
p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].title,
|
||||
p_dispwidget->cheevo_height
|
||||
+ p_dispwidget->simple_widget_padding - unfold_offet,
|
||||
p_dispwidget->cheevo_y
|
||||
+ p_dispwidget->cheevo_height
|
||||
- p_dispwidget->gfx_widget_fonts.regular.line_height
|
||||
- p_dispwidget->gfx_widget_fonts.regular.line_descender,
|
||||
video_width, video_height,
|
||||
TEXT_COLOR_INFO,
|
||||
TEXT_ALIGN_LEFT,
|
||||
true);
|
||||
|
||||
if (scissor_me_timbers)
|
||||
{
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.regular);
|
||||
gfx_display_scissor_end(userdata,
|
||||
video_width, video_height);
|
||||
}
|
||||
}
|
||||
|
||||
SLOCK_UNLOCK(p_dispwidget->cheevo_popup_queue_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* FPS Counter */
|
||||
if ( fps_show
|
||||
|| framecount_show
|
||||
@ -1811,9 +1666,6 @@ bool gfx_widgets_init(uintptr_t widgets_active_ptr,
|
||||
{
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)
|
||||
dispwidget_get_ptr();
|
||||
#ifdef HAVE_CHEEVOS
|
||||
p_dispwidget->cheevo_popup_queue_read_index = -1;
|
||||
#endif
|
||||
p_dispwidget->divider_width_1px = 1;
|
||||
p_dispwidget->gfx_widgets_generic_tag = (uintptr_t)widgets_active_ptr;
|
||||
|
||||
@ -2189,50 +2041,6 @@ static void gfx_widgets_context_destroy(dispgfx_widget_t *p_dispwidget)
|
||||
gfx_widgets_font_free(&p_dispwidget->gfx_widget_fonts.msg_queue);
|
||||
}
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
static void gfx_widgets_achievement_free_current(dispgfx_widget_t *p_dispwidget)
|
||||
{
|
||||
if (p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].title)
|
||||
{
|
||||
free(p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].title);
|
||||
p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].title = NULL;
|
||||
}
|
||||
|
||||
if (p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].badge)
|
||||
{
|
||||
video_driver_texture_unload(&p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].badge);
|
||||
p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].badge = 0;
|
||||
}
|
||||
|
||||
p_dispwidget->cheevo_popup_queue_read_index = (
|
||||
p_dispwidget->cheevo_popup_queue_read_index + 1) % CHEEVO_QUEUE_SIZE;
|
||||
}
|
||||
|
||||
static void gfx_widgets_achievement_next(void* userdata)
|
||||
{
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
SLOCK_LOCK(p_dispwidget->cheevo_popup_queue_lock);
|
||||
|
||||
if (p_dispwidget->cheevo_popup_queue_read_index >= 0)
|
||||
{
|
||||
gfx_widgets_achievement_free_current(p_dispwidget);
|
||||
|
||||
/* start the next popup (if present) */
|
||||
if (p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].title)
|
||||
gfx_widgets_start_achievement_notification(p_dispwidget);
|
||||
}
|
||||
|
||||
SLOCK_UNLOCK(p_dispwidget->cheevo_popup_queue_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void gfx_widgets_free(dispgfx_widget_t *p_dispwidget)
|
||||
{
|
||||
size_t i;
|
||||
@ -2310,24 +2118,6 @@ static void gfx_widgets_free(dispgfx_widget_t *p_dispwidget)
|
||||
|
||||
p_dispwidget->msg_queue_tasks_count = 0;
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
/* Achievement notification */
|
||||
if (p_dispwidget->cheevo_popup_queue_read_index >= 0)
|
||||
{
|
||||
SLOCK_LOCK(p_dispwidget->cheevo_popup_queue_lock);
|
||||
|
||||
while (p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].title)
|
||||
gfx_widgets_achievement_free_current(p_dispwidget);
|
||||
|
||||
SLOCK_UNLOCK(p_dispwidget->cheevo_popup_queue_lock);
|
||||
}
|
||||
#ifdef HAVE_THREADS
|
||||
slock_free(p_dispwidget->cheevo_popup_queue_lock);
|
||||
p_dispwidget->cheevo_popup_queue_lock = NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Font */
|
||||
video_coord_array_free(
|
||||
&p_dispwidget->gfx_widget_fonts.regular.raster_block.carr);
|
||||
@ -2511,145 +2301,3 @@ void gfx_widgets_start_load_content_animation(
|
||||
p_dispwidget->load_content_animation_running = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
static void gfx_widgets_achievement_dismiss(void *userdata)
|
||||
{
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
|
||||
/* Slide up animation */
|
||||
entry.cb = gfx_widgets_achievement_next;
|
||||
entry.duration = MSG_QUEUE_ANIMATION_DURATION;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &p_dispwidget->cheevo_y;
|
||||
entry.tag = p_dispwidget->gfx_widgets_generic_tag;
|
||||
entry.target_value = (float)(-(int)(p_dispwidget->cheevo_height));
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
static void gfx_widgets_achievement_fold(void *userdata)
|
||||
{
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
|
||||
/* Fold */
|
||||
entry.cb = gfx_widgets_achievement_dismiss;
|
||||
entry.duration = MSG_QUEUE_ANIMATION_DURATION;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &p_dispwidget->cheevo_unfold;
|
||||
entry.tag = p_dispwidget->gfx_widgets_generic_tag;
|
||||
entry.target_value = 0.0f;
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
static void gfx_widgets_achievement_unfold(void *userdata)
|
||||
{
|
||||
gfx_timer_ctx_entry_t timer;
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
|
||||
/* Unfold */
|
||||
entry.cb = NULL;
|
||||
entry.duration = MSG_QUEUE_ANIMATION_DURATION;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &p_dispwidget->cheevo_unfold;
|
||||
entry.tag = p_dispwidget->gfx_widgets_generic_tag;
|
||||
entry.target_value = 1.0f;
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
|
||||
/* Wait before dismissing */
|
||||
timer.cb = gfx_widgets_achievement_fold;
|
||||
timer.duration = MSG_QUEUE_ANIMATION_DURATION + CHEEVO_NOTIFICATION_DURATION;
|
||||
timer.userdata = NULL;
|
||||
|
||||
gfx_timer_start(&p_dispwidget->cheevo_timer, &timer);
|
||||
}
|
||||
|
||||
static void gfx_widgets_start_achievement_notification(
|
||||
dispgfx_widget_t *p_dispwidget)
|
||||
{
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
p_dispwidget->cheevo_height =
|
||||
p_dispwidget->gfx_widget_fonts.regular.line_height * 4;
|
||||
p_dispwidget->cheevo_width = MAX(
|
||||
font_driver_get_message_width(
|
||||
p_dispwidget->gfx_widget_fonts.regular.font,
|
||||
msg_hash_to_str(MSG_ACHIEVEMENT_UNLOCKED), 0, 1),
|
||||
font_driver_get_message_width(
|
||||
p_dispwidget->gfx_widget_fonts.regular.font,
|
||||
p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_read_index].title, 0, 1)
|
||||
);
|
||||
p_dispwidget->cheevo_width += p_dispwidget->simple_widget_padding * 2;
|
||||
p_dispwidget->cheevo_y = (float)(-(int)p_dispwidget->cheevo_height);
|
||||
p_dispwidget->cheevo_unfold = 0.0f;
|
||||
|
||||
/* Slide down animation */
|
||||
entry.cb = gfx_widgets_achievement_unfold;
|
||||
entry.duration = MSG_QUEUE_ANIMATION_DURATION;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &p_dispwidget->cheevo_y;
|
||||
entry.tag = p_dispwidget->gfx_widgets_generic_tag;
|
||||
entry.target_value = 0.0f;
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
void gfx_widgets_push_achievement(const char *title, const char *badge)
|
||||
{
|
||||
dispgfx_widget_t *p_dispwidget = (dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
int start_notification = 1;
|
||||
|
||||
/* important - this must be done outside the lock because it has the potential to need to
|
||||
* lock the video thread, which may be waiting for the popup queue lock to render popups */
|
||||
uintptr_t badge_id = cheevos_get_badge_texture(badge, 0);
|
||||
|
||||
if (p_dispwidget->cheevo_popup_queue_read_index < 0)
|
||||
{
|
||||
/* queue uninitialized */
|
||||
memset(&p_dispwidget->cheevo_popup_queue, 0,
|
||||
sizeof(p_dispwidget->cheevo_popup_queue));
|
||||
p_dispwidget->cheevo_popup_queue_read_index = 0;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
p_dispwidget->cheevo_popup_queue_lock = slock_new();
|
||||
#endif
|
||||
}
|
||||
|
||||
SLOCK_LOCK(p_dispwidget->cheevo_popup_queue_lock);
|
||||
|
||||
if (p_dispwidget->cheevo_popup_queue_write_index
|
||||
== p_dispwidget->cheevo_popup_queue_read_index)
|
||||
{
|
||||
if (p_dispwidget->cheevo_popup_queue[
|
||||
p_dispwidget->cheevo_popup_queue_write_index].title)
|
||||
{
|
||||
/* queue full */
|
||||
SLOCK_UNLOCK(p_dispwidget->cheevo_popup_queue_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* queue empty */
|
||||
}
|
||||
else
|
||||
start_notification = 0; /* notification already being displayed */
|
||||
|
||||
p_dispwidget->cheevo_popup_queue[p_dispwidget->cheevo_popup_queue_write_index].badge = badge_id;
|
||||
p_dispwidget->cheevo_popup_queue[p_dispwidget->cheevo_popup_queue_write_index].title = strdup(title);
|
||||
|
||||
p_dispwidget->cheevo_popup_queue_write_index = (p_dispwidget->cheevo_popup_queue_write_index + 1) % CHEEVO_QUEUE_SIZE;
|
||||
|
||||
if (start_notification)
|
||||
gfx_widgets_start_achievement_notification(p_dispwidget);
|
||||
|
||||
SLOCK_UNLOCK(p_dispwidget->cheevo_popup_queue_lock);
|
||||
}
|
||||
#endif
|
||||
|
@ -37,7 +37,6 @@
|
||||
#define MSG_QUEUE_ONSCREEN_MAX 4
|
||||
|
||||
#define MSG_QUEUE_ANIMATION_DURATION 330
|
||||
#define CHEEVO_NOTIFICATION_DURATION 4000
|
||||
#define TASK_FINISHED_DURATION 3000
|
||||
#define HOURGLASS_INTERVAL 5000
|
||||
#define HOURGLASS_DURATION 1000
|
||||
@ -52,10 +51,6 @@
|
||||
#endif
|
||||
#define TEXT_COLOR_FAINT 0x878787FF
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
#define CHEEVO_QUEUE_SIZE 8
|
||||
#endif
|
||||
|
||||
enum gfx_widgets_icon
|
||||
{
|
||||
MENU_WIDGETS_ICON_PAUSED = 0,
|
||||
@ -155,19 +150,9 @@ typedef struct dispgfx_widget
|
||||
bool load_content_animation_running;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
int cheevo_popup_queue_read_index;
|
||||
#endif
|
||||
#ifdef HAVE_TRANSLATE
|
||||
int ai_service_overlay_state;
|
||||
#endif
|
||||
#ifdef HAVE_CHEEVOS
|
||||
int cheevo_popup_queue_write_index;
|
||||
#endif
|
||||
#ifdef HAVE_CHEEVOS
|
||||
float cheevo_unfold;
|
||||
float cheevo_y;
|
||||
#endif
|
||||
#ifdef HAVE_MENU
|
||||
float load_content_animation_icon_color[16];
|
||||
float load_content_animation_icon_size;
|
||||
@ -189,10 +174,7 @@ typedef struct dispgfx_widget
|
||||
unsigned msg_queue_kill;
|
||||
/* Count of messages bound to a task in current_msgs */
|
||||
unsigned msg_queue_tasks_count;
|
||||
#ifdef HAVE_CHEEVOS
|
||||
unsigned cheevo_width;
|
||||
unsigned cheevo_height;
|
||||
#endif
|
||||
|
||||
unsigned simple_widget_padding;
|
||||
unsigned simple_widget_height;
|
||||
|
||||
@ -241,14 +223,6 @@ typedef struct dispgfx_widget
|
||||
#endif
|
||||
uintptr_t gfx_widgets_generic_tag;
|
||||
gfx_widget_fonts_t gfx_widget_fonts;
|
||||
#ifdef HAVE_CHEEVOS
|
||||
/* Achievement notification */
|
||||
cheevo_popup cheevo_popup_queue[CHEEVO_QUEUE_SIZE];
|
||||
gfx_timer_t cheevo_timer;
|
||||
#ifdef HAVE_THREADS
|
||||
slock_t* cheevo_popup_queue_lock;
|
||||
#endif
|
||||
#endif
|
||||
fifo_buffer_t *msg_queue;
|
||||
menu_widget_msg_t* current_msgs[MSG_QUEUE_ONSCREEN_MAX];
|
||||
size_t current_msgs_size;
|
||||
@ -296,6 +270,8 @@ struct gfx_widget
|
||||
|
||||
/* called every frame
|
||||
* (on the video thread if threaded video is on)
|
||||
* -- data is a video_frame_info_t
|
||||
* -- userdata is a dispgfx_widget_t
|
||||
* -> draw the widget here */
|
||||
void (*frame)(void* data, void *userdata);
|
||||
};
|
||||
@ -401,7 +377,9 @@ void gfx_widgets_start_load_content_animation(
|
||||
|
||||
void gfx_widgets_cleanup_load_content_animation(void);
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
void gfx_widgets_push_achievement(const char *title, const char *badge);
|
||||
#endif
|
||||
|
||||
/* Warning: not thread safe! */
|
||||
void gfx_widget_set_message(char *message);
|
||||
@ -427,5 +405,8 @@ 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;
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
extern const gfx_widget_t gfx_widget_achievement_popup;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
414
gfx/widgets/gfx_widget_achievement_popup.c
Normal file
414
gfx/widgets/gfx_widget_achievement_popup.c
Normal file
@ -0,0 +1,414 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2014-2017 - Jean-André Santoni
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
* Copyright (C) 2018-2020 - natinusala
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* 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 "../gfx_display.h"
|
||||
#include "../gfx_widgets.h"
|
||||
|
||||
#include "../cheevos/badges.h"
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#define SLOCK_LOCK(x) slock_lock(x)
|
||||
#define SLOCK_UNLOCK(x) slock_unlock(x)
|
||||
#else
|
||||
#define SLOCK_LOCK(x)
|
||||
#define SLOCK_UNLOCK(x)
|
||||
#endif
|
||||
|
||||
#define CHEEVO_NOTIFICATION_DURATION 4000
|
||||
|
||||
#define CHEEVO_QUEUE_SIZE 8
|
||||
|
||||
struct gfx_widget_achievement_popup_state
|
||||
{
|
||||
gfx_timer_t timer;
|
||||
float unfold;
|
||||
float y;
|
||||
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
|
||||
cheevo_popup queue[CHEEVO_QUEUE_SIZE];
|
||||
int queue_read_index;
|
||||
int queue_write_index;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
slock_t* queue_lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct gfx_widget_achievement_popup_state gfx_widget_achievement_popup_state_t;
|
||||
|
||||
static gfx_widget_achievement_popup_state_t p_w_achievement_popup_st;
|
||||
|
||||
static gfx_widget_achievement_popup_state_t* gfx_widget_achievement_popup_get_ptr(void)
|
||||
{
|
||||
return &p_w_achievement_popup_st;
|
||||
}
|
||||
|
||||
/* Forward declarations */
|
||||
static void gfx_widget_achievement_popup_start(
|
||||
gfx_widget_achievement_popup_state_t* state);
|
||||
static void gfx_widget_achievement_popup_free_current(
|
||||
gfx_widget_achievement_popup_state_t* state);
|
||||
|
||||
static bool gfx_widget_achievement_popup_init(bool video_is_threaded, bool fullscreen)
|
||||
{
|
||||
gfx_widget_achievement_popup_state_t* state = gfx_widget_achievement_popup_get_ptr();
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
state->queue_read_index = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void gfx_widget_achievement_popup_free(void)
|
||||
{
|
||||
gfx_widget_achievement_popup_state_t* state = gfx_widget_achievement_popup_get_ptr();
|
||||
|
||||
if (state->queue_read_index >= 0)
|
||||
{
|
||||
SLOCK_LOCK(state->queue_lock);
|
||||
|
||||
while (state->queue[state->queue_read_index].title)
|
||||
gfx_widget_achievement_popup_free_current(state);
|
||||
|
||||
SLOCK_UNLOCK(state->queue_lock);
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
slock_free(state->queue_lock);
|
||||
state->queue_lock = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gfx_widget_achievement_popup_frame(void* data, void* userdata)
|
||||
{
|
||||
gfx_widget_achievement_popup_state_t* state = gfx_widget_achievement_popup_get_ptr();
|
||||
|
||||
/* if there's nothing in the queue, just bail */
|
||||
if (state->queue_read_index < 0 || !state->queue[state->queue_read_index].title)
|
||||
return;
|
||||
|
||||
SLOCK_LOCK(state->queue_lock);
|
||||
|
||||
if (state->queue[state->queue_read_index].title)
|
||||
{
|
||||
const video_frame_info_t* video_info = (const video_frame_info_t*)data;
|
||||
const unsigned video_width = video_info->width;
|
||||
const unsigned video_height = video_info->height;
|
||||
|
||||
dispgfx_widget_t* p_dispwidget = (dispgfx_widget_t*)userdata;
|
||||
const unsigned unfold_offet = ((1.0f - state->unfold) * state->width / 2);
|
||||
|
||||
int scissor_me_timbers = 0;
|
||||
|
||||
gfx_display_set_alpha(gfx_widgets_get_backdrop_orig(), DEFAULT_BACKDROP);
|
||||
gfx_display_set_alpha(gfx_widgets_get_pure_white(), 1.0f);
|
||||
|
||||
/* Default icon */
|
||||
if (!state->queue[state->queue_read_index].badge)
|
||||
{
|
||||
/* Backdrop */
|
||||
gfx_display_draw_quad(video_info->userdata,
|
||||
video_width, video_height,
|
||||
0, (int)state->y,
|
||||
state->height,
|
||||
state->height,
|
||||
video_width, video_height,
|
||||
gfx_widgets_get_backdrop_orig());
|
||||
|
||||
/* Icon */
|
||||
if (p_dispwidget->gfx_widgets_icons_textures[MENU_WIDGETS_ICON_ACHIEVEMENT])
|
||||
{
|
||||
gfx_display_blend_begin(userdata);
|
||||
gfx_widgets_draw_icon(
|
||||
video_info->userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->height,
|
||||
state->height,
|
||||
p_dispwidget->gfx_widgets_icons_textures[MENU_WIDGETS_ICON_ACHIEVEMENT],
|
||||
0,
|
||||
state->y,
|
||||
video_width, video_height, 0, 1, gfx_widgets_get_pure_white());
|
||||
gfx_display_blend_end(userdata);
|
||||
}
|
||||
}
|
||||
/* Badge */
|
||||
else
|
||||
{
|
||||
gfx_widgets_draw_icon(
|
||||
video_info->userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->height,
|
||||
state->height,
|
||||
state->queue[state->queue_read_index].badge,
|
||||
0,
|
||||
state->y,
|
||||
video_width,
|
||||
video_height,
|
||||
0,
|
||||
1,
|
||||
gfx_widgets_get_pure_white());
|
||||
}
|
||||
|
||||
/* I _think_ state->unfold changes in another thread */
|
||||
scissor_me_timbers = (fabs(state->unfold - 1.0f) > 0.01);
|
||||
if (scissor_me_timbers)
|
||||
gfx_display_scissor_begin(video_info->userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->height,
|
||||
0,
|
||||
(unsigned)((float)(state->width) * state->unfold),
|
||||
state->height);
|
||||
|
||||
/* Backdrop */
|
||||
gfx_display_draw_quad(
|
||||
video_info->userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
state->height,
|
||||
(int)state->y,
|
||||
state->width,
|
||||
state->height,
|
||||
video_width,
|
||||
video_height,
|
||||
gfx_widgets_get_backdrop_orig());
|
||||
|
||||
/* Title */
|
||||
gfx_widgets_draw_text(&p_dispwidget->gfx_widget_fonts.regular,
|
||||
msg_hash_to_str(MSG_ACHIEVEMENT_UNLOCKED),
|
||||
state->height + p_dispwidget->simple_widget_padding - unfold_offet,
|
||||
state->y + p_dispwidget->gfx_widget_fonts.regular.line_height
|
||||
+ p_dispwidget->gfx_widget_fonts.regular.line_ascender,
|
||||
video_width, video_height,
|
||||
TEXT_COLOR_FAINT,
|
||||
TEXT_ALIGN_LEFT,
|
||||
true);
|
||||
|
||||
/* Cheevo name */
|
||||
|
||||
/* TODO: is a ticker necessary ? */
|
||||
gfx_widgets_draw_text(&p_dispwidget->gfx_widget_fonts.regular,
|
||||
state->queue[state->queue_read_index].title,
|
||||
state->height + p_dispwidget->simple_widget_padding - unfold_offet,
|
||||
state->y + state->height
|
||||
- p_dispwidget->gfx_widget_fonts.regular.line_height
|
||||
- p_dispwidget->gfx_widget_fonts.regular.line_descender,
|
||||
video_width, video_height,
|
||||
TEXT_COLOR_INFO,
|
||||
TEXT_ALIGN_LEFT,
|
||||
true);
|
||||
|
||||
if (scissor_me_timbers)
|
||||
{
|
||||
gfx_widgets_flush_text(video_width, video_height,
|
||||
&p_dispwidget->gfx_widget_fonts.regular);
|
||||
gfx_display_scissor_end(userdata,
|
||||
video_width, video_height);
|
||||
}
|
||||
}
|
||||
|
||||
SLOCK_UNLOCK(state->queue_lock);
|
||||
}
|
||||
|
||||
static void gfx_widget_achievement_popup_free_current(gfx_widget_achievement_popup_state_t* state)
|
||||
{
|
||||
if (state->queue[state->queue_read_index].title)
|
||||
{
|
||||
free(state->queue[state->queue_read_index].title);
|
||||
state->queue[state->queue_read_index].title = NULL;
|
||||
}
|
||||
|
||||
if (state->queue[state->queue_read_index].badge)
|
||||
{
|
||||
video_driver_texture_unload(&state->queue[state->queue_read_index].badge);
|
||||
state->queue[state->queue_read_index].badge = 0;
|
||||
}
|
||||
|
||||
state->queue_read_index = (state->queue_read_index + 1) % ARRAY_SIZE(state->queue);
|
||||
}
|
||||
|
||||
static void gfx_widget_achievement_popup_next(void* userdata)
|
||||
{
|
||||
gfx_widget_achievement_popup_state_t* state = gfx_widget_achievement_popup_get_ptr();
|
||||
|
||||
SLOCK_LOCK(state->queue_lock);
|
||||
|
||||
if (state->queue_read_index >= 0)
|
||||
{
|
||||
gfx_widget_achievement_popup_free_current(state);
|
||||
|
||||
/* start the next popup (if present) */
|
||||
if (state->queue[state->queue_read_index].title)
|
||||
gfx_widget_achievement_popup_start(state);
|
||||
}
|
||||
|
||||
SLOCK_UNLOCK(state->queue_lock);
|
||||
}
|
||||
|
||||
static void gfx_widget_achievement_popup_dismiss(void *userdata)
|
||||
{
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
const dispgfx_widget_t *p_dispwidget = (const dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
gfx_widget_achievement_popup_state_t* state = gfx_widget_achievement_popup_get_ptr();
|
||||
|
||||
/* Slide up animation */
|
||||
entry.cb = gfx_widget_achievement_popup_next;
|
||||
entry.duration = MSG_QUEUE_ANIMATION_DURATION;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &state->y;
|
||||
entry.tag = p_dispwidget->gfx_widgets_generic_tag;
|
||||
entry.target_value = (float)(-(int)(state->height));
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
static void gfx_widget_achievement_popup_fold(void *userdata)
|
||||
{
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
const dispgfx_widget_t *p_dispwidget = (const dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
gfx_widget_achievement_popup_state_t* state = gfx_widget_achievement_popup_get_ptr();
|
||||
|
||||
/* Fold */
|
||||
entry.cb = gfx_widget_achievement_popup_dismiss;
|
||||
entry.duration = MSG_QUEUE_ANIMATION_DURATION;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &state->unfold;
|
||||
entry.tag = p_dispwidget->gfx_widgets_generic_tag;
|
||||
entry.target_value = 0.0f;
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
static void gfx_widget_achievement_popup_unfold(void *userdata)
|
||||
{
|
||||
gfx_timer_ctx_entry_t timer;
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
const dispgfx_widget_t *p_dispwidget = (const dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
gfx_widget_achievement_popup_state_t* state = gfx_widget_achievement_popup_get_ptr();
|
||||
|
||||
/* Unfold */
|
||||
entry.cb = NULL;
|
||||
entry.duration = MSG_QUEUE_ANIMATION_DURATION;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &state->unfold;
|
||||
entry.tag = p_dispwidget->gfx_widgets_generic_tag;
|
||||
entry.target_value = 1.0f;
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
|
||||
/* Wait before dismissing */
|
||||
timer.cb = gfx_widget_achievement_popup_fold;
|
||||
timer.duration = MSG_QUEUE_ANIMATION_DURATION + CHEEVO_NOTIFICATION_DURATION;
|
||||
timer.userdata = NULL;
|
||||
|
||||
gfx_timer_start(&state->timer, &timer);
|
||||
}
|
||||
|
||||
static void gfx_widget_achievement_popup_start(
|
||||
gfx_widget_achievement_popup_state_t* state)
|
||||
{
|
||||
const dispgfx_widget_t* p_dispwidget = (const dispgfx_widget_t*)dispwidget_get_ptr();
|
||||
gfx_animation_ctx_entry_t entry;
|
||||
|
||||
state->height = p_dispwidget->gfx_widget_fonts.regular.line_height * 4;
|
||||
state->width = MAX(
|
||||
font_driver_get_message_width(
|
||||
p_dispwidget->gfx_widget_fonts.regular.font,
|
||||
msg_hash_to_str(MSG_ACHIEVEMENT_UNLOCKED), 0, 1),
|
||||
font_driver_get_message_width(
|
||||
p_dispwidget->gfx_widget_fonts.regular.font,
|
||||
state->queue[state->queue_read_index].title, 0, 1)
|
||||
);
|
||||
state->width += p_dispwidget->simple_widget_padding * 2;
|
||||
state->y = (float)(-(int)state->height);
|
||||
state->unfold = 0.0f;
|
||||
|
||||
/* Slide down animation */
|
||||
entry.cb = gfx_widget_achievement_popup_unfold;
|
||||
entry.duration = MSG_QUEUE_ANIMATION_DURATION;
|
||||
entry.easing_enum = EASING_OUT_QUAD;
|
||||
entry.subject = &state->y;
|
||||
entry.tag = p_dispwidget->gfx_widgets_generic_tag;
|
||||
entry.target_value = 0.0f;
|
||||
entry.userdata = NULL;
|
||||
|
||||
gfx_animation_push(&entry);
|
||||
}
|
||||
|
||||
void gfx_widgets_push_achievement(const char *title, const char *badge)
|
||||
{
|
||||
gfx_widget_achievement_popup_state_t* state = gfx_widget_achievement_popup_get_ptr();
|
||||
int start_notification = 1;
|
||||
|
||||
/* important - this must be done outside the lock because it has the potential to need to
|
||||
* lock the video thread, which may be waiting for the popup queue lock to render popups */
|
||||
uintptr_t badge_id = cheevos_get_badge_texture(badge, 0);
|
||||
|
||||
if (state->queue_read_index < 0)
|
||||
{
|
||||
/* queue uninitialized */
|
||||
memset(&state->queue, 0, sizeof(state->queue));
|
||||
state->queue_read_index = 0;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
state->queue_lock = slock_new();
|
||||
#endif
|
||||
}
|
||||
|
||||
SLOCK_LOCK(state->queue_lock);
|
||||
|
||||
if (state->queue_write_index == state->queue_read_index)
|
||||
{
|
||||
if (state->queue[state->queue_write_index].title)
|
||||
{
|
||||
/* queue full */
|
||||
SLOCK_UNLOCK(state->queue_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* queue empty */
|
||||
}
|
||||
else
|
||||
start_notification = 0; /* notification already being displayed */
|
||||
|
||||
state->queue[state->queue_write_index].badge = badge_id;
|
||||
state->queue[state->queue_write_index].title = strdup(title);
|
||||
|
||||
state->queue_write_index = (state->queue_write_index + 1) % ARRAY_SIZE(state->queue);
|
||||
|
||||
if (start_notification)
|
||||
gfx_widget_achievement_popup_start(state);
|
||||
|
||||
SLOCK_UNLOCK(state->queue_lock);
|
||||
}
|
||||
|
||||
const gfx_widget_t gfx_widget_achievement_popup = {
|
||||
&gfx_widget_achievement_popup_init,
|
||||
&gfx_widget_achievement_popup_free,
|
||||
NULL, /* context_reset*/
|
||||
NULL, /* context_destroy */
|
||||
NULL, /* layout */
|
||||
NULL, /* iterate */
|
||||
&gfx_widget_achievement_popup_frame
|
||||
};
|
@ -1276,6 +1276,9 @@ MENU
|
||||
#include "../gfx/widgets/gfx_widget_volume.c"
|
||||
#include "../gfx/widgets/gfx_widget_generic_message.c"
|
||||
#include "../gfx/widgets/gfx_widget_libretro_message.c"
|
||||
#ifdef HAVE_CHEEVOS
|
||||
#include "../gfx/widgets/gfx_widget_achievement_popup.c"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
Loading…
x
Reference in New Issue
Block a user