From 02c5ca2f2269b44cc56438847c55b8139a1c8dd2 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 23 May 2022 20:00:33 +0200 Subject: Fix possible issues when mixing link & append for asset drag & drop The operators to handle object drag and drop (from the asset browser, outliner, etc.) used the object name to find the object to add and place. This is problematic with linking and/or library overrides, since this may lead to multiple objects with the same name. So the wrong object would be used by the drop operators. Partially fixes T97320. T95706 probably needs the same fix but for materials. As a side-effect, the "Name" button won't show up in the Adjust Last Operation panel anymore. This isn't really useful, and I doubt this was ever intentionally exposed in the UI. --- source/blender/editors/object/object_add.cc | 124 +++++++++++++++------ source/blender/editors/space_view3d/space_view3d.c | 4 +- 2 files changed, 94 insertions(+), 34 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index db8860efdd8..5bd4ca3a861 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -252,6 +252,65 @@ static int object_add_drop_xy_generic_invoke(bContext *C, wmOperator *op, const return op->type->exec(C, op); } +/** + * Tries to find an ID in \a bmain. Three needs to be either a "name" string or "session_uuid" int + * property defined and set. The former has priority. + * + * See #id_add_lookup_props for a helper to add the properties. + */ +static ID *id_add_lookup_from_name_or_session_uuid_props(Main *bmain, + const wmOperator *op, + const ID_Type type) +{ + PropertyRNA *prop_name = RNA_struct_find_property(op->ptr, "name"); + PropertyRNA *prop_session_uuid = RNA_struct_find_property(op->ptr, "session_uuid"); + + if (prop_name && RNA_property_is_set(op->ptr, prop_name)) { + char name[MAX_ID_NAME - 2]; + RNA_property_string_get(op->ptr, prop_name, name); + return BKE_libblock_find_name(bmain, type, name); + } + + if (prop_session_uuid && RNA_property_is_set(op->ptr, prop_session_uuid)) { + const uint32_t session_uuid = (uint32_t)RNA_property_int_get(op->ptr, prop_session_uuid); + return BKE_libblock_find_session_uuid(bmain, type, session_uuid); + } + + return nullptr; +} + +/** + * Adds "name" and "session_uuid" properties to the operator so the caller can tell the operator + * which ID to add. See #id_add_find_from_name_or_session_uuid_op_props(). Both properties will be + * hidden in the UI. + * + * \note New operators should probably use "session_uuid" only (set \a add_name_prop to #false), + * since this works with linked data and/or library overrides (in both cases, multiple IDs with the + * same name and type may be present). The "name" property is only kept to not break compatibility + * with old scripts using these operators. + */ +static void id_add_lookup_props(wmOperatorType *ot, const bool add_name_prop = false) +{ + PropertyRNA *prop; + + if (add_name_prop) { + prop = RNA_def_string( + ot->srna, "name", nullptr, MAX_ID_NAME - 2, "Name", "Name of the data-block to add"); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); + } + + prop = RNA_def_int(ot->srna, + "session_uuid", + 0, + INT32_MIN, + INT32_MAX, + "Session UUID", + "Session UUID of the data-block to add", + INT32_MIN, + INT32_MAX); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -1651,19 +1710,12 @@ static std::optional collection_add_info_get_from_op(bContext Main *bmain = CTX_data_main(C); PropertyRNA *prop_location = RNA_struct_find_property(op->ptr, "location"); - PropertyRNA *prop_session_uuid = RNA_struct_find_property(op->ptr, "session_uuid"); - PropertyRNA *prop_name = RNA_struct_find_property(op->ptr, "name"); + + add_info.collection = reinterpret_cast( + id_add_lookup_from_name_or_session_uuid_props(bmain, op, ID_GR)); bool update_location_if_necessary = false; - if (prop_name && RNA_property_is_set(op->ptr, prop_name)) { - char name[MAX_ID_NAME - 2]; - RNA_property_string_get(op->ptr, prop_name, name); - add_info.collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name); - update_location_if_necessary = true; - } - else if (RNA_property_is_set(op->ptr, prop_session_uuid)) { - const uint32_t session_uuid = (uint32_t)RNA_property_int_get(op->ptr, prop_session_uuid); - add_info.collection = (Collection *)BKE_libblock_find_session_uuid(bmain, ID_GR, session_uuid); + if (add_info.collection) { update_location_if_necessary = true; } else { @@ -3718,15 +3770,13 @@ static int object_add_named_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *basen; - Object *ob; const bool linked = RNA_boolean_get(op->ptr, "linked"); const eDupli_ID_Flags dupflag = (linked) ? (eDupli_ID_Flags)0 : (eDupli_ID_Flags)U.dupflag; - char name[MAX_ID_NAME - 2]; - /* find object, create fake base */ - RNA_string_get(op->ptr, "name", name); - ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name); + /* Find object, create fake base. */ + + Object *ob = reinterpret_cast( + id_add_lookup_from_name_or_session_uuid_props(bmain, op, ID_OB)); if (ob == nullptr) { BKE_report(op->reports, RPT_ERROR, "Object not found"); @@ -3734,7 +3784,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op) } /* prepare dupli */ - basen = object_add_duplicate_internal( + Base *basen = object_add_duplicate_internal( bmain, scene, view_layer, @@ -3814,7 +3864,7 @@ void OBJECT_OT_add_named(wmOperatorType *ot) "Linked", "Duplicate object but not object data, linking to the original data"); - RNA_def_string(ot->srna, "name", nullptr, MAX_ID_NAME - 2, "Name", "Object name to add"); + id_add_lookup_props(ot, true); prop = RNA_def_float_matrix( ot->srna, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f); @@ -3836,14 +3886,11 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob; - if (RNA_struct_property_is_set(op->ptr, "name")) { - char name[MAX_ID_NAME - 2]; - RNA_string_get(op->ptr, "name", name); - ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name); - } - else { + Object *ob = reinterpret_cast( + id_add_lookup_from_name_or_session_uuid_props(bmain, op, ID_OB)); + + if (!ob) { ob = OBACT(view_layer); } @@ -3922,12 +3969,25 @@ void OBJECT_OT_transform_to_mouse(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; PropertyRNA *prop; - RNA_def_string(ot->srna, - "name", - nullptr, - MAX_ID_NAME - 2, - "Name", - "Object name to place (when unset use the active object)"); + prop = RNA_def_string( + ot->srna, + "name", + nullptr, + MAX_ID_NAME - 2, + "Name", + "Object name to place (uses the active object when this and 'session_uuid' are unset)"); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); + prop = RNA_def_int(ot->srna, + "session_uuid", + 0, + INT32_MIN, + INT32_MAX, + "Session UUID", + "Session UUID of the object to place (uses the active object when this and " + "'name' are unset)", + INT32_MIN, + INT32_MAX); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); prop = RNA_def_float_matrix( ot->srna, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index a02058fde6b..5ddfc4fe3cc 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -716,7 +716,7 @@ static void view3d_ob_drop_copy_local_id(bContext *UNUSED(C), wmDrag *drag, wmDr { ID *id = WM_drag_get_local_ID(drag, ID_OB); - RNA_string_set(drop->ptr, "name", id->name + 2); + RNA_int_set(drop->ptr, "session_uuid", id->session_uuid); /* Don't duplicate ID's which were just imported. Only do that for existing, local IDs. */ BLI_assert(drag->type != WM_DRAG_ASSET); @@ -751,7 +751,7 @@ static void view3d_ob_drop_copy_external_asset(bContext *UNUSED(C), wmDrag *drag DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); - RNA_string_set(drop->ptr, "name", id->name + 2); + RNA_int_set(drop->ptr, "session_uuid", id->session_uuid); Base *base = BKE_view_layer_base_find(view_layer, (Object *)id); if (base != NULL) { -- cgit v1.2.3 From 0d6dda4555bcae82cf581bdb23d639e9733057b5 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 23 May 2022 20:32:36 +0200 Subject: Cleanup: Move new utilities for ID lookup operator properties Move them to a more accessible place, so that other operators in different files can use them. The following commit needs this. --- source/blender/editors/object/object_add.cc | 67 ++--------------------------- 1 file changed, 4 insertions(+), 63 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index 5bd4ca3a861..0fc504f7de5 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -252,65 +252,6 @@ static int object_add_drop_xy_generic_invoke(bContext *C, wmOperator *op, const return op->type->exec(C, op); } -/** - * Tries to find an ID in \a bmain. Three needs to be either a "name" string or "session_uuid" int - * property defined and set. The former has priority. - * - * See #id_add_lookup_props for a helper to add the properties. - */ -static ID *id_add_lookup_from_name_or_session_uuid_props(Main *bmain, - const wmOperator *op, - const ID_Type type) -{ - PropertyRNA *prop_name = RNA_struct_find_property(op->ptr, "name"); - PropertyRNA *prop_session_uuid = RNA_struct_find_property(op->ptr, "session_uuid"); - - if (prop_name && RNA_property_is_set(op->ptr, prop_name)) { - char name[MAX_ID_NAME - 2]; - RNA_property_string_get(op->ptr, prop_name, name); - return BKE_libblock_find_name(bmain, type, name); - } - - if (prop_session_uuid && RNA_property_is_set(op->ptr, prop_session_uuid)) { - const uint32_t session_uuid = (uint32_t)RNA_property_int_get(op->ptr, prop_session_uuid); - return BKE_libblock_find_session_uuid(bmain, type, session_uuid); - } - - return nullptr; -} - -/** - * Adds "name" and "session_uuid" properties to the operator so the caller can tell the operator - * which ID to add. See #id_add_find_from_name_or_session_uuid_op_props(). Both properties will be - * hidden in the UI. - * - * \note New operators should probably use "session_uuid" only (set \a add_name_prop to #false), - * since this works with linked data and/or library overrides (in both cases, multiple IDs with the - * same name and type may be present). The "name" property is only kept to not break compatibility - * with old scripts using these operators. - */ -static void id_add_lookup_props(wmOperatorType *ot, const bool add_name_prop = false) -{ - PropertyRNA *prop; - - if (add_name_prop) { - prop = RNA_def_string( - ot->srna, "name", nullptr, MAX_ID_NAME - 2, "Name", "Name of the data-block to add"); - RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); - } - - prop = RNA_def_int(ot->srna, - "session_uuid", - 0, - INT32_MIN, - INT32_MAX, - "Session UUID", - "Session UUID of the data-block to add", - INT32_MIN, - INT32_MAX); - RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -1712,7 +1653,7 @@ static std::optional collection_add_info_get_from_op(bContext PropertyRNA *prop_location = RNA_struct_find_property(op->ptr, "location"); add_info.collection = reinterpret_cast( - id_add_lookup_from_name_or_session_uuid_props(bmain, op, ID_GR)); + WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op, ID_GR)); bool update_location_if_necessary = false; if (add_info.collection) { @@ -3776,7 +3717,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op) /* Find object, create fake base. */ Object *ob = reinterpret_cast( - id_add_lookup_from_name_or_session_uuid_props(bmain, op, ID_OB)); + WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op, ID_OB)); if (ob == nullptr) { BKE_report(op->reports, RPT_ERROR, "Object not found"); @@ -3864,7 +3805,7 @@ void OBJECT_OT_add_named(wmOperatorType *ot) "Linked", "Duplicate object but not object data, linking to the original data"); - id_add_lookup_props(ot, true); + WM_operator_properties_id_lookup(ot, true); prop = RNA_def_float_matrix( ot->srna, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f); @@ -3888,7 +3829,7 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = reinterpret_cast( - id_add_lookup_from_name_or_session_uuid_props(bmain, op, ID_OB)); + WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op, ID_OB)); if (!ob) { ob = OBACT(view_layer); -- cgit v1.2.3 From 8f79fa9c6780dd5526dccce039c49bc7f69f47df Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 23 May 2022 20:54:15 +0200 Subject: Fix further issues when mixing link & append for asset drag & drop 917c096be6b9 applied to objects only, this also applies the same fix for the general 3D View drop operations, e.g. used for dragging materials, images, worlds, etc. This is needed to fix T95706, but apparently something else is still going on. Needs further investigation. --- source/blender/editors/object/object_relations.c | 8 +++----- source/blender/editors/space_view3d/space_view3d.c | 6 +++--- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 76dcfbd8d36..0a85a60eda8 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2629,11 +2629,9 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent Object *ob = ED_view3d_give_material_slot_under_cursor(C, event->mval, &mat_slot); mat_slot = max_ii(mat_slot, 1); - Material *ma; - char name[MAX_ID_NAME - 2]; + Material *ma = (Material *)WM_operator_properties_id_lookup_from_name_or_session_uuid( + bmain, op, ID_MA); - RNA_string_get(op->ptr, "name", name); - ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name); if (ob == NULL || ma == NULL) { return OPERATOR_CANCELLED; } @@ -2663,7 +2661,7 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot) ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; /* properties */ - RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign"); + WM_operator_properties_id_lookup(ot, true); } /** \} */ diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 5ddfc4fe3cc..e7732f07ed9 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -823,15 +823,15 @@ static void view3d_id_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *dr { ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); - RNA_string_set(drop->ptr, "name", id->name + 2); + WM_operator_properties_id_lookup_set_from_id(drop->ptr, id); } static void view3d_id_drop_copy_with_type(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop) { ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); - RNA_string_set(drop->ptr, "name", id->name + 2); RNA_enum_set(drop->ptr, "type", GS(id->name)); + WM_operator_properties_id_lookup_set_from_id(drop->ptr, id); } static void view3d_id_path_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop) @@ -839,7 +839,7 @@ static void view3d_id_path_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBo ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); if (id) { - RNA_string_set(drop->ptr, "name", id->name + 2); + WM_operator_properties_id_lookup_set_from_id(drop->ptr, id); RNA_struct_property_unset(drop->ptr, "filepath"); } else if (drag->path[0]) { -- cgit v1.2.3