Merge pull request #8657 from jdgleaver/rgui-particle-effects

(RGUI) Add 'particle effect' animation system
This commit is contained in:
Twinaphex 2019-04-29 23:07:38 +02:00 committed by GitHub
commit b0b4f859cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 677 additions and 140 deletions

View File

@ -398,7 +398,7 @@ static bool rgui_full_width_layout = true;
static unsigned rgui_aspect = RGUI_ASPECT_RATIO_4_3;
static unsigned rgui_aspect_lock = RGUI_ASPECT_RATIO_LOCK_NONE;
static bool rgui_shadows = false;
static bool rgui_snow = false;
static unsigned rgui_particle_effect = RGUI_PARTICLE_EFFECT_NONE;
static bool rgui_extended_ascii = false;
#else

View File

@ -1519,7 +1519,6 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("rgui_border_filler_thickness_enable", &settings->bools.menu_rgui_border_filler_thickness_enable, true, true, false);
SETTING_BOOL("rgui_border_filler_enable", &settings->bools.menu_rgui_border_filler_enable, true, true, false);
SETTING_BOOL("menu_rgui_shadows", &settings->bools.menu_rgui_shadows, true, rgui_shadows, false);
SETTING_BOOL("menu_rgui_snow", &settings->bools.menu_rgui_snow, true, rgui_snow, false);
SETTING_BOOL("menu_rgui_full_width_layout", &settings->bools.menu_rgui_full_width_layout, true, rgui_full_width_layout, false);
SETTING_BOOL("rgui_inline_thumbnails", &settings->bools.menu_rgui_inline_thumbnails, true, rgui_inline_thumbnails, false);
SETTING_BOOL("rgui_swap_thumbnails", &settings->bools.menu_rgui_swap_thumbnails, true, rgui_swap_thumbnails, false);
@ -1716,6 +1715,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
SETTING_UINT("rgui_internal_upscale_level", &settings->uints.menu_rgui_internal_upscale_level, true, rgui_internal_upscale_level, false);
SETTING_UINT("rgui_aspect_ratio", &settings->uints.menu_rgui_aspect_ratio, true, rgui_aspect, false);
SETTING_UINT("rgui_aspect_ratio_lock", &settings->uints.menu_rgui_aspect_ratio_lock, true, rgui_aspect_lock, false);
SETTING_UINT("rgui_particle_effect", &settings->uints.menu_rgui_particle_effect, true, rgui_particle_effect, false);
#endif
#ifdef HAVE_LIBNX
SETTING_UINT("split_joycon_p1", &settings->uints.input_split_joycon[0], true, 0, false);

View File

@ -173,7 +173,6 @@ typedef struct settings
bool menu_rgui_border_filler_enable;
bool menu_rgui_full_width_layout;
bool menu_rgui_shadows;
bool menu_rgui_snow;
bool menu_rgui_inline_thumbnails;
bool menu_rgui_swap_thumbnails;
bool menu_rgui_extended_ascii;
@ -455,6 +454,7 @@ typedef struct settings
unsigned menu_rgui_internal_upscale_level;
unsigned menu_rgui_aspect_ratio;
unsigned menu_rgui_aspect_ratio_lock;
unsigned menu_rgui_particle_effect;
unsigned menu_ticker_type;
unsigned playlist_show_inline_core_name;

View File

@ -1627,8 +1627,8 @@ MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_FULL_WIDTH_LAYOUT,
"menu_rgui_full_width_layout")
MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_SHADOWS,
"menu_rgui_shadows")
MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_SNOW,
"menu_rgui_snow")
MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT,
"rgui_particle_effect")
MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_EXTENDED_ASCII,
"rgui_extended_ascii")
MSG_HASH(MENU_ENUM_LABEL_CONTENT_SHOW_REWIND,

View File

@ -6959,13 +6959,37 @@ MSG_HASH(
"Enable drop shadows for menu text, borders and thumbnails. Has a modest performance impact."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_MENU_RGUI_SNOW,
"Snow"
MENU_ENUM_LABEL_VALUE_MENU_RGUI_PARTICLE_EFFECT,
"Background Animation"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_MENU_RGUI_SNOW,
"Enable snow, forces menu to update every frame"
MENU_ENUM_SUBLABEL_MENU_RGUI_PARTICLE_EFFECT,
"Enable background particle animation effect. Has a significant performance impact."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_NONE,
"OFF"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_SNOW,
"Snow (Light)"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_SNOW_ALT,
"Snow (Heavy)"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_RAIN,
"Rain"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_VORTEX,
"Vortex"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_STARFIELD,
"Star Field"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_MENU_RGUI_EXTENDED_ASCII,
"Extended ASCII Support"

View File

@ -535,7 +535,7 @@ default_sublabel_macro(action_bind_sublabel_menu_rgui_aspect_ratio_lock,
default_sublabel_macro(action_bind_sublabel_rgui_menu_color_theme, MENU_ENUM_SUBLABEL_RGUI_MENU_COLOR_THEME)
default_sublabel_macro(action_bind_sublabel_rgui_menu_theme_preset, MENU_ENUM_SUBLABEL_RGUI_MENU_THEME_PRESET)
default_sublabel_macro(action_bind_sublabel_menu_rgui_shadows, MENU_ENUM_SUBLABEL_MENU_RGUI_SHADOWS)
default_sublabel_macro(action_bind_sublabel_menu_rgui_snow, MENU_ENUM_SUBLABEL_MENU_RGUI_SNOW)
default_sublabel_macro(action_bind_sublabel_menu_rgui_particle_effect, MENU_ENUM_SUBLABEL_MENU_RGUI_PARTICLE_EFFECT)
default_sublabel_macro(action_bind_sublabel_menu_rgui_inline_thumbnails, MENU_ENUM_SUBLABEL_MENU_RGUI_INLINE_THUMBNAILS)
default_sublabel_macro(action_bind_sublabel_menu_rgui_swap_thumbnails, MENU_ENUM_SUBLABEL_MENU_RGUI_SWAP_THUMBNAILS)
default_sublabel_macro(action_bind_sublabel_menu_rgui_thumbnail_downscaler, MENU_ENUM_SUBLABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER)
@ -2452,8 +2452,8 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_MENU_RGUI_SHADOWS:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_shadows);
break;
case MENU_ENUM_LABEL_MENU_RGUI_SNOW:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_snow);
case MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_particle_effect);
break;
case MENU_ENUM_LABEL_MENU_RGUI_INLINE_THUMBNAILS:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_inline_thumbnails);

View File

