[Bf-blender-cvs] [9e87069c3ec] tmp-static-override-insertion: Static override: initial work for generating 'insertion' in collections.

Bastien Montagne noreply at git.blender.org
Wed May 2 11:38:15 CEST 2018


Commit: 9e87069c3ec4c4327f0d2e8c2c450436cd7866a0
Author: Bastien Montagne
Date:   Tue May 1 15:24:17 2018 +0200
Branches: tmp-static-override-insertion
https://developer.blender.org/rB9e87069c3ec4c4327f0d2e8c2c450436cd7866a0

Static override: initial work for generating 'insertion' in collections.

Does not yet support applying those operations, only detecting
insertions and generating matching rules was already rather complicated.

Also got rid of ;ost rna_path string allocation in collection diffing
code, could help a bit with speed too.

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

M	source/blender/makesrna/RNA_types.h
M	source/blender/makesrna/intern/rna_object.c
M	source/blender/makesrna/intern/rna_pose.c
M	source/blender/makesrna/intern/rna_rna.c

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

diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 77d9aabd661..5d6f309ad65 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -158,7 +158,7 @@ typedef enum PropertySubType {
 
 /* Make sure enums are updated with these */
 /* HIGHEST FLAG IN USE: 1 << 31
- * FREE FLAGS: 9, 11, 13, 14, 15, 30 */
+ * FREE FLAGS: 11, 13, 14, 15, 30 */
 typedef enum PropertyFlag {
 	/* editable means the property is editable in the user
 	 * interface, properties are editable by default except
@@ -178,6 +178,8 @@ typedef enum PropertyFlag {
 
 	/* Means the property can be overriden by a local 'proxy' of some linked datablock. */
 	PROP_OVERRIDABLE_STATIC      = (1 << 2),
+	/* The property supports insertion (collections only). */
+	PROP_OVERRIDABLE_STATIC_INSERTION = (1 << 9),
 
 	/* Forbid usage of this property in comparison (& hence override) code.
 	 * Useful e.g. for collections of data like mesh's geometry, particles, etc. */
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 464fcc3856e..0fec39f9676 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -2067,13 +2067,13 @@ static void rna_def_object(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE);
 	RNA_def_property_struct_type(prop, "Modifier");
 	RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting the geometric data of the object");
-	RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
+	RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC | PROP_OVERRIDABLE_STATIC_INSERTION);
 	rna_def_object_modifiers(brna, prop);
 
 	/* constraints */
 	prop = RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE);
 	RNA_def_property_struct_type(prop, "Constraint");
-	RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
+	RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC | PROP_OVERRIDABLE_STATIC_INSERTION);
 	RNA_def_property_ui_text(prop, "Constraints", "Constraints affecting the transformation of the object");
 /*	RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "constraints__add", "constraints__remove"); */
 	rna_def_object_constraints(brna, prop);
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index a2005dbb161..df1e7a63bd9 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -806,7 +806,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
 	/* Bone Constraints */
 	prop = RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE);
 	RNA_def_property_struct_type(prop, "Constraint");
