From 0a3e73a91fb06ca340e4de70a3ddd1ac037e9e33 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 3 Jul 2019 20:36:49 +0200 Subject: Fix T65899, T66314, T61808: various issues appending workspaces This fixes crashes, wrong names and inability to append workspaces in edit mode. We now bypass the append operator so we can easily return a datablock pointer and work in any mode. --- source/blender/editors/screen/workspace_edit.c | 53 +++++----------------- source/blender/windowmanager/WM_api.h | 5 ++ .../blender/windowmanager/intern/wm_files_link.c | 42 ++++++++++++++++- 3 files changed, 57 insertions(+), 43 deletions(-) diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index f4138dd7847..e2c4331b3ba 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -331,30 +331,6 @@ static void WORKSPACE_OT_delete(wmOperatorType *ot) ot->exec = workspace_delete_exec; } -static bool workspace_append_activate_poll(bContext *C) -{ - wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false); - return WM_operator_poll(C, ot); -} - -static int workspace_append(bContext *C, const char *directory, const char *idname) -{ - wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false); - PointerRNA opptr; - int retval; - - WM_operator_properties_create_ptr(&opptr, ot); - RNA_string_set(&opptr, "directory", directory); - RNA_string_set(&opptr, "filename", idname); - RNA_boolean_set(&opptr, "autoselect", false); - - retval = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &opptr); - - WM_operator_properties_free(&opptr); - - return retval; -} - static int workspace_append_activate_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -367,23 +343,20 @@ static int workspace_append_activate_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "idname", idname); RNA_string_get(op->ptr, "filepath", filepath); - 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); + WorkSpace *appended_workspace = (WorkSpace *)WM_file_append_datablock( + C, filepath, ID_WS, idname); - if (appended_workspace) { - /* Set defaults. */ - BLO_update_defaults_workspace(appended_workspace, NULL); + if (appended_workspace) { + /* Set defaults. */ + BLO_update_defaults_workspace(appended_workspace, NULL); - /* Reorder to last position. */ - BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true); + /* 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); + /* Changing workspace changes context. Do delayed! */ + WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace); - return OPERATOR_FINISHED; - } + return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; @@ -398,7 +371,6 @@ static void WORKSPACE_OT_append_activate(wmOperatorType *ot) /* api callbacks */ ot->exec = workspace_append_activate_exec; - ot->poll = workspace_append_activate_poll; RNA_def_string(ot->srna, "idname", @@ -449,20 +421,17 @@ static void workspace_append_button(uiLayout *layout, { const ID *id = (ID *)workspace; PointerRNA opptr; - char lib_path[FILE_MAX_LIBEXTRA]; const char *filepath = from_main->name; if (strlen(filepath) == 0) { filepath = BLO_EMBEDDED_STARTUP_BLEND; } - BLI_path_join(lib_path, sizeof(lib_path), filepath, BKE_idcode_to_name(GS(id->name)), NULL); - BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate")); uiItemFullO_ptr( 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, "filepath", lib_path); + RNA_string_set(&opptr, "filepath", filepath); } static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v) diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index d3c1e5f146d..04e3f7e88dc 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -42,6 +42,7 @@ extern "C" { struct ARegion; struct GHashIterator; struct GPUViewport; +struct ID; struct IDProperty; struct ImBuf; struct ImageFormatData; @@ -178,6 +179,10 @@ void WM_autosave_init(struct wmWindowManager *wm); void WM_recover_last_session(struct bContext *C, struct ReportList *reports); void WM_file_tag_modified(void); +struct ID *WM_file_append_datablock(struct bContext *C, + const char *filepath, + const short id_code, + const char *id_name); void WM_lib_reload(struct Library *lib, struct bContext *C, struct ReportList *reports); /* mouse cursors */ diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index 069dc8f441f..5a6606984ba 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -618,10 +618,50 @@ void WM_OT_append(wmOperatorType *ot) "Localize all appended data, including those indirectly linked from other libraries"); } -/** \name Reload/relocate libraries. +/** \name Append single datablock and return it. + * + * Used for appending workspace from startup files. * * \{ */ +ID *WM_file_append_datablock(bContext *C, + const char *filepath, + const short id_code, + const char *id_name) +{ + Main *bmain = CTX_data_main(C); + + /* Tag everything so we can make local only the new datablock. */ + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); + + /* Define working data, with just the one item we want to append. */ + WMLinkAppendData *lapp_data = wm_link_append_data_new(0); + + wm_link_append_data_library_add(lapp_data, filepath); + WMLinkAppendDataItem *item = wm_link_append_data_item_add(lapp_data, id_name, id_code, NULL); + BLI_BITMAP_ENABLE(item->libraries, 0); + + /* Link datablock. */ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + wm_link_do(lapp_data, NULL, bmain, scene, view_layer, v3d); + + /* Get linked datablock and free working data. */ + ID *id = item->new_id; + wm_link_append_data_free(lapp_data); + + /* Make datablock local. */ + BKE_library_make_local(bmain, NULL, NULL, true, false); + + /* Clear pre existing tag. */ + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); + + return id; +} + +/** \} */ + static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Library *lib; -- cgit v1.2.3