From d24cdbfb15c14dfb3430bf19ba79530aea997acc Mon Sep 17 00:00:00 2001 From: retroNUC <71151161+retroNUC@users.noreply.github.com> Date: Fri, 30 Dec 2022 15:55:38 +0000 Subject: [PATCH] Allow repositioning of RetroAchievement notifications (#14777) * Allow repositioning of achievement notifications * PS4/ORBIS build fix Would have thought cheevos-related notification code was wrapped in HAVE_CHEEVOS, but guess not. --- config.def.h | 4 + configuration.c | 8 + configuration.h | 6 + gfx/gfx_widgets.h | 12 + gfx/widgets/gfx_widget_achievement_popup.c | 471 +++++++++++++-------- intl/msg_hash_lbl.h | 16 + intl/msg_hash_us.h | 67 +++ menu/cbs/menu_cbs_deferred_push.c | 5 + menu/cbs/menu_cbs_ok.c | 5 + menu/cbs/menu_cbs_sublabel.c | 20 + menu/cbs/menu_cbs_title.c | 2 + menu/drivers/materialui.c | 1 + menu/drivers/ozone.c | 1 + menu/drivers/xmb.c | 1 + menu/menu_cbs.h | 1 + menu/menu_displaylist.c | 50 ++- menu/menu_displaylist.h | 1 + menu/menu_setting.c | 146 +++++++ msg_hash.h | 15 + ui/drivers/qt/qt_options.cpp | 57 ++- ui/drivers/qt/qt_options.h | 5 + 21 files changed, 707 insertions(+), 187 deletions(-) diff --git a/config.def.h b/config.def.h index aea4a06e02..6a214c73a1 100644 --- a/config.def.h +++ b/config.def.h @@ -185,6 +185,10 @@ #ifdef HAVE_CHEEVOS #define DEFAULT_CHEEVOS_ENABLE false +#define DEFAULT_CHEEVOS_APPEARANCE_ANCHOR 0 /* CHEEVOS_APPEARANCE_ANCHOR_TOPLEFT */ +#define DEFAULT_CHEEVOS_APPEARANCE_PADDING_AUTO true +#define DEFAULT_CHEEVOS_APPEARANCE_PADDING_H 0.0f +#define DEFAULT_CHEEVOS_APPEARANCE_PADDING_V 0.0f #endif /* VIDEO */ diff --git a/configuration.c b/configuration.c index f70c5f3ea0..fd4b96e7dc 100644 --- a/configuration.c +++ b/configuration.c @@ -1946,6 +1946,7 @@ static struct config_bool_setting *populate_settings_bool( SETTING_BOOL("cheevos_auto_screenshot", &settings->bools.cheevos_auto_screenshot, true, false, false); SETTING_BOOL("cheevos_badges_enable", &settings->bools.cheevos_badges_enable, true, false, false); SETTING_BOOL("cheevos_start_active", &settings->bools.cheevos_start_active, true, false, false); + SETTING_BOOL("cheevos_appearance_padding_auto", &settings->bools.cheevos_appearance_padding_auto, true, DEFAULT_CHEEVOS_APPEARANCE_PADDING_AUTO, false); #endif #ifdef HAVE_OVERLAY SETTING_BOOL("input_overlay_enable", &settings->bools.input_overlay_enable, true, config_overlay_enable_default(), false); @@ -2118,6 +2119,10 @@ static struct config_float_setting *populate_settings_float( #ifdef HAVE_OZONE SETTING_FLOAT("ozone_thumbnail_scale_factor", &settings->floats.ozone_thumbnail_scale_factor, true, DEFAULT_OZONE_THUMBNAIL_SCALE_FACTOR, false); #endif +#endif +#ifdef HAVE_CHEEVOS + SETTING_FLOAT("cheevos_appearance_padding_h", &settings->floats.cheevos_appearance_padding_h, true, DEFAULT_CHEEVOS_APPEARANCE_PADDING_H, false); + SETTING_FLOAT("cheevos_appearance_padding_v", &settings->floats.cheevos_appearance_padding_v, true, DEFAULT_CHEEVOS_APPEARANCE_PADDING_V, false); #endif SETTING_FLOAT("video_message_pos_x", &settings->floats.video_msg_pos_x, true, DEFAULT_MESSAGE_POS_OFFSET_X, false); SETTING_FLOAT("video_message_pos_y", &settings->floats.video_msg_pos_y, true, DEFAULT_MESSAGE_POS_OFFSET_Y, false); @@ -2271,6 +2276,9 @@ static struct config_uint_setting *populate_settings_uint( #ifdef HAVE_OZONE SETTING_UINT("ozone_menu_color_theme", &settings->uints.menu_ozone_color_theme, true, DEFAULT_OZONE_COLOR_THEME, false); #endif +#endif +#ifdef HAVE_CHEEVOS + SETTING_UINT("cheevos_appearance_anchor", &settings->uints.cheevos_appearance_anchor, true, DEFAULT_CHEEVOS_APPEARANCE_ANCHOR, false); #endif SETTING_UINT("audio_out_rate", &settings->uints.audio_output_sample_rate, true, DEFAULT_OUTPUT_RATE, false); SETTING_UINT("custom_viewport_width", &settings->video_viewport_custom.width, false, 0 /* TODO */, false); diff --git a/configuration.h b/configuration.h index c45a831b89..dbe94a7fae 100644 --- a/configuration.h +++ b/configuration.h @@ -340,6 +340,8 @@ typedef struct settings #ifdef HAVE_MIST unsigned steam_rich_presence_format; #endif + + unsigned cheevos_appearance_anchor; } uints; struct @@ -371,6 +373,9 @@ typedef struct settings float menu_screensaver_animation_speed; float ozone_thumbnail_scale_factor; + float cheevos_appearance_padding_h; + float cheevos_appearance_padding_v; + float audio_max_timing_skew; float audio_volume; /* dB scale. */ float audio_mixer_volume; /* dB scale. */ @@ -825,6 +830,7 @@ typedef struct settings bool cheevos_start_active; bool cheevos_unlock_sound_enable; bool cheevos_challenge_indicators; + bool cheevos_appearance_padding_auto; /* Camera */ bool camera_allow; diff --git a/gfx/gfx_widgets.h b/gfx/gfx_widgets.h index d173c537a6..7dc67bb731 100644 --- a/gfx/gfx_widgets.h +++ b/gfx/gfx_widgets.h @@ -88,6 +88,17 @@ enum notification_show_screenshot_flash NOTIFICATION_SHOW_SCREENSHOT_FLASH_LAST }; +enum cheevos_appearance_anchor +{ + CHEEVOS_APPEARANCE_ANCHOR_TOPLEFT = 0, + CHEEVOS_APPEARANCE_ANCHOR_TOPCENTER, + CHEEVOS_APPEARANCE_ANCHOR_TOPRIGHT, + CHEEVOS_APPEARANCE_ANCHOR_BOTTOMLEFT, + CHEEVOS_APPEARANCE_ANCHOR_BOTTOMCENTER, + CHEEVOS_APPEARANCE_ANCHOR_BOTTOMRIGHT, + CHEEVOS_APPEARANCE_ANCHOR_LAST +}; + /* This structure holds all objects + metadata * corresponding to a particular font */ typedef struct @@ -365,6 +376,7 @@ void gfx_widgets_ai_service_overlay_unload(void); #endif #ifdef HAVE_CHEEVOS +void gfx_widgets_update_cheevos_appearance(); void gfx_widgets_push_achievement(const char *title, const char* subtitle, const char *badge); void gfx_widgets_set_leaderboard_display(unsigned id, const char* value); void gfx_widgets_set_challenge_display(unsigned id, const char* badge); diff --git a/gfx/widgets/gfx_widget_achievement_popup.c b/gfx/widgets/gfx_widget_achievement_popup.c index 6faaea49fd..24d0bdd6cb 100644 --- a/gfx/widgets/gfx_widget_achievement_popup.c +++ b/gfx/widgets/gfx_widget_achievement_popup.c @@ -37,14 +37,22 @@ struct gfx_widget_achievement_popup_state slock_t* queue_lock; #endif cheevo_popup queue[CHEEVO_QUEUE_SIZE]; /* ptr alignment */ - const dispgfx_widget_t *dispwidget_ptr; + const dispgfx_widget_t* dispwidget_ptr; int queue_read_index; int queue_write_index; - unsigned width; - unsigned height; - float timer; /* float alignment */ - float unfold; - float y; + unsigned width; /* Width of popup (in pixels), set in _start (length of strings) */ + unsigned height; /* Height of popup (in pixels), set in _start (4 x line height) */ + float timer; /* For delay of CHEEVO_NOTIFICATION_DURATION before starting _fold */ + float unfold; /* Progress of unfolding animation, changes in _unfold and _fold */ + float slide_h; /* Progress of horizontal sliding animation, changes in _unfold and _fold (stay centered) */ + float slide_v; /* Progress of vertical sliding animation, changes in _start and _dismiss (slide on/off screen) */ + + /* Values copied from user config in _start to prevent accessing every _frame */ + float target_h; /* Horizontal sliding target, 0.0 to 0.5, convert to screen-space before use */ + float target_v; /* Vertical sliding target, 0.0 to 0.5, convert to screen-space before use */ + bool padding_auto; /* Should we use target h/v or grab pixel values from p_dispwidget? */ + enum { ANCHOR_LEFT = 0, ANCHOR_CENTER, ANCHOR_RIGHT } anchor_h; /* Horizontal anchor */ + enum { ANCHOR_TOP = 0, ANCHOR_BOTTOM } anchor_v; /* Vertical anchor */ }; typedef struct gfx_widget_achievement_popup_state gfx_widget_achievement_popup_state_t; @@ -57,14 +65,12 @@ static void gfx_widget_achievement_popup_start( static void gfx_widget_achievement_popup_free_current( gfx_widget_achievement_popup_state_t* state); -static bool gfx_widget_achievement_popup_init( - gfx_display_t *p_disp, - gfx_animation_t *p_anim, - bool video_is_threaded, bool fullscreen) +static bool gfx_widget_achievement_popup_init(gfx_display_t* p_disp, + gfx_animation_t* p_anim, bool video_is_threaded, bool fullscreen) { gfx_widget_achievement_popup_state_t* state = &p_w_achievement_popup_st; memset(state, 0, sizeof(*state)); - state->dispwidget_ptr = (const dispgfx_widget_t*) + state->dispwidget_ptr = (const dispgfx_widget_t*) dispwidget_get_ptr(); state->queue_read_index = -1; @@ -89,32 +95,31 @@ static void gfx_widget_achievement_popup_free_all(gfx_widget_achievement_popup_s static void gfx_widget_achievement_popup_free(void) { - gfx_widget_achievement_popup_state_t *state = &p_w_achievement_popup_st; + gfx_widget_achievement_popup_state_t* state = &p_w_achievement_popup_st; gfx_widget_achievement_popup_free_all(state); #ifdef HAVE_THREADS slock_free(state->queue_lock); - state->queue_lock = NULL; + state->queue_lock = NULL; #endif state->dispwidget_ptr = NULL; } static void gfx_widget_achievement_popup_context_destroy(void) { - gfx_widget_achievement_popup_state_t *state = &p_w_achievement_popup_st; + gfx_widget_achievement_popup_state_t* state = &p_w_achievement_popup_st; gfx_widget_achievement_popup_free_all(state); } static void gfx_widget_achievement_popup_frame(void* data, void* userdata) { - gfx_widget_achievement_popup_state_t *state = &p_w_achievement_popup_st; + gfx_widget_achievement_popup_state_t* state = &p_w_achievement_popup_st; /* if there's nothing in the queue, just bail */ - if ( - state->queue_read_index < 0 - || !state->queue[state->queue_read_index].title) + if (state->queue_read_index < 0 + || !state->queue[state->queue_read_index].title) return; #ifdef HAVE_THREADS @@ -122,7 +127,7 @@ static void gfx_widget_achievement_popup_frame(void* data, void* userdata) #endif { - static float pure_white[16] = { + static float pure_white[16] = { 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, @@ -131,51 +136,108 @@ static void gfx_widget_achievement_popup_frame(void* data, void* userdata) 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; - gfx_display_t *p_disp = (gfx_display_t*)video_info->disp_userdata; - gfx_display_ctx_driver_t *dispctx = p_disp->dispctx; + gfx_display_t* p_disp = (gfx_display_t*)video_info->disp_userdata; + gfx_display_ctx_driver_t* dispctx = p_disp->dispctx; 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; + + unsigned text_unfold_offset = 0; + bool is_folding = false; + unsigned screen_padding_x = 0; + unsigned screen_padding_y = 0; + int screen_pos_x = 0; + int screen_pos_y = 0; + + /* Slight additional offset for title/subtitle while unfolding */ + text_unfold_offset = ((1.0f - state->unfold) * state->width) * 0.5; + + /* Whether gfx scissoring should occur, partially hiding popup */ + is_folding = fabs(state->unfold - 1.0f) > 0.01; + + /* Calculate padding in screen space */ + if (state->padding_auto) + { + screen_padding_x = p_dispwidget->msg_queue_rect_start_x - + p_dispwidget->msg_queue_icon_size_x; + screen_padding_y = screen_padding_x; + } + else + { + screen_padding_x = state->target_h * video_width; + screen_padding_y = state->target_v * video_height; + } + + /* Initial horizontal position, then apply animated offset */ + switch (state->anchor_h) + { + case ANCHOR_LEFT: + screen_pos_x = screen_padding_x; + break; + case ANCHOR_CENTER: + screen_pos_x = (video_width - state->height) * 0.5; + screen_pos_x -= (state->width / 2.0f) * state->slide_h; + break; + case ANCHOR_RIGHT: + screen_pos_x = video_width - state->height - screen_padding_x; + screen_pos_x -= state->width * state->slide_h; + break; + } + + /* Initial vertical position (off-screen), then apply animated offset */ + switch (state->anchor_v) + { + case ANCHOR_TOP: + screen_pos_y = -(state->height); + screen_pos_y += (screen_padding_y + state->height) * state->slide_v; + break; + case ANCHOR_BOTTOM: + screen_pos_y = video_height; + screen_pos_y -= (screen_padding_y + state->height) * state->slide_v; + break; + } gfx_display_set_alpha(p_dispwidget->backdrop_orig, DEFAULT_BACKDROP); gfx_display_set_alpha(pure_white, 1.0f); - /* Default icon */ + /* Default Badge */ if (!state->queue[state->queue_read_index].badge) { /* Backdrop */ gfx_display_draw_quad( - p_disp, - video_info->userdata, - video_width, video_height, - 0, (int)state->y, - state->height, - state->height, - video_width, video_height, - p_dispwidget->backdrop_orig, - NULL); + p_disp, + video_info->userdata, + video_width, + video_height, + screen_pos_x, + screen_pos_y, + state->height, + state->height, + video_width, + video_height, + p_dispwidget->backdrop_orig, + NULL); /* Icon */ if (p_dispwidget->gfx_widgets_icons_textures[MENU_WIDGETS_ICON_ACHIEVEMENT]) { if (dispctx && dispctx->blend_begin) dispctx->blend_begin(video_info->userdata); + gfx_widgets_draw_icon( - video_info->userdata, - p_disp, - video_width, - video_height, - state->height, - state->height, - p_dispwidget->gfx_widgets_icons_textures[ + video_info->userdata, + p_disp, + video_width, + video_height, + state->height, + state->height, + p_dispwidget->gfx_widgets_icons_textures[ MENU_WIDGETS_ICON_ACHIEVEMENT], - 0, - state->y, - 0.0f, /* rad */ - 1.0f, /* cos(rad) = cos(0) = 1.0f */ - 0.0f, /* sine(rad) = sine(0) = 0.0f */ - pure_white); + screen_pos_x, + screen_pos_y, + 0.0f, /* rad */ + 1.0f, /* cos(rad) = cos(0) = 1.0f */ + 0.0f, /* sine(rad) = sine(0) = 0.0f */ + pure_white); + if (dispctx && dispctx->blend_end) dispctx->blend_end(video_info->userdata); } @@ -184,81 +246,89 @@ static void gfx_widget_achievement_popup_frame(void* data, void* userdata) else { gfx_widgets_draw_icon( - video_info->userdata, - p_disp, - video_width, - video_height, - state->height, - state->height, - state->queue[state->queue_read_index].badge, - 0, - state->y, - 0.0f, /* rad */ - 1.0f, /* cos(rad) = cos(0) = 1.0f */ - 0.0f, /* sine(rad) = sine(0) = 0.0f */ - pure_white); + video_info->userdata, + p_disp, + video_width, + video_height, + state->height, + state->height, + state->queue[state->queue_read_index].badge, + screen_pos_x, + screen_pos_y, + 0.0f, /* rad */ + 1.0f, /* cos(rad) = cos(0) = 1.0f */ + 0.0f, /* sine(rad) = sine(0) = 0.0f */ + pure_white); } - /* I _think_ state->unfold changes in another thread */ - scissor_me_timbers = (fabs(state->unfold - 1.0f) > 0.01); - if (scissor_me_timbers) + if (is_folding) + { gfx_display_scissor_begin( - p_disp, - video_info->userdata, - video_width, - video_height, - state->height, - 0, - (unsigned)((float)(state->width) * state->unfold), - state->height); - - /* Backdrop */ - gfx_display_draw_quad( p_disp, video_info->userdata, video_width, video_height, - state->height, - (int)state->y, - state->width, - state->height, - video_width, - video_height, - p_dispwidget->backdrop_orig, - NULL); + screen_pos_x + state->height, + screen_pos_y, + (unsigned)((float)(state->width) * state->unfold), + state->height); + } + + /* Backdrop */ + gfx_display_draw_quad( + p_disp, + video_info->userdata, + video_width, + video_height, + screen_pos_x + state->height, + screen_pos_y, + state->width, + state->height, + video_width, + video_height, + p_dispwidget->backdrop_orig, + NULL); /* Title */ - 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 + 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); + gfx_widgets_draw_text( + &p_dispwidget->gfx_widget_fonts.regular, + state->queue[state->queue_read_index].title, + screen_pos_x + state->height - text_unfold_offset + + p_dispwidget->simple_widget_padding, + screen_pos_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 */ + /* Subtitle */ /* TODO: is a ticker necessary ? */ - gfx_widgets_draw_text(&p_dispwidget->gfx_widget_fonts.regular, - state->queue[state->queue_read_index].subtitle, - 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); + gfx_widgets_draw_text( + &p_dispwidget->gfx_widget_fonts.regular, + state->queue[state->queue_read_index].subtitle, + screen_pos_x + state->height - text_unfold_offset + + p_dispwidget->simple_widget_padding, + screen_pos_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) + if (is_folding) { gfx_widgets_flush_text(video_width, video_height, - &p_dispwidget->gfx_widget_fonts.regular); + &p_dispwidget->gfx_widget_fonts.regular); + if (dispctx && dispctx->scissor_end) dispctx->scissor_end(video_info->userdata, - video_width, video_height); + video_width, video_height); } } @@ -268,7 +338,7 @@ static void gfx_widget_achievement_popup_frame(void* data, void* userdata) } static void gfx_widget_achievement_popup_free_current( - gfx_widget_achievement_popup_state_t* state) + gfx_widget_achievement_popup_state_t* state) { if (state->queue[state->queue_read_index].title) { @@ -293,7 +363,7 @@ static void gfx_widget_achievement_popup_free_current( static void gfx_widget_achievement_popup_next(void* userdata) { - gfx_widget_achievement_popup_state_t *state = &p_w_achievement_popup_st; + gfx_widget_achievement_popup_state_t* state = &p_w_achievement_popup_st; #ifdef HAVE_THREADS slock_lock(state->queue_lock); @@ -314,37 +384,18 @@ static void gfx_widget_achievement_popup_next(void* userdata) #endif } -static void gfx_widget_achievement_popup_dismiss(void *userdata) +static void gfx_widget_achievement_popup_dismiss(void* userdata) { gfx_animation_ctx_entry_t entry; - gfx_widget_achievement_popup_state_t *state = &p_w_achievement_popup_st; - const dispgfx_widget_t *p_dispwidget = (const dispgfx_widget_t*) + gfx_widget_achievement_popup_state_t* state = &p_w_achievement_popup_st; + const dispgfx_widget_t* p_dispwidget = (const dispgfx_widget_t*) state->dispwidget_ptr; - /* Slide up animation */ + /* Slide off-screen */ 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; - gfx_widget_achievement_popup_state_t *state = &p_w_achievement_popup_st; - const dispgfx_widget_t *p_dispwidget = (const dispgfx_widget_t*) - state->dispwidget_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.subject = &state->slide_v; entry.tag = p_dispwidget->gfx_widgets_generic_tag; entry.target_value = 0.0f; entry.userdata = NULL; @@ -352,26 +403,75 @@ static void gfx_widget_achievement_popup_fold(void *userdata) gfx_animation_push(&entry); } -static void gfx_widget_achievement_popup_unfold(void *userdata) +static void gfx_widget_achievement_popup_fold(void* userdata) +{ + gfx_animation_ctx_entry_t anim_fold; + gfx_animation_ctx_entry_t anim_slide; + gfx_widget_achievement_popup_state_t* state = &p_w_achievement_popup_st; + const dispgfx_widget_t* p_dispwidget = (const dispgfx_widget_t*) + state->dispwidget_ptr; + + /* Fold */ + anim_fold.cb = gfx_widget_achievement_popup_dismiss; + anim_fold.duration = MSG_QUEUE_ANIMATION_DURATION; + anim_fold.easing_enum = EASING_OUT_QUAD; + anim_fold.subject = &state->unfold; + anim_fold.tag = p_dispwidget->gfx_widgets_generic_tag; + anim_fold.target_value = 0.0f; + anim_fold.userdata = NULL; + + gfx_animation_push(&anim_fold); + + /* Slide horizontal (if required) */ + if (state->anchor_h != ANCHOR_LEFT) + { + anim_slide.cb = NULL; + anim_slide.duration = MSG_QUEUE_ANIMATION_DURATION; + anim_slide.easing_enum = EASING_OUT_QUAD; + anim_slide.subject = &state->slide_h; + anim_slide.tag = p_dispwidget->gfx_widgets_generic_tag; + anim_slide.target_value = 0.0f; + anim_slide.userdata = NULL; + + gfx_animation_push(&anim_slide); + } +} + +static void gfx_widget_achievement_popup_unfold(void* userdata) { gfx_timer_ctx_entry_t timer; - gfx_animation_ctx_entry_t entry; - gfx_widget_achievement_popup_state_t *state = &p_w_achievement_popup_st; - const dispgfx_widget_t *p_dispwidget = (const dispgfx_widget_t*) + gfx_animation_ctx_entry_t anim_unfold; + gfx_animation_ctx_entry_t anim_slide; + gfx_widget_achievement_popup_state_t* state = &p_w_achievement_popup_st; + const dispgfx_widget_t* p_dispwidget = (const dispgfx_widget_t*) state->dispwidget_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; + anim_unfold.cb = NULL; + anim_unfold.duration = MSG_QUEUE_ANIMATION_DURATION; + anim_unfold.easing_enum = EASING_OUT_QUAD; + anim_unfold.subject = &state->unfold; + anim_unfold.tag = p_dispwidget->gfx_widgets_generic_tag; + anim_unfold.target_value = 1.0f; + anim_unfold.userdata = NULL; - gfx_animation_push(&entry); + gfx_animation_push(&anim_unfold); - /* Wait before dismissing */ + /* Slide horizontal (if required) */ + if (state->anchor_h != ANCHOR_LEFT) + { + anim_slide.cb = NULL; + anim_slide.duration = MSG_QUEUE_ANIMATION_DURATION; + anim_slide.easing_enum = EASING_OUT_QUAD; + anim_slide.subject = &state->slide_h; + anim_slide.tag = p_dispwidget->gfx_widgets_generic_tag; + anim_slide.target_value = 1.0f; + anim_slide.userdata = NULL; + + gfx_animation_push(&anim_slide); + } + + /* Wait before folding */ timer.cb = gfx_widget_achievement_popup_fold; timer.duration = MSG_QUEUE_ANIMATION_DURATION + CHEEVO_NOTIFICATION_DURATION; timer.userdata = NULL; @@ -379,44 +479,75 @@ static void gfx_widget_achievement_popup_unfold(void *userdata) gfx_animation_timer_start(&state->timer, &timer); } +void gfx_widgets_update_cheevos_appearance() +{ + gfx_widget_achievement_popup_state_t* state = &p_w_achievement_popup_st; + const settings_t* settings = config_get_ptr(); + const float target_h = settings->floats.cheevos_appearance_padding_h; + const float target_v = settings->floats.cheevos_appearance_padding_v; + const bool autopadding = settings->bools.cheevos_appearance_padding_auto; + const unsigned anchor = settings->uints.cheevos_appearance_anchor; + + state->target_h = target_h; + state->target_v = target_v; + state->padding_auto = autopadding; + + if (anchor == CHEEVOS_APPEARANCE_ANCHOR_TOPCENTER || + anchor == CHEEVOS_APPEARANCE_ANCHOR_BOTTOMCENTER) + state->anchor_h = ANCHOR_CENTER; + else if (anchor == CHEEVOS_APPEARANCE_ANCHOR_TOPRIGHT || + anchor == CHEEVOS_APPEARANCE_ANCHOR_BOTTOMRIGHT) + state->anchor_h = ANCHOR_RIGHT; + else + state->anchor_h = ANCHOR_LEFT; + + if (anchor == CHEEVOS_APPEARANCE_ANCHOR_BOTTOMLEFT || + anchor == CHEEVOS_APPEARANCE_ANCHOR_BOTTOMCENTER || + anchor == CHEEVOS_APPEARANCE_ANCHOR_BOTTOMRIGHT) + state->anchor_v = ANCHOR_BOTTOM; + else + state->anchor_v = ANCHOR_TOP; +} + static void gfx_widget_achievement_popup_start( gfx_widget_achievement_popup_state_t* state) { - gfx_animation_ctx_entry_t entry; - const dispgfx_widget_t *p_dispwidget = (const dispgfx_widget_t*) + gfx_animation_ctx_entry_t anim_slide; + const dispgfx_widget_t* p_dispwidget = (const dispgfx_widget_t*) state->dispwidget_ptr; - size_t title_len = strlen(state->queue[state->queue_read_index].title); - size_t stitle_len = strlen(state->queue[state->queue_read_index].subtitle); - 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, - state->queue[state->queue_read_index].title, title_len, - 1.0f), - font_driver_get_message_width( - p_dispwidget->gfx_widget_fonts.regular.font, - state->queue[state->queue_read_index].subtitle, stitle_len, - 1.0f) + + state->height = p_dispwidget->gfx_widget_fonts.regular.line_height * 4.0f; + state->width = MAX( + font_driver_get_message_width( + p_dispwidget->gfx_widget_fonts.regular.font, + state->queue[state->queue_read_index].title, 0, 1.0f), + font_driver_get_message_width( + p_dispwidget->gfx_widget_fonts.regular.font, + state->queue[state->queue_read_index].subtitle, 0, 1.0f) ); state->width += p_dispwidget->simple_widget_padding * 2; - state->y = (float)(-(int)state->height); state->unfold = 0.0f; + state->slide_h = 0.0f; + state->slide_v = 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; + /* Store settings to prevent lookup every _frame */ + gfx_widgets_update_cheevos_appearance(); - gfx_animation_push(&entry); + /* Slide vertical onto screen */ + anim_slide.cb = gfx_widget_achievement_popup_unfold; + anim_slide.duration = MSG_QUEUE_ANIMATION_DURATION; + anim_slide.easing_enum = EASING_OUT_QUAD; + anim_slide.subject = &state->slide_v; + anim_slide.tag = p_dispwidget->gfx_widgets_generic_tag; + anim_slide.target_value = 1.0f; + anim_slide.userdata = NULL; + + gfx_animation_push(&anim_slide); } -void gfx_widgets_push_achievement(const char *title, const char* subtitle, const char *badge) +void gfx_widgets_push_achievement(const char* title, const char* subtitle, const char* badge) { - gfx_widget_achievement_popup_state_t *state = &p_w_achievement_popup_st; + gfx_widget_achievement_popup_state_t* state = &p_w_achievement_popup_st; int start_notification = 1; /* important - this must be done outside the lock because it has the potential to need to diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 466f2b5759..f2dcc254c0 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -440,6 +440,18 @@ MSG_HASH( MENU_ENUM_LABEL_CHEEVOS_CHALLENGE_INDICATORS, "cheevos_challenge_indicators" ) +MSG_HASH( + MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_SETTINGS, + "cheevos_appearance_settings" + ) +MSG_HASH( + MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_ANCHOR, + "cheevos_appearance_anchor" + ) +MSG_HASH( + MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_AUTO, + "cheevos_appearance_padding_auto" + ) MSG_HASH( MENU_ENUM_LABEL_CLOSE_CONTENT, "unload_core" @@ -1116,6 +1128,10 @@ MSG_HASH( MENU_ENUM_LABEL_DEFERRED_RETRO_ACHIEVEMENTS_SETTINGS_LIST, "deferred_retro_achievements_settings_list" ) +MSG_HASH( + MENU_ENUM_LABEL_DEFERRED_CHEEVOS_APPEARANCE_SETTINGS_LIST, + "deferred_cheevos_appearance_settings_list" + ) MSG_HASH( MENU_ENUM_LABEL_DEFERRED_REWIND_SETTINGS_LIST, "deferred_rewind_settings_list" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 452f5bdf47..32472d91b9 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -5866,6 +5866,73 @@ MSG_HASH( "Allows achievements to display an on-screen indicator while the achievement can be earned." ) +/* Settings > Achievements > Appearance */ + +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_SETTINGS, + "Appearance" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CHEEVOS_APPEARANCE_SETTINGS, + "Change the position and offsets of on-screen achievement notifications." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR, + "Position" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CHEEVOS_APPEARANCE_ANCHOR, + "Set the corner/edge of the screen which achievement notifications will appear from." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_TOPLEFT, + "Top Left" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_TOPCENTER, + "Top Center" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_TOPRIGHT, + "Top Right" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_BOTTOMLEFT, + "Bottom Left" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_BOTTOMCENTER, + "Bottom Center" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_BOTTOMRIGHT, + "Bottom Right" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_PADDING_AUTO, + "Aligned Padding" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CHEEVOS_APPEARANCE_PADDING_AUTO, + "Set whether achievement notifications should align with other types of on-screen notifications. Disable to set manual padding/position values." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_PADDING_H, + "Manual Horizontal Padding" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CHEEVOS_APPEARANCE_PADDING_H, + "Distance from left/right screen edge, which can compensate for display overscan." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_PADDING_V, + "Manual Vertical Padding" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CHEEVOS_APPEARANCE_PADDING_V, + "Distance from top/bottom screen edge, which can compensate for display overscan." + ) + /* Settings > Network */ MSG_HASH( diff --git a/menu/cbs/menu_cbs_deferred_push.c b/menu/cbs/menu_cbs_deferred_push.c index 5c8103744c..54aae7f858 100644 --- a/menu/cbs/menu_cbs_deferred_push.c +++ b/menu/cbs/menu_cbs_deferred_push.c @@ -204,6 +204,7 @@ GENERIC_DEFERRED_PUSH(deferred_push_menu_bottom_settings_list, DISPLAYLIST_ GENERIC_DEFERRED_PUSH(deferred_push_user_interface_settings_list, DISPLAYLIST_USER_INTERFACE_SETTINGS_LIST) GENERIC_DEFERRED_PUSH(deferred_push_power_management_settings_list, DISPLAYLIST_POWER_MANAGEMENT_SETTINGS_LIST) GENERIC_DEFERRED_PUSH(deferred_push_retro_achievements_settings_list,DISPLAYLIST_RETRO_ACHIEVEMENTS_SETTINGS_LIST) +GENERIC_DEFERRED_PUSH(deferred_push_cheevos_appearance_settings_list,DISPLAYLIST_CHEEVOS_APPEARANCE_SETTINGS_LIST) GENERIC_DEFERRED_PUSH(deferred_push_updater_settings_list, DISPLAYLIST_UPDATER_SETTINGS_LIST) GENERIC_DEFERRED_PUSH(deferred_push_bluetooth_settings_list, DISPLAYLIST_BLUETOOTH_SETTINGS_LIST) GENERIC_DEFERRED_PUSH(deferred_push_wifi_settings_list, DISPLAYLIST_WIFI_SETTINGS_LIST) @@ -717,6 +718,7 @@ static int menu_cbs_init_bind_deferred_push_compare_label( {MENU_ENUM_LABEL_DEFERRED_POWER_MANAGEMENT_SETTINGS_LIST, deferred_push_power_management_settings_list}, {MENU_ENUM_LABEL_DEFERRED_MENU_SOUNDS_LIST, deferred_push_menu_sounds_list}, {MENU_ENUM_LABEL_DEFERRED_RETRO_ACHIEVEMENTS_SETTINGS_LIST, deferred_push_retro_achievements_settings_list}, + {MENU_ENUM_LABEL_DEFERRED_CHEEVOS_APPEARANCE_SETTINGS_LIST, deferred_push_cheevos_appearance_settings_list}, {MENU_ENUM_LABEL_DEFERRED_UPDATER_SETTINGS_LIST, deferred_push_updater_settings_list}, {MENU_ENUM_LABEL_DEFERRED_NETWORK_SETTINGS_LIST, deferred_push_network_settings_list}, {MENU_ENUM_LABEL_DEFERRED_SUBSYSTEM_SETTINGS_LIST, deferred_push_subsystem_settings_list}, @@ -1258,6 +1260,9 @@ static int menu_cbs_init_bind_deferred_push_compare_label( case MENU_ENUM_LABEL_DEFERRED_REWIND_SETTINGS_LIST: BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_rewind_settings_list); break; + case MENU_ENUM_LABEL_DEFERRED_CHEEVOS_APPEARANCE_SETTINGS_LIST: + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_cheevos_appearance_settings_list); + break; case MENU_ENUM_LABEL_DEFERRED_ONSCREEN_DISPLAY_SETTINGS_LIST: BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_onscreen_display_settings_list); break; diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 548bd0a956..6db4b412e7 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -411,6 +411,8 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl) return MENU_ENUM_LABEL_DEFERRED_MENU_FILE_BROWSER_SETTINGS_LIST; case ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST: return MENU_ENUM_LABEL_DEFERRED_RETRO_ACHIEVEMENTS_SETTINGS_LIST; + case ACTION_OK_DL_CHEEVOS_APPEARANCE_SETTINGS_LIST: + return MENU_ENUM_LABEL_DEFERRED_CHEEVOS_APPEARANCE_SETTINGS_LIST; case ACTION_OK_DL_UPDATER_SETTINGS_LIST: return MENU_ENUM_LABEL_DEFERRED_UPDATER_SETTINGS_LIST; case ACTION_OK_DL_NETWORK_HOSTING_SETTINGS_LIST: @@ -1595,6 +1597,7 @@ int generic_action_ok_displaylist_push(const char *path, case ACTION_OK_DL_MENU_SOUNDS_LIST: case ACTION_OK_DL_MENU_FILE_BROWSER_SETTINGS_LIST: case ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST: + case ACTION_OK_DL_CHEEVOS_APPEARANCE_SETTINGS_LIST: case ACTION_OK_DL_UPDATER_SETTINGS_LIST: case ACTION_OK_DL_NETWORK_SETTINGS_LIST: case ACTION_OK_DL_NETWORK_HOSTING_SETTINGS_LIST: @@ -5837,6 +5840,7 @@ DEFAULT_ACTION_OK_FUNC(action_ok_menu_sounds_list, ACTION_OK_DL_MENU_SOUNDS_LIST DEFAULT_ACTION_OK_FUNC(action_ok_user_interface_list, ACTION_OK_DL_USER_INTERFACE_SETTINGS_LIST) DEFAULT_ACTION_OK_FUNC(action_ok_menu_file_browser_list, ACTION_OK_DL_MENU_FILE_BROWSER_SETTINGS_LIST) DEFAULT_ACTION_OK_FUNC(action_ok_retro_achievements_list, ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST) +DEFAULT_ACTION_OK_FUNC(action_ok_cheevos_appearance_list, ACTION_OK_DL_CHEEVOS_APPEARANCE_SETTINGS_LIST) DEFAULT_ACTION_OK_FUNC(action_ok_updater_list, ACTION_OK_DL_UPDATER_SETTINGS_LIST) DEFAULT_ACTION_OK_FUNC(action_ok_lakka_services, ACTION_OK_DL_LAKKA_SERVICES_LIST) DEFAULT_ACTION_OK_FUNC(action_ok_user_list, ACTION_OK_DL_USER_SETTINGS_LIST) @@ -8342,6 +8346,7 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs, {MENU_ENUM_LABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS, action_ok_open_uwp_permission_settings}, {MENU_ENUM_LABEL_FILE_BROWSER_OPEN_PICKER, action_ok_open_picker}, {MENU_ENUM_LABEL_RETRO_ACHIEVEMENTS_SETTINGS, action_ok_retro_achievements_list}, + {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_SETTINGS, action_ok_cheevos_appearance_list}, {MENU_ENUM_LABEL_UPDATER_SETTINGS, action_ok_updater_list}, #ifdef HAVE_BLUETOOTH {MENU_ENUM_LABEL_BLUETOOTH_SETTINGS, action_ok_bluetooth_list}, diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index dc19855469..749c831c7d 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -306,6 +306,11 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_unlock_sound_enable, MENU_ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_auto_screenshot, MENU_ENUM_SUBLABEL_CHEEVOS_AUTO_SCREENSHOT) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_start_active, MENU_ENUM_SUBLABEL_CHEEVOS_START_ACTIVE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_verbose_enable, MENU_ENUM_SUBLABEL_CHEEVOS_VERBOSE_ENABLE) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_appearance_settings, MENU_ENUM_SUBLABEL_CHEEVOS_APPEARANCE_SETTINGS) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_appearance_anchor, MENU_ENUM_SUBLABEL_CHEEVOS_APPEARANCE_ANCHOR) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_appearance_padding_auto, MENU_ENUM_SUBLABEL_CHEEVOS_APPEARANCE_PADDING_AUTO) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_appearance_padding_h, MENU_ENUM_SUBLABEL_CHEEVOS_APPEARANCE_PADDING_H) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_appearance_padding_v, MENU_ENUM_SUBLABEL_CHEEVOS_APPEARANCE_PADDING_V) #endif DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_views_settings_list, MENU_ENUM_SUBLABEL_MENU_VIEWS_SETTINGS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_quick_menu_views_settings_list, MENU_ENUM_SUBLABEL_QUICK_MENU_VIEWS_SETTINGS) @@ -4283,6 +4288,21 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_CHEEVOS_START_ACTIVE: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cheevos_start_active); break; + case MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_SETTINGS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cheevos_appearance_settings); + break; + case MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_ANCHOR: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cheevos_appearance_anchor); + break; + case MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_AUTO: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cheevos_appearance_padding_auto); + break; + case MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_H: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cheevos_appearance_padding_h); + break; + case MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_V: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cheevos_appearance_padding_v); + break; #endif case MENU_ENUM_LABEL_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_settings); diff --git a/menu/cbs/menu_cbs_title.c b/menu/cbs/menu_cbs_title.c index f5d18fbbba..2d7c7c2b53 100644 --- a/menu/cbs/menu_cbs_title.c +++ b/menu/cbs/menu_cbs_title.c @@ -657,6 +657,7 @@ DEFAULT_TITLE_MACRO(action_get_cpu_policy_entry_list, MENU_ENUM_LABEL_ DEFAULT_TITLE_MACRO(action_get_menu_sounds_list, MENU_ENUM_LABEL_VALUE_MENU_SOUNDS) DEFAULT_TITLE_MACRO(action_get_menu_file_browser_settings_list, MENU_ENUM_LABEL_VALUE_MENU_FILE_BROWSER_SETTINGS) DEFAULT_TITLE_MACRO(action_get_retro_achievements_settings_list,MENU_ENUM_LABEL_VALUE_RETRO_ACHIEVEMENTS_SETTINGS) +DEFAULT_TITLE_MACRO(action_get_cheevos_appearance_settings_list,MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_SETTINGS) DEFAULT_TITLE_MACRO(action_get_bluetooth_settings_list, MENU_ENUM_LABEL_VALUE_BLUETOOTH_SETTINGS) DEFAULT_TITLE_MACRO(action_get_wifi_networks_list, MENU_ENUM_LABEL_VALUE_WIFI_NETWORKS) DEFAULT_TITLE_MACRO(action_get_wifi_settings_list, MENU_ENUM_LABEL_VALUE_WIFI_SETTINGS) @@ -1017,6 +1018,7 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs, {MENU_ENUM_LABEL_DEFERRED_MENU_SOUNDS_LIST, action_get_menu_sounds_list}, {MENU_ENUM_LABEL_DEFERRED_MENU_FILE_BROWSER_SETTINGS_LIST, action_get_menu_file_browser_settings_list}, {MENU_ENUM_LABEL_DEFERRED_RETRO_ACHIEVEMENTS_SETTINGS_LIST, action_get_retro_achievements_settings_list}, + {MENU_ENUM_LABEL_DEFERRED_CHEEVOS_APPEARANCE_SETTINGS_LIST, action_get_cheevos_appearance_settings_list}, {MENU_ENUM_LABEL_DEFERRED_BLUETOOTH_SETTINGS_LIST, action_get_bluetooth_settings_list}, {MENU_ENUM_LABEL_DEFERRED_WIFI_NETWORKS_LIST, action_get_wifi_networks_list}, {MENU_ENUM_LABEL_DEFERRED_WIFI_SETTINGS_LIST, action_get_wifi_settings_list}, diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c index 92881aa7a0..b02a698b70 100644 --- a/menu/drivers/materialui.c +++ b/menu/drivers/materialui.c @@ -10774,6 +10774,7 @@ static void materialui_list_insert( string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_POWER_MANAGEMENT_SETTINGS)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_LIST)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_RETRO_ACHIEVEMENTS_SETTINGS)) || + string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_SETTINGS)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_ACCOUNTS_YOUTUBE)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_ACCOUNTS_TWITCH)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_ACCOUNTS_FACEBOOK)) || diff --git a/menu/drivers/ozone.c b/menu/drivers/ozone.c index 93d1087e12..2d22b322bb 100644 --- a/menu/drivers/ozone.c +++ b/menu/drivers/ozone.c @@ -2090,6 +2090,7 @@ static uintptr_t ozone_entries_icon_get_texture( case MENU_ENUM_LABEL_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES: return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_OVERRIDE]; case MENU_ENUM_LABEL_ONSCREEN_NOTIFICATIONS_SETTINGS: + case MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_SETTINGS: return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_NOTIFICATIONS]; #ifdef HAVE_NETWORKING case MENU_ENUM_LABEL_NETPLAY_ENABLE_HOST: diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 450a8a3cbf..4897febc6d 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -3195,6 +3195,7 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb, case MENU_ENUM_LABEL_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES: return xmb->textures.list[XMB_TEXTURE_OVERRIDE]; case MENU_ENUM_LABEL_ONSCREEN_NOTIFICATIONS_SETTINGS: + case MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_SETTINGS: return xmb->textures.list[XMB_TEXTURE_NOTIFICATIONS]; #ifdef HAVE_NETWORKING case MENU_ENUM_LABEL_NETPLAY_ENABLE_HOST: diff --git a/menu/menu_cbs.h b/menu/menu_cbs.h index c931abe8bb..9d0eba1dee 100644 --- a/menu/menu_cbs.h +++ b/menu/menu_cbs.h @@ -197,6 +197,7 @@ enum ACTION_OK_DL_MENU_SOUNDS_LIST, ACTION_OK_DL_MENU_FILE_BROWSER_SETTINGS_LIST, ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST, + ACTION_OK_DL_CHEEVOS_APPEARANCE_SETTINGS_LIST, ACTION_OK_DL_ACHIEVEMENTS_HARDCORE_PAUSE_LIST, ACTION_OK_DL_UPDATER_SETTINGS_LIST, ACTION_OK_DL_BLUETOOTH_SETTINGS_LIST, diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index b9af1ad426..63f4a0a64a 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -8207,9 +8207,10 @@ unsigned menu_displaylist_build_list( { bool cheevos_enable = settings->bools.cheevos_enable; menu_displaylist_build_info_selective_t build_list[] = { - {MENU_ENUM_LABEL_CHEEVOS_ENABLE, PARSE_ONLY_BOOL, true }, - {MENU_ENUM_LABEL_CHEEVOS_USERNAME, PARSE_ONLY_STRING, false }, - {MENU_ENUM_LABEL_CHEEVOS_PASSWORD, PARSE_ONLY_STRING, false }, + {MENU_ENUM_LABEL_CHEEVOS_ENABLE, PARSE_ONLY_BOOL, true }, + {MENU_ENUM_LABEL_CHEEVOS_USERNAME, PARSE_ONLY_STRING, false }, + {MENU_ENUM_LABEL_CHEEVOS_PASSWORD, PARSE_ONLY_STRING, false }, + {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_SETTINGS, PARSE_ACTION, false }, {MENU_ENUM_LABEL_CHEEVOS_HARDCORE_MODE_ENABLE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_CHEEVOS_LEADERBOARDS_ENABLE, PARSE_ONLY_STRING_OPTIONS, false }, {MENU_ENUM_LABEL_CHEEVOS_CHALLENGE_INDICATORS, PARSE_ONLY_BOOL, false }, @@ -8246,6 +8247,48 @@ unsigned menu_displaylist_build_list( } } break; + case DISPLAYLIST_CHEEVOS_APPEARANCE_SETTINGS_LIST: + { + unsigned cheevos_anchor = settings->uints.cheevos_appearance_anchor; + bool cheevos_autopad = settings->bools.cheevos_appearance_padding_auto; + bool gfx_widgets = settings->bools.menu_enable_widgets; + menu_displaylist_build_info_selective_t build_list[] = { + {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_ANCHOR, PARSE_ONLY_UINT, true}, + {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_AUTO, PARSE_ONLY_BOOL, true}, + {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_H, PARSE_ONLY_FLOAT, false}, + {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_V, PARSE_ONLY_FLOAT, false}, + }; + +#if defined(HAVE_CHEEVOS) && defined(HAVE_GFX_WIDGETS) + for (i = 0; i < ARRAY_SIZE(build_list); i++) + { + if (!gfx_widgets) + build_list[i].checked = false; + else if (!cheevos_autopad) + { + if (build_list[i].enum_idx == MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_V) + build_list[i].checked = true; + + if (build_list[i].enum_idx == MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_H && + !(cheevos_anchor == CHEEVOS_APPEARANCE_ANCHOR_TOPCENTER || + cheevos_anchor == CHEEVOS_APPEARANCE_ANCHOR_BOTTOMCENTER)) + build_list[i].checked = true; + } + } +#endif + + for (i = 0; i < ARRAY_SIZE(build_list); i++) + { + if (!build_list[i].checked && !include_everything) + continue; + + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + build_list[i].enum_idx, build_list[i].parse_type, + false) == 0) + count++; + } + } + break; case DISPLAYLIST_ACCOUNTS_TWITCH_LIST: if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_TWITCH_STREAM_KEY, @@ -12988,6 +13031,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, case DISPLAYLIST_USER_INTERFACE_SETTINGS_LIST: case DISPLAYLIST_ACCOUNTS_TWITCH_LIST: case DISPLAYLIST_RETRO_ACHIEVEMENTS_SETTINGS_LIST: + case DISPLAYLIST_CHEEVOS_APPEARANCE_SETTINGS_LIST: case DISPLAYLIST_ACCOUNTS_YOUTUBE_LIST: case DISPLAYLIST_ACCOUNTS_FACEBOOK_LIST: case DISPLAYLIST_RECORDING_SETTINGS_LIST: diff --git a/menu/menu_displaylist.h b/menu/menu_displaylist.h index 573cacc2fb..778e0f55a6 100644 --- a/menu/menu_displaylist.h +++ b/menu/menu_displaylist.h @@ -214,6 +214,7 @@ enum menu_displaylist_ctl_state DISPLAYLIST_POWER_MANAGEMENT_SETTINGS_LIST, DISPLAYLIST_MENU_SOUNDS_LIST, DISPLAYLIST_RETRO_ACHIEVEMENTS_SETTINGS_LIST, + DISPLAYLIST_CHEEVOS_APPEARANCE_SETTINGS_LIST, DISPLAYLIST_UPDATER_SETTINGS_LIST, DISPLAYLIST_BLUETOOTH_SETTINGS_LIST, DISPLAYLIST_WIFI_SETTINGS_LIST, diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 8b11f701a3..48375bc3d6 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -305,6 +305,7 @@ enum settings_list_type SETTINGS_LIST_MENU_SOUNDS, SETTINGS_LIST_PLAYLIST, SETTINGS_LIST_CHEEVOS, + SETTINGS_LIST_CHEEVOS_APPEARANCE, SETTINGS_LIST_CORE_UPDATER, SETTINGS_LIST_NETPLAY, SETTINGS_LIST_LAKKA_SERVICES, @@ -8772,6 +8773,60 @@ static void achievement_leaderboards_get_string_representation(rarch_setting_t* #endif } +#ifdef HAVE_GFX_WIDGETS +static void setting_get_string_representation_uint_cheevos_appearance_anchor( + rarch_setting_t* setting, + char* s, size_t len) +{ + if (!setting) + return; + + switch (*setting->value.target.unsigned_integer) + { + case CHEEVOS_APPEARANCE_ANCHOR_TOPLEFT: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_TOPLEFT), + len); + break; + case CHEEVOS_APPEARANCE_ANCHOR_TOPCENTER: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_TOPCENTER), + len); + break; + case CHEEVOS_APPEARANCE_ANCHOR_TOPRIGHT: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_TOPRIGHT), + len); + break; + case CHEEVOS_APPEARANCE_ANCHOR_BOTTOMLEFT: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_BOTTOMLEFT), + len); + break; + case CHEEVOS_APPEARANCE_ANCHOR_BOTTOMCENTER: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_BOTTOMCENTER), + len); + break; + case CHEEVOS_APPEARANCE_ANCHOR_BOTTOMRIGHT: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_BOTTOMRIGHT), + len); + break; + } +} + +static void cheevos_appearance_write_handler(rarch_setting_t* setting) +{ + gfx_widgets_update_cheevos_appearance(); +} +#endif #endif static void update_streaming_url_write_handler(rarch_setting_t *setting) @@ -10047,6 +10102,14 @@ static bool setting_append_list( &group_info, &subgroup_info, parent_group); + + CONFIG_ACTION( + list, list_info, + MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_SETTINGS, + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_SETTINGS, + &group_info, + &subgroup_info, + parent_group); #endif CONFIG_ACTION( @@ -19976,6 +20039,88 @@ static bool setting_append_list( ); MENU_SETTINGS_LIST_CURRENT_ADD_CMD(list, list_info, CMD_EVENT_CHEEVOS_HARDCORE_MODE_TOGGLE); + END_SUB_GROUP(list, list_info, parent_group); + END_GROUP(list, list_info, parent_group); +#endif + break; + case SETTINGS_LIST_CHEEVOS_APPEARANCE: +#ifdef HAVE_CHEEVOS + START_GROUP(list, list_info, &group_info, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_SETTINGS), + parent_group); + parent_group = msg_hash_to_str(MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_SETTINGS); + START_SUB_GROUP(list, list_info, "State", &group_info, &subgroup_info, parent_group); + +#ifdef HAVE_GFX_WIDGETS + CONFIG_UINT( + list, list_info, + &settings->uints.cheevos_appearance_anchor, + MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_ANCHOR, + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR, + DEFAULT_CHEEVOS_APPEARANCE_ANCHOR, + &group_info, + &subgroup_info, + parent_group, + cheevos_appearance_write_handler, + general_read_handler); + (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; + (*list)[list_info->index - 1].action_left = &setting_uint_action_left_with_refresh; + (*list)[list_info->index - 1].action_right = &setting_uint_action_right_with_refresh; + (*list)[list_info->index - 1].get_string_representation = + &setting_get_string_representation_uint_cheevos_appearance_anchor; + menu_settings_list_current_add_range(list, list_info, 0, CHEEVOS_APPEARANCE_ANCHOR_LAST - 1, 1, true, true); + (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX; + + CONFIG_BOOL( + list, list_info, + &settings->bools.cheevos_appearance_padding_auto, + MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_AUTO, + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_PADDING_AUTO, + true, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + cheevos_appearance_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_FLOAT( + list, list_info, + &settings->floats.cheevos_appearance_padding_h, + MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_H, + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_PADDING_H, + DEFAULT_CHEEVOS_APPEARANCE_PADDING_H, + "%.2f", + &group_info, + &subgroup_info, + parent_group, + cheevos_appearance_write_handler, + general_read_handler + ); + menu_settings_list_current_add_range(list, list_info, 0.0, 0.5, 0.01, true, true); + + CONFIG_FLOAT( + list, list_info, + &settings->floats.cheevos_appearance_padding_v, + MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_V, + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_PADDING_V, + DEFAULT_CHEEVOS_APPEARANCE_PADDING_V, + "%.2f", + &group_info, + &subgroup_info, + parent_group, + cheevos_appearance_write_handler, + general_read_handler + ); + menu_settings_list_current_add_range(list, list_info, 0.0, 0.5, 0.01, true, true); +#endif + END_SUB_GROUP(list, list_info, parent_group); END_GROUP(list, list_info, parent_group); #endif @@ -22017,6 +22162,7 @@ static rarch_setting_t *menu_setting_new_internal(rarch_setting_info_t *list_inf SETTINGS_LIST_MENU_SOUNDS, SETTINGS_LIST_PLAYLIST, SETTINGS_LIST_CHEEVOS, + SETTINGS_LIST_CHEEVOS_APPEARANCE, SETTINGS_LIST_CORE_UPDATER, SETTINGS_LIST_NETPLAY, SETTINGS_LIST_LAKKA_SERVICES, diff --git a/msg_hash.h b/msg_hash.h index 87bc79df61..3578a0a837 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1617,6 +1617,20 @@ enum msg_hash_enums MENU_LABEL(CHEEVOS_CHALLENGE_INDICATORS), MENU_LABEL(CHEEVOS_ENABLE), MENU_LABEL(CHEEVOS_DESCRIPTION), + + MENU_LABEL(CHEEVOS_APPEARANCE_SETTINGS), + MENU_LABEL(CHEEVOS_APPEARANCE_ANCHOR), + MENU_LABEL(CHEEVOS_APPEARANCE_PADDING_AUTO), + MENU_LABEL(CHEEVOS_APPEARANCE_PADDING_H), + MENU_LABEL(CHEEVOS_APPEARANCE_PADDING_V), + + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_TOPLEFT, + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_TOPCENTER, + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_TOPRIGHT, + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_BOTTOMLEFT, + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_BOTTOMCENTER, + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_ANCHOR_BOTTOMRIGHT, + MENU_LABEL(ACCOUNTS_RETRO_ACHIEVEMENTS), MENU_LABEL(ACCOUNTS_TWITCH), MENU_LABEL(ACCOUNTS_YOUTUBE), @@ -1771,6 +1785,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_DEFERRED_MENU_SOUNDS_LIST, MENU_ENUM_LABEL_DEFERRED_MENU_FILE_BROWSER_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_RETRO_ACHIEVEMENTS_SETTINGS_LIST, + MENU_ENUM_LABEL_DEFERRED_CHEEVOS_APPEARANCE_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_UPDATER_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_BLUETOOTH_SETTINGS_LIST, MENU_ENUM_LABEL_DEFERRED_WIFI_SETTINGS_LIST, diff --git a/ui/drivers/qt/qt_options.cpp b/ui/drivers/qt/qt_options.cpp index 9f84e66722..37b12bb068 100644 --- a/ui/drivers/qt/qt_options.cpp +++ b/ui/drivers/qt/qt_options.cpp @@ -48,29 +48,52 @@ AchievementsPage::AchievementsPage(QObject *parent) : QWidget *AchievementsPage::widget() { unsigned i; - QWidget *widget = new QWidget; - QVBoxLayout *layout = new QVBoxLayout; - enum msg_hash_enums check_setting = MENU_ENUM_LABEL_CHEEVOS_ENABLE; - CheckableSettingsGroup *group = new CheckableSettingsGroup(check_setting); - settings_t *settings = config_get_ptr(); - file_list_t *list = (file_list_t*)calloc(1, sizeof(*list)); - menu_displaylist_build_list(list, settings, - DISPLAYLIST_RETRO_ACHIEVEMENTS_SETTINGS_LIST, true); + QWidget *widget = new QWidget; + QVBoxLayout *layout = new QVBoxLayout; + settings_t* settings = config_get_ptr(); + CheckBox *enabledCheckBox = new CheckBox(MENU_ENUM_LABEL_CHEEVOS_ENABLE); + file_list_t *generalList = (file_list_t*)calloc(1, sizeof(*generalList)); + file_list_t *appearanceList = (file_list_t*)calloc(1, sizeof(*appearanceList)); - for (i = 0; i < list->size; i++) + m_generalGroup = new SettingsGroup("General"); + m_appearanceGroup = new SettingsGroup(msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_CHEEVOS_APPEARANCE_SETTINGS)); + + menu_displaylist_build_list(generalList, settings, + DISPLAYLIST_RETRO_ACHIEVEMENTS_SETTINGS_LIST, true); + + for (i = 0; i < generalList->size; i++) { menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*) - file_list_get_actiondata_at_offset(list, i); + file_list_get_actiondata_at_offset(generalList, i); - if (cbs->enum_idx == check_setting) + if (cbs->enum_idx == MENU_ENUM_LABEL_CHEEVOS_ENABLE) continue; - group->add(cbs->enum_idx); + m_generalGroup->add(cbs->enum_idx); } + file_list_free(generalList); - file_list_free(list); + menu_displaylist_build_list(appearanceList, settings, + DISPLAYLIST_CHEEVOS_APPEARANCE_SETTINGS_LIST, true); - layout->addWidget(group); + for (i = 0; i < appearanceList->size; i++) + { + menu_file_list_cbs_t* cbs = (menu_file_list_cbs_t*) + file_list_get_actiondata_at_offset(appearanceList, i); + + m_appearanceGroup->add(cbs->enum_idx); + } + file_list_free(appearanceList); + + connect(enabledCheckBox, SIGNAL(stateChanged(int)), + this, SLOT(onAchievementEnabledChanged(int))); + + onAchievementEnabledChanged(enabledCheckBox->checkState()); + + layout->addWidget(enabledCheckBox); + layout->addWidget(m_generalGroup); + layout->addWidget(m_appearanceGroup); layout->addStretch(); @@ -79,6 +102,12 @@ QWidget *AchievementsPage::widget() return widget; } +void AchievementsPage::onAchievementEnabledChanged(int state) +{ + m_generalGroup->setDisabled(state == Qt::Unchecked); + m_appearanceGroup->setDisabled(state == Qt::Unchecked); +} + AudioCategory::AudioCategory(QWidget *parent) : OptionsCategory(parent) { diff --git a/ui/drivers/qt/qt_options.h b/ui/drivers/qt/qt_options.h index e607974c27..6e6ecf5cbf 100644 --- a/ui/drivers/qt/qt_options.h +++ b/ui/drivers/qt/qt_options.h @@ -464,6 +464,11 @@ class AchievementsPage : public OptionsPage public: AchievementsPage(QObject *parent = nullptr); QWidget *widget(); +private slots: + void onAchievementEnabledChanged(int); +private: + SettingsGroup* m_generalGroup; + SettingsGroup* m_appearanceGroup; }; /************************************************************