diff --git a/release/extensions/system/readme.txt b/release/extensions/system/readme.txt new file mode 100644 index 00000000000..44860437d98 --- /dev/null +++ b/release/extensions/system/readme.txt @@ -0,0 +1,7 @@ +System Extensions + +Extensions extracted into this directory will be available from the +default "System" repository. + +This allows extensions to be bundled with Blender outside of +user repositories. diff --git a/scripts/startup/bl_ui/space_userpref.py b/scripts/startup/bl_ui/space_userpref.py index f5d6b5f2dfb..8b63faec90a 100644 --- a/scripts/startup/bl_ui/space_userpref.py +++ b/scripts/startup/bl_ui/space_userpref.py @@ -2211,6 +2211,10 @@ class USERPREF_PT_extensions_repos(Panel): # valid UTF-8 which will raise a Python exception when passed in as text. sub.prop(active_repo, "directory", text="") + row = layout_panel.row() + row.active = not use_custom_directory + row.prop(active_repo, "source") + if active_repo.use_remote_url: row = layout_panel.row(align=True, heading="Authentication") row.prop(active_repo, "use_access_token") diff --git a/source/blender/blenkernel/BKE_appdir.hh b/source/blender/blenkernel/BKE_appdir.hh index 6002e3fcebc..7f70cf153a0 100644 --- a/source/blender/blenkernel/BKE_appdir.hh +++ b/source/blender/blenkernel/BKE_appdir.hh @@ -168,7 +168,8 @@ enum { /* system */ BLENDER_SYSTEM_DATAFILES = 52, BLENDER_SYSTEM_SCRIPTS = 53, - BLENDER_SYSTEM_PYTHON = 54, + BLENDER_SYSTEM_EXTENSIONS = 54, + BLENDER_SYSTEM_PYTHON = 55, }; /** For #BKE_appdir_folder_id_version only. */ diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 77289f10407..2d6b06b7987 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -29,7 +29,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 55 +#define BLENDER_FILE_SUBVERSION 56 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/BKE_preferences.h b/source/blender/blenkernel/BKE_preferences.h index 14e311f5f1a..68d497f3313 100644 --- a/source/blender/blenkernel/BKE_preferences.h +++ b/source/blender/blenkernel/BKE_preferences.h @@ -90,6 +90,7 @@ bUserExtensionRepo *BKE_preferences_extension_repo_add(UserDef *userdef, void BKE_preferences_extension_repo_remove(UserDef *userdef, bUserExtensionRepo *repo); bUserExtensionRepo *BKE_preferences_extension_repo_add_default_remote(UserDef *userdef); bUserExtensionRepo *BKE_preferences_extension_repo_add_default_user(UserDef *userdef); +bUserExtensionRepo *BKE_preferences_extension_repo_add_default_system(UserDef *userdef); /** Create all default repositories, only use when repositories are empty. */ void BKE_preferences_extension_repo_add_defaults_all(UserDef *userdef); diff --git a/source/blender/blenkernel/intern/appdir.cc b/source/blender/blenkernel/intern/appdir.cc index 7b3cd188f0d..f3d86c4a58a 100644 --- a/source/blender/blenkernel/intern/appdir.cc +++ b/source/blender/blenkernel/intern/appdir.cc @@ -656,6 +656,18 @@ bool BKE_appdir_folder_id_ex(const int folder_id, } return false; + case BLENDER_SYSTEM_EXTENSIONS: + if (get_path_environment(path, path_maxncpy, subfolder, "BLENDER_SYSTEM_EXTENSIONS")) { + break; + } + if (get_path_system(path, path_maxncpy, "extensions", subfolder)) { + break; + } + if (get_path_local(path, path_maxncpy, "extensions", subfolder)) { + break; + } + return false; + case BLENDER_SYSTEM_PYTHON: if (get_path_environment(path, path_maxncpy, subfolder, "BLENDER_SYSTEM_PYTHON")) { break; diff --git a/source/blender/blenkernel/intern/preferences.cc b/source/blender/blenkernel/intern/preferences.cc index 91075bc903e..2633e9d62d2 100644 --- a/source/blender/blenkernel/intern/preferences.cc +++ b/source/blender/blenkernel/intern/preferences.cc @@ -216,11 +216,19 @@ bUserExtensionRepo *BKE_preferences_extension_repo_add_default_user(UserDef *use return repo; } +bUserExtensionRepo *BKE_preferences_extension_repo_add_default_system(UserDef *userdef) +{ + bUserExtensionRepo *repo = BKE_preferences_extension_repo_add(userdef, "System", "system", ""); + repo->source = USER_EXTENSION_REPO_SOURCE_SYSTEM; + return repo; +} + void BKE_preferences_extension_repo_add_defaults_all(UserDef *userdef) { BLI_assert(BLI_listbase_is_empty(&userdef->extension_repos)); BKE_preferences_extension_repo_add_default_remote(userdef); BKE_preferences_extension_repo_add_default_user(userdef); + BKE_preferences_extension_repo_add_default_system(userdef); } void BKE_preferences_extension_repo_name_set(UserDef *userdef, @@ -269,8 +277,19 @@ size_t BKE_preferences_extension_repo_dirpath_get(const bUserExtensionRepo *repo return BLI_strncpy_rlen(dirpath, repo->custom_dirpath, dirpath_maxncpy); } - std::optional path = BKE_appdir_folder_id_user_notest(BLENDER_USER_EXTENSIONS, - nullptr); + std::optional path = std::nullopt; + + switch (repo->source) { + case USER_EXTENSION_REPO_SOURCE_SYSTEM: { + path = BKE_appdir_folder_id(BLENDER_SYSTEM_EXTENSIONS, nullptr); + break; + } + default: { /* #USER_EXTENSION_REPO_SOURCE_USER. */ + path = BKE_appdir_folder_id_user_notest(BLENDER_USER_EXTENSIONS, nullptr); + break; + } + } + /* Highly unlikely to fail as the directory doesn't have to exist. */ if (!path) { dirpath[0] = '\0'; diff --git a/source/blender/blenloader/intern/versioning_userdef.cc b/source/blender/blenloader/intern/versioning_userdef.cc index 11dbcfaac1f..8e0fcdd53e2 100644 --- a/source/blender/blenloader/intern/versioning_userdef.cc +++ b/source/blender/blenloader/intern/versioning_userdef.cc @@ -973,6 +973,10 @@ void blo_do_versions_userdef(UserDef *userdef) userdef->sequencer_editor_flag |= USER_SEQ_ED_SIMPLE_TWEAKING; } + if (!USER_VERSION_ATLEAST(402, 56)) { + BKE_preferences_extension_repo_add_default_system(userdef); + } + /** * Always bump subversion in BKE_blender_version.h when adding versioning * code here, and wrap it inside a USER_VERSION_ATLEAST check. diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index e1ecea0a938..6da48d48330 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -649,8 +649,11 @@ typedef struct bUserExtensionRepo { char custom_dirpath[1024]; /* FILE_MAX */ char remote_url[1024]; /* FILE_MAX */ - int flag; - char _pad0[4]; + uint8_t flag; + /** The source location when the custom directory isn't used (#eUserExtensionRepo_Source).*/ + uint8_t source; + + char _pad0[6]; } bUserExtensionRepo; typedef enum eUserExtensionRepo_Flag { @@ -663,6 +666,15 @@ typedef enum eUserExtensionRepo_Flag { USER_EXTENSION_REPO_FLAG_USE_ACCESS_TOKEN = 1 << 5, } eUserExtensionRepo_Flag; +/** + * The source to use (User or System), only valid when the + * #USER_EXTENSION_REPO_FLAG_USE_CUSTOM_DIRECTORY flag isn't set. + */ +typedef enum eUserExtensionRepo_Source { + USER_EXTENSION_REPO_SOURCE_USER = 0, + USER_EXTENSION_REPO_SOURCE_SYSTEM = 1, +} eUserExtensionRepo_Source; + typedef struct SolidLight { int flag; float smooth; diff --git a/source/blender/makesrna/intern/rna_userdef.cc b/source/blender/makesrna/intern/rna_userdef.cc index 8168ea5b47d..f881345070f 100644 --- a/source/blender/makesrna/intern/rna_userdef.cc +++ b/source/blender/makesrna/intern/rna_userdef.cc @@ -439,6 +439,15 @@ static void rna_userdef_extension_repo_use_remote_url_set(PointerRNA *ptr, bool ptr, value, USER_EXTENSION_REPO_FLAG_USE_REMOTE_URL); } +static void rna_userdef_extension_repo_source_set(PointerRNA *ptr, int value) +{ + Main *bmain = G.main; + bUserExtensionRepo *repo = (bUserExtensionRepo *)ptr->data; + BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_PRE); + repo->source = value; + BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_POST); +} + static void rna_userdef_script_autoexec_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *ptr) @@ -6750,6 +6759,20 @@ static void rna_def_userdef_filepaths_extension_repo(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static const EnumPropertyItem source_type_items[] = { + {USER_EXTENSION_REPO_SOURCE_USER, + "USER", + 0, + "User", + "Repository managed by the user, stored in user directories"}, + {USER_EXTENSION_REPO_SOURCE_SYSTEM, + "SYSTEM", + 0, + "System", + "Read-only repository provided by the system"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + srna = RNA_def_struct(brna, "UserExtensionRepo", nullptr); RNA_def_struct_sdna(srna, "bUserExtensionRepo"); RNA_def_struct_ui_text( @@ -6801,6 +6824,14 @@ static void rna_def_userdef_filepaths_extension_repo(BlenderRNA *brna) "rna_userdef_extension_repo_access_token_length", "rna_userdef_extension_repo_access_token_set"); + prop = RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, source_type_items); + RNA_def_property_enum_funcs(prop, nullptr, "rna_userdef_extension_repo_source_set", nullptr); + RNA_def_property_ui_text( + prop, + "Source", + "Select if the repository is in a user managed or system provided directory"); + /* NOTE(@ideasman42): this is intended to be used by a package manger component * which is not yet integrated. */ prop = RNA_def_property(srna, "use_cache", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/python/intern/bpy.cc b/source/blender/python/intern/bpy.cc index a2affd0f800..d23092d29e5 100644 --- a/source/blender/python/intern/bpy.cc +++ b/source/blender/python/intern/bpy.cc @@ -266,7 +266,7 @@ PyDoc_STRVAR( "\n" " Return a system resource path.\n" "\n" - " :arg type: string in ['DATAFILES', 'SCRIPTS', 'PYTHON'].\n" + " :arg type: string in ['DATAFILES', 'SCRIPTS', 'EXTENSIONS', 'PYTHON'].\n" " :type type: string\n" " :arg path: Optional subdirectory.\n" " :type path: string or bytes\n"); @@ -275,6 +275,7 @@ static PyObject *bpy_system_resource(PyObject * /*self*/, PyObject *args, PyObje const PyC_StringEnumItems type_items[] = { {BLENDER_SYSTEM_DATAFILES, "DATAFILES"}, {BLENDER_SYSTEM_SCRIPTS, "SCRIPTS"}, + {BLENDER_SYSTEM_EXTENSIONS, "EXTENSIONS"}, {BLENDER_SYSTEM_PYTHON, "PYTHON"}, {0, nullptr}, }; diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index d7033fd0ea2..b8d6a83ffc2 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -1659,6 +1659,13 @@ if(DEFINED TARGETDIR_TEXT) ) endif() +# Create a system extensions directory (users or administrators may populate this). +# This only contains a `readme.txt` explaining it's purpose. +install( + DIRECTORY ${CMAKE_SOURCE_DIR}/release/extensions + DESTINATION ${TARGETDIR_VER} +) + # Install more files specified elsewhere. delayed_do_install(${TARGETDIR_VER}) diff --git a/source/creator/creator_args.cc b/source/creator/creator_args.cc index 95dcef1c733..03bdec798e1 100644 --- a/source/creator/creator_args.cc +++ b/source/creator/creator_args.cc @@ -853,6 +853,7 @@ static void print_help(bArgs *ba, bool all) PRINT("\n"); PRINT(" $BLENDER_SYSTEM_RESOURCES Replace default directory of all bundled resource files.\n"); PRINT(" $BLENDER_SYSTEM_SCRIPTS Directory to add more bundled scripts.\n"); + PRINT(" $BLENDER_SYSTEM_EXTENSIONS Directory for system extensions repository.\n"); PRINT(" $BLENDER_SYSTEM_DATAFILES Directory to replace bundled datafiles.\n"); PRINT(" $BLENDER_SYSTEM_PYTHON Directory to replace bundled Python libraries.\n"); @@ -1533,6 +1534,9 @@ static const char arg_handle_env_system_set_doc_scripts[] = static const char arg_handle_env_system_set_doc_python[] = "\n\t" "Set the " STRINGIFY_ARG(BLENDER_SYSTEM_PYTHON) " environment variable."; +static const char arg_handle_env_system_set_doc_extensions[] = + "\n\t" + "Set the " STRINGIFY_ARG(BLENDER_SYSTEM_EXTENSIONS) " environment variable."; static int arg_handle_env_system_set(int argc, const char **argv, void * /*data*/) { @@ -2542,6 +2546,11 @@ void main_args_setup(bContext *C, bArgs *ba, bool all) ba, nullptr, "--env-system-scripts", CB_EX(arg_handle_env_system_set, scripts), nullptr); BLI_args_add( ba, nullptr, "--env-system-python", CB_EX(arg_handle_env_system_set, python), nullptr); + BLI_args_add(ba, + nullptr, + "--env-system-extensions", + CB_EX(arg_handle_env_system_set, extensions), + nullptr); BLI_args_add(ba, "-t", "--threads", CB(arg_handle_threads_set), nullptr);