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:
-rw-r--r--source/blender/blenkernel/BKE_armature.h2
-rw-r--r--source/blender/blenkernel/intern/armature.c124
-rw-r--r--source/blender/blenkernel/intern/armature_update.c11
-rw-r--r--source/blender/makesrna/intern/rna_armature_api.c53
-rw-r--r--source/blender/makesrna/intern/rna_pose_api.c71
5 files changed, 206 insertions, 55 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 1831e93cccb..0e356c1557f 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -165,9 +165,11 @@ typedef struct BBoneSplineParameters {
} BBoneSplineParameters;
void BKE_pchan_get_bbone_handles(struct bPoseChannel *pchan, struct bPoseChannel **r_prev, struct bPoseChannel **r_next);
+void BKE_pchan_get_bbone_spline_parameters(struct bPoseChannel *pchan, const bool rest, struct BBoneSplineParameters *r_param);
void b_bone_spline_setup(struct bPoseChannel *pchan, const bool rest, Mat4 result_array[MAX_BBONE_SUBDIV]);
+void BKE_compute_b_bone_handles(const BBoneSplineParameters *param, float h1[3], float *r_roll1, float h2[3], float *r_roll2, bool ease, bool offsets);
int BKE_compute_b_bone_spline(struct BBoneSplineParameters *param, Mat4 result_array[MAX_BBONE_SUBDIV]);
void BKE_pchan_cache_bbone_segments(struct bPoseChannel *pchan);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 2004b66c1ef..9abd20679d8 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -462,20 +462,18 @@ void BKE_pchan_get_bbone_handles(bPoseChannel *pchan, bPoseChannel **r_prev, bPo
}
}
-/* Fills the array with the desired amount of bone->segments elements.
- * This calculation is done within unit bone space. */
-void b_bone_spline_setup(bPoseChannel *pchan, const bool rest, Mat4 result_array[MAX_BBONE_SUBDIV])
+/* Compute B-Bone spline parameters for the given channel. */
+void BKE_pchan_get_bbone_spline_parameters(struct bPoseChannel *pchan, const bool rest, struct BBoneSplineParameters *param)
{
bPoseChannel *next, *prev;
Bone *bone = pchan->bone;
- BBoneSplineParameters param;
float imat[4][4], posemat[4][4];
float delta[3];
- memset(&param, 0, sizeof(param));
+ memset(param, 0, sizeof(*param));
- param.segments = bone->segments;
- param.length = bone->length;
+ param->segments = bone->segments;
+ param->length = bone->length;
if (!rest) {
float scale[3];
@@ -484,8 +482,8 @@ void b_bone_spline_setup(bPoseChannel *pchan, const bool rest, Mat4 result_array
mat4_to_size(scale, pchan->pose_mat);
if (fabsf(scale[0] - scale[1]) > 1e-6f || fabsf(scale[1] - scale[2]) > 1e-6f) {
- param.do_scale = true;
- copy_v3_v3(param.scale, scale);
+ param->do_scale = true;
+ copy_v3_v3(param->scale, scale);
}
}
@@ -497,7 +495,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, const bool rest, Mat4 result_array
if (rest) {
invert_m4_m4(imat, pchan->bone->arm_mat);
}
- else if (param.do_scale) {
+ else if (param->do_scale) {
copy_m4_m4(posemat, pchan->pose_mat);
normalize_m4(posemat);
invert_m4_m4(imat, posemat);
@@ -510,14 +508,14 @@ void b_bone_spline_setup(bPoseChannel *pchan, const bool rest, Mat4 result_array
float h1[3];
bool done = false;
- param.use_prev = true;
+ param->use_prev = true;
/* Transform previous point inside this bone space. */
if (bone->bbone_prev_type == BBONE_HANDLE_RELATIVE) {
/* Use delta movement (from restpose), and apply this relative to the current bone's head. */
if (rest) {
/* In restpose, arm_head == pose_head */
- zero_v3(param.prev_h);
+ zero_v3(param->prev_h);
done = true;
}
else {
@@ -538,19 +536,19 @@ void b_bone_spline_setup(bPoseChannel *pchan, const bool rest, Mat4 result_array
}
else {
/* Apply special handling for smoothly joining B-Bone chains */
- param.prev_bbone = (prev->bone->segments > 1);
+ param->prev_bbone = (prev->bone->segments > 1);
/* Use bone head as absolute position. */
copy_v3_v3(h1, rest ? prev->bone->arm_head : prev->pose_head);
}
if (!done) {
- mul_v3_m4v3(param.prev_h, imat, h1);
+ mul_v3_m4v3(param->prev_h, imat, h1);
}
- if (!param.prev_bbone) {
+ if (!param->prev_bbone) {
/* Find the previous roll to interpolate. */
- mul_m4_m4m4(param.prev_mat, imat, rest ? prev->bone->arm_mat : prev->pose_mat);
+ mul_m4_m4m4(param->prev_mat, imat, rest ? prev->bone->arm_mat : prev->pose_mat);
}
}
@@ -558,14 +556,14 @@ void b_bone_spline_setup(bPoseChannel *pchan, const bool rest, Mat4 result_array
float h2[3];
bool done = false;
- param.use_next = true;
+ param->use_next = true;
/* Transform next point inside this bone space. */
if (bone->bbone_next_type == BBONE_HANDLE_RELATIVE) {
/* Use delta movement (from restpose), and apply this relative to the current bone's tail. */
if (rest) {
/* In restpose, arm_head == pose_head */
- copy_v3_fl3(param.next_h, 0.0f, param.length, 0.0);
+ copy_v3_fl3(param->next_h, 0.0f, param->length, 0.0);
done = true;
}
else {
@@ -586,18 +584,18 @@ void b_bone_spline_setup(bPoseChannel *pchan, const bool rest, Mat4 result_array
}
else {
/* Apply special handling for smoothly joining B-Bone chains */
- param.next_bbone = (next->bone->segments > 1);
+ param->next_bbone = (next->bone->segments > 1);
/* Use bone tail as absolute position. */
copy_v3_v3(h2, rest ? next->bone->arm_tail : next->pose_tail);
}
if (!done) {
- mul_v3_m4v3(param.next_h, imat, h2);
+ mul_v3_m4v3(param->next_h, imat, h2);
}
/* Find the next roll to interpolate as well. */
- mul_m4_m4m4(param.next_mat, imat, rest ? next->bone->arm_mat : next->pose_mat);
+ mul_m4_m4m4(param->next_mat, imat, rest ? next->bone->arm_mat : next->pose_mat);
}
/* Add effects from bbone properties over the top
@@ -615,64 +613,65 @@ void b_bone_spline_setup(bPoseChannel *pchan, const bool rest, Mat4 result_array
* end up animating
*/
{
- param.ease1 = bone->ease1 + (!rest ? pchan->ease1 : 0.0f);
- param.ease2 = bone->ease2 + (!rest ? pchan->ease2 : 0.0f);
+ param->ease1 = bone->ease1 + (!rest ? pchan->ease1 : 0.0f);
+ param->ease2 = bone->ease2 + (!rest ? pchan->ease2 : 0.0f);
- param.roll1 = bone->roll1 + (!rest ? pchan->roll1 : 0.0f);
- param.roll2 = bone->roll2 + (!rest ? pchan->roll2 : 0.0f);
+ param->roll1 = bone->roll1 + (!rest ? pchan->roll1 : 0.0f);
+ param->roll2 = bone->roll2 + (!rest ? pchan->roll2 : 0.0f);
if (bone->flag & BONE_ADD_PARENT_END_ROLL) {
if (prev) {
if (prev->bone) {
- param.roll1 += prev->bone->roll2;
+ param->roll1 += prev->bone->roll2;
}
if (!rest) {
- param.roll1 += prev->roll2;
+ param->roll1 += prev->roll2;
}
}
}
- param.scaleIn = bone->scaleIn * (!rest ? pchan->scaleIn : 1.0f);
- param.scaleOut = bone->scaleOut * (!rest ? pchan->scaleOut : 1.0f);
+ param->scaleIn = bone->scaleIn * (!rest ? pchan->scaleIn : 1.0f);
+ param->scaleOut = bone->scaleOut * (!rest ? pchan->scaleOut : 1.0f);
/* Extra curve x / y */
- param.curveInX = bone->curveInX + (!rest ? pchan->curveInX : 0.0f);
- param.curveInY = bone->curveInY + (!rest ? pchan->curveInY : 0.0f);
+ param->curveInX = bone->curveInX + (!rest ? pchan->curveInX : 0.0f);
+ param->curveInY = bone->curveInY + (!rest ? pchan->curveInY : 0.0f);
- param.curveOutX = bone->curveOutX + (!rest ? pchan->curveOutX : 0.0f);
- param.curveOutY = bone->curveOutY + (!rest ? pchan->curveOutY : 0.0f);
+ param->curveOutX = bone->curveOutX + (!rest ? pchan->curveOutX : 0.0f);
+ param->curveOutY = bone->curveOutY + (!rest ? pchan->curveOutY : 0.0f);
}
-
- bone->segments = BKE_compute_b_bone_spline(&param, result_array);
}
/* Fills the array with the desired amount of bone->segments elements.
* This calculation is done within unit bone space. */
-int BKE_compute_b_bone_spline(BBoneSplineParameters *param, Mat4 result_array[MAX_BBONE_SUBDIV])
+void b_bone_spline_setup(bPoseChannel *pchan, const bool rest, Mat4 result_array[MAX_BBONE_SUBDIV])
{
- float scalemat[4][4], iscalemat[4][4];
- float mat3[3][3];
- float h1[3], roll1, h2[3], roll2;
- float data[MAX_BBONE_SUBDIV + 1][4], *fp;
- int a;
+ BBoneSplineParameters param;
+
+ BKE_pchan_get_bbone_spline_parameters(pchan, rest, &param);
+ pchan->bone->segments = BKE_compute_b_bone_spline(&param, result_array);
+}
+
+/* Computes the bezier handle vectors and rolls coming from custom handles. */
+void BKE_compute_b_bone_handles(const BBoneSplineParameters *param, float h1[3], float *r_roll1, float h2[3], float *r_roll2, bool ease, bool offsets)
+{
+ float mat3[3][3];
float length = param->length;
if (param->do_scale) {
- size_to_mat4(scalemat, param->scale);
- invert_m4_m4(iscalemat, scalemat);
-
length *= param->scale[1];
}
+ *r_roll1 = *r_roll2 = 0.0f;
+
if (param->use_prev) {
copy_v3_v3(h1, param->prev_h);
if (param->prev_bbone) {
/* If previous bone is B-bone too, use average handle direction. */
h1[1] -= length;
- roll1 = 0.0f;
}
normalize_v3(h1);
@@ -681,12 +680,11 @@ int BKE_compute_b_bone_spline(BBoneSplineParameters *param, Mat4 result_array[MA
if (!param->prev_bbone) {
/* Find the previous roll to interpolate. */
copy_m3_m4(mat3, param->prev_mat);
- mat3_vec_to_roll(mat3, h1, &roll1);
+ mat3_vec_to_roll(mat3, h1, r_roll1);
}
}
else {
h1[0] = 0.0f; h1[1] = 1.0; h1[2] = 0.0f;
- roll1 = 0.0f;
}
if (param->use_next) {
@@ -704,14 +702,13 @@ int BKE_compute_b_bone_spline(BBoneSplineParameters *param, Mat4 result_array[MA
/* Find the next roll to interpolate as well. */
copy_m3_m4(mat3, param->next_mat);
- mat3_vec_to_roll(mat3, h2, &roll2);
+ mat3_vec_to_roll(mat3, h2, r_roll2);
}
else {
h2[0] = 0.0f; h2[1] = 1.0f; h2[2] = 0.0f;
- roll2 = 0.0;
}
- {
+ if (ease) {
const float circle_factor = length * (cubic_tangent_factor_circle_v3(h1, h2) / 0.75f);
const float hlength1 = param->ease1 * circle_factor;
@@ -736,10 +733,10 @@ int BKE_compute_b_bone_spline(BBoneSplineParameters *param, Mat4 result_array[MA
* - The "pchan" level offsets are the ones that animators actually
* end up animating
*/
- {
+ if (offsets) {
/* Add extra rolls. */
- roll1 += param->roll1;
- roll2 += param->roll2;
+ *r_roll1 += param->roll1;
+ *r_roll2 += param->roll2;
/* Extra curve x / y */
/* NOTE: Scale correction factors here are to compensate for some random floating-point glitches
@@ -755,6 +752,27 @@ int BKE_compute_b_bone_spline(BBoneSplineParameters *param, Mat4 result_array[MA
h2[0] += param->curveOutX * xscale_correction;
h2[2] += param->curveOutY * yscale_correction;
}
+}
+
+/* Fills the array with the desired amount of bone->segments elements.
+ * This calculation is done within unit bone space. */
+int BKE_compute_b_bone_spline(BBoneSplineParameters *param, Mat4 result_array[MAX_BBONE_SUBDIV])
+{
+ float scalemat[4][4], iscalemat[4][4];
+ float mat3[3][3];
+ float h1[3], roll1, h2[3], roll2;
+ float data[MAX_BBONE_SUBDIV + 1][4], *fp;
+ float length = param->length;
+ int a;
+
+ if (param->do_scale) {
+ size_to_mat4(scalemat, param->scale);
+ invert_m4_m4(iscalemat, scalemat);
+
+ length *= param->scale[1];
+ }
+
+ BKE_compute_b_bone_handles(param, h1, &roll1, h2, &roll2, true, true);
/* Make curve. */
CLAMP_MAX(param->segments, MAX_BBONE_SUBDIV);
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index b917aae08de..f5519966ac2 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -715,17 +715,24 @@ void BKE_pose_bone_done(struct Depsgraph *depsgraph,
copy_v3_v3(pchan_orig->pose_head, pchan->pose_mat[3]);
copy_m4_m4(pchan_orig->constinv, pchan->constinv);
BKE_pose_where_is_bone_tail(pchan_orig);
+ if (pchan->bone == NULL || pchan->bone->segments <= 1) {
+ BKE_pose_channel_free_bbone_cache(pchan_orig);
+ }
}
}
void BKE_pose_eval_bbone_segments(struct Depsgraph *depsgraph,
- struct Object *ob,
- int pchan_index)
+ struct Object *ob,
+ int pchan_index)
{
bPoseChannel *pchan = pose_pchan_get_indexed(ob, pchan_index);
DEG_debug_print_eval(depsgraph, __func__, pchan->name, pchan);
if (pchan->bone != NULL && pchan->bone->segments > 1) {
BKE_pchan_cache_bbone_segments(pchan);
+ bArmature *arm = (bArmature *)ob->data;
+ if (DEG_is_active(depsgraph) && arm->edbo == NULL) {
+ BKE_pchan_copy_bbone_segments_cache(pchan->orig_pchan, pchan);
+ }
}
}
diff --git a/source/blender/makesrna/intern/rna_armature_api.c b/source/blender/makesrna/intern/rna_armature_api.c
index 222baf99afd..55caac973d8 100644
--- a/source/blender/makesrna/intern/rna_armature_api.c
+++ b/source/blender/makesrna/intern/rna_armature_api.c
@@ -42,6 +42,7 @@
#include <stddef.h>
+#include "BLI_math_vector.h"
#include "BKE_armature.h"
static void rna_EditBone_align_roll(EditBone *ebo, float no[3])
@@ -56,6 +57,24 @@ static float rna_Bone_do_envelope(Bone *bone, float *vec)
bone->rad_tail * scale, bone->dist * scale);
}
+static void rna_Bone_MatrixFromAxisRoll(float *axis, float roll, float *r_matrix)
+{
+ vec_roll_to_mat3(axis, roll, (float (*)[3])r_matrix);
+}
+
+static void rna_Bone_AxisRollFromMatrix(float *matrix, float *axis_override, float *r_axis, float *r_roll)
+{
+ float mat[3][3];
+
+ normalize_m3_m3(mat, (float (*)[3])matrix);
+
+ if (normalize_v3_v3(r_axis, axis_override) != 0.0f) {
+ mat3_vec_to_roll(mat, r_axis, r_roll);
+ }
+ else {
+ mat3_to_vec_roll(mat, r_axis, r_roll);
+ }
+}
#else
void RNA_api_armature_edit_bone(StructRNA *srna)
@@ -83,6 +102,40 @@ void RNA_api_bone(StructRNA *srna)
/* return value */
parm = RNA_def_float(func, "factor", 0, -FLT_MAX, FLT_MAX, "Factor", "Envelope factor", -FLT_MAX, FLT_MAX);
RNA_def_function_return(func, parm);
+
+ /* Conversions between Matrix and Axis + Roll representations. */
+ func = RNA_def_function(srna, "MatrixFromAxisRoll", "rna_Bone_MatrixFromAxisRoll");
+ RNA_def_function_ui_description(func, "Convert the axis + roll representation to a matrix");
+ RNA_def_function_flag(func, FUNC_NO_SELF);
+ parm = RNA_def_property(func, "axis", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_array(parm, 3);
+ RNA_def_property_ui_text(parm, "", "The main axis of the bone (tail - head)");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_property(func, "roll", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(parm, "", "The roll of the bone");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_property(func, "result_matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_3x3);
+ RNA_def_property_ui_text(parm, "", "The resulting orientation matrix");
+ RNA_def_function_output(func, parm);
+
+ func = RNA_def_function(srna, "AxisRollFromMatrix", "rna_Bone_AxisRollFromMatrix");
+ RNA_def_function_ui_description(func, "Convert a rotational matrix to the axis + roll representation");
+ RNA_def_function_flag(func, FUNC_NO_SELF);
+ parm = RNA_def_property(func, "matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_3x3);
+ RNA_def_property_ui_text(parm, "", "The orientation matrix of the bone");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_property(func, "axis", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_array(parm, 3);
+ RNA_def_property_ui_text(parm, "", "The optional override for the axis (finds closest approximation for the matrix)");
+ parm = RNA_def_property(func, "result_axis", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_array(parm, 3);
+ RNA_def_property_ui_text(parm, "", "The main axis of the bone");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_property(func, "result_roll", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(parm, "", "The roll of the bone");
+ RNA_def_function_output(func, parm);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_pose_api.c b/source/blender/makesrna/intern/rna_pose_api.c
index 04ecdd497f6..f4463e0f7d8 100644
--- a/source/blender/makesrna/intern/rna_pose_api.c
+++ b/source/blender/makesrna/intern/rna_pose_api.c
@@ -59,6 +59,45 @@ static float rna_PoseBone_do_envelope(bPoseChannel *chan, float *vec)
return distfactor_to_bone(vec, chan->pose_head, chan->pose_tail, bone->rad_head * scale,
bone->rad_tail * scale, bone->dist * scale);
}
+
+static void rna_PoseBone_bbone_segment_matrix(bPoseChannel *pchan, ReportList *reports, float mat_ret[16], int index, bool rest)
+{
+ if (!pchan->bone || pchan->bone->segments <= 1) {
+ BKE_reportf(reports, RPT_ERROR, "Bone '%s' is not a B-Bone!", pchan->name);
+ return;
+ }
+ if (pchan->runtime.bbone_segments != pchan->bone->segments) {
+ BKE_reportf(reports, RPT_ERROR, "Bone '%s' has out of date B-Bone segment data!", pchan->name);
+ return;
+ }
+ if (index < 0 || index >= pchan->runtime.bbone_segments) {
+ BKE_reportf(reports, RPT_ERROR, "Invalid index %d for B-Bone segments of '%s'!", index, pchan->name);
+ return;
+ }
+
+ if (rest) {
+ copy_m4_m4((float (*)[4])mat_ret, pchan->runtime.bbone_rest_mats[index].mat);
+ }
+ else {
+ copy_m4_m4((float (*)[4])mat_ret, pchan->runtime.bbone_pose_mats[index].mat);
+ }
+}
+
+static void rna_PoseBone_compute_bbone_handles(
+ bPoseChannel *pchan, ReportList *reports,
+ float ret_h1[3], float *ret_roll1, float ret_h2[3], float *ret_roll2,
+ bool rest, bool ease, bool offsets)
+{
+ if (!pchan->bone || pchan->bone->segments <= 1) {
+ BKE_reportf(reports, RPT_ERROR, "Bone '%s' is not a B-Bone!", pchan->name);
+ return;
+ }
+
+ BBoneSplineParameters params;
+
+ BKE_pchan_get_bbone_spline_parameters(pchan, rest, &params);
+ BKE_compute_b_bone_handles(&params, ret_h1, ret_roll1, ret_h2, ret_roll2, ease || offsets, offsets);
+}
#else
void RNA_api_pose(StructRNA *UNUSED(srna))
@@ -80,6 +119,38 @@ void RNA_api_pose_channel(StructRNA *srna)
/* return value */
parm = RNA_def_float(func, "factor", 0, -FLT_MAX, FLT_MAX, "Factor", "Envelope factor", -FLT_MAX, FLT_MAX);
RNA_def_function_return(func, parm);
+
+ /* B-Bone segment matrices */
+ func = RNA_def_function(srna, "bbone_segment_matrix", "rna_PoseBone_bbone_segment_matrix");
+ RNA_def_function_ui_description(func, "Retrieve the matrix of the B-Bone segment if available");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_property(func, "matrix_return", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(parm, "", "The resulting matrix in bone local space");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of the segment", 0, 10000);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_boolean(func, "rest", false, "", "Return the rest pose matrix");
+
+ /* B-Bone custom handle positions */
+ func = RNA_def_function(srna, "compute_bbone_handles", "rna_PoseBone_compute_bbone_handles");
+ RNA_def_function_ui_description(func, "Retrieve the vectors and rolls coming from B-Bone custom handles");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_property(func, "handle1", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_array(parm, 3);
+ RNA_def_property_ui_text(parm, "", "The direction vector of the start handle in bone local space");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_float(func, "roll1", 0, -FLT_MAX, FLT_MAX, "", "Roll of the start handle", -FLT_MAX, FLT_MAX);
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_property(func, "handle2", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_array(parm, 3);
+ RNA_def_property_ui_text(parm, "", "The direction vector of the end handle in bone local space");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_float(func, "roll2", 0, -FLT_MAX, FLT_MAX, "", "Roll of the end handle", -FLT_MAX, FLT_MAX);
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_boolean(func, "rest", false, "", "Return the rest pose state");
+ parm = RNA_def_boolean(func, "ease", false, "", "Apply scale from ease values");
+ parm = RNA_def_boolean(func, "offsets", false, "", "Apply roll and curve offsets from bone properties");
}