diff options
-rw-r--r-- | release/scripts/startup/bl_ui/space_topbar.py | 71 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_userpref.py | 51 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_appdir.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/appdir.c | 30 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_path_util.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/path_util.c | 42 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 3 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_templates.c | 10 | ||||
-rw-r--r-- | source/blender/editors/screen/workspace_edit.c | 121 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_ui_api.c | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files.c | 51 |
12 files changed, 263 insertions, 123 deletions
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index ce4a1ad8c74..80a7215f90b 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -47,7 +47,7 @@ class TOPBAR_HT_upper_bar(Header): if not screen.show_fullscreen: layout.template_ID_tabs( window, "workspace", - new="workspace.add_menu", + new="workspace.add", menu="TOPBAR_MT_workspace_menu", ) else: @@ -287,7 +287,7 @@ class TOPBAR_MT_file(Menu): layout = self.layout layout.operator_context = 'INVOKE_AREA' - layout.operator("wm.read_homefile", text="New", icon='NEW') + layout.menu("TOPBAR_MT_file_new", text="New", icon='NEW') layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER') layout.menu("TOPBAR_MT_file_open_recent") layout.operator("wm.revert_mainfile") @@ -305,10 +305,27 @@ class TOPBAR_MT_file(Menu): layout.operator("wm.save_as_mainfile", text="Save Copy...").copy = True layout.separator() - layout.operator_context = 'INVOKE_AREA' - layout.operator("wm.save_homefile") - layout.operator("wm.read_factory_settings") + + if any(bpy.utils.app_template_paths()): + app_template = context.user_preferences.app_template + else: + app_template = None + + if app_template: + layout.label(text=bpy.path.display_name(app_template)) + layout.operator("wm.save_homefile") + layout.operator( + "wm.read_factory_settings", + text="Load Factory Settings", + ).app_template = app_template + else: + layout.operator("wm.save_homefile") + layout.operator("wm.read_factory_settings") + + layout.separator() + + layout.operator("wm.app_template_install", text="Install Application Template...") layout.separator() @@ -334,6 +351,49 @@ class TOPBAR_MT_file(Menu): layout.operator("wm.quit_blender", text="Quit", icon='QUIT') +class TOPBAR_MT_file_new(Menu): + bl_label = "New File" + + @staticmethod + def app_template_paths(): + import os + + template_paths = bpy.utils.app_template_paths() + + # expand template paths + app_templates = [] + for path in template_paths: + for d in os.listdir(path): + if d.startswith(("__", ".")): + continue + template = os.path.join(path, d) + if os.path.isdir(template): + # template_paths_expand.append(template) + app_templates.append(d) + + return sorted(app_templates) + + def draw_ex(self, context, *, use_splash=False, use_default=False): + layout = self.layout + + # now draw the presets + layout.operator_context = 'EXEC_DEFAULT' + + if use_default: + props = layout.operator("wm.read_homefile", text="General") + props.app_template = "" + + for d in TOPBAR_MT_file_new.app_template_paths(): + props = layout.operator( + "wm.read_homefile", + text=bpy.path.display_name(d), + ) + props.app_template = d + + def draw(self, context): + self.draw_ex(context, use_splash=False, use_default=True) + + class TOPBAR_MT_file_import(Menu): bl_idname = "TOPBAR_MT_file_import" bl_label = "Import" @@ -647,6 +707,7 @@ classes = ( TOPBAR_MT_workspace_menu, TOPBAR_MT_editor_menus, TOPBAR_MT_file, + TOPBAR_MT_file_new, TOPBAR_MT_file_import, TOPBAR_MT_file_export, TOPBAR_MT_file_external_data, diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index ee2bd2645fc..b1604489605 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -81,60 +81,12 @@ class USERPREF_MT_interaction_presets(Menu): draw = Menu.draw_preset -class USERPREF_MT_app_templates(Menu): - bl_label = "Application Templates" - preset_subdir = "app_templates" - - def draw_ex(self, context, *, use_splash=False, use_default=False, use_install=False): - import os - - layout = self.layout - - # now draw the presets - layout.operator_context = 'EXEC_DEFAULT' - - if use_default: - props = layout.operator("wm.read_homefile", text="Default") - props.use_splash = True - props.app_template = "" - layout.separator() - - template_paths = bpy.utils.app_template_paths() - - # expand template paths - app_templates = [] - for path in template_paths: - for d in os.listdir(path): - if d.startswith(("__", ".")): - continue - template = os.path.join(path, d) - if os.path.isdir(template): - # template_paths_expand.append(template) - app_templates.append(d) - - for d in sorted(app_templates): - props = layout.operator( - "wm.read_homefile", - text=bpy.path.display_name(d), - ) - props.use_splash = True - props.app_template = d - - if use_install: - layout.separator() - layout.operator_context = 'INVOKE_DEFAULT' - props = layout.operator("wm.app_template_install") - - def draw(self, context): - self.draw_ex(context, use_splash=False, use_default=True, use_install=True) - - class USERPREF_MT_templates_splash(Menu): bl_label = "Startup Templates" preset_subdir = "templates" def draw(self, context): - USERPREF_MT_app_templates.draw_ex(self, context, use_splash=True, use_default=True) + bpy.types.TOPBAR_MT_file_new.draw_ex(self, context, use_splash=True, use_default=True) class USERPREF_MT_appconfigs(Menu): @@ -1650,7 +1602,6 @@ classes = ( USERPREF_PT_tabs, USERPREF_MT_interaction_presets, USERPREF_MT_templates_splash, - USERPREF_MT_app_templates, USERPREF_MT_appconfigs, USERPREF_MT_splash, USERPREF_MT_splash_footer, diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index ac8f861fa56..6162c7b6bf6 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -23,6 +23,7 @@ /** \file BKE_appdir.h * \ingroup bli */ +struct ListBase; /* note on naming: typical _get() suffix is omitted here, * since its the main purpose of the API. */ @@ -35,6 +36,7 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con bool BKE_appdir_app_template_any(void); bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len); +void BKE_appdir_app_templates(struct ListBase *templates); /* Initialize path to program executable */ void BKE_appdir_program_path_init(const char *argv0); diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 46f25815481..2848c245553 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -28,9 +28,11 @@ #include <stdio.h> #include "BLI_utildefines.h" -#include "BLI_string.h" #include "BLI_fileops.h" +#include "BLI_fileops_types.h" +#include "BLI_listbase.h" #include "BLI_path_util.h" +#include "BLI_string.h" #include "BKE_blender_version.h" #include "BKE_appdir.h" /* own include */ @@ -738,6 +740,32 @@ bool BKE_appdir_app_template_id_search(const char *app_template, char *path, siz return false; } +void BKE_appdir_app_templates(ListBase *templates) +{ + BLI_listbase_clear(templates); + + for (int i = 0; i < 2; i++) { + char subdir[FILE_MAX]; + if (!BKE_appdir_folder_id_ex( + app_template_directory_id[i], app_template_directory_search[i], + subdir, sizeof(subdir))) + { + continue; + } + + struct direntry *dir; + uint totfile = BLI_filelist_dir_contents(subdir, &dir); + for (int f = 0; f < totfile; f++) { + if (!FILENAME_IS_CURRPAR(dir[f].relname) && S_ISDIR(dir[f].type)) { + char *template = BLI_strdup(dir[f].relname); + BLI_addtail(templates, BLI_genericNodeN(template)); + } + } + + BLI_filelist_free(dir, totfile); + } +} + /** * Gets the temp directory when blender first runs. * If the default path is not found, use try $TEMP diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index e434e83416b..dcfb2c9cbc9 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -108,6 +108,8 @@ void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL(); bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; bool BLI_path_is_unc(const char *path); +void BLI_path_to_display_name(char *display_name, int maxlen, const char *name) ATTR_NONNULL(); + #if defined(WIN32) void BLI_cleanup_unc_16(wchar_t *path_16); void BLI_cleanup_unc(char *path_16, int maxlen); diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 10ca0fa6cbf..b3ab33312ba 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -928,6 +928,48 @@ bool BLI_path_frame_check_chars(const char *path) } /** + * Creates a display string from path to be used menus and the user interface. + * Like bpy.path.display_name(). + */ +void BLI_path_to_display_name(char *display_name, int maxlen, const char *name) +{ + /* Strip leading underscores and spaces. */ + int strip_offset = 0; + while (ELEM(name[strip_offset], '_', ' ')) { + strip_offset++; + } + + BLI_strncpy(display_name, name + strip_offset, maxlen); + + /* Replace underscores with spaces. */ + BLI_str_replace_char(display_name, '_', ' '); + + /* Strip extension. */ + BLI_path_extension_replace(display_name, maxlen, ""); + + /* Test if string has any upper case characters. */ + bool all_lower = true; + for (int i = 0; display_name[i]; i++) { + if (isupper(display_name[i])) { + all_lower = false; + break; + } + } + + if (all_lower) { + /* For full lowercase string, use title case. */ + bool prevspace = true; + for (int i = 0; display_name[i]; i++) { + if (prevspace) { + display_name[i] = toupper(display_name[i]); + } + + prevspace = isspace(display_name[i]); + } + } +} + +/** * If path begins with "//", strips that and replaces it with basepath directory. * * \note Also converts drive-letter prefix to something more sensible diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index db6dacd2064..04896eacb43 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -8938,6 +8938,9 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) link_list(fd, &user->uistyles); + /* Don't read the active app template, use the default one. */ + user->app_template[0] = '\0'; + /* free fd->datamap again */ oldnewmap_free_unused(fd->datamap); oldnewmap_clear(fd->datamap); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 0fe4b63763f..4e0a0711473 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1039,7 +1039,7 @@ void uiTemplateIDPreview( void uiTemplateIDTabs( uiLayout *layout, struct bContext *C, PointerRNA *ptr, const char *propname, - const char *newop, const char *openop, const char *menu, + const char *newop, const char *menu, int filter); void uiTemplateAnyID( uiLayout *layout, struct PointerRNA *ptr, const char *propname, diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index a5762b8566f..b7a553d1bd5 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -838,7 +838,7 @@ ID *UI_context_active_but_get_tab_ID(bContext *C) static void template_ID_tabs( bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag, - const char *newop, const char *UNUSED(openop), const char *menu) + const char *newop, const char *menu) { const ARegion *region = CTX_wm_region(C); const PointerRNA active_ptr = RNA_property_pointer_get(&template->ptr, template->prop); @@ -934,7 +934,7 @@ static void ui_template_id( if (template_ui->idlb) { if (use_tabs) { uiLayoutRow(layout, true); - template_ID_tabs(C, layout, template_ui, type, flag, newop, openop, unlinkop); + template_ID_tabs(C, layout, template_ui, type, flag, newop, unlinkop); } else { uiLayoutRow(layout, true); @@ -996,13 +996,13 @@ void uiTemplateGpencilColorPreview( void uiTemplateIDTabs( uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, - const char *newop, const char *openop, const char *unlinkop, + const char *newop, const char *unlinkop, int filter) { ui_template_id( layout, C, ptr, propname, - newop, openop, unlinkop, - UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, + newop, NULL, unlinkop, + UI_ID_BROWSE | UI_ID_RENAME, 0, 0, filter, true, 1.0f, false); } diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index db60bfc9fb6..a6a85a0f201 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -349,20 +349,23 @@ static int workspace_append(bContext *C, const char *directory, const char *idna static int workspace_append_activate_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - char idname[MAX_ID_NAME - 2], directory[FILE_MAX]; + char idname[MAX_ID_NAME - 2], filepath[FILE_MAX]; if (!RNA_struct_property_is_set(op->ptr, "idname") || - !RNA_struct_property_is_set(op->ptr, "directory")) + !RNA_struct_property_is_set(op->ptr, "filepath")) { return OPERATOR_CANCELLED; } RNA_string_get(op->ptr, "idname", idname); - RNA_string_get(op->ptr, "directory", directory); + RNA_string_get(op->ptr, "filepath", filepath); - if (workspace_append(C, directory, idname) != OPERATOR_CANCELLED) { + if (workspace_append(C, filepath, idname) != OPERATOR_CANCELLED) { WorkSpace *appended_workspace = BLI_findstring(&bmain->workspaces, idname, offsetof(ID, name) + 2); - BLI_assert(appended_workspace != NULL); + + /* Reorder to last position. */ + BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true); + /* Changing workspace changes context. Do delayed! */ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace); @@ -385,37 +388,39 @@ static void WORKSPACE_OT_append_activate(wmOperatorType *ot) RNA_def_string(ot->srna, "idname", NULL, MAX_ID_NAME - 2, "Identifier", "Name of the workspace to append and activate"); - RNA_def_string(ot->srna, "directory", NULL, FILE_MAX, "Directory", + RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath", "Path to the library"); } -static void workspace_config_file_path_from_folder_id( - const Main *bmain, int folder_id, char *r_path) +static WorkspaceConfigFileData *workspace_config_file_read(const char *app_template) { - const char *app_template = U.app_template[0] ? U.app_template : NULL; - const char * const cfgdir = BKE_appdir_folder_id(folder_id, app_template); + const char *cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, app_template); + char startup_file_path[FILE_MAX] = {0}; if (cfgdir) { - BLI_make_file_string(bmain->name, r_path, cfgdir, BLENDER_STARTUP_FILE); - } - else { - r_path[0] = '\0'; + BLI_join_dirfile(startup_file_path, sizeof(startup_file_path), cfgdir, BLENDER_STARTUP_FILE); } + + bool has_path = BLI_exists(startup_file_path); + return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL; } -ATTR_NONNULL(1) -static WorkspaceConfigFileData *workspace_config_file_read( - const Main *bmain, ReportList *reports) +static WorkspaceConfigFileData *workspace_system_file_read(const char *app_template) { - char workspace_config_path[FILE_MAX]; - bool has_path = false; + if (app_template == NULL) { + return BKE_blendfile_workspace_config_read(NULL, datatoc_startup_blend, datatoc_startup_blend_size, NULL); + } - workspace_config_file_path_from_folder_id(bmain, BLENDER_USER_CONFIG, workspace_config_path); - if (BLI_exists(workspace_config_path)) { - has_path = true; + char template_dir[FILE_MAX]; + if (!BKE_appdir_app_template_id_search(app_template, template_dir, sizeof(template_dir))) { + return NULL; } - return (has_path) ? BKE_blendfile_workspace_config_read(workspace_config_path, NULL, 0, reports) : NULL; + char startup_file_path[FILE_MAX]; + BLI_join_dirfile(startup_file_path, sizeof(startup_file_path), template_dir, BLENDER_STARTUP_FILE); + + bool has_path = BLI_exists(startup_file_path); + return (has_path) ? BKE_blendfile_workspace_config_read(startup_file_path, NULL, 0, NULL) : NULL; } static void workspace_append_button( @@ -438,32 +443,28 @@ static void workspace_append_button( layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr); RNA_string_set(&opptr, "idname", id->name + 2); - RNA_string_set(&opptr, "directory", lib_path); + RNA_string_set(&opptr, "filepath", lib_path); } -ATTR_NONNULL(1, 2) -static void workspace_config_file_append_buttons( - uiLayout *layout, const Main *bmain, ReportList *reports) +static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v) { + Main *bmain = CTX_data_main(C); + const char *app_template = template_v; + bool has_startup_items = false; + wmOperatorType *ot_append = WM_operatortype_find("WORKSPACE_OT_append_activate", true); - WorkspaceConfigFileData *startup_config = workspace_config_file_read(bmain, reports); - WorkspaceConfigFileData *builtin_config = BKE_blendfile_workspace_config_read(NULL, datatoc_startup_blend, datatoc_startup_blend_size, reports); + WorkspaceConfigFileData *startup_config = workspace_config_file_read(app_template); + WorkspaceConfigFileData *builtin_config = workspace_system_file_read(app_template); if (startup_config) { - bool has_title = false; - for (WorkSpace *workspace = startup_config->workspaces.first; workspace; workspace = workspace->id.next) { + uiLayout *row = uiLayoutRow(layout, false); if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) { - continue; - } - - if (!has_title) { - uiItemS(layout); - uiItemL(layout, IFACE_("Startup File"), ICON_NONE); - has_title = true; + uiLayoutSetActive(row, false); } - workspace_append_button(layout, ot_append, workspace, startup_config->main); + workspace_append_button(row, ot_append, workspace, startup_config->main); + has_startup_items = true; } } @@ -471,22 +472,23 @@ static void workspace_config_file_append_buttons( bool has_title = false; for (WorkSpace *workspace = builtin_config->workspaces.first; workspace; workspace = workspace->id.next) { - if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) { - continue; - } if (startup_config && BLI_findstring(&startup_config->workspaces, workspace->id.name, offsetof(ID, name))) { continue; } if (!has_title) { - uiItemS(layout); - uiItemL(layout, IFACE_("Builtin"), ICON_NONE); + if (has_startup_items) { + uiItemS(layout); + } has_title = true; } - if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name)) == NULL) { - workspace_append_button(layout, ot_append, workspace, builtin_config->main); + uiLayout *row = uiLayoutRow(layout, false); + if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) { + uiLayoutSetActive(row, false); } + + workspace_append_button(row, ot_append, workspace, builtin_config->main); } } @@ -500,26 +502,41 @@ static void workspace_config_file_append_buttons( static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - const Main *bmain = CTX_data_main(C); - uiPopupMenu *pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE); uiLayout *layout = UI_popup_menu_layout(pup); + uiItemMenuF(layout, IFACE_("General"), ICON_NONE, workspace_add_menu, NULL); + + ListBase templates; + BKE_appdir_app_templates(&templates); + + for (LinkData *link = templates.first; link; link = link->next) { + char *template = link->data; + char display_name[FILE_MAX]; + + BLI_path_to_display_name(display_name, sizeof(display_name), template); + + /* Steals ownership of link data string. */ + uiItemMenuF(layout, display_name, ICON_NONE, workspace_add_menu, template); + } + + BLI_freelistN(&templates); + + uiItemS(layout); uiItemO(layout, "Duplicate Current", ICON_NONE, "WORKSPACE_OT_duplicate"); - workspace_config_file_append_buttons(layout, bmain, op->reports); UI_popup_menu_end(C, pup); return OPERATOR_INTERFACE; } -static void WORKSPACE_OT_add_menu(wmOperatorType *ot) +static void WORKSPACE_OT_add(wmOperatorType *ot) { /* identifiers */ ot->name = "Add Workspace"; ot->description = "Add a new workspace by duplicating the current one or appending one " "from the user configuration"; - ot->idname = "WORKSPACE_OT_add_menu"; + ot->idname = "WORKSPACE_OT_add"; /* api callbacks */ ot->invoke = workspace_add_invoke; @@ -575,7 +592,7 @@ void ED_operatortypes_workspace(void) { WM_operatortype_append(WORKSPACE_OT_duplicate); WM_operatortype_append(WORKSPACE_OT_delete); - WM_operatortype_append(WORKSPACE_OT_add_menu); + WM_operatortype_append(WORKSPACE_OT_add); WM_operatortype_append(WORKSPACE_OT_append_activate); WM_operatortype_append(WORKSPACE_OT_reorder_to_back); WM_operatortype_append(WORKSPACE_OT_reorder_to_front); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index bafc7dc69c1..694d44a87e8 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -791,7 +791,6 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); api_ui_item_rna_common(func); RNA_def_string(func, "new", NULL, 0, "", "Operator identifier to create a new ID block"); - RNA_def_string(func, "open", NULL, 0, "", "Operator identifier to open a file for creating a new ID block"); RNA_def_string(func, "menu", NULL, 0, "", "Context menu identifier"); RNA_def_enum(func, "filter", id_template_filter_items, UI_TEMPLATE_ID_FILTER_ALL, "", "Optionally limit the items which can be selected"); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 65f4823464a..7883b2aded6 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -696,6 +696,25 @@ const char *WM_init_state_app_template_get(void) return wm_init_state_app_template.override ? wm_init_state_app_template.app_template : NULL; } + +static bool wm_app_template_has_userpref(const char *app_template) +{ + /* Test if app template provides a userpref.blend. If not, we will + * share user preferences with the rest of Blender. */ + if (!app_template && app_template[0]) { + return false; + } + + char app_template_path[FILE_MAX]; + if (!BKE_appdir_app_template_id_search(app_template, app_template_path, sizeof(app_template_path))) { + return false; + } + + char userpref_path[FILE_MAX]; + BLI_path_join(userpref_path, sizeof(userpref_path), app_template_path, BLENDER_USERPREF_FILE, NULL); + return BLI_exists(userpref_path); +} + /** * Called on startup, (context entirely filled with NULLs) * or called for 'New File' both startup.blend and userpref.blend are checked. @@ -1489,7 +1508,7 @@ void WM_OT_save_homefile(wmOperatorType *ot) { ot->name = "Save Startup File"; ot->idname = "WM_OT_save_homefile"; - ot->description = "Make the current file the default .blend file, includes preferences"; + ot->description = "Make the current file the default .blend file"; ot->invoke = WM_operator_confirm; ot->exec = wm_homefile_write_exec; @@ -1543,6 +1562,7 @@ static int wm_userpref_write_exec(bContext *C, wmOperator *op) char filepath[FILE_MAX]; const char *cfgdir; bool ok = true; + bool use_template_userpref = wm_app_template_has_userpref(U.app_template); /* update keymaps in user preferences */ WM_keyconfig_update(wm); @@ -1550,9 +1570,8 @@ static int wm_userpref_write_exec(bContext *C, wmOperator *op) if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) { bool ok_write; BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); - printf("trying to save userpref at %s ", filepath); - if (U.app_template[0]) { + if (use_template_userpref) { ok_write = BKE_blendfile_userdef_write_app_template(filepath, op->reports); } else { @@ -1571,11 +1590,10 @@ static int wm_userpref_write_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path"); } - if (U.app_template[0]) { + if (use_template_userpref) { if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) { /* Also save app-template prefs */ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); - printf("trying to save app-template userpref at %s ", filepath); if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) { printf("ok\n"); } @@ -1664,8 +1682,9 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) RNA_property_string_get(op->ptr, prop_app_template, app_template_buf); app_template = app_template_buf; - /* Always load preferences when switching templates. */ - use_userdef = true; + /* Always load preferences when switching templates with own preferences. */ + use_userdef = wm_app_template_has_userpref(app_template) || + wm_app_template_has_userpref(U.app_template); /* Turn override off, since we're explicitly loading a different app-template. */ WM_init_state_app_template_set(NULL); @@ -1686,6 +1705,22 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) } } +static int wm_homefile_read_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) +{ + /* Draw menu which includes default startup and application templates. */ + uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("New File"), ICON_NEW); + uiLayout *layout = UI_popup_menu_layout(pup); + + MenuType *mt = WM_menutype_find("TOPBAR_MT_file_new", false); + if (mt) { + UI_menutype_draw(C, mt, layout); + } + + UI_popup_menu_end(C, pup); + + return OPERATOR_INTERFACE; +} + void WM_OT_read_homefile(wmOperatorType *ot) { PropertyRNA *prop; @@ -1693,7 +1728,7 @@ void WM_OT_read_homefile(wmOperatorType *ot) ot->idname = "WM_OT_read_homefile"; ot->description = "Open the default file (doesn't save the current file)"; - ot->invoke = WM_operator_confirm; + ot->invoke = wm_homefile_read_invoke; ot->exec = wm_homefile_read_exec; prop = RNA_def_string_file_path(ot->srna, "filepath", NULL, |