From b1b80916679ae3b07c154b81bad0ecfc8d43e4f8 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 1 Jun 2023 17:29:20 +0200 Subject: [PATCH] Fix 106976: Crash when setting custom asset preview When the temporary File Browser uses a maximized editor, it reuses the File/Asset Browser under the cursor. When the file browsing action is confirmed, the old editor state is restored but the file-list cleared, so it fails to find the active asset and the ID it represents in context. Work around this by getting the ID before spawning the File Browser from the operator. --- source/blender/editors/util/ed_util_ops.cc | 34 ++++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/util/ed_util_ops.cc b/source/blender/editors/util/ed_util_ops.cc index cefbdaa3ca7..798b91f64e5 100644 --- a/source/blender/editors/util/ed_util_ops.cc +++ b/source/blender/editors/util/ed_util_ops.cc @@ -67,6 +67,17 @@ static bool lib_id_preview_editing_poll(bContext *C) return true; } +static ID *lib_id_load_custom_preview_id_get(bContext *C, const wmOperator *op) +{ + /* #invoke() gets the ID from context and saves it in the custom data. */ + if (op->customdata) { + return static_cast(op->customdata); + } + + PointerRNA idptr = CTX_data_pointer_get(C, "id"); + return static_cast(idptr.data); +} + static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op) { char filepath[FILE_MAX]; @@ -78,8 +89,12 @@ static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - PointerRNA idptr = CTX_data_pointer_get(C, "id"); - ID *id = (ID *)idptr.data; + ID *id = lib_id_load_custom_preview_id_get(C, op); + if (!id) { + BKE_report( + op->reports, RPT_ERROR, "Failed to set preview: no ID in context (incorrect context?)"); + return OPERATOR_CANCELLED; + } BKE_previewimg_id_custom_set(id, filepath); @@ -88,6 +103,19 @@ static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +/** + * Obtain the ID from context, and spawn a File Browser to select the preview image. The + * File Browser may re-use the Asset Browser under the cursor, and clear the file-list on + * confirmation, leading to failure to obtain the ID at that point. So get it before spawning the + * File Browser (store it in the operator custom data). + */ +static int lib_id_load_custom_preview_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + PointerRNA idptr = CTX_data_pointer_get(C, "id"); + op->customdata = idptr.data; + return WM_operator_filesel(C, op, event); +} + static void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot) { ot->name = "Load Custom Preview"; @@ -97,7 +125,7 @@ static void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot) /* api callbacks */ ot->poll = lib_id_preview_editing_poll; ot->exec = lib_id_load_custom_preview_exec; - ot->invoke = WM_operator_filesel; + ot->invoke = lib_id_load_custom_preview_invoke; /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;