-	RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
+	RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC | PROP_OVERRIDABLE_STATIC_INSERTION);
 	RNA_def_property_ui_text(prop, "Constraints", "Constraints that act on this PoseChannel");
 
 	rna_def_pose_channel_constraints(brna, prop);
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 448d0882fb3..bdb5c215da2 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -106,6 +106,7 @@ const EnumPropertyItem rna_enum_property_unit_items[] = {
 #ifdef RNA_RUNTIME
 #include "MEM_guardedalloc.h"
 #include "BLI_ghash.h"
+#include "BLI_string.h"
 
 #include "BKE_library_override.h"
 
@@ -1093,39 +1094,129 @@ static int rna_BlenderRNA_structs_lookup_string(PointerRNA *ptr, const char *key
 
 /* Default override (and compare) callbacks. */
 
-/* Used for both Pointer and Collection properties. */
-static int rna_property_override_diff_propptr(
-        PointerRNA *propptr_a, PointerRNA *propptr_b, eRNACompareMode mode, const bool no_ownership,
-        IDOverrideStatic *override, const char *rna_path, const int flags, bool *r_override_changed)
+/* Ensures it makes sense to go inside the pointers to compare their content
+ * (if they are IDs, or have different names or RNA type, then this would be meaningless). */
+static bool rna_property_override_diff_propptr_validate_diffing(
+        PointerRNA *propptr_a, PointerRNA *propptr_b,
+        bool *r_is_id, bool *r_is_null, bool *r_is_type_diff,
+        char **r_propname_a, char *propname_a_buff, size_t propname_a_buff_size,
+        char **r_propname_b, char *propname_b_buff, size_t propname_b_buff_size)
 {
-	const bool do_create = override != NULL && (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0 && rna_path != NULL;
+	BLI_assert(propptr_a != NULL);
 
-	bool is_id = false;
-	bool is_type_null = false;
+	bool is_valid_for_diffing = true;
+	const bool do_force_name = r_propname_a != NULL;
+
+	if (do_force_name) {
+		BLI_assert(r_propname_a != NULL);
+		BLI_assert(r_propname_b != NULL);
+	}
+
+	*r_is_id = *r_is_null = *r_is_type_diff = false;
 
 	/* Beware, PointerRNA_NULL has no type and is considered a 'blank page'! */
 	if (propptr_a->type == NULL) {
-		if (propptr_b->type == NULL) {
-			if (r_override_changed) {
-				*r_override_changed = false;
-			}
-			return 0;
+		if (propptr_b == NULL || propptr_b->type == NULL) {
+			*r_is_null = true;
 		}
-		is_id = RNA_struct_is_ID(propptr_b->type);
-		is_type_null = true;
+		else {
+			*r_is_id = RNA_struct_is_ID(propptr_b->type);
+			*r_is_null = true;
+			*r_is_type_diff = true;
+		}
+		is_valid_for_diffing = false;
 	}
 	else {
-		is_id = RNA_struct_is_ID(propptr_a->type);
-		is_type_null = (propptr_b->type == NULL);
+		*r_is_id = RNA_struct_is_ID(propptr_a->type);
+		*r_is_null = *r_is_type_diff = (ELEM(NULL, propptr_b, propptr_b->type));
+		is_valid_for_diffing = !(*r_is_id || *r_is_null);
 	}
 
-	if (is_id) {
+	if (propptr_b == NULL || propptr_a->type != propptr_b->type) {
+		*r_is_type_diff = true;
+		is_valid_for_diffing = false;
+//		printf("%s: different pointer RNA types\n", rna_path ? rna_path : "<UNKNOWN>");
+	}
+
+	/* We do a generic quick first comparison checking for "name" and/or "type" properties.
+	 * We assume that is any of those are false, then we are not handling the same data.
+	 * This helps a lot in static override case, especially to detect inserted items in collections. */
+	if (is_valid_for_diffing || do_force_name) {
+		PropertyRNA *nameprop_a = RNA_struct_name_property(propptr_a->type);
+		PropertyRNA *nameprop_b = (propptr_b != NULL) ? RNA_struct_name_property(propptr_b->type) : NULL;
+
+		int propname_a_len = 0, propname_b_len = 0;
+		char *propname_a = NULL;
+		char *propname_b = NULL;
+		char buff_a[4096];
+		char buff_b[4096];
+		if (nameprop_a != NULL) {
+			if (r_propname_a == NULL && propname_a_buff == NULL) {
+				propname_a_buff = buff_a;
+				propname_a_buff_size = sizeof(buff_a);
+			}
+
+			propname_a = RNA_property_string_get_alloc(
+			                 propptr_a, nameprop_a, propname_a_buff, propname_a_buff_size, &propname_a_len);
+//			printf("propname_a = %s\n", propname_a ? propname_a : "<NONE>");
+
+			if (r_propname_a != NULL) {
+				*r_propname_a = propname_a;
+			}
+		}
+//		else printf("item of type %s a has no name property!\n", propptr_a->type->name);
+		if (nameprop_b != NULL) {
+			if (r_propname_b == NULL && propname_b_buff == NULL) {
+				propname_b_buff = buff_b;
+				propname_b_buff_size = sizeof(buff_b);
+			}
+
+			propname_b = RNA_property_string_get_alloc(
+			                 propptr_b, nameprop_b, propname_b_buff, propname_b_buff_size, &propname_b_len);
+
+			if (r_propname_b != NULL) {
+				*r_propname_b = propname_b;
+			}
+		}
+		if (propname_a != NULL && propname_b != NULL) {
+			if (propname_a_len != propname_b_len ||
+			    propname_a[0] != propname_b[0] ||
+			    !STREQ(propname_a, propname_b))
+			{
+				is_valid_for_diffing = false;
+//				printf("%s: different names\n", rna_path ? rna_path : "<UNKNOWN>");
+			}
+		}
+	}
+
+	if (*r_is_id) {
 		BLI_assert(propptr_a->data == propptr_a->id.data && propptr_b->data == propptr_b->id.data);
+	}
+
+	return is_valid_for_diffing;
+}
+
+/* Used for both Pointer and Collection properties. */
+static int rna_property_override_diff_propptr(
+        PointerRNA *propptr_a, PointerRNA *propptr_b, eRNACompareMode mode, const bool no_ownership,
+        IDOverrideStatic *override, const char *rna_path, const int flags, bool *r_override_changed)
+{
+	const bool do_create = override != NULL && (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0 && rna_path != NULL;
+
+	bool is_id = false;
+	bool is_null = false;
+	bool is_type_diff = false;
+	/* If false, it means that the whole data itself is different, so no point in going inside of it at all! */
+	bool is_valid_for_diffing = rna_property_override_diff_propptr_validate_diffing(
+	                                propptr_a, propptr_b, &is_id, &is_null, &is_type_diff,
+	                                NULL, NULL, 0, NULL, NULL, 0);
+
+	if (is_id) {
 		BLI_assert(no_ownership);  /* For now, once we deal with nodetrees we'll want to get rid of that one. */
 	}
 
 	if (override) {
-		if (no_ownership /* || is_id */ || is_type_null) {
+		if (no_ownership /* || is_id */ || is_null || is_type_diff || !is_valid_for_diffing) {
 			/* In case this pointer prop does not own its data (or one is NULL), do not compare structs!
 			 * This is a quite safe path to infinite loop, among other nasty issues.
 			 * Instead, just compare pointers themselves. */
@@ -1156,6 +1247,8 @@ static int rna_property_override_diff_propptr(
 		}
 	}
 	else {
+		/* We could also use is_diff_pointer, but then we potentially lose the gt/lt info -
+		 * and don't think performances are critical here for now anyway... */
 		return !RNA_struct_equals(propptr_a, propptr_b, mode);
 	}
 }
@@ -1374,10 +1467,13 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
 
 		case PROP_STRING:
 		{
-			char fixed_a[128], fixed_b[128];
+			char fixed_a[4096], fixed_b[4096];
 			int len_str_a, len_str_b;
 			char *value_a = RNA_property_string_get_alloc(ptr_a, prop_a, fixed_a, sizeof(fixed_a), &len_str_a);
 			char *value_b = RNA_property_string_get_alloc(ptr_b, prop_b, fixed_b, sizeof(fixed_b), &len_str_b);
+			/* TODO we could do a check on length too, but then we wou

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list