diff --git a/config.def.h b/config.def.h index 0797e7dd6e..c24f223e78 100644 --- a/config.def.h +++ b/config.def.h @@ -687,6 +687,10 @@ static const float message_bgcolor_opacity = 1.0f; /* Watch shader files for changes and auto-apply as necessary. */ #define DEFAULT_VIDEO_SHADER_WATCH_FILES false +/* Initialise file browser with last used directory + * when selecting shader presets/passes via the menu */ +#define DEFAULT_VIDEO_SHADER_REMEMBER_LAST_DIR false + /* Screenshots named automatically. */ #define DEFAULT_AUTO_SCREENSHOT_FILENAME true diff --git a/configuration.c b/configuration.c index 752d125b24..7e3f0a3b81 100644 --- a/configuration.c +++ b/configuration.c @@ -1449,6 +1449,7 @@ static struct config_bool_setting *populate_settings_bool( SETTING_BOOL("audio_sync", &settings->bools.audio_sync, true, DEFAULT_AUDIO_SYNC, false); SETTING_BOOL("video_shader_enable", &settings->bools.video_shader_enable, true, DEFAULT_SHADER_ENABLE, false); SETTING_BOOL("video_shader_watch_files", &settings->bools.video_shader_watch_files, true, DEFAULT_VIDEO_SHADER_WATCH_FILES, false); + SETTING_BOOL("video_shader_remember_last_dir", &settings->bools.video_shader_remember_last_dir, true, DEFAULT_VIDEO_SHADER_REMEMBER_LAST_DIR, false); /* Let implementation decide if automatic, or 1:1 PAR. */ SETTING_BOOL("video_aspect_ratio_auto", &settings->bools.video_aspect_ratio_auto, true, DEFAULT_ASPECT_RATIO_AUTO, false); diff --git a/configuration.h b/configuration.h index 94877a694f..fd1f12c67a 100644 --- a/configuration.h +++ b/configuration.h @@ -445,6 +445,7 @@ typedef struct settings bool video_scale_integer; bool video_shader_enable; bool video_shader_watch_files; + bool video_shader_remember_last_dir; bool video_threaded; bool video_font_enable; bool video_disable_composition; diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 9edf8d3b17..c9c091976d 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -2598,6 +2598,10 @@ MSG_HASH( MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES, "video_shader_watch_files" ) +MSG_HASH( + MENU_ENUM_LABEL_VIDEO_SHADER_REMEMBER_LAST_DIR, + "video_shader_remember_last_dir" + ) MSG_HASH( MENU_ENUM_LABEL_SHADER_OPTIONS, "shader_options" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index c41683987c..02256734b1 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -6407,6 +6407,14 @@ MSG_HASH( MENU_ENUM_SUBLABEL_SHADER_WATCH_FOR_CHANGES, "Automatically apply changes made to shader files on disk." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_REMEMBER_LAST_DIR, + "Remember Last Used Shader Directory" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_SHADER_REMEMBER_LAST_DIR, + "Open the file browser at the last used directory when loading shader presets and passes." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET, "Load Shader Preset" diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 88d64412c8..b76d3af226 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -454,15 +454,6 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl) return MSG_UNKNOWN; } -#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) -static const char *get_default_shader_dir(void) -{ - settings_t *settings = config_get_ptr(); - const char *def_shader_dir = settings->paths.directory_video_shader; - return def_shader_dir; -} -#endif - int generic_action_ok_displaylist_push(const char *path, const char *new_path, const char *label, unsigned type, size_t idx, size_t entry_idx, @@ -819,7 +810,7 @@ int generic_action_ok_displaylist_push(const char *path, filebrowser_clear_type(); info.type = type; info.directory_ptr = idx; - info_path = get_default_shader_dir(); + info_path = menu_driver_get_last_shader_pass_dir(); info_label = label; dl_type = DISPLAYLIST_FILE_BROWSER_SELECT_FILE; #endif @@ -829,7 +820,7 @@ int generic_action_ok_displaylist_push(const char *path, filebrowser_clear_type(); info.type = type; info.directory_ptr = idx; - info_path = get_default_shader_dir(); + info_path = menu_driver_get_last_shader_preset_dir(); info_label = label; dl_type = DISPLAYLIST_FILE_BROWSER_SELECT_FILE; #endif @@ -1727,8 +1718,12 @@ static int generic_action_ok(const char *path, { struct video_shader *shader = menu_shader_get(); flush_char = msg_hash_to_str(flush_id); + + /* Cache selected shader parent directory */ + menu_driver_set_last_shader_preset_dir(action_path); + menu_shader_manager_set_preset(shader, - video_shader_parse_type(action_path), + menu_driver_get_last_shader_preset_type(), action_path, true); } @@ -1743,6 +1738,9 @@ static int generic_action_ok(const char *path, if (shader_pass) { + /* Cache selected shader parent directory */ + menu_driver_set_last_shader_pass_dir(action_path); + strlcpy( shader_pass->source.path, action_path, diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index aae0f2fa60..b6735e313f 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -766,6 +766,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_recording_config_directory, DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_font_path, MENU_ENUM_SUBLABEL_VIDEO_FONT_PATH) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_shader_apply_changes, MENU_ENUM_SUBLABEL_SHADER_APPLY_CHANGES) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_shader_watch_for_changes, MENU_ENUM_SUBLABEL_SHADER_WATCH_FOR_CHANGES) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_shader_remember_last_dir, MENU_ENUM_SUBLABEL_VIDEO_SHADER_REMEMBER_LAST_DIR) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_shader_num_passes, MENU_ENUM_SUBLABEL_VIDEO_SHADER_NUM_PASSES) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_shader_preset, MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_shader_preset_save, MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE) @@ -1855,6 +1856,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_shader_watch_for_changes); break; + case MENU_ENUM_LABEL_VIDEO_SHADER_REMEMBER_LAST_DIR: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_shader_remember_last_dir); + break; case MENU_ENUM_LABEL_VIDEO_FONT_PATH: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_font_path); break; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 5599e4bcf3..1f43c202af 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -9787,6 +9787,14 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, 0, 0, 0)) count++; } + + if (menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_REMEMBER_LAST_DIR), + msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_REMEMBER_LAST_DIR), + MENU_ENUM_LABEL_VIDEO_SHADER_REMEMBER_LAST_DIR, + 0, 0, 0)) + count++; + if (menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET), diff --git a/menu/menu_driver.h b/menu/menu_driver.h index bac1781ed6..a4c8491e0f 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -329,6 +329,18 @@ typedef struct } scratchpad; unsigned rpl_entry_selection_ptr; + /* Used to cache the type and directory + * of the last shader preset/pass loaded + * via the menu file browser */ + struct + { + enum rarch_shader_type preset_type; + enum rarch_shader_type pass_type; + + char preset_dir[PATH_MAX_LENGTH]; + char pass_dir[PATH_MAX_LENGTH]; + } last_shader_selection; + char menu_state_msg[8192]; /* Scratchpad variables. These are used for instance * by the filebrowser when having to store intermediary @@ -500,6 +512,15 @@ struct string_list *menu_driver_search_get_terms(void); * search terms to specified string */ void menu_driver_search_append_terms_string(char *s, size_t len); +#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) +void menu_driver_set_last_shader_preset_dir(const char *shader_path); +void menu_driver_set_last_shader_pass_dir(const char *shader_pass_path); +enum rarch_shader_type menu_driver_get_last_shader_preset_type(void); +enum rarch_shader_type menu_driver_get_last_shader_pass_type(void); +const char *menu_driver_get_last_shader_preset_dir(void); +const char *menu_driver_get_last_shader_pass_dir(void); +#endif + menu_handle_t *menu_driver_get_ptr(void); enum action_iterate_type diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 91b42fdfca..a090b9aaca 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -10762,6 +10762,22 @@ static bool setting_append_list( SD_FLAG_NONE ); + CONFIG_BOOL( + list, list_info, + &settings->bools.video_shader_remember_last_dir, + MENU_ENUM_LABEL_VIDEO_SHADER_REMEMBER_LAST_DIR, + MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_REMEMBER_LAST_DIR, + DEFAULT_VIDEO_SHADER_REMEMBER_LAST_DIR, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); + #if !defined(RARCH_MOBILE) if (video_driver_test_all_flags(GFX_CTX_FLAGS_BLACK_FRAME_INSERTION)) { diff --git a/msg_hash.h b/msg_hash.h index 18f607702c..3f8f90f971 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -2234,6 +2234,7 @@ enum msg_hash_enums MENU_LABEL(LAKKA_SERVICES), MENU_LABEL(SHADER_APPLY_CHANGES), MENU_LABEL(SHADER_WATCH_FOR_CHANGES), + MENU_LABEL(VIDEO_SHADER_REMEMBER_LAST_DIR), MENU_LABEL(SAVE_NEW_CONFIG), MENU_LABEL(ONSCREEN_DISPLAY_SETTINGS), MENU_LABEL(ONSCREEN_OVERLAY_SETTINGS), diff --git a/retroarch.c b/retroarch.c index 12ebff178f..3672184b60 100644 --- a/retroarch.c +++ b/retroarch.c @@ -7433,6 +7433,147 @@ void menu_driver_search_append_terms_string(char *s, size_t len) } } +#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) + +static void menu_driver_set_last_shader_dir_int( + const char *shader_path, + enum rarch_shader_type *type, + char *shader_dir, size_t len) +{ + if (!type || !shader_dir || (len < 1)) + return; + + /* Reset existing cache */ + *type = RARCH_SHADER_NONE; + shader_dir[0] = '\0'; + + /* If path is empty, do nothing */ + if (string_is_empty(shader_path)) + return; + + /* Get shader type */ + *type = video_shader_parse_type(shader_path); + + /* If type is invalid, do nothing */ + if (*type == RARCH_SHADER_NONE) + return; + + /* Cache parent directory */ + fill_pathname_parent_dir(shader_dir, shader_path, len); +} + +void menu_driver_set_last_shader_preset_dir(const char *shader_path) +{ + struct rarch_state *p_rarch = &rarch_st; + menu_handle_t *menu = p_rarch->menu_driver_data; + + if (!menu) + return; + + menu_driver_set_last_shader_dir_int( + shader_path, + &menu->last_shader_selection.preset_type, + menu->last_shader_selection.preset_dir, + sizeof(menu->last_shader_selection.preset_dir)); +} + +void menu_driver_set_last_shader_pass_dir(const char *shader_pass_path) +{ + struct rarch_state *p_rarch = &rarch_st; + menu_handle_t *menu = p_rarch->menu_driver_data; + + if (!menu) + return; + + menu_driver_set_last_shader_dir_int( + shader_pass_path, + &menu->last_shader_selection.pass_type, + menu->last_shader_selection.pass_dir, + sizeof(menu->last_shader_selection.pass_dir)); +} + +enum rarch_shader_type menu_driver_get_last_shader_preset_type(void) +{ + struct rarch_state *p_rarch = &rarch_st; + menu_handle_t *menu = p_rarch->menu_driver_data; + + if (!menu) + return RARCH_SHADER_NONE; + + return menu->last_shader_selection.preset_type; +} + +enum rarch_shader_type menu_driver_get_last_shader_pass_type(void) +{ + struct rarch_state *p_rarch = &rarch_st; + menu_handle_t *menu = p_rarch->menu_driver_data; + + if (!menu) + return RARCH_SHADER_NONE; + + return menu->last_shader_selection.pass_type; +} + +static const char *menu_driver_get_last_shader_dir_int( + enum rarch_shader_type type, const char *shader_dir) +{ + struct rarch_state *p_rarch = &rarch_st; + settings_t *settings = p_rarch->configuration_settings; + bool remember_last_dir = settings->bools.video_shader_remember_last_dir; + const char *video_shader_dir = settings->paths.directory_video_shader; + + /* If any of the following are true: + * - Directory caching is disabled + * - No directory has been cached + * - Cached directory is invalid + * - Last selected shader is incompatible with + * the current video driver + * ...use the default setting */ + if (!remember_last_dir || + (type == RARCH_SHADER_NONE) || + string_is_empty(shader_dir) || + !path_is_directory(shader_dir) || + !video_shader_is_supported(type)) + return video_shader_dir; + + return shader_dir; +} + + +const char *menu_driver_get_last_shader_preset_dir(void) +{ + struct rarch_state *p_rarch = &rarch_st; + menu_handle_t *menu = p_rarch->menu_driver_data; + enum rarch_shader_type type = RARCH_SHADER_NONE; + const char *shader_dir = NULL; + + if (menu) + { + type = menu->last_shader_selection.preset_type; + shader_dir = menu->last_shader_selection.preset_dir; + } + + return menu_driver_get_last_shader_dir_int(type, shader_dir); +} + +const char *menu_driver_get_last_shader_pass_dir(void) +{ + struct rarch_state *p_rarch = &rarch_st; + menu_handle_t *menu = p_rarch->menu_driver_data; + enum rarch_shader_type type = RARCH_SHADER_NONE; + const char *shader_dir = NULL; + + if (menu) + { + type = menu->last_shader_selection.pass_type; + shader_dir = menu->last_shader_selection.pass_dir; + } + + return menu_driver_get_last_shader_dir_int(type, shader_dir); +} + +#endif + bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data) { struct rarch_state *p_rarch = &rarch_st;