@ -80,6 +80,12 @@
#define NUM_FONT_GLYPHS_REGULAR 128
#define NUM_FONT_GLYPHS_EXTENDED 256
#define NUM_PARTICLES 256
#ifndef PI
#define PI 3.14159265359f
#endif
typedef struct
{
unsigned start_x;
@ -101,6 +107,7 @@ typedef struct
uint32_t border_dark_color;
uint32_t border_light_color;
uint32_t shadow_color;
uint32_t particle_color;
} rgui_theme_t;
static const rgui_theme_t rgui_theme_classic_red = {
@ -111,7 +118,8 @@ static const rgui_theme_t rgui_theme_classic_red = {
0xC0404040, /* bg_light_color */
0xC08C0000, /* border_dark_color */
0xC0CC0E03, /* border_light_color */
0xC0000000 /* shadow_color */
0xC0000000, /* shadow_color */
0xC09E8686 /* particle_color */
};
static const rgui_theme_t rgui_theme_classic_orange = {
@ -122,7 +130,8 @@ static const rgui_theme_t rgui_theme_classic_orange = {
0xC0404040, /* bg_light_color */
0xC0962800, /* border_dark_color */
0xC0E46C03, /* border_light_color */
0xC0000000 /* shadow_color */
0xC0000000, /* shadow_color */
0xC09E9286 /* particle_color */
};
static const rgui_theme_t rgui_theme_classic_yellow = {
@ -133,7 +142,8 @@ static const rgui_theme_t rgui_theme_classic_yellow = {
0xC0404040, /* bg_light_color */
0xC0AC7800, /* border_dark_color */
0xC0F3C60D, /* border_light_color */
0xC0000000 /* shadow_color */
0xC0000000, /* shadow_color */
0xC0999581 /* particle_color */
};
static const rgui_theme_t rgui_theme_classic_green = {
@ -144,7 +154,8 @@ static const rgui_theme_t rgui_theme_classic_green = {
0xC0404040, /* bg_light_color */
0xC0204020, /* border_dark_color */
0xC0408040, /* border_light_color */
0xC0000000 /* shadow_color */
0xC0000000, /* shadow_color */
0xC0879E87 /* particle_color */
};
static const rgui_theme_t rgui_theme_classic_blue = {
@ -155,7 +166,8 @@ static const rgui_theme_t rgui_theme_classic_blue = {
0xC0404040, /* bg_light_color */
0xC0005BA6, /* border_dark_color */
0xC02E94E2, /* border_light_color */
0xC0000000 /* shadow_color */
0xC0000000, /* shadow_color */
0xC086949E /* particle_color */
};
static const rgui_theme_t rgui_theme_classic_violet = {
@ -166,7 +178,8 @@ static const rgui_theme_t rgui_theme_classic_violet = {
0xC0404040, /* bg_light_color */
0xC04C0A60, /* border_dark_color */
0xC0842DCE, /* border_light_color */
0xC0000000 /* shadow_color */
0xC0000000, /* shadow_color */
0xC08E8299 /* particle_color */
};
static const rgui_theme_t rgui_theme_classic_grey = {
@ -177,7 +190,8 @@ static const rgui_theme_t rgui_theme_classic_grey = {
0xC0404040, /* bg_light_color */
0xC0505050, /* border_dark_color */
0xC0798A99, /* border_light_color */
0xC0000000 /* shadow_color */
0xC0000000, /* shadow_color */
0xC078828A /* particle_color */
};
static const rgui_theme_t rgui_theme_legacy_red = {
@ -188,7 +202,8 @@ static const rgui_theme_t rgui_theme_legacy_red = {
0xC0B34B41, /* bg_light_color */
0xC0BF5E58, /* border_dark_color */
0xC0F27A6F, /* border_light_color */
0xC01F0C0A /* shadow_color */
0xC01F0C0A, /* shadow_color */
0xC0F75431 /* particle_color */
};
static const rgui_theme_t rgui_theme_dark_purple = {
@ -199,7 +214,8 @@ static const rgui_theme_t rgui_theme_dark_purple = {
0xC0663A66, /* bg_light_color */
0xC0885783, /* border_dark_color */
0xC0A675A1, /* border_light_color */
0xC0140A14 /* shadow_color */
0xC0140A14, /* shadow_color */
0xC09786A0 /* particle_color */
};
static const rgui_theme_t rgui_theme_midnight_blue = {
@ -210,7 +226,8 @@ static const rgui_theme_t rgui_theme_midnight_blue = {
0xC03C4D5E, /* bg_light_color */
0xC046586A, /* border_dark_color */
0xC06D7F91, /* border_light_color */
0xC00A0F14 /* shadow_color */
0xC00A0F14, /* shadow_color */
0xC084849E /* particle_color */
};
static const rgui_theme_t rgui_theme_golden = {
@ -219,9 +236,10 @@ static const rgui_theme_t rgui_theme_golden = {
0xFFFFCC00, /* title_color */
0xC0B88D0B, /* bg_dark_color */
0xC0BF962B, /* bg_light_color */
0xC0e1ad21, /* border_dark_color */
0xC0E1AD21, /* border_dark_color */
0xC0FCC717, /* border_light_color */
0xC0382B03 /* shadow_color */
0xC0382B03, /* shadow_color */
0xC0F7D15E /* particle_color */
};
static const rgui_theme_t rgui_theme_electric_blue = {
@ -232,7 +250,8 @@ static const rgui_theme_t rgui_theme_electric_blue = {
0xC0007FFF, /* bg_light_color */
0xC034A5D8, /* border_dark_color */
0xC070C9FF, /* border_light_color */
0xC012294D /* shadow_color */
0xC012294D, /* shadow_color */
0xC080C7E6 /* particle_color */
};
static const rgui_theme_t rgui_theme_apple_green = {
@ -243,7 +262,8 @@ static const rgui_theme_t rgui_theme_apple_green = {
0xC0688539, /* bg_light_color */
0xC0608E3A, /* border_dark_color */
0xC09AB973, /* border_light_color */
0xC01F2E19 /* shadow_color */
0xC01F2E19, /* shadow_color */
0xC0A3C44E /* particle_color */
};
static const rgui_theme_t rgui_theme_volcanic_red = {
@ -254,7 +274,8 @@ static const rgui_theme_t rgui_theme_volcanic_red = {
0xC0BD0F1E, /* bg_light_color */
0xC0CE2029, /* border_dark_color */
0xC0FF0000, /* border_light_color */
0xC0330D0D /* shadow_color */
0xC0330D0D, /* shadow_color */
0xC0E67D45 /* particle_color */
};
static const rgui_theme_t rgui_theme_lagoon = {
@ -265,7 +286,8 @@ static const rgui_theme_t rgui_theme_lagoon = {
0xC0526778, /* bg_light_color */
0xC058848F, /* border_dark_color */
0xC060909C, /* border_light_color */
0xC01C2329 /* shadow_color */
0xC01C2329, /* shadow_color */
0xC09FB1C7 /* particle_color */
};
static const rgui_theme_t rgui_theme_brogrammer = {
@ -276,7 +298,8 @@ static const rgui_theme_t rgui_theme_brogrammer = {
0xC0242424, /* bg_light_color */
0xC0E74C3C, /* border_dark_color */
0xC0E74C3C, /* border_light_color */
0xC0000000 /* shadow_color */
0xC0000000, /* shadow_color */
0xC0606060 /* particle_color */
};
static const rgui_theme_t rgui_theme_dracula = {
@ -287,7 +310,8 @@ static const rgui_theme_t rgui_theme_dracula = {
0xC02F3240, /* bg_light_color */
0xC06272A4, /* border_dark_color */
0xC06272A4, /* border_light_color */
0xC00F0F0F /* shadow_color */
0xC00F0F0F, /* shadow_color */
0xC06272A4 /* particle_color */
};
static const rgui_theme_t rgui_theme_fairyfloss = {
@ -298,7 +322,8 @@ static const rgui_theme_t rgui_theme_fairyfloss = {
0xC0675F87, /* bg_light_color */
0xC08077A8, /* border_dark_color */
0xC08077A8, /* border_light_color */
0xC0262433 /* shadow_color */
0xC0262433, /* shadow_color */
0xC0C5A3FF /* particle_color */
};
static const rgui_theme_t rgui_theme_flatui = {
@ -309,7 +334,8 @@ static const rgui_theme_t rgui_theme_flatui = {
0xE0ECF0F1, /* bg_light_color */
0xE095A5A6, /* border_dark_color */
0xE095A5A6, /* border_light_color */
0xE0C3DBDE /* shadow_color */
0xE0C3DBDE, /* shadow_color */
0xE0B3DFFF /* particle_color */
};
static const rgui_theme_t rgui_theme_gruvbox_dark = {
@ -320,7 +346,8 @@ static const rgui_theme_t rgui_theme_gruvbox_dark = {
0xC03D3D3D, /* bg_light_color */
0xC099897A, /* border_dark_color */
0xC099897A, /* border_light_color */
0xC0000000 /* shadow_color */
0xC0000000, /* shadow_color */
0xC098971A /* particle_color */
};
static const rgui_theme_t rgui_theme_gruvbox_light = {
@ -331,7 +358,8 @@ static const rgui_theme_t rgui_theme_gruvbox_light = {
0xE0FBEBC7, /* bg_light_color */
0xE0928374, /* border_dark_color */
0xE0928374, /* border_light_color */
0xE0D5C4A1 /* shadow_color */
0xE0D5C4A1, /* shadow_color */
0xE0D5C4A1 /* particle_color */
};
static const rgui_theme_t rgui_theme_hacking_the_kernel = {
@ -342,7 +370,8 @@ static const rgui_theme_t rgui_theme_hacking_the_kernel = {
0xC0000000, /* bg_light_color */
0xC0036303, /* border_dark_color */
0xC0036303, /* border_light_color */
0xC0154D2B /* shadow_color */
0xC0154D2B, /* shadow_color */
0xC0008C00 /* particle_color */
};
static const rgui_theme_t rgui_theme_nord = {
@ -353,7 +382,8 @@ static const rgui_theme_t rgui_theme_nord = {
0xC0363C4F, /* bg_light_color */
0xC04E596E, /* border_dark_color */
0xC04E596E, /* border_light_color */
0xC0040505 /* shadow_color */
0xC0040505, /* shadow_color */
0xC05E81AC /* particle_color */
};
static const rgui_theme_t rgui_theme_nova = {
@ -364,7 +394,8 @@ static const rgui_theme_t rgui_theme_nova = {
0xC0485B66, /* bg_light_color */
0xC0627985, /* border_dark_color */
0xC0627985, /* border_light_color */
0xC01E272C /* shadow_color */
0xC01E272C, /* shadow_color */
0xC0889BA7 /* particle_color */
};
static const rgui_theme_t rgui_theme_one_dark = {
@ -375,7 +406,8 @@ static const rgui_theme_t rgui_theme_one_dark = {
0xC02D323B, /* bg_light_color */
0xC0495162, /* border_dark_color */
0xC0495162, /* border_light_color */
0xC007080A /* shadow_color */
0xC007080A, /* shadow_color */
0xC05F697A /* particle_color */
};
static const rgui_theme_t rgui_theme_palenight = {
@ -386,7 +418,8 @@ static const rgui_theme_t rgui_theme_palenight = {
0xC02F3347, /* bg_light_color */
0xC0697098, /* border_dark_color */
0xC0697098, /* border_light_color */
0xC00D0E14 /* shadow_color */
0xC00D0E14, /* shadow_color */
0xC0697098 /* particle_color */
};
static const rgui_theme_t rgui_theme_solarized_dark = {
@ -397,7 +430,8 @@ static const rgui_theme_t rgui_theme_solarized_dark = {
0xC0003542, /* bg_light_color */
0xC093A1A1, /* border_dark_color */
0xC093A1A1, /* border_light_color */
0xC000141A /* shadow_color */
0xC000141A, /* shadow_color */
0xC0586E75 /* particle_color */
};
static const rgui_theme_t rgui_theme_solarized_light = {
@ -408,7 +442,8 @@ static const rgui_theme_t rgui_theme_solarized_light = {
0xE0FDEDDF, /* bg_light_color */
0xE093A1A1, /* border_dark_color */
0xE093A1A1, /* border_light_color */
0xE0E0DBC9 /* shadow_color */
0xE0E0DBC9, /* shadow_color */
0xE0FFC5AD /* particle_color */
};
static const rgui_theme_t rgui_theme_tango_dark = {
@ -419,7 +454,8 @@ static const rgui_theme_t rgui_theme_tango_dark = {
0xC0384042, /* bg_light_color */
0xC06A767A, /* border_dark_color */
0xC06A767A, /* border_light_color */
0xC01A1A1A /* shadow_color */
0xC01A1A1A, /* shadow_color */
0xC0C4A000 /* particle_color */
};
static const rgui_theme_t rgui_theme_tango_light = {
@ -430,7 +466,8 @@ static const rgui_theme_t rgui_theme_tango_light = {
0xE0EEEEEC, /* bg_light_color */
0xE0C7C7C7, /* border_dark_color */
0xE0C7C7C7, /* border_light_color */
0xE0D3D7CF /* shadow_color */
0xE0D3D7CF, /* shadow_color */
0xE0FFCA78 /* particle_color */
};
static const rgui_theme_t rgui_theme_zenburn = {
@ -441,7 +478,8 @@ static const rgui_theme_t rgui_theme_zenburn = {
0xC04F4F4F, /* bg_light_color */
0xC0636363, /* border_dark_color */
0xC0636363, /* border_light_color */
0xC01F1F1F /* shadow_color */
0xC01F1F1F, /* shadow_color */
0xC0AC7373 /* particle_color */
};
static const rgui_theme_t rgui_theme_anti_zenburn = {
@ -452,7 +490,8 @@ static const rgui_theme_t rgui_theme_anti_zenburn = {
0xE0C0C0C0, /* bg_light_color */
0xE0A0A0A0, /* border_dark_color */
0xE0A0A0A0, /* border_light_color */
0xE0B0B0B0 /* shadow_color */
0xE0B0B0B0, /* shadow_color */
0xE0B090B0 /* particle_color */
};
typedef struct
@ -465,6 +504,7 @@ typedef struct
uint16_t border_dark_color;
uint16_t border_light_color;
uint16_t shadow_color;
uint16_t particle_color;
} rgui_colors_t;
typedef struct
@ -484,7 +524,7 @@ typedef struct
bool border_thickness;
bool border_enable;
bool shadow_enable;
bool snow_enable;
unsigned particle_effect;
bool extended_ascii_enable;
float scroll_y;
char *msgbox;
@ -519,7 +559,24 @@ static unsigned mini_thumbnail_max_height = 0;
static bool font_lut[NUM_FONT_GLYPHS_EXTENDED][FONT_WIDTH * FONT_HEIGHT];
float snowflakes[1024];
/* A 'particle' is just 4 float variables that can
* be used for any purpose - e.g.:
* > a = x pos
* > b = y pos
* > c = x velocity
* or:
* > a = radius
* > b = theta
* etc. */
typedef struct
{
float a;
float b;
float c;
float d;
} rgui_particle_t;
static rgui_particle_t particles[NUM_PARTICLES] = {{ 0.0f }};
/* ==============================
* Custom Symbols (glyphs) START
@ -835,6 +892,420 @@ static void rgui_color_rect(
data[j * (pitch >> 1) + i] = color;
}
static void rgui_render_border(rgui_t *rgui, uint16_t *data,
size_t fb_pitch, unsigned fb_width, unsigned fb_height)
{
/* Sanity check */
if (!rgui || !data)
return;
/* Draw border */
rgui_fill_rect(rgui, data, fb_pitch, 5, 5, fb_width - 10, 5, rgui_border_filler);
rgui_fill_rect(rgui, data, fb_pitch, 5, fb_height - 10, fb_width - 10, 5, rgui_border_filler);
rgui_fill_rect(rgui, data, fb_pitch, 5, 5, 5, fb_height - 10, rgui_border_filler);
rgui_fill_rect(rgui, data, fb_pitch, fb_width - 10, 5, 5, fb_height - 10, rgui_border_filler);
/* Draw drop shadow, if required */
if (rgui->shadow_enable)
{
rgui_color_rect(data, fb_pitch, fb_width, fb_height,
10, 10, 1, fb_height - 20, rgui->colors.shadow_color);
rgui_color_rect(data, fb_pitch, fb_width, fb_height,
10, 10, fb_width - 20, 1, rgui->colors.shadow_color);
rgui_color_rect(data, fb_pitch, fb_width, fb_height,
fb_width - 5, 6, 1, fb_height - 10, rgui->colors.shadow_color);
rgui_color_rect(data, fb_pitch, fb_width, fb_height,
6, fb_height - 5, fb_width - 10, 1, rgui->colors.shadow_color);
}
}
/* Returns true if particle is on screen */
static bool INLINE rgui_draw_particle(
uint16_t *data,
unsigned fb_width, unsigned fb_height,
int x, int y,
unsigned width, unsigned height,
uint16_t color)
{
unsigned x_index, y_index;
/* This great convoluted mess just saves us
* having to perform comparisons on every
* iteration of the for loops... */
int x_start = x > 0 ? x : 0;
int y_start = y > 0 ? y : 0;
int x_end = x + width;
int y_end = y + height;
x_start = x_start <= fb_width ? x_start : fb_width;
y_start = y_start <= fb_height ? y_start : fb_height;
x_end = x_end > 0 ? x_end : 0;
x_end = x_end <= fb_width ? x_end : fb_width;
y_end = y_end > 0 ? y_end : 0;
y_end = y_end <= fb_height ? y_end : fb_height;
for (x_index = (unsigned)x_start; x_index < (unsigned)x_end; x_index++)
for (y_index = (unsigned)y_start; y_index < (unsigned)y_end; y_index++)
data[(y_index * fb_width) + x_index] = color;
return (x_end > x_start) && (y_end > y_start);
}
static void rgui_init_particle_effect(rgui_t *rgui)
{
size_t fb_pitch;
unsigned fb_width, fb_height;
size_t i;
/* Sanity check */
if (!rgui)
return;
menu_display_get_fb_size(&fb_width, &fb_height, &fb_pitch);
switch (rgui->particle_effect)
{
case RGUI_PARTICLE_EFFECT_SNOW:
case RGUI_PARTICLE_EFFECT_SNOW_ALT:
{
for (i = 0; i < NUM_PARTICLES; i++)
{
rgui_particle_t *particle = &particles[i];
particle->a = (float)(rand() % fb_width);
particle->b = (float)(rand() % fb_height);
particle->c = (float)(rand() % 64 - 16) * 0.1f;
particle->d = (float)(rand() % 64 - 48) * 0.1f;
}
}
break;
case RGUI_PARTICLE_EFFECT_RAIN:
{
uint8_t weights[] = { /* 60 entries */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6,
7, 7, 7, 7,
8, 8, 8,
9, 9,
10};
unsigned num_drops = (unsigned)(0.85f * ((float)fb_width / 426.0f) * (float)NUM_PARTICLES);
num_drops = num_drops < NUM_PARTICLES ? num_drops : NUM_PARTICLES;
for (i = 0; i < num_drops; i++)
{
rgui_particle_t *particle = &particles[i];
/* x pos */
particle->a = (float)(rand() % (fb_width / 3)) * 3.0f;
/* y pos */
particle->b = (float)(rand() % fb_height);
/* drop length */
particle->c = (float)weights[(unsigned)(rand() % 61)];
/* drop speed (larger drops fall faster) */
particle->d = (particle->c / 12.0f) * (0.5f + ((float)(rand() % 150) / 200.0f));
}
}
break;
case RGUI_PARTICLE_EFFECT_VORTEX:
{
float max_radius = (float)sqrt((double)((fb_width * fb_width) + (fb_height * fb_height))) / 2.0f;
float one_degree_radians = PI / 360.0f;
for (i = 0; i < NUM_PARTICLES; i++)
{
rgui_particle_t *particle = &particles[i];
/* radius */
particle->a = 1.0f + (((float)rand() / (float)RAND_MAX) * max_radius);
/* theta */
particle->b = ((float)rand() / (float)RAND_MAX) * 2.0f * PI;
/* radial speed */
particle->c = (float)((rand() % 100) + 1) * 0.001f;
/* rotational speed */
particle->d = (((float)((rand() % 50) + 1) / 200.0f) + 0.1f) * one_degree_radians;
}
}
break;
case RGUI_PARTICLE_EFFECT_STARFIELD:
{
float min_depth = (float)fb_width / 12.0f;
for (i = 0; i < NUM_PARTICLES; i++)
{
rgui_particle_t *particle = &particles[i];
/* x pos */
particle->a = (float)(rand() % fb_width);
/* y pos */
particle->b = (float)(rand() % fb_height);
/* depth */
particle->c = (float)fb_width;
/* speed */
particle->d = 1.0f + ((float)(rand() % 20) * 0.01f);
}
}
break;
default:
/* Do nothing... */
break;
}
}
static void rgui_render_particle_effect(rgui_t *rgui)
{
size_t fb_pitch;
unsigned fb_width, fb_height;
size_t i;
/* Sanity check */
if (!rgui || !rgui_frame_buf.data)
return;
menu_display_get_fb_size(&fb_width, &fb_height, &fb_pitch);
/* Note: It would be more elegant to have 'update' and 'draw'
* as separate functions, since 'update' is the part that
* varies with particle effect whereas 'draw' is always
* pretty much the same. However, this has the following
* disadvantages:
* - It means we have to loop through all particles twice,
* and given that we're already using a heap of CPU cycles
* to draw these effects any further performance overheads
* are to be avoided
* - It locks us into a particular draw style. e.g. What if
* an effect calls for round particles, instead of square
* ones? This would make a mess of any 'standardised'
* drawing
* So we go with the simple option of having the entire
* update/draw sequence here. This results in some code
* repetition, but it has better performance and allows for
* complete flexibility */
switch (rgui->particle_effect)
{
case RGUI_PARTICLE_EFFECT_SNOW:
case RGUI_PARTICLE_EFFECT_SNOW_ALT:
{
unsigned particle_size;
bool on_screen;
for (i = 0; i < NUM_PARTICLES; i++)
{
rgui_particle_t *particle = &particles[i];
/* Update particle 'speed' */
particle->c = particle->c + (float)(rand() % 16 - 9) * 0.01f;
particle->d = particle->d + (float)(rand() % 16 - 7) * 0.01f;
particle->c = (particle->c < -0.4f) ? -0.4f : particle->c;
particle->c = (particle->c > 0.1f) ? 0.1f : particle->c;
particle->d = (particle->d < -0.1f) ? -0.1f : particle->d;
particle->d = (particle->d > 0.4f) ? 0.4f : particle->d;
/* Update particle location */
particle->a = fmod(particle->a + particle->c, fb_width);
particle->b = fmod(particle->b + particle->d, fb_height);
/* Get particle size */
particle_size = 1;
if (rgui->particle_effect == RGUI_PARTICLE_EFFECT_SNOW_ALT)
{
/* Gives the following distribution:
* 1x1: 32
* 2x2: 128
* 3x3: 32 */
if (!(i & 0x2))
particle_size = 2;
else if ((i & 0x7) == 0x7)
particle_size = 3;
}
/* Draw particle */
on_screen = rgui_draw_particle(rgui_frame_buf.data, fb_width, fb_height,
(int)particle->a, (int)particle->b,
particle_size, particle_size, rgui->colors.particle_color);
/* Reset particle if it has fallen off screen */
if (!on_screen)
{
particle->a = (particle->a < 0.0f) ? (particle->a + (float)fb_width) : particle->a;
particle->b = (particle->b < 0.0f) ? (particle->b + (float)fb_height) : particle->b;
}
}
}
break;
case RGUI_PARTICLE_EFFECT_RAIN:
{
uint8_t weights[] = { /* 60 entries */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6,
7, 7, 7, 7,
8, 8, 8,
9, 9,
10};
unsigned num_drops = (unsigned)(0.85f * ((float)fb_width / 426.0f) * (float)NUM_PARTICLES);
bool on_screen;
num_drops = num_drops < NUM_PARTICLES ? num_drops : NUM_PARTICLES;
for (i = 0; i < num_drops; i++)
{
rgui_particle_t *particle = &particles[i];
/* Draw particle */
on_screen = rgui_draw_particle(rgui_frame_buf.data, fb_width, fb_height,
(int)particle->a, (int)particle->b,
2, (unsigned)particle->c, rgui->colors.particle_color);
/* Update y pos */
particle->b += particle->d;
/* Reset particle if it has fallen off the bottom of the screen */
if (!on_screen)
{
/* x pos */
particle->a = (float)(rand() % (fb_width / 3)) * 3.0f;
/* y pos */
particle->b = 0.0f;
/* drop length */
particle->c = (float)weights[(unsigned)(rand() % 61)];
/* drop speed (larger drops fall faster) */
particle->d = (particle->c / 12.0f) * (0.5f + ((float)(rand() % 150) / 200.0f));
}
}
}
break;
case RGUI_PARTICLE_EFFECT_VORTEX:
{
float max_radius = (float)sqrt((double)((fb_width * fb_width) + (fb_height * fb_height))) / 2.0f;
float one_degree_radians = PI / 360.0f;
int x_centre = (int)(fb_width >> 1);
int y_centre = (int)(fb_height >> 1);
unsigned particle_size;
float r_speed, theta_speed;
int x, y;
for (i = 0; i < NUM_PARTICLES; i++)
{
rgui_particle_t *particle = &particles[i];
/* Get particle location */
x = (int)(particle->a * cos(particle->b)) + x_centre;
y = (int)(particle->a * sin(particle->b)) + y_centre;
/* Get particle size */
particle_size = 1 + (unsigned)(((1.0f - ((max_radius - particle->a) / max_radius)) * 3.5f) + 0.5f);
/* Draw particle */
rgui_draw_particle(rgui_frame_buf.data, fb_width, fb_height,
x, y, particle_size, particle_size, rgui->colors.particle_color);
/* Update particle speed */
r_speed = particle->c;
theta_speed = particle->d;
if ((particle->a > 0.0f) && (particle->a < (float)fb_height))
{
float base_scale_factor = ((float)fb_height - particle->a) / (float)fb_height;
r_speed *= 1.0f + (base_scale_factor * 8.0f);
theta_speed *= 1.0f + (base_scale_factor * base_scale_factor * 6.0f);
}
particle->a -= r_speed;
particle->b += theta_speed;
/* Reset particle if it has reached the centre of the screen */
if (particle->a < 0.0f)
{
/* radius
* Note: In theory, this should be:
* > particle->a = max_radius;
* ...but it turns out that spawning new particles at random
* locations produces a more visually appealing result... */
particle->a = 1.0f + (((float)rand() / (float)RAND_MAX) * max_radius);
/* theta */
particle->b = ((float)rand() / (float)RAND_MAX) * 2.0f * PI;
/* radial speed */
particle->c = (float)((rand() % 100) + 1) * 0.001f;
/* rotational speed */
particle->d = (((float)((rand() % 50) + 1) / 200.0f) + 0.1f) * one_degree_radians;
}
}
}
break;
case RGUI_PARTICLE_EFFECT_STARFIELD:
{
float focal_length = (float)fb_width * 2.0f;
int x_centre = (int)(fb_width >> 1);
int y_centre = (int)(fb_height >> 1);
unsigned particle_size;
int x, y;
bool on_screen;
/* Based on an example found here:
* https://codepen.io/nodws/pen/pejBNb */
for (i = 0; i < NUM_PARTICLES; i++)
{
rgui_particle_t *particle = &particles[i];
/* Get particle location */
x = (int)((particle->a - (float)x_centre) * (focal_length / particle->c));
x += x_centre;
y = (int)((particle->b - (float)y_centre) * (focal_length / particle->c));
y += y_centre;
/* Get particle size */
particle_size = (unsigned)(focal_length / (2.0f * particle->c));
/* Draw particle */
on_screen = rgui_draw_particle(rgui_frame_buf.data, fb_width, fb_height,
x, y, particle_size, particle_size, rgui->colors.particle_color);
/* Update depth */
particle->c -= particle->d;
/* Reset particle if it has:
* - Dropped off the edge of the screen
* - Reached the screen depth
* - Grown larger than 16 pixels across
* (this is an arbitrary limit, set to reduce overall
* performance impact - i.e. larger particles are slower
* to draw, and without setting a limit they can fill the screen...) */
if (!on_screen || (particle->c <= 0.0f) || particle_size > 16)
{
/* x pos */
particle->a = (float)(rand() % fb_width);
/* y pos */
particle->b = (float)(rand() % fb_height);
/* depth */
particle->c = (float)fb_width;
/* speed */
particle->d = 1.0f + ((float)(rand() % 20) * 0.01f);
}
}
}
break;
default:
/* Do nothing... */
break;
}
/* If border is enabled, it must be drawn *above*
* particle effect
* (Wastes CPU cycles, but nothing we can do about it...) */
if (rgui->border_enable && !rgui->show_wallpaper)
rgui_render_border(rgui, rgui_frame_buf.data, fb_pitch, fb_width, fb_height);
}
static void request_wallpaper(const char *path)
{
/* Ensure that path is valid... */
@ -1385,7 +1856,7 @@ static void load_custom_theme(rgui_t *rgui, rgui_theme_t *theme_colors, const ch
unsigned normal_color, hover_color, title_color,
bg_dark_color, bg_light_color,
border_dark_color, border_light_color,
shadow_color;
shadow_color, particle_color;
char wallpaper_file[PATH_MAX_LENGTH];
config_file_t *conf = NULL;
char *wallpaper_key = NULL;
@ -1450,6 +1921,12 @@ static void load_custom_theme(rgui_t *rgui, rgui_theme_t *theme_colors, const ch
if(!config_get_hex(conf, "rgui_shadow_color", &shadow_color))
shadow_color = 0xFF000000;
/* Make particle colour optional too (fallback to normal
* rgb with bg_light alpha) */
if(!config_get_hex(conf, "rgui_particle_color", &particle_color))
particle_color = (normal_color & 0x00FFFFFF) |
(bg_light_color & 0xFF000000);
config_get_array(conf, wallpaper_key,
wallpaper_file, sizeof(wallpaper_file));
@ -1467,6 +1944,7 @@ end:
theme_colors->border_dark_color = (uint32_t)border_dark_color;
theme_colors->border_light_color = (uint32_t)border_light_color;
theme_colors->shadow_color = (uint32_t)shadow_color;
theme_colors->particle_color = (uint32_t)particle_color;
/* Load wallpaper, if required */
if (!string_is_empty(wallpaper_file))
@ -1489,6 +1967,7 @@ end:
theme_colors->border_dark_color = rgui_theme_classic_green.border_dark_color;
theme_colors->border_light_color = rgui_theme_classic_green.border_light_color;
theme_colors->shadow_color = rgui_theme_classic_green.shadow_color;
theme_colors->particle_color = rgui_theme_classic_green.particle_color;
}
if (conf)
@ -1536,35 +2015,7 @@ static void rgui_cache_background(rgui_t *rgui)
}
if (rgui->border_enable)
{
/* Draw border */
rgui_fill_rect(rgui, rgui_background_buf.data, fb_pitch, 5, 5, fb_width - 10, 5, rgui_border_filler);
rgui_fill_rect(rgui, rgui_background_buf.data, fb_pitch, 5, fb_height - 10, fb_width - 10, 5, rgui_border_filler);
rgui_fill_rect(rgui, rgui_background_buf.data, fb_pitch, 5, 5, 5, fb_height - 10, rgui_border_filler);
rgui_fill_rect(rgui, rgui_background_buf.data, fb_pitch, fb_width - 10, 5, 5, fb_height - 10, rgui_border_filler);
/* Draw drop shadow, if required */
if (rgui->shadow_enable)
{
rgui_color_rect(rgui_background_buf.data, fb_pitch, fb_width, fb_height,
10, 10, 1, fb_height - 20, rgui->colors.shadow_color);
rgui_color_rect(rgui_background_buf.data, fb_pitch, fb_width, fb_height,
10, 10, fb_width - 20, 1, rgui->colors.shadow_color);
rgui_color_rect(rgui_background_buf.data, fb_pitch, fb_width, fb_height,
fb_width - 5, 6, 1, fb_height - 10, rgui->colors.shadow_color);
rgui_color_rect(rgui_background_buf.data, fb_pitch, fb_width, fb_height,
6, fb_height - 5, fb_width - 10, 1, rgui->colors.shadow_color);
}
}
if (rgui->snow_enable) {
size_t i = 0;
for (i = 0; i < 1024; i += 4) {
snowflakes[i ] = rand()%fb_width;
snowflakes[i + 1] = rand()%fb_height;
snowflakes[i + 2] = (rand()%64 - 16)*.1;
snowflakes[i + 3] = (rand()%64 - 48)*.1;
}
}
rgui_render_border(rgui, rgui_background_buf.data, fb_pitch, fb_width, fb_height);
}
static void prepare_rgui_colors(rgui_t *rgui, settings_t *settings)
@ -1590,6 +2041,7 @@ static void prepare_rgui_colors(rgui_t *rgui, settings_t *settings)
theme_colors.border_dark_color = current_theme->border_dark_color;
theme_colors.border_light_color = current_theme->border_light_color;
theme_colors.shadow_color = current_theme->shadow_color;
theme_colors.particle_color = current_theme->particle_color;
}
rgui->colors.hover_color = argb32_to_pixel_platform_format(theme_colors.hover_color);
rgui->colors.normal_color = argb32_to_pixel_platform_format(theme_colors.normal_color);
@ -1599,6 +2051,7 @@ static void prepare_rgui_colors(rgui_t *rgui, settings_t *settings)
rgui->colors.border_dark_color = argb32_to_pixel_platform_format(theme_colors.border_dark_color);
rgui->colors.border_light_color = argb32_to_pixel_platform_format(theme_colors.border_light_color);
rgui->colors.shadow_color = argb32_to_pixel_platform_format(theme_colors.shadow_color);
rgui->colors.particle_color = argb32_to_pixel_platform_format(theme_colors.particle_color);
rgui->bg_modified = true;
rgui->force_redraw = true;
@ -2006,8 +2459,10 @@ static void rgui_render_messagebox(rgui_t *rgui, const char *message)
{
rgui_fill_rect(rgui, rgui_frame_buf.data, fb_pitch, x + 5, y + 5, width - 10, height - 10, rgui_bg_filler);
if (rgui->border_enable)
{
/* Note: We draw borders around message boxes regardless
* of the rgui->border_enable setting, because they look
* ridiculous without... */
/* Draw drop shadow, if required */
if (rgui->shadow_enable)
{
@ -2027,20 +2482,6 @@ static void rgui_render_messagebox(rgui_t *rgui, const char *message)
rgui_fill_rect(rgui, rgui_frame_buf.data, fb_pitch, x + 5, y + height - 5, width - 5, 5, rgui_border_filler);
rgui_fill_rect(rgui, rgui_frame_buf.data, fb_pitch, x, y + 5, 5, height - 5, rgui_border_filler);
}
else if (rgui->shadow_enable)
{
/* Without a border, this is a bit silly...
* All we can do is draw a sort of frame... */
rgui_color_rect(rgui_frame_buf.data, fb_pitch, fb_width, fb_height,
x + 4, y + 4, 1, height - 8, rgui->colors.shadow_color);
rgui_color_rect(rgui_frame_buf.data, fb_pitch, fb_width, fb_height,
x + 5, y + 4, width - 10, 1, rgui->colors.shadow_color);
rgui_color_rect(rgui_frame_buf.data, fb_pitch, fb_width, fb_height,
x + width - 5, y + 4, 1, height - 8, rgui->colors.shadow_color);
rgui_color_rect(rgui_frame_buf.data, fb_pitch, fb_width, fb_height,
x + 5, y + height - 5, width - 10, 1, rgui->colors.shadow_color);
}
}
for (i = 0; i < list->size; i++)
{
@ -2328,6 +2769,7 @@ static void rgui_render(void *data, bool is_idle)
int bottom;
size_t entries_end = 0;
bool msg_force = false;
bool fb_size_changed = false;
settings_t *settings = config_get_ptr();
rgui_t *rgui = (rgui_t*)data;
@ -2364,10 +2806,17 @@ static void rgui_render(void *data, bool is_idle)
menu_display_get_fb_size(&fb_width, &fb_height,
&fb_pitch);
/* if the framebuffer changed size, recache the background */
if (rgui->bg_modified || rgui->last_width != fb_width || rgui->last_height != fb_height)
/* If the framebuffer changed size, or the background config has
* changed, recache the background buffer */
fb_size_changed = (rgui->last_width != fb_width) || (rgui->last_height != fb_height);
if (rgui->bg_modified || fb_size_changed)
{
rgui_cache_background(rgui);
/* Reinitialise particle effect, if required */
if (fb_size_changed && (rgui->particle_effect != RGUI_PARTICLE_EFFECT_NONE))
rgui_init_particle_effect(rgui);
rgui->last_width = fb_width;
rgui->last_height = fb_height;
}
@ -2441,22 +2890,9 @@ static void rgui_render(void *data, bool is_idle)
/* Render background */
rgui_render_background();
/* Snow */
if (rgui->snow_enable && rgui_frame_buf.data) {
for (i = 0; i < 1024; i += 4) {
snowflakes[i + 2] = snowflakes[i + 2] + (rand()%16 - 9)*.01;
snowflakes[i + 3] = snowflakes[i + 3] + (rand()%16 - 7)*.01;
if (snowflakes[i + 2] < -0.4) snowflakes[i + 2] = -0.4;
if (snowflakes[i + 2] > 0.1) snowflakes[i + 2] = 0.1;
if (snowflakes[i + 3] < -0.1) snowflakes[i + 3] = -0.1;
if (snowflakes[i + 3] > 0.4) snowflakes[i + 3] = 0.4;
snowflakes[i ] = fmod(snowflakes[i ] + snowflakes[i + 2], fb_width);
snowflakes[i + 1] = fmod(snowflakes[i + 1] + snowflakes[i + 3], fb_height);
if (snowflakes[i ] < 0) snowflakes[i ] += fb_width;
if (snowflakes[i + 1] < 0) snowflakes[i + 1] += fb_height;
rgui_frame_buf.data[ (int) snowflakes[i+1] * (fb_pitch >> 1) + (int) snowflakes[i]] = rgui->colors.normal_color;
}
}
/* Render particle effect, if required */
if (rgui->particle_effect != RGUI_PARTICLE_EFFECT_NONE)
rgui_render_particle_effect(rgui);
/* We use a single ticker for all text animations,
* with the following configuration: */
@ -3172,12 +3608,16 @@ static void *rgui_init(void **userdata, bool video_is_threaded)
rgui->border_thickness = settings->bools.menu_rgui_border_filler_thickness_enable;
rgui->border_enable = settings->bools.menu_rgui_border_filler_enable;
rgui->shadow_enable = settings->bools.menu_rgui_shadows;
rgui->snow_enable = settings->bools.menu_rgui_snow;
rgui->particle_effect = settings->uints.menu_rgui_particle_effect;
rgui->extended_ascii_enable = settings->bools.menu_rgui_extended_ascii;
rgui->last_width = rgui_frame_buf.width;
rgui->last_height = rgui_frame_buf.height;
/* Initialise particle effect, if required */
if (rgui->particle_effect != RGUI_PARTICLE_EFFECT_NONE)
rgui_init_particle_effect(rgui);
/* Set initial 'blit_line/symbol' functions */
rgui_set_blit_functions(
settings->bools.menu_rgui_shadows, settings->bools.menu_rgui_extended_ascii);
@ -3667,8 +4107,6 @@ static void rgui_frame(void *data, video_frame_info_t *video_info)
{
rgui_t *rgui = (rgui_t*)data;
settings_t *settings = config_get_ptr();
if (rgui->snow_enable)
rgui->force_redraw = true;
if (settings->bools.menu_rgui_background_filler_thickness_enable != rgui->bg_thickness)
{
@ -3701,12 +4139,19 @@ static void rgui_frame(void *data, video_frame_info_t *video_info)
rgui->force_redraw = true;
}
if (settings->bools.menu_rgui_snow != rgui->snow_enable)
if (settings->uints.menu_rgui_particle_effect != rgui->particle_effect)
{
rgui->snow_enable = settings->bools.menu_rgui_snow;
rgui->bg_modified = true;
rgui->particle_effect = settings->uints.menu_rgui_particle_effect;
if (rgui->particle_effect != RGUI_PARTICLE_EFFECT_NONE)
rgui_init_particle_effect(rgui);
rgui->force_redraw = true;
}
if (rgui->particle_effect != RGUI_PARTICLE_EFFECT_NONE)
rgui->force_redraw = true;
if (settings->bools.menu_rgui_extended_ascii != rgui->extended_ascii_enable)
{
rgui_set_blit_functions(

View File

@ -267,6 +267,17 @@ enum rgui_aspect_ratio_lock
RGUI_ASPECT_RATIO_LOCK_LAST
};
enum rgui_particle_animation_effect
{
RGUI_PARTICLE_EFFECT_NONE = 0,
RGUI_PARTICLE_EFFECT_SNOW,
RGUI_PARTICLE_EFFECT_SNOW_ALT,
RGUI_PARTICLE_EFFECT_RAIN,
RGUI_PARTICLE_EFFECT_VORTEX,
RGUI_PARTICLE_EFFECT_STARFIELD,
RGUI_PARTICLE_EFFECT_LAST
};
enum menu_action
{
MENU_ACTION_NOOP = 0,

View File

@ -4306,7 +4306,7 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct
{MENU_ENUM_LABEL_RGUI_MENU_COLOR_THEME, PARSE_ONLY_UINT},
{MENU_ENUM_LABEL_RGUI_MENU_THEME_PRESET, PARSE_ONLY_PATH},
{MENU_ENUM_LABEL_MENU_RGUI_SHADOWS, PARSE_ONLY_BOOL},
{MENU_ENUM_LABEL_MENU_RGUI_SNOW, PARSE_ONLY_BOOL},
{MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT, PARSE_ONLY_UINT},
{MENU_ENUM_LABEL_DPI_OVERRIDE_ENABLE, PARSE_ONLY_BOOL},
{MENU_ENUM_LABEL_DPI_OVERRIDE_VALUE, PARSE_ONLY_UINT},
{MENU_ENUM_LABEL_XMB_ALPHA_FACTOR, PARSE_ONLY_UINT},

View File

@ -970,6 +970,54 @@ static void setting_get_string_representation_uint_rgui_aspect_ratio_lock(
}
}
static void setting_get_string_representation_uint_rgui_particle_effect(
rarch_setting_t *setting,
char *s, size_t len)
{
if (!setting)
return;
switch (*setting->value.target.unsigned_integer)
{
case RGUI_PARTICLE_EFFECT_NONE:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_NONE),
len);
break;
case RGUI_PARTICLE_EFFECT_SNOW:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_SNOW),
len);
break;
case RGUI_PARTICLE_EFFECT_SNOW_ALT:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_SNOW_ALT),
len);
break;
case RGUI_PARTICLE_EFFECT_RAIN:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_RAIN),
len);
break;
case RGUI_PARTICLE_EFFECT_VORTEX:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_VORTEX),
len);
break;
case RGUI_PARTICLE_EFFECT_STARFIELD:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_STARFIELD),
len);
break;
}
}
static void setting_get_string_representation_uint_menu_ticker_type(
rarch_setting_t *setting,
char *s, size_t len)
@ -8599,20 +8647,22 @@ static bool setting_append_list(
general_read_handler,
SD_FLAG_NONE);
CONFIG_BOOL(
CONFIG_UINT(
list, list_info,
&settings->bools.menu_rgui_snow,
MENU_ENUM_LABEL_MENU_RGUI_SNOW,
MENU_ENUM_LABEL_VALUE_MENU_RGUI_SNOW,
rgui_snow,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&settings->uints.menu_rgui_particle_effect,
MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT,
MENU_ENUM_LABEL_VALUE_MENU_RGUI_PARTICLE_EFFECT,
rgui_particle_effect,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE);
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_uint_rgui_particle_effect;
menu_settings_list_current_add_range(list, list_info, 0, RGUI_PARTICLE_EFFECT_LAST-1, 1, true, true);
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX;
CONFIG_BOOL(
list, list_info,

View File

@ -873,7 +873,7 @@ enum msg_hash_enums
MENU_LABEL(MENU_RGUI_ASPECT_RATIO_LOCK),
MENU_LABEL(MENU_RGUI_FULL_WIDTH_LAYOUT),
MENU_LABEL(MENU_RGUI_SHADOWS),
MENU_LABEL(MENU_RGUI_SNOW),
MENU_LABEL(MENU_RGUI_PARTICLE_EFFECT),
MENU_LABEL(MENU_RGUI_EXTENDED_ASCII),
MENU_LABEL(MENU_LINEAR_FILTER),
MENU_LABEL(MENU_HORIZONTAL_ANIMATION),
@ -2016,6 +2016,13 @@ enum msg_hash_enums
MENU_ENUM_LABEL_VALUE_RGUI_ASPECT_RATIO_LOCK_FIT_SCREEN,
MENU_ENUM_LABEL_VALUE_RGUI_ASPECT_RATIO_LOCK_INTEGER,
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_NONE,
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_SNOW,
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_SNOW_ALT,
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_RAIN,
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_VORTEX,
MENU_ENUM_LABEL_VALUE_RGUI_PARTICLE_EFFECT_STARFIELD,
/* Callback strings */
MENU_ENUM_LABEL_CB_CORE_CONTENT_DIRS_LIST,
MENU_ENUM_LABEL_CB_CORE_CONTENT_DOWNLOAD,