Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <julian@blender.org>2022-05-23 21:00:33 +0300
committerJulian Eisel <julian@blender.org>2022-05-23 21:11:37 +0300
commit917c096be6b93ce5ad1eb284d344da10000ab896 (patch)
tree732619bb3d84e8626381cd0853bd26467f159273 /source/blender/editors/object/object_add.cc
parentffa262c9f8c43498293a9f45876bad9214b283dc (diff)
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.
Diffstat (limited to 'source/blender/editors/object/object_add.cc')
-rw-r--r--source/blender/editors/object/object_add.cc124
1 files changed, 92 insertions, 32 deletions
diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc
index ac8ab834cb7..fe22cd63b74 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<CollectionAddInfo> 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<Collection *>(
+ 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 {
@@ -3802,15 +3854,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<Object *>(
+ 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");
@@ -3818,7 +3868,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,
@@ -3898,7 +3948,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);
@@ -3920,14 +3970,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<Object *>(
+ id_add_lookup_from_name_or_session_uuid_props(bmain, op, ID_OB));
+
+ if (!ob) {
ob = OBACT(view_layer);
}
@@ -4006,12 +4053,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);