[Bf-blender-cvs] [5336e68] master: Fix T41062: "copy to selected" doens't work for all attributes.

Bastien Montagne noreply at git.blender.org
Tue Aug 5 19:26:57 CEST 2014


Commit: 5336e68e110252b1da18bf8749b62b6a9f01c10a
Author: Bastien Montagne
Date:   Tue Aug 5 18:59:02 2014 +0200
Branches: master
https://developer.blender.org/rB5336e68e110252b1da18bf8749b62b6a9f01c10a

Fix T41062: "copy to selected" doens't work for all attributes.

The issue was that some properties are no direct children of the struct we support in 'copy to selected'
(RNA_Sequence in this case). Since we can't use the ID of sequences here (it's the scene, while we need
a sequence level of control), we had to add a new API helper to RNA path, which takes a RNA type
and return a path relative to the closest ancester of that type.

This way, we get a path from the RNA_Sequence, and can easily apply it to all other valid sequences
to copy the property.

Review, suggestions and edits by Campbell Barton, thanks!

===================================================================

M	source/blender/editors/interface/interface_ops.c
M	source/blender/makesrna/RNA_access.h
M	source/blender/makesrna/intern/rna_access.c

===================================================================

diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 32b073b..458aca4 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -262,28 +262,43 @@ 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 *r_lb, bool *r_use_path_from_id, char **r_path)
 {
-	*use_path = false;
+	*r_use_path_from_id = false;
+	*r_path = NULL;
 
-	if (RNA_struct_is_a(ptr->type, &RNA_EditBone))
-		*lb = CTX_data_collection_get(C, "selected_editable_bones");
-	else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone))
-		*lb = CTX_data_collection_get(C, "selected_pose_bones");
-	else if (RNA_struct_is_a(ptr->type, &RNA_Sequence))
-		*lb = CTX_data_collection_get(C, "selected_editable_sequences");
-	else {
+	if (RNA_struct_is_a(ptr->type, &RNA_EditBone)) {
+		*r_lb = CTX_data_collection_get(C, "selected_editable_bones");
+	}
+	else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
+		*r_lb = CTX_data_collection_get(C, "selected_pose_bones");
+	}
+	else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
+		*r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
+	}
+	else if (ptr->id.data) {
 		ID *id = ptr->id.data;
 
-		if (id && GS(id->name) == ID_OB) {
-			*lb = CTX_data_collection_get(C, "selected_editable_objects");
-			*use_path = true;
+		if (GS(id->name) == ID_OB) {
+			*r_lb = CTX_data_collection_get(C, "selected_editable_objects");
+			*r_use_path_from_id = true;
+			*r_path = RNA_path_from_ID_to_property(ptr, prop);
 		}
-		else {
-			return false;
+		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 ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != NULL) {
+				*r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
+			}
 		}
+		return (*r_path != NULL);
 	}
-	
+	else {
+		return false;
+	}
+
 	return true;
 }
 
@@ -307,47 +322,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..ba2dd8b 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -927,9 +927,22 @@ bool RNA_path_resolve_property(PointerRNA *ptr, const char *path,
 bool RNA_path_resolve_property_full(PointerRNA *ptr, const char *path,
                                     PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index);
 
+typedef struct PropertyElemRNA PropertyElemRNA;
+struct PropertyElemRNA {
+	PropertyElemRNA *next, *prev;
+	PointerRNA ptr;
+	PropertyRNA *prop;
+	int index;
+};
+bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, struct ListBase *r_elements);
+
 char *RNA_path_from_ID_to_struct(PointerRNA *ptr);
 char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop);
 
+char *RNA_path_resolve_from_type_to_property(
+        struct PointerRNA *ptr, struct PropertyRNA *prop,
+        const 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..8c76edd 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -4015,11 +4015,14 @@ static bool rna_path_parse_array_index(const char **path, PointerRNA *ptr, Prope
 }
 
 static bool rna_path_parse(PointerRNA *ptr, const char *path,
-                           PointerRNA *r_ptr, PropertyRNA **r_prop, int *index,
+                           PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index,
+                           ListBase *r_elements,
                            const bool eval_pointer)
 {
 	PropertyRNA *prop;
 	PointerRNA curptr;
+	PropertyElemRNA *prop_elem = NULL;
+	int index = -1;
 	char fixedbuf[256];
 	int type;
 
@@ -4061,6 +4064,14 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
 		if (!prop)
 			return false;
 
+		if (r_elements) {
+			prop_elem = MEM_mallocN(sizeof(PropertyElemRNA), __func__);
+			prop_elem->ptr = curptr;
+			prop_elem->prop = prop;
+			prop_elem->index = -1;  /* index will be added later, if needed. */
+			BLI_addtail(r_elements, prop_elem);
+		}
+
 		type = RNA_property_type(prop);
 
 		/* now look up the value of this property if it is a pointer or
@@ -4076,7 +4087,7 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
 					
 					curptr = nextptr;
 					prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
-					if (index) *index = -1;
+					index = -1;
 				}
 				break;
 			}
@@ -4093,21 +4104,38 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
 					
 					curptr = nextptr;
 					prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
-					if (index) *index = -1;
+					index = -1;
 				}
 				break;
 			}
 			default:
-				if (index) {
-					if (!rna_path_parse_array_index(&path, &curptr, prop, index))
+				if (r_index || prop_elem) {
+					if (!rna_path_parse_array_index(&path, &curptr, prop, &index)) {
 						return false;
+					}
+
+					if (prop_elem) {
+						prop_elem->index = index;
+					}
 				}
 				break;
 		}
 	}
 
-	*r_ptr = curptr;
-	*r_prop = prop;
+	if (r_ptr)
+		*r_ptr = curptr;
+	if (r_prop)
+		*r_prop = prop;
+	if (r_index)
+		*r_index = index;
+
+	if (prop_elem && (prop_elem->ptr.data != curptr.data || prop_elem->prop != prop || prop_elem->index != index)) {
+		PropertyElemRNA *prop_elem = MEM_mallocN(sizeof(PropertyElemRNA), __func__);
+		prop_elem->ptr = curptr;
+		prop_elem->prop = prop;
+		prop_elem->index = index;
+		BLI_addtail(r_elements, prop_elem);
+	}
 
 	return true;
 }
@@ -4120,7 +4148,7 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
  */
 bool RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
 {
-	if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, true))
+	if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, NULL, true))
 		return false;
 
 	return r_ptr->data != NULL;
@@ -4134,7 +4162,7 @@ bool RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, Prop
  */
 bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
 {
-	if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, true))
+	if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, true))
 		return false;
 
 	return r_ptr->data != NULL;
@@ -4149,7 +4177,7 @@ bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr,
  */
 bool RNA_path_resolve_property(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
 {
-	if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, false))
+	if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, NULL, false))
 		return false;
 
 	return r_ptr->data != NULL && *r_prop != NULL;
@@ -4165,12 +4193,25 @@ bool RNA_path_resolve_property(PointerRNA *ptr, const char *path, PointerRNA *r_
  */
 bool RNA_path_resolve_property_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
 {
-	if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, false))
+	if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, false))
 		return false;
 
 	return r_ptr->data != NULL && *r_prop != NULL;
 }
 
+/**
+ * Resolve the given RNA Path into a linked list of PropertyElemRNA's.
+ *
+ * To be used when complex operations over path are needed, like e.g. get relative paths, to avoid too much
+ * string operations.
+ *
+ * \return T

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list