[Bf-blender-cvs] [16aa7dfa196] blender2.8: Fix T58391: correctly handle Curve Shape Key layout in Python API.

Alexander Gavrilov noreply at git.blender.org
Wed Dec 5 16:37:12 CET 2018


Commit: 16aa7dfa196df376f5c23f8892b172128b38bb52
Author: Alexander Gavrilov
Date:   Wed Dec 5 18:30:42 2018 +0300
Branches: blender2.8
https://developer.blender.org/rB16aa7dfa196df376f5c23f8892b172128b38bb52

Fix T58391: correctly handle Curve Shape Key layout in Python API.

The layout changed when the radius property was added to shape
keys in 2.8, but the RNA code wasn't updated.

Also, even before that, the code didn't do anything to correctly
handle mixing sub-curves of different type (nurbs vs bezier) in
the same Curve object. Now that case is handled correctly but not
very efficiently by allocating a mapping table when necessary. To
recover some performance, a custom index lookup function is added.

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

M	source/blender/makesrna/intern/rna_key.c

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

diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index ed1e0d2690e..684756c0b12 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -35,6 +35,7 @@
 
 #include "BLI_string_utils.h"
 #include "BLI_utildefines.h"
+#include "BLI_math.h"
 
 #include "BLT_translation.h"
 
@@ -42,6 +43,8 @@
 #include "RNA_define.h"
 #include "RNA_enum_types.h"
 
+#include "MEM_guardedalloc.h"
+
 #include "rna_internal.h"
 
 #ifdef RNA_RUNTIME
@@ -336,6 +339,19 @@ static void rna_ShapeKeyCurvePoint_tilt_set(PointerRNA *ptr, float value)
 	vec[3] = value;
 }
 
