diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 32b073b..3855ce4 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -262,9 +262,11 @@ static void UI_OT_unset_property_button(wmOperatorType *ot)
/* Copy To Selected Operator ------------------------ */
-static bool copy_to_selected_list(bContext *C, PointerRNA *ptr, ListBase *lb, bool *use_path)
+static bool copy_to_selected_list(bContext *C, PointerRNA *ptr, PropertyRNA *prop, ListBase *lb,
+ bool *use_path_from_id, char **path)
{
- *use_path = false;
+ *use_path_from_id = false;
+ *path = NULL;
if (RNA_struct_is_a(ptr->type, &RNA_EditBone))
*lb = CTX_data_collection_get(C, "selected_editable_bones");
@@ -275,15 +277,23 @@ static bool copy_to_selected_list(bContext *C, PointerRNA *ptr, ListBase *lb, bo
else {
ID *id = ptr->id.data;
- if (id && GS(id->name) == ID_OB) {
- *lb = CTX_data_collection_get(C, "selected_editable_objects");
- *use_path = true;
- }
- else {
- return false;
+ if (id) {
+ if (GS(id->name) == ID_OB) {
+ *lb = CTX_data_collection_get(C, "selected_editable_objects");
+ *use_path_from_id = true;
+ *path = RNA_path_from_ID_to_property(ptr, prop);
+ }
+ else if (GS(id->name) == ID_SCE) { /* Sequencer's ID is scene :/ */
+ /* Try to recursively find an RNA_Sequence ancestor, to handle situations like T41062... */
+ if ((*path = RNA_path_from_ancestor_type_to_property(ptr, prop, &RNA_Sequence)) != NULL) {
+ *lb = CTX_data_collection_get(C, "selected_editable_sequences");
+ }
+ }
+ return (*path != NULL);
}
+ return false;
}
-
+
return true;
}
@@ -307,47 +317,54 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
/* if there is a valid property that is editable... */
if (ptr.data && prop) {
char *path = NULL;
- bool use_path;
+ bool use_path_from_id;
CollectionPointerLink *link;
ListBase lb;
- if (!copy_to_selected_list(C, &ptr, &lb, &use_path))
+ if (!copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path))
return success;
- if (!use_path || (path = RNA_path_from_ID_to_property(&ptr, prop))) {
- for (link = lb.first; link; link = link->next) {
- if (link->ptr.data != ptr.data) {
- if (use_path) {
- lprop = NULL;
- RNA_id_pointer_create(link->ptr.id.data, &idptr);
- RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
- }
- else {
- lptr = link->ptr;
- lprop = prop;
- }
+ for (link = lb.first; link; link = link->next) {
+ if (link->ptr.data != ptr.data) {
+ if (use_path_from_id) {
+ /* Path relative to ID. */
+ lprop = NULL;
+ RNA_id_pointer_create(link->ptr.id.data, &idptr);
+ RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
+ }
+ else if (path) {
+ /* Path relative to elements from list. */
+ lprop = NULL;
+ RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
+ }
+ else {
+ lptr = link->ptr;
+ lprop = prop;
+ }
- if (lprop == prop) {
- if (RNA_property_editable(&lptr, lprop)) {
- if (poll) {
+ if (lptr.data == ptr.data) {
+ /* lptr might not be the same as link->ptr! */
+ continue;
+ }
+
+ if (lprop == prop) {
+ if (RNA_property_editable(&lptr, lprop)) {
+ if (poll) {
+ success = true;
+ break;
+ }
+ else {
+ if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
+ RNA_property_update(C, &lptr, prop);
success = true;
- break;
- }
- else {
- if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
- RNA_property_update(C, &lptr, prop);
- success = true;
- }
}
}
}
}
}
-
- if (path)
- MEM_freeN(path);
}
+ MEM_SAFE_FREE(path);
BLI_freelistN(&lb);
}
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index a2bbaf6..f888734 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -930,6 +930,8 @@ bool RNA_path_resolve_property_full(PointerRNA *ptr, const char *path,
char *RNA_path_from_ID_to_struct(PointerRNA *ptr);
char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop);
+char *RNA_path_from_ancestor_type_to_property(struct PointerRNA *ptr, struct PropertyRNA *prop, struct StructRNA *type);
+
char *RNA_path_full_ID_py(struct ID *id);
char *RNA_path_full_struct_py(struct PointerRNA *ptr);
char *RNA_path_full_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 271f907..d98ef45 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -4498,6 +4498,40 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
}
/**
+ * Assumes ptr is not an instance of type!
+ * \return the path to given ptr/prop from the closest ancestor of given type, if any (else return NULL).
+ */
+char *RNA_path_from_ancestor_type_to_property(PointerRNA *ptr, PropertyRNA *prop, StructRNA *type)
+{
+ /* Try to recursively find an "type"'d ancestor, to handle situations where path from ID is not enough. */
+ PointerRNA idptr, tptr;
+ PropertyRNA *tprop;
+ char *path = NULL;
+ char *full_path = RNA_path_from_ID_to_property(ptr, prop);
+ char *path_t1 = RNA_path_back(full_path); /* We remove property... */
+ char *path_t2 = RNA_path_back(path_t1); /* ... and first struct, which we assume as 'invalid'. */
+ MEM_SAFE_FREE(path_t1);
+ path_t1 = path_t2;
+
+ RNA_id_pointer_create(ptr->id.data, &idptr);
+
+ while (path_t1 && RNA_path_resolve(&idptr, path_t1, &tptr, &tprop)) {
+ if (RNA_struct_is_a(tptr.type, type)) {
+ path = BLI_strdup(full_path + strlen(path_t1) + 1); /* +1 for the linking '.' */
+ MEM_SAFE_FREE(path_t1);
+ break;
+ }
+
+ path_t2 = RNA_path_back(path_t1);
+ MEM_SAFE_FREE(path_t1);
+ path_t1 = path_t2;
+ }
+
+ MEM_SAFE_FREE(full_path);
+ return path;
+}
+
+/**
* Get the ID as a python representation, eg:
* bpy.data.foo["bar"]
*/