From 2858c3b287d7007a6eaf0723562f96b9331d3ea1 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 7 Aug 2024 09:35:10 +0200 Subject: [PATCH] Link/Append: separate instantiation of loose data from core link/append code When appending e.g. an object, it's generally expected that it is not just appended but also added to the active collection. Something similar happens for adding collections, or just geometry like a mesh data-block. This is called "loose data instantiation" in the source code. Which data is instantiated and how depends on context. Generally, it's best to first do the low-level link or append operation and only afterwards do the instantiation at a higher level where more context is known. For example, when dragging an object asset into the 3D view, it's expected that the object is added to the active collection. When dragging a node group into the node editor that uses an object internally (e.g. as mesh storage), not so much. This patch adds a new `BKE_blendfile_link_append_instantiate_loose` method that does the "default instantiation", i.e. the one we want to happen when using the general link/append operator to import data. Instead of calling this directly from low level `BKE_blendfile_append`, it's now called in `wm_link_append_exec` (and other places where desired). Furthermore, `view3d_ob_drop_copy_external_asset` does not use this anymore, but explicitly adds only the dragged object to the active collection. Some places, e.g. when linking/appending using the Python API, don't do any instantiation at all. They didn't do this before either, but it was way less obvious (it used `BLO_library_link_params_init` instead of `BLO_library_link_params_init_with_context`). Now there is always an explicit call to do instantiation in higher level code. Pull Request: https://projects.blender.org/blender/blender/pulls/125814 --- .../blenkernel/BKE_blendfile_link_append.hh | 6 ++++ .../blenkernel/intern/blender_copybuffer.cc | 3 ++ .../intern/blendfile_link_append.cc | 35 ++++++++----------- .../editors/space_view3d/space_view3d.cc | 28 ++++++++++----- .../windowmanager/intern/wm_files_link.cc | 3 ++ 5 files changed, 46 insertions(+), 29 deletions(-) diff --git a/source/blender/blenkernel/BKE_blendfile_link_append.hh b/source/blender/blenkernel/BKE_blendfile_link_append.hh index 5ae60bff991..0e70a602d60 100644 --- a/source/blender/blenkernel/BKE_blendfile_link_append.hh +++ b/source/blender/blenkernel/BKE_blendfile_link_append.hh @@ -168,6 +168,12 @@ void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList * */ void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *reports); +/** + * Instantiate loose data in the scene (e.g. add object to the active collection). + */ +void BKE_blendfile_link_append_instantiate_loose(BlendfileLinkAppendContext *lapp_context, + ReportList *reports); + /** * Options controlling the behavior of liboverrides creation. */ diff --git a/source/blender/blenkernel/intern/blender_copybuffer.cc b/source/blender/blenkernel/intern/blender_copybuffer.cc index aa2ca44317b..ffbca5a1313 100644 --- a/source/blender/blenkernel/intern/blender_copybuffer.cc +++ b/source/blender/blenkernel/intern/blender_copybuffer.cc @@ -50,6 +50,9 @@ static void copybuffer_append(BlendfileLinkAppendContext *lapp_context, /* Append, rather than linking */ BKE_blendfile_append(lapp_context, reports); + /* Instantiate loose data in the scene (e.g. add object to the active collection). */ + BKE_blendfile_link_append_instantiate_loose(lapp_context, reports); + /* This must be unset, otherwise these object won't link into other scenes from this blend * file. */ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); diff --git a/source/blender/blenkernel/intern/blendfile_link_append.cc b/source/blender/blenkernel/intern/blendfile_link_append.cc index 07f6c17582a..94323aef735 100644 --- a/source/blender/blenkernel/intern/blendfile_link_append.cc +++ b/source/blender/blenkernel/intern/blendfile_link_append.cc @@ -1476,12 +1476,6 @@ void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList * } BKE_id_multi_tagged_delete(bmain); - /* Instantiate newly created (duplicated) IDs as needed. */ - LooseDataInstantiateContext instantiate_context{}; - instantiate_context.lapp_context = lapp_context; - instantiate_context.active_collection = nullptr; - loose_data_instantiate(&instantiate_context); - BKE_main_id_newptr_and_tag_clear(bmain); BlendFileReadReport bf_reports{}; @@ -1535,12 +1529,13 @@ static int foreach_libblock_link_finalize_cb(LibraryIDLinkCallbackData *cb_data) return IDWALK_RET_NOP; } -static void blendfile_link_finalize(BlendfileLinkAppendContext *lapp_context, ReportList *reports) +void BKE_blendfile_link_append_instantiate_loose(BlendfileLinkAppendContext *lapp_context, + ReportList *reports) { - BLI_assert((lapp_context->params->flag & FILE_LINK) != 0); - - /* Instantiate newly linked IDs as needed. */ - if (lapp_context->params->context.scene != nullptr) { + if (!lapp_context->params->context.scene) { + return; + } + if (lapp_context->params->flag & FILE_LINK) { new_id_to_item_mapping_create(lapp_context); /* Add items for all not yet known IDs (i.e. implicitly linked indirect dependencies) to the * list. @@ -1564,16 +1559,12 @@ static void blendfile_link_finalize(BlendfileLinkAppendContext *lapp_context, Re &cb_data, IDWALK_NOP); } - - LooseDataInstantiateContext instantiate_context{}; - instantiate_context.lapp_context = lapp_context; - instantiate_context.active_collection = nullptr; - loose_data_instantiate(&instantiate_context); } - BlendFileReadReport bf_reports{}; - bf_reports.reports = reports; - BLO_read_do_version_after_setup(lapp_context->params->bmain, &bf_reports); + LooseDataInstantiateContext instantiate_context{}; + instantiate_context.lapp_context = lapp_context; + instantiate_context.active_collection = nullptr; + loose_data_instantiate(&instantiate_context); } void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *reports) @@ -1646,8 +1637,10 @@ void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *re * * In append case, the finalizing process is much more complex and requires and additional call * to #BKE_blendfile_append for caller code. */ - if ((lapp_context->params->flag & FILE_LINK) != 0) { - blendfile_link_finalize(lapp_context, reports); + if (lapp_context->params->flag & FILE_LINK) { + BlendFileReadReport bf_reports{}; + bf_reports.reports = reports; + BLO_read_do_version_after_setup(lapp_context->params->bmain, &bf_reports); } } diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index 9236b80a46b..fe2e4ebe341 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -780,26 +780,38 @@ static void view3d_ob_drop_copy_external_asset(bContext *C, wmDrag *drag, wmDrop * can use the context setup here to place the objects. */ BLI_assert(drag->type == WM_DRAG_ASSET); + Main *bmain = CTX_data_main(C); wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); BKE_view_layer_base_deselect_all(scene, view_layer); - ID *id = WM_drag_asset_id_import(C, asset_drag, FILE_AUTOSELECT); + Object *object = reinterpret_cast( + WM_drag_asset_id_import(C, asset_drag, FILE_AUTOSELECT)); + + LayerCollection *lc = BKE_layer_collection_get_active(view_layer); + Collection *collection = BKE_collection_parent_editable_find_recursive(view_layer, + lc->collection); + object->visibility_flag &= ~(OB_HIDE_VIEWPORT | OB_HIDE_SELECT); + + BKE_collection_object_add(bmain, collection, object); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_base_find(view_layer, object); + base->local_view_bits |= v3d->local_view_uid; + base->flag |= BASE_SELECTED; + BKE_scene_object_base_flag_sync_from_base(base); /* TODO(sergey): Only update relations for the current scene. */ DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); - RNA_int_set(drop->ptr, "session_uid", id->session_uid); + RNA_int_set(drop->ptr, "session_uid", object->id.session_uid); BKE_view_layer_synced_ensure(scene, view_layer); - Base *base = BKE_view_layer_base_find(view_layer, (Object *)id); - if (base != nullptr) { - BKE_view_layer_base_select_and_set_active(view_layer, base); - WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene); - } + BKE_view_layer_base_select_and_set_active(view_layer, base); + WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); ED_outliner_select_sync_from_object_tag(C); @@ -812,7 +824,7 @@ static void view3d_ob_drop_copy_external_asset(bContext *C, wmDrag *drag, wmDrop if (snap_state) { float obmat_final[4][4]; - view3d_ob_drop_matrix_from_snap(snap_state, (Object *)id, obmat_final); + view3d_ob_drop_matrix_from_snap(snap_state, object, obmat_final); RNA_float_set_array(drop->ptr, "matrix", &obmat_final[0][0]); } diff --git a/source/blender/windowmanager/intern/wm_files_link.cc b/source/blender/windowmanager/intern/wm_files_link.cc index b294aa126d9..2cc1f76bc11 100644 --- a/source/blender/windowmanager/intern/wm_files_link.cc +++ b/source/blender/windowmanager/intern/wm_files_link.cc @@ -366,6 +366,9 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) BKE_blendfile_append(lapp_context, op->reports); } + /* Instantiate loose data in the scene (e.g. add object to the active collection). */ + BKE_blendfile_link_append_instantiate_loose(lapp_context, op->reports); + BKE_blendfile_link_append_context_free(lapp_context); /* Important we unset, otherwise these object won't