+static float rna_ShapeKeyCurvePoint_radius_get(PointerRNA *ptr)
+{
+	float *vec = (float *)ptr->data;
+	return vec[4];
+}
+
+static void rna_ShapeKeyCurvePoint_radius_set(PointerRNA *ptr, float value)
+{
+	float *vec = (float *)ptr->data;
+	CLAMP_MIN(value, 0.0f);
+	vec[4] = value;
+}
+
 static void rna_ShapeKeyBezierPoint_co_get(PointerRNA *ptr, float *values)
 {
 	float *vec = (float *)ptr->data;
@@ -390,35 +406,166 @@ static void rna_ShapeKeyBezierPoint_handle_2_co_set(PointerRNA *ptr, const float
 	vec[6 + 2] = values[2];
 }
 
-#if 0
 static float rna_ShapeKeyBezierPoint_tilt_get(PointerRNA *ptr)
 {
 	float *vec = (float *)ptr->data;
-	return vec[10];
+	return vec[9];
 }
 
 static void rna_ShapeKeyBezierPoint_tilt_set(PointerRNA *ptr, float value)
 {
 	float *vec = (float *)ptr->data;
+	vec[9] = value;
+}
+
+static float rna_ShapeKeyBezierPoint_radius_get(PointerRNA *ptr)
+{
+	float *vec = (float *)ptr->data;
+	return vec[10];
+}
+
+static void rna_ShapeKeyBezierPoint_radius_set(PointerRNA *ptr, float value)
+{
+	float *vec = (float *)ptr->data;
+	CLAMP_MIN(value, 0.0f);
 	vec[10] = value;
 }
-#endif
+
+/* Indexing and iteration of Curve points through sub-curves. */
+typedef struct NurbInfo {
+	Nurb *nu;
+	int nurb_size, nurb_elem_step;
+
+	/* Current index in the Nurb */
+	int nurb_index;
+
+	/* Total index as item and element. */
+	int item_index, elem_index;
+} NurbInfo;
+
+StructRNA *rna_ShapeKey_curve_point_type(Nurb *nu)
+{
+	if (nu->bezt) {
+		return &RNA_ShapeKeyBezierPoint;
+	}
+	else {
+		return &RNA_ShapeKeyCurvePoint;
+	}
+}
+
+static void rna_ShapeKey_NurbInfo_init(NurbInfo *r_info, Nurb *nu)
+{
+	r_info->nu = nu;
+
+	if (nu->bezt) {
+		r_info->nurb_size = nu->pntsu;
+		r_info->nurb_elem_step = KEYELEM_ELEM_LEN_BEZTRIPLE;
+	}
+	else {
+		r_info->nurb_size = nu->pntsu * nu->pntsv;
+		r_info->nurb_elem_step = KEYELEM_ELEM_LEN_BPOINT;
+	}
+}
+
+static void rna_ShapeKey_NurbInfo_step(NurbInfo *r_info, Nurb *nu, int *p_raw_index, bool input_elem)
+{
+	rna_ShapeKey_NurbInfo_init(r_info, nu);
+
+	if (input_elem) {
+		r_info->nurb_index = MIN2(r_info->nurb_size, *p_raw_index / r_info->nurb_elem_step);
+		*p_raw_index -= r_info->nurb_size * r_info->nurb_elem_step;
+	}
+	else {
+		r_info->nurb_index = MIN2(r_info->nurb_size, *p_raw_index);
+		*p_raw_index -= r_info->nurb_size;
+	}
+
+	r_info->item_index += r_info->nurb_index;
+	r_info->elem_index += r_info->nurb_index * r_info->nurb_elem_step;
+}
+
+static void rna_ShapeKey_NurbInfo_find_index(Key *key, int raw_index, bool input_elem, NurbInfo *r_info)
+{
+	Curve *cu = (Curve *)key->from;
+
+	memset(r_info, 0, sizeof(*r_info));
+
+	for (Nurb *nu = cu->nurb.first; nu && raw_index >= 0; nu = nu->next) {
+		rna_ShapeKey_NurbInfo_step(r_info, nu, &raw_index, input_elem);
+	}
+}
+
+static int rna_ShapeKey_curve_find_index(Key *key, int elem_index)
+{
+	NurbInfo info;
+	rna_ShapeKey_NurbInfo_find_index(key, elem_index, true, &info);
+	return info.item_index;
+}
+
+typedef struct ShapeKeyCurvePoint {
+	StructRNA *type;
+	void *data;
+} ShapeKeyCurvePoint;
+
+/* Build a mapping array for Curve objects with mixed sub-curve types. */
+static void rna_ShapeKey_data_begin_mixed(CollectionPropertyIterator *iter, Key *key, KeyBlock *kb, Curve *cu)
+{
+	int point_count = rna_ShapeKey_curve_find_index(key, kb->totelem);
+
+	ShapeKeyCurvePoint *points = MEM_malloc_arrayN(sizeof(ShapeKeyCurvePoint), point_count, __func__);
+
+	char *databuf = kb->data;
+	int items_left = point_count;
+	NurbInfo info = { NULL };
+
+	for (Nurb *nu = cu->nurb.first; nu && items_left > 0; nu = nu->next) {
+		ShapeKeyCurvePoint *nurb_points = points + info.item_index;
+		char *nurb_data = databuf + info.elem_index * key->elemsize;
+
+		rna_ShapeKey_NurbInfo_step(&info, nu, &items_left, false);
+
+		StructRNA *type = rna_ShapeKey_curve_point_type(nu);
+
+		for (int i = 0; i < info.nurb_index; i++) {
+			nurb_points[i].type = type;
+			nurb_points[i].data = nurb_data + i * info.nurb_elem_step * key->elemsize;
+		}
+	}
+
+	rna_iterator_array_begin(iter, points, sizeof(*points), point_count, true, NULL);
+}
 
 static void rna_ShapeKey_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
 	Key *key = rna_ShapeKey_find_key(ptr->id.data);
 	KeyBlock *kb = (KeyBlock *)ptr->data;
-	Curve *cu;
-	Nurb *nu;
 	int tot = kb->totelem, size = key->elemsize;
 
-	if (GS(key->from->name) == ID_CU) {
-		cu = (Curve *)key->from;
-		nu = cu->nurb.first;
+	if (GS(key->from->name) == ID_CU && tot > 0) {
+		Curve *cu = (Curve *)key->from;
+		StructRNA *type = NULL;
+		NurbInfo info = { 0 };
+
+		/* Check if all sub-curves have the same type. */
+		for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
+			if (type == NULL) {
+				type = rna_ShapeKey_curve_point_type(nu);
+				rna_ShapeKey_NurbInfo_init(&info, nu);
+			}
+			else if (type != rna_ShapeKey_curve_point_type(nu)) {
+				type = NULL;
+				break;
+			}
+		}
 
-		if (nu->bezt) {
-			tot /= 3;
-			size *= 3;
+		/* If types are mixed, build a mapping array. */
+		if (type == NULL) {
+			rna_ShapeKey_data_begin_mixed(iter, key, kb, cu);
+			return;
+		}
+		else {
+			tot /= info.nurb_elem_step;
+			size *= info.nurb_elem_step;
 		}
 	}
 
@@ -429,16 +576,10 @@ static int rna_ShapeKey_data_length(PointerRNA *ptr)
 {
 	Key *key = rna_ShapeKey_find_key(ptr->id.data);
 	KeyBlock *kb = (KeyBlock *)ptr->data;
-	Curve *cu;
-	Nurb *nu;
 	int tot = kb->totelem;
 
 	if (GS(key->from->name) == ID_CU) {
-		cu = (Curve *)key->from;
-		nu = cu->nurb.first;
-
-		if (nu->bezt)
-			tot /= 3;
+		tot = rna_ShapeKey_curve_find_index(key, tot);
 	}
 
 	return tot;
@@ -447,23 +588,57 @@ static int rna_ShapeKey_data_length(PointerRNA *ptr)
 static PointerRNA rna_ShapeKey_data_get(CollectionPropertyIterator *iter)
 {
 	Key *key = rna_ShapeKey_find_key(iter->parent.id.data);
-	StructRNA *type;
-	Curve *cu;
-	Nurb *nu;
+	void *ptr = rna_iterator_array_get(iter);
+	StructRNA *type = &RNA_ShapeKeyPoint;
+
+	/* If data_begin allocated a mapping array, access it. */
+	if (iter->internal.array.free_ptr) {
+		ShapeKeyCurvePoint *point = ptr;
+
+		return rna_pointer_inherit_refine(&iter->parent, point->type, point->data);
+	}
 
 	if (GS(key->from->name) == ID_CU) {
-		cu = (Curve *)key->from;
-		nu = cu->nurb.first;
+		Curve *cu = (Curve *)key->from;
 
-		if (nu->bezt)
-			type = &RNA_ShapeKeyBezierPoint;
-		else
-			type = &RNA_ShapeKeyCurvePoint;
+		type = rna_ShapeKey_curve_point_type(cu->nurb.first);
+	}
+
+	return rna_pointer_inherit_refine(&iter->parent, type, ptr);
+}
+
+int rna_ShapeKey_data_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr)
+{
+	Key *key = rna_ShapeKey_find_key(ptr->id.data);
+	KeyBlock *kb = (KeyBlock *)ptr->data;
+	int elemsize = key->elemsize;
+	char *databuf = kb->data;
+
+	memset(r_ptr, 0, sizeof(*r_ptr));
+
+	if (index < 0) {
+		return false;
+	}
+
+	if (GS(key->from->name) == ID_CU) {
+		NurbInfo info;
+		rna_ShapeKey_NurbInfo_find_index(key, index, false, &info);
+
+		if (info.nu && info.nurb_index < info.nurb_size) {
+			StructRNA *type = rna_ShapeKey_curve_point_type(info.nu);
+
+			*r_ptr = rna_pointer_inherit_refine(ptr, type, databuf + elemsize * info.elem_index);
+			return true;
+		}
+	}
+	else {
+		if (index < kb->totelem) {
+			*r_ptr = rna_pointer_inherit_refine(ptr, &RNA_ShapeKeyPoint, databuf + elemsize * index);
+			return true;
+		}
 	}
-	else
-		type = &RNA_ShapeKeyPoint;
 
-	return rna_pointer_inherit_refine(&iter->parent, type, rna_iterator_array_get(iter));
+	return false;
 }
 
 static char *rna_ShapeKey_path(PointerRNA *ptr)
@@ -547,19 +722,6 @@ static int rna_ShapeKeyPoint_get_index(Key *key, KeyBlock *kb, float *point)
 	return (int)(pt - start) / key->elemsize;
 }
 
-static int rna_ShapeKeyBezierPoint_get_index(KeyBlock *kb, float *point)
-{
-	float *start = (float *)kb->data;
-
-	/* Unlike with rna_ShapeKeyPoint_get_index(), we cannot use key->elemsize here
-	 * since the default value for curves (16) is actually designed for BPoints
-	 * (i.e. NURBS Surfaces). The magic number "12" here was found by empirical
-	 * testing on a 64-bit system, and is similar to what's used for meshes and
-	 * lattices. For more details, see T38013
-	 */
-	return (int)(point - start) / 12;
-}
-
 static char *rna_ShapeKeyPoint_path(PointerRNA *ptr)
 {
 	ID *id = (ID *)ptr->id.data;
@@ -574,10 +736,11 @@ static char *rna_ShapeKeyPoint_path(PointerRNA *ptr)
 		char name_esc_kb[sizeof(kb->name) * 2];
 		int index;
 
-		if (ptr->type == &RNA_ShapeKeyBezierPoint)
-			index = rna_ShapeKeyBezierPoint_get_index(kb, point);
-		else
-			index = rna_ShapeKeyPoint_get_index(key, kb, point);
+		index = rna_ShapeKeyPoint_get_index(key, kb, point);
+
+		if (ELEM(ptr->type, &RNA_ShapeKeyBezierPoint, &RNA_ShapeKeyCurvePoint)) {
+			index = rna_ShapeKey_curve_find_index(key, index);
+		}
 
 		BLI_strescape(name_esc_kb, kb->name, sizeof(name_esc_kb));
 
@@ -600,6 +763,8 @@ const EnumPropertyItem rna_enum_keyblock_type_items[] = {
 	{0, NULL, 0, NULL, NULL}
 };
 
+static const float tilt_limit = DEG2RADF(21600.0f);
+
 static void rna_def_keydata(BlenderRNA *brna)
 {
 	StructRNA *srna;
@@ -626,9 +791,17 @@ static void rna_def_keydata(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Location", "");
 	RNA_def_property_update(prop, 0, "rna_Key_update_data");
 
-	prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_NONE);
+	prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_ANGLE);
 	RNA_def_property_float_funcs(prop, "rna_ShapeKeyCurvePoint_tilt_get", "rna_ShapeKeyCurvePoint_tilt_set", NULL);
-	RNA_def_property_ui_text(prop, "Tilt", "");
+	RNA_def_property_ran

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list