From fc5bf09fd88c331b568c5b485bb0e487179ecb44 Mon Sep 17 00:00:00 2001 From: Yuki Shirakawa Date: Tue, 11 May 2021 11:22:41 +0200 Subject: Rigging: Add transform for custom bone shapes Add translation/rotation/scale parameters for custom bones shapes. The new scale is a 3D vector `custom_shape_scale_xyz`, and replaces the `custom_shape_scale` float. Reviewed By: #animation_rigging, sybren, zeddb Differential Revision: https://developer.blender.org/D10974 --- .../scripts/startup/bl_ui/properties_data_bone.py | 7 ++++++- source/blender/blenkernel/intern/action.c | 8 ++++++-- source/blender/blenkernel/intern/armature.c | 3 ++- source/blender/blenloader/intern/versioning_300.c | 11 +++++++++++ .../draw/engines/overlay/overlay_armature.c | 22 +++++++++++++++------- source/blender/makesdna/DNA_action_types.h | 14 ++++++++------ source/blender/makesrna/intern/rna_pose.c | 19 ++++++++++++++++--- 7 files changed, 64 insertions(+), 20 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py index f3e116ca321..6452ad8465b 100644 --- a/release/scripts/startup/bl_ui/properties_data_bone.py +++ b/release/scripts/startup/bl_ui/properties_data_bone.py @@ -292,10 +292,15 @@ class BONE_PT_display_custom_shape(BoneButtonsPanel, Panel): sub = col.column() sub.active = bool(pchan and pchan.custom_shape) sub.separator() - sub.prop(pchan, "custom_shape_scale", text="Scale") + + sub.prop(pchan, "custom_shape_scale_xyz", text="Scale") + sub.prop(pchan, "custom_shape_translation", text="Translation") + sub.prop(pchan, "custom_shape_rotation_euler", text="Rotation") + sub.prop_search(pchan, "custom_shape_transform", ob.pose, "bones", text="Override Transform") sub.prop(pchan, "use_custom_shape_bone_size") + sub.separator() sub.prop(bone, "show_wire", text="Wireframe") diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 3f3aa0386e2..a7e36b09516 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -656,7 +656,9 @@ bPoseChannel *BKE_pose_channel_ensure(bPose *pose, const char *name) BLI_strncpy(chan->name, name, sizeof(chan->name)); - chan->custom_scale = 1.0f; + copy_v3_fl(chan->custom_scale_xyz, 1.0f); + zero_v3(chan->custom_translation); + zero_v3(chan->custom_rotation_euler); /* init vars to prevent math errors */ unit_qt(chan->quat); @@ -1235,8 +1237,10 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f if (pchan->custom) { id_us_plus(&pchan->custom->id); } + copy_v3_v3(pchan->custom_scale_xyz, pchan_from->custom_scale_xyz); + copy_v3_v3(pchan->custom_translation, pchan_from->custom_translation); + copy_v3_v3(pchan->custom_rotation_euler, pchan_from->custom_rotation_euler); - pchan->custom_scale = pchan_from->custom_scale; pchan->drawflag = pchan_from->drawflag; } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 80992cff34d..f67c2cb4372 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2881,7 +2881,8 @@ bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden NULL; if (bb_custom) { float mat[4][4], smat[4][4]; - scale_m4_fl(smat, PCHAN_CUSTOM_DRAW_SIZE(pchan)); + scale_m4_fl(smat, PCHAN_CUSTOM_BONE_LENGTH(pchan)); + mul_m4_v3(smat, pchan->custom_scale_xyz); mul_m4_series(mat, ob->obmat, pchan_tx->pose_mat, smat); BKE_boundbox_minmax(bb_custom, mat, r_min, r_max); } diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 182231b5878..ae2371402e4 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -21,6 +21,7 @@ #define DNA_DEPRECATED_ALLOW #include "BLI_listbase.h" +#include "BLI_math_vector.h" #include "BLI_utildefines.h" #include "DNA_brush_types.h" @@ -95,5 +96,15 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) */ { /* Keep this block, even when empty. */ + if (!DNA_struct_elem_find(fd->filesdna, "bPoseChannel", "float", "custom_scale_xyz[3]")) { + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + if (ob->pose == NULL) { + continue; + } + LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { + copy_v3_fl(pchan->custom_scale_xyz, pchan->custom_scale); + } + } + } } } diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index 54224071d23..e4072879adc 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -1031,7 +1031,7 @@ static void pchan_draw_data_init(bPoseChannel *pchan) static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel *pchan) { float ebmat[4][4]; - float length; + float bone_scale[3]; float(*bone_mat)[4]; float(*disp_mat)[4]; float(*disp_tail_mat)[4]; @@ -1040,23 +1040,23 @@ static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel * * and not be tight to the draw pass creation. * This would refresh armature without invalidating the draw cache */ if (pchan) { - length = pchan->bone->length; bone_mat = pchan->pose_mat; disp_mat = pchan->disp_mat; disp_tail_mat = pchan->disp_tail_mat; + mul_v3_v3fl(bone_scale, pchan->custom_scale_xyz, pchan->bone->length); } else { eBone->length = len_v3v3(eBone->tail, eBone->head); ED_armature_ebone_to_mat4(eBone, ebmat); - length = eBone->length; + copy_v3_fl(bone_scale, eBone->length); bone_mat = ebmat; disp_mat = eBone->disp_mat; disp_tail_mat = eBone->disp_tail_mat; } copy_m4_m4(disp_mat, bone_mat); - rescale_m4(disp_mat, (float[3]){length, length, length}); + rescale_m4(disp_mat, bone_scale); copy_m4_m4(disp_tail_mat, disp_mat); translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f); } @@ -1255,19 +1255,27 @@ static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pc static void draw_bone_update_disp_matrix_custom(bPoseChannel *pchan) { - float length; + float bone_scale[3]; float(*bone_mat)[4]; float(*disp_mat)[4]; float(*disp_tail_mat)[4]; + float rot_mat[3][3]; /* See TODO above */ - length = PCHAN_CUSTOM_DRAW_SIZE(pchan); + mul_v3_v3fl(bone_scale, pchan->custom_scale_xyz, PCHAN_CUSTOM_BONE_LENGTH(pchan)); bone_mat = pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat; disp_mat = pchan->disp_mat; disp_tail_mat = pchan->disp_tail_mat; + eulO_to_mat3(rot_mat, pchan->custom_rotation_euler, ROT_MODE_XYZ); + copy_m4_m4(disp_mat, bone_mat); - rescale_m4(disp_mat, (float[3]){length, length, length}); + translate_m4(disp_mat, + pchan->custom_translation[0], + pchan->custom_translation[1], + pchan->custom_translation[2]); + mul_m4_m4m3(disp_mat, disp_mat, rot_mat); + rescale_m4(disp_mat, bone_scale); copy_m4_m4(disp_tail_mat, disp_mat); translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f); } diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 5cc525a6cff..05d33f5b339 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -265,9 +265,10 @@ typedef struct bPoseChannel { * since the alternative is highly complicated - campbell */ struct bPoseChannel *custom_tx; - float custom_scale; - - char _pad1[4]; + float custom_scale; /* Deprecated */ + float custom_scale_xyz[3]; + float custom_translation[3]; + float custom_rotation_euler[3]; /** Transforms - written in by actions or transform. */ float loc[3]; @@ -417,9 +418,10 @@ typedef enum ePchan_DrawFlag { PCHAN_DRAW_NO_CUSTOM_BONE_SIZE = (1 << 0), } ePchan_DrawFlag; -#define PCHAN_CUSTOM_DRAW_SIZE(pchan) \ - (pchan)->custom_scale *( \ - ((pchan)->drawflag & PCHAN_DRAW_NO_CUSTOM_BONE_SIZE) ? 1.0f : (pchan)->bone->length) + +/* Note: It doesn't take custom_scale_xyz into account */ +#define PCHAN_CUSTOM_BONE_LENGTH(pchan) \ + (((pchan)->drawflag & PCHAN_DRAW_NO_CUSTOM_BONE_SIZE) ? 1.0f : (pchan)->bone->length) #ifdef DNA_DEPRECATED_ALLOW /* PoseChannel->bboneflag */ diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index ba65e42895c..5ffbe1613e0 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -1359,12 +1359,25 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_dependency_update"); - prop = RNA_def_property(srna, "custom_shape_scale", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "custom_scale"); - RNA_def_property_range(prop, 0.0f, 1000.0f); + prop = RNA_def_property(srna, "custom_shape_scale_xyz", PROP_FLOAT, PROP_XYZ); + RNA_def_property_float_sdna(prop, NULL, "custom_scale_xyz"); + RNA_def_property_flag(prop, PROP_PROPORTIONAL); + RNA_def_property_float_array_default(prop, rna_default_scale_3d); RNA_def_property_ui_text(prop, "Custom Shape Scale", "Adjust the size of the custom shape"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); + prop = RNA_def_property(srna, "custom_shape_translation", PROP_FLOAT, PROP_XYZ); + RNA_def_property_float_sdna(prop, NULL, "custom_translation"); + RNA_def_property_flag(prop, PROP_PROPORTIONAL); + RNA_def_property_ui_text(prop, "Custom Shape Translation", "Adjust the location of the custom shape"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); + + prop = RNA_def_property(srna, "custom_shape_rotation_euler", PROP_FLOAT, PROP_EULER); + RNA_def_property_float_sdna(prop, NULL, "custom_rotation_euler"); + RNA_def_property_ui_text(prop, "Custom Shape Rotation", "Adjust the rotation of the custom shape"); + RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); + prop = RNA_def_property(srna, "use_custom_shape_bone_size", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "drawflag", PCHAN_DRAW_NO_CUSTOM_BONE_SIZE); RNA_def_property_ui_text( -- cgit v1.2.3