Move B-Bone custom handle settings to Edit mode.
authorAlexander Gavrilov <angavrilov@gmail.com>
Sun, 5 Aug 2018 15:48:05 +0000 (18:48 +0300)
committerAlexander Gavrilov <angavrilov@gmail.com>
Thu, 4 Oct 2018 16:55:44 +0000 (19:55 +0300)
Custom handle settings actually affect the B-Bone rest shape,
so they should be changed in Edit mode rather than Pose mode.
This is necessary to be able to display the correct rest shape
of the bone in Edit Mode.

Also, instead of flags, introduce an enum to specify the handle
operation modes, so that new ones could be added later.

Differential Revision: https://developer.blender.org/D3588

15 files changed:
release/scripts/startup/bl_ui/properties_data_bone.py
source/blender/blenkernel/BKE_blender_version.h
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/armature.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/versioning_280.c
source/blender/editors/armature/armature_add.c
source/blender/editors/armature/armature_intern.h
source/blender/editors/armature/armature_utils.c
source/blender/editors/armature/editarmature_retarget.c
source/blender/editors/include/ED_armature.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_armature_types.h
source/blender/makesrna/intern/rna_armature.c
source/blender/makesrna/intern/rna_pose.c

index 3fc0c66b0b43d8d68e63f10734ea97af67e24918..bdee55666fdd07a4b9f6e3d8b065c786dafd3168 100644 (file)
@@ -130,6 +130,7 @@ class BONE_PT_curved(BoneButtonsPanel, Panel):
         bone = context.bone
         # arm = context.armature
         pchan = None
+        edit = False
 
         if ob and bone:
             pchan = ob.pose.bones[bone.name]
@@ -137,6 +138,7 @@ class BONE_PT_curved(BoneButtonsPanel, Panel):
         elif bone is None:
             bone = context.edit_bone
             bbone = bone
+            edit = True
         else:
             bbone = bone
 
@@ -169,24 +171,27 @@ class BONE_PT_curved(BoneButtonsPanel, Panel):
         col.prop(bbone, "bbone_easein", text="Ease In")
         col.prop(bbone, "bbone_easeout", text="Out")
 
-        if pchan:
-            topcol.separator()
-
-            col = topcol.column()
-            col.use_property_split = False
-            col.prop(pchan, "use_bbone_custom_handles")
+        col = topcol.column(align=True)
+        col.prop(bone, "bbone_handle_type_start", text="Start Handle")
 
-            col = topcol.column(align=True)
-            col.active = pchan.use_bbone_custom_handles
-            col.use_property_split = True
+        col = col.column(align=True)
+        col.active = (bone.bbone_handle_type_start != "AUTO")
+        if edit:
+            col.prop_search(bone, "bbone_custom_handle_start", ob.data, "edit_bones", text="Custom")
+        else:
+            # read-only
+            col.prop(bbone, "bbone_custom_handle_start", text="Custom")
 
-            sub = col.column()
-            sub.prop_search(pchan, "bbone_custom_handle_start", ob.pose, "bones", text="Custom Handle Start")
-            sub.prop_search(pchan, "bbone_custom_handle_end", ob.pose, "bones", text="End")
+        col = topcol.column(align=True)
+        col.prop(bone, "bbone_handle_type_end", text="End Handle")
 
-            sub = col.column(align=True)
-            sub.prop(pchan, "use_bbone_relative_start_handle", text="Relative Handle Start")
-            sub.prop(pchan, "use_bbone_relative_end_handle", text="End")
+        col = col.column(align=True)
+        col.active = (bone.bbone_handle_type_end != "AUTO")
+        if edit:
+            col.prop_search(bone, "bbone_custom_handle_end", ob.data, "edit_bones", text="Custom")
+        else:
+            # read-only
+            col.prop(bbone, "bbone_custom_handle_end", text="Custom")
 
 
 class BONE_PT_relations(BoneButtonsPanel, Panel):
index 7ac59d6c9d407e6233ede38760af92135aa7b33e..84451fe31d4e78b60efde94337cb3404648d4e69 100644 (file)
@@ -28,7 +28,7 @@
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         280
-#define BLENDER_SUBVERSION      24
+#define BLENDER_SUBVERSION      25
 /* Several breakages with 280, e.g. collections vs layers */
 #define BLENDER_MINVERSION      280
 #define BLENDER_MINSUBVERSION   0
index 9c407d27c297a06c95dde68c04599e97f6188e4f..68029ea72f6a236030aed8062a52ae637a8572bb 100644 (file)
@@ -887,7 +887,6 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f
        pchan->iklinweight = pchan_from->iklinweight;
 
        /* bbone settings (typically not animated) */
-       pchan->bboneflag = pchan_from->bboneflag;
        pchan->bbone_next = pchan_from->bbone_next;
        pchan->bbone_prev = pchan_from->bbone_prev;
 
@@ -1356,7 +1355,6 @@ void BKE_pose_copyesult_pchan_result(bPoseChannel *pchanto, const bPoseChannel *
        pchanto->rotmode = pchanfrom->rotmode;
        pchanto->flag = pchanfrom->flag;
        pchanto->protectflag = pchanfrom->protectflag;
-       pchanto->bboneflag = pchanfrom->bboneflag;
 }
 
 /* both poses should be in sync */
index e2a41f46e69ac275601bea84bc6f4ebf3bcda6ed..61472068399c9640db88f71da65793455aabbf77 100644 (file)
@@ -433,23 +433,31 @@ void equalize_bbone_bezier(float *data, int desired)
        copy_qt_qt(fp, temp[MAX_BBONE_SUBDIV]);
 }
 
-/* get "next" and "prev" bones - these are used for handle calculations */
+/* Get "next" and "prev" bones - these are used for handle calculations. */
 void BKE_pchan_get_bbone_handles(bPoseChannel *pchan, bPoseChannel **r_prev, bPoseChannel **r_next)
 {
-       if (pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES) {
-               /* use the provided bones as the next/prev - leave blank to eliminate this effect altogether */
-               *r_prev = pchan->bbone_prev;
-               *r_next = pchan->bbone_next;
-       }
-       else {
-               /* evaluate next and prev bones */
-               if (pchan->bone->flag & BONE_CONNECTED)
+       if (pchan->bone->bbone_prev_type == BBONE_HANDLE_AUTO) {
+               /* Use connected parent. */
+               if (pchan->bone->flag & BONE_CONNECTED) {
                        *r_prev = pchan->parent;
-               else
+               }
+               else {
                        *r_prev = NULL;
+               }
+       }
+       else {
+               /* Use the provided bone as prev - leave blank to eliminate this effect altogether. */
+               *r_prev = pchan->bbone_prev;
+       }
 
+       if (pchan->bone->bbone_next_type == BBONE_HANDLE_AUTO) {
+               /* Use connected child. */
                *r_next = pchan->child;
        }
+       else {
+               /* Use the provided bone as next - leave blank to eliminate this effect altogether. */
+               *r_next = pchan->bbone_next;
+       }
 }
 
 /* returns pointer to static array, filled with desired amount of bone->segments elements */
@@ -499,8 +507,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
                float difmat[4][4], result[3][3], imat3[3][3];
 
                /* transform previous point inside this bone space */
-               if ((pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES) &&
-                   (pchan->bboneflag & PCHAN_BBONE_CUSTOM_START_REL))
+               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) {
@@ -555,8 +562,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
                float difmat[4][4], result[3][3], imat3[3][3];
 
                /* transform next point inside this bone space */
-               if ((pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES) &&
-                   (pchan->bboneflag & PCHAN_BBONE_CUSTOM_END_REL))
+               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) {
@@ -2019,6 +2025,22 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
                        BKE_pose_channels_hash_free(pose);
                        BLI_freelinkN(&pose->chanbase, pchan);
                }
+               else {
+                       /* Find the custom B-Bone handles. */
+                       if (pchan->bone->bbone_prev) {
+                               pchan->bbone_prev = BKE_pose_channel_find_name(pose, pchan->bone->bbone_prev->name);
+                       }
+                       else {
+                               pchan->bbone_prev = NULL;
+                       }
+
+                       if (pchan->bone->bbone_next) {
+                               pchan->bbone_next = BKE_pose_channel_find_name(pose, pchan->bone->bbone_next->name);
+                       }
+                       else {
+                               pchan->bbone_next = NULL;
+                       }
+               }
        }
        /* printf("rebuild pose %s, %d bones\n", ob->id.name, counter); */
 
index 005e2c62b85c38a0fd21c1dd21c369b4a28b2c2f..275d14dbca3ebf0173b7957913b9cbfe7531540e 100644 (file)
@@ -3546,7 +3546,7 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
        bool rebuild = false;
 
        if (fd->memfile == NULL) {
-               if (ob->proxy || (ob->id.lib==NULL && arm->id.lib)) {
+               if (ob->proxy || ob->id.lib != arm->id.lib) {
                        rebuild = true;
                }
        }
@@ -3628,6 +3628,9 @@ static void direct_link_bones(FileData *fd, Bone *bone)
        bone->prop = newdataadr(fd, bone->prop);
        IDP_DirectLinkGroup_OrFree(&bone->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
 
+       bone->bbone_next = newdataadr(fd, bone->bbone_next);
+       bone->bbone_prev = newdataadr(fd, bone->bbone_prev);
+
        bone->flag &= ~BONE_DRAW_ACTIVE;
 
        link_list(fd, &bone->childbase);
index 1e2ae48ccb16b2e23ca1ec29a4f60f78c3f9f66d..5392e1dd4e8c1b219661f0c2bbc7c89e4ca0110f 100644 (file)
@@ -60,7 +60,9 @@
 #include "DNA_workspace_types.h"
 #include "DNA_key_types.h"
 #include "DNA_curve_types.h"
+#include "DNA_armature_types.h"
 
+#include "BKE_action.h"
 #include "BKE_collection.h"
 #include "BKE_constraint.h"
 #include "BKE_customdata.h"
@@ -87,6 +89,8 @@
 #include "BKE_key.h"
 #include "BKE_unit.h"
 
+#include "DEG_depsgraph.h"
+
 #include "BLT_translation.h"
 
 #include "BLO_readfile.h"
@@ -860,6 +864,51 @@ void do_versions_after_linking_280(Main *bmain)
                        }
                }
        }
+
+       /* Move B-Bone custom handle settings from bPoseChannel to Bone. */
+       if (!MAIN_VERSION_ATLEAST(bmain, 280, 25)) {
+               for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+                       bArmature *arm = ob->data;
+
+                       /* If it is an armature from the same file. */
+                       if (ob->pose && arm && arm->id.lib == ob->id.lib) {
+                               bool rebuild = false;
+
+                               for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+                                       /* If the 2.7 flag is enabled, processing is needed. */
+                                       if (pchan->bone && (pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES)) {
+                                               /* If the settings in the Bone are not set, copy. */
+                                               if (pchan->bone->bbone_prev_type == BBONE_HANDLE_AUTO &&
+                                                   pchan->bone->bbone_next_type == BBONE_HANDLE_AUTO &&
+                                                   pchan->bone->bbone_prev == NULL && pchan->bone->bbone_next == NULL)
+                                               {
+                                                       pchan->bone->bbone_prev_type = (pchan->bboneflag & PCHAN_BBONE_CUSTOM_START_REL) ? BBONE_HANDLE_RELATIVE : BBONE_HANDLE_ABSOLUTE;
+                                                       pchan->bone->bbone_next_type = (pchan->bboneflag & PCHAN_BBONE_CUSTOM_END_REL) ? BBONE_HANDLE_RELATIVE : BBONE_HANDLE_ABSOLUTE;
+
+                                                       if (pchan->bbone_prev) {
+                                                               pchan->bone->bbone_prev = pchan->bbone_prev->bone;
+                                                       }
+                                                       if (pchan->bbone_next) {
+                                                               pchan->bone->bbone_next = pchan->bbone_next->bone;
+                                                       }
+                                               }
+
+                                               rebuild = true;
+                                               pchan->bboneflag = 0;
+                                       }
+                               }
+
+                               /* Tag pose rebuild for all objects that use this armature. */
+                               if (rebuild) {
+                                       for (Object *ob2 = bmain->object.first; ob2; ob2 = ob2->id.next) {
+                                               if (ob2->pose && ob2->data == arm) {
+                                                       ob2->pose->flag |= POSE_RECALC;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
 }
 
 /* NOTE: this version patch is intended for versions < 2.52.2, but was initially introduced in 2.27 already.
index cf0b2457eca4bc6fadb21dbc0d18656d01dbe226..a636e19faa25e7ef3b31b3152ffcffddc71ea6e6 100644 (file)
@@ -561,6 +561,14 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
                                ebone->flag &= ~BONE_CONNECTED;
                        }
 
+                       /* Update custom handle links. */
+                       if (ebone_iter->bbone_prev && ebone_iter->bbone_prev->temp.ebone) {
+                               ebone_iter->bbone_prev = ebone_iter->bbone_prev->temp.ebone;
+                       }
+                       if (ebone_iter->bbone_next && ebone_iter->bbone_next->temp.ebone) {
+                               ebone_iter->bbone_next = ebone_iter->bbone_next->temp.ebone;
+                       }
+
                        /* Lets try to fix any constraint subtargets that might
                         * have been duplicated
                         */
@@ -751,6 +759,14 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
                                ebone->parent = ebone_parent;
                        }
 
+                       /* Update custom handle links. */
+                       if (ebone_iter->bbone_prev && ebone_iter->bbone_prev->temp.ebone) {
+                               ebone_iter->bbone_prev = ebone_iter->bbone_prev->temp.ebone;
+                       }
+                       if (ebone_iter->bbone_next && ebone_iter->bbone_next->temp.ebone) {
+                               ebone_iter->bbone_next = ebone_iter->bbone_next->temp.ebone;
+                       }
+
                        /* Lets try to fix any constraint subtargets that might
                         * have been duplicated
                         */
index e28e9877ebacfaa25476b2994c6d6d68c5f08a7f..e5efb3315d0ca73ee8e72a99aaae988a07944d50 100644 (file)
@@ -213,7 +213,7 @@ void POSE_OT_propagate(struct wmOperatorType *ot);
  * within each file, but some tools still have a bit of overlap which makes things messy -- Feb 2013
  */
 
-EditBone *make_boneList(struct ListBase *edbo, struct ListBase *bones, struct EditBone *parent, struct Bone *actBone);
+EditBone *make_boneList(struct ListBase *edbo, struct ListBase *bones, struct Bone *actBone);
 
 /* duplicate method */
 void preEditBoneDuplicate(struct ListBase *editbones);
index 2b28b76bcf68ba8c73788f2b92bf08f30755d5a7..339f03067794d24efc1359562c5c6423fba9086d 100644 (file)
@@ -131,6 +131,16 @@ void bone_free(bArmature *arm, EditBone *bone)
                MEM_freeN(bone->prop);
        }
 
+       /* Clear references from other edit bones. */
+       for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+               if (ebone->bbone_next == bone) {
+                       ebone->bbone_next = NULL;
+               }
+               if (ebone->bbone_prev == bone) {
+                       ebone->bbone_prev = NULL;
+               }
+       }
+
        BLI_freelinkN(arm->edbo, bone);
 }
 
@@ -426,7 +436,7 @@ void ED_armature_edit_transform_mirror_update(Object *obedit)
 /* Armature EditMode Conversions */
 
 /* converts Bones to EditBone list, used for tools as well */
-EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone)
+static EditBone *make_boneList_rec(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone)
 {
        EditBone    *eBone;
        EditBone    *eBoneAct = NULL;
@@ -435,6 +445,7 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
 
        for (curBone = bones->first; curBone; curBone = curBone->next) {
                eBone = MEM_callocN(sizeof(EditBone), "make_editbone");
+               eBone->temp.bone = curBone;
 
                /* Copy relevant data from bone to eBone
                 * Keep selection logic in sync with ED_armature_edit_sync_selection.
@@ -490,6 +501,9 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
                eBone->scaleIn = curBone->scaleIn;
                eBone->scaleOut = curBone->scaleOut;
 
+               eBone->bbone_prev_type = curBone->bbone_prev_type;
+               eBone->bbone_next_type = curBone->bbone_next_type;
+
                if (curBone->prop)
                        eBone->prop = IDP_CopyProperty(curBone->prop);
 
@@ -497,7 +511,7 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
 
                /*      Add children if necessary */
                if (curBone->childbase.first) {
-                       eBoneTest = make_boneList(edbo, &curBone->childbase, eBone, actBone);
+                       eBoneTest = make_boneList_rec(edbo, &curBone->childbase, eBone, actBone);
                        if (eBoneTest)
                                eBoneAct = eBoneTest;
                }
@@ -509,6 +523,36 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
        return eBoneAct;
 }
 
+static EditBone *find_ebone_link(ListBase *edbo, Bone *link)
+{
+       if (link != NULL) {
+               for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) {
+                       if (ebone->temp.bone == link) {
+                               return ebone;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+EditBone *make_boneList(ListBase *edbo, ListBase *bones, struct Bone *actBone)
+{
+       BLI_assert(!edbo->first && !edbo->last);
+
+       EditBone *active = make_boneList_rec(edbo, bones, NULL, actBone);
+
+       for (EditBone *ebone = edbo->first; ebone; ebone = ebone->next) {
+               Bone *bone = ebone->temp.bone;
+
+               /* Convert custom B-Bone handle links. */
+               ebone->bbone_prev = find_ebone_link(edbo, bone->bbone_prev);
+               ebone->bbone_next = find_ebone_link(edbo, bone->bbone_next);
+       }
+
+       return active;
+}
+
 /* This function:
  *     - sets local head/tail rest locations using parent bone's arm_mat.
  *     - calls BKE_armature_where_is_bone() which uses parent's transform (arm_mat) to define this bone's transform.
@@ -655,6 +699,8 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
                newBone->scaleIn = eBone->scaleIn;
                newBone->scaleOut = eBone->scaleOut;
 
+               newBone->bbone_prev_type = eBone->bbone_prev_type;
+               newBone->bbone_next_type = eBone->bbone_next_type;
 
                if (eBone->prop)
                        newBone->prop = IDP_CopyProperty(eBone->prop);
@@ -673,6 +719,14 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
                else {
                        BLI_addtail(&arm->bonebase, newBone);
                }
+
+               /* Also transfer B-Bone custom handles. */
+               if (eBone->bbone_prev) {
+                       newBone->bbone_prev = eBone->bbone_prev->temp.bone;
+               }
+               if (eBone->bbone_next) {
+                       newBone->bbone_next = eBone->bbone_next->temp.bone;
+               }
        }
 
        /* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */
@@ -715,7 +769,7 @@ void ED_armature_to_edit(bArmature *arm)
 {
        ED_armature_edit_free(arm);
        arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
-       arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, NULL, arm->act_bone);
+       arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, arm->act_bone);
 }
 
 /* *************************************************************** */
index 89e510e6f3e95d538adc63332cf66063283f194d..0c770bcbcc40fc5e3108f62400157d03ac180188 100644 (file)
@@ -1348,7 +1348,7 @@ RigGraph *RIG_graphFromArmature(const bContext *C, Object *ob, bArmature *arm)
        }
        else {
                rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
-               make_boneList(rg->editbones, &arm->bonebase, NULL, NULL);
+               make_boneList(rg->editbones, &arm->bonebase, NULL);
                rg->flag |= RIG_FREE_BONELIST;
        }
 
@@ -1396,7 +1396,7 @@ static RigGraph *armatureSelectedToGraph(bContext *C, Object *ob, bArmature *arm
        }
        else {
                rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
-               make_boneList(rg->editbones, &arm->bonebase, NULL, NULL);
+               make_boneList(rg->editbones, &arm->bonebase, NULL);
                rg->flag |= RIG_FREE_BONELIST;
        }
 
index 3044543795c1de5c0bd3fbf1db77dc697f59390c..9347d2037b0eae467bc63342c97923c21b742887 100644 (file)
@@ -90,6 +90,11 @@ typedef struct EditBone {
 
        short segments;
 
+       char bbone_prev_type;   /* Type of next/prev bone handles */
+       char bbone_next_type;
+       struct EditBone *bbone_prev;    /* Next/prev bones to use as handle references when calculating bbones (optional) */
+       struct EditBone *bbone_next;
+
        /* Used for display */
        float disp_mat[4][4];  /*  in Armature space, rest pos matrix */
        float disp_tail_mat[4][4];  /*  in Armature space, rest pos matrix */
index 55e1a43925d560e70f072c3a2b2d71ad26a858ba..d6991041ec675fceda09321236b469b47eaebcfc 100644 (file)
@@ -224,7 +224,7 @@ typedef struct bPoseChannel {
        char constflag;                 /* for quick detecting which constraints affect this channel */
        char selectflag;                /* copy of bone flag, so you can work with library armatures, not for runtime use */
        char drawflag;
-       char bboneflag;
+       char bboneflag DNA_DEPRECATED;
        char pad0[4];
 
        struct Bone         *bone;      /* set on read file or rebuild pose */
@@ -278,7 +278,7 @@ typedef struct bPoseChannel {
        float ease1, ease2;
        float scaleIn, scaleOut;
 
-       struct bPoseChannel *bbone_prev; /* next/prev bones to use as handle references when calculating bbones (optional) */
+       struct bPoseChannel *bbone_prev; /* B-Bone custom handles; set on read file or rebuild pose based on pchan->bone data */
        struct bPoseChannel *bbone_next;
 
        void        *temp;              /* use for outliner */
@@ -361,6 +361,7 @@ typedef enum ePchan_DrawFlag {
 #define PCHAN_CUSTOM_DRAW_SIZE(pchan) \
        (pchan)->custom_scale * (((pchan)->drawflag & PCHAN_DRAW_NO_CUSTOM_BONE_SIZE) ? 1.0f : (pchan)->bone->length)
 
+#ifdef DNA_DEPRECATED_ALLOW
 /* PoseChannel->bboneflag */
 typedef enum ePchan_BBoneFlag {
        /* Use custom reference bones (for roll and handle alignment), instead of immediate neighbors */
@@ -370,6 +371,7 @@ typedef enum ePchan_BBoneFlag {
        /* Evaluate end handle as being "relative" */
        PCHAN_BBONE_CUSTOM_END_REL    = (1 << 3),
 } ePchan_BBoneFlag;
+#endif
 
 /* PoseChannel->rotmode and Object->rotmode */
 typedef enum eRotationModes {
index 937caffb71ef12ae46de0add2fd829b63b116c7e..141ad7c3ce0371e181bbf98a623f2c0112bed7d5 100644 (file)
@@ -78,8 +78,10 @@ typedef struct Bone {
        int          layer;          /* layers that bone appears on */
        short        segments;       /*  for B-bones */
 
-       short            pad1;
-
+       char         bbone_prev_type;   /* Type of next/prev bone handles */
+       char         bbone_next_type;
+       struct Bone *bbone_prev;        /* Next/prev bones to use as handle references when calculating bbones (optional) */
+       struct Bone *bbone_next;
 } Bone;
 
 typedef struct bArmature {
@@ -214,6 +216,13 @@ typedef enum eBone_Flag {
 
 } eBone_Flag;
 
+/* bone->bbone_prev_type, bbone_next_type */
+typedef enum eBone_BBoneHandleType {
+       BBONE_HANDLE_AUTO = 0,  /* Default mode based on parents & children. */
+       BBONE_HANDLE_ABSOLUTE,  /* Custom handle in absolute position mode. */
+       BBONE_HANDLE_RELATIVE,  /* Custom handle in relative position mode. */
+} eBone_BBoneHandleType;
+
 #define MAXBONENAME 64
 
 #endif
index d557714d228b4447b9741f42b0201f829f8e7437..4fd42a97568fac9e7c9ad5f4e790a57324db2191 100644 (file)
@@ -449,6 +449,40 @@ static void rna_EditBone_matrix_set(PointerRNA *ptr, const float *values)
        ED_armature_ebone_from_mat4(ebone, (float(*)[4])values);
 }
 
+static PointerRNA rna_EditBone_bbone_prev_get(PointerRNA *ptr)
+{
+       EditBone *data = (EditBone *)(ptr->data);
+       return rna_pointer_inherit_refine(ptr, &RNA_EditBone, data->bbone_prev);
+}
+
+static void rna_EditBone_bbone_prev_set(PointerRNA *ptr, PointerRNA value)
+{
+       EditBone *ebone = (EditBone *)(ptr->data);
+       EditBone *hbone = (EditBone *)value.data;
+
+       /* Within the same armature? */
+       if (hbone == NULL || value.id.data == ptr->id.data) {
+               ebone->bbone_prev = hbone;
+       }
+}
+
+static PointerRNA rna_EditBone_bbone_next_get(PointerRNA *ptr)
+{
+       EditBone *data = (EditBone *)(ptr->data);
+       return rna_pointer_inherit_refine(ptr, &RNA_EditBone, data->bbone_next);
+}
+
+static void rna_EditBone_bbone_next_set(PointerRNA *ptr, PointerRNA value)
+{
+       EditBone *ebone = (EditBone *)(ptr->data);
+       EditBone *hbone = (EditBone *)value.data;
+
+       /* Within the same armature? */
+       if (hbone == NULL || value.id.data == ptr->id.data) {
+               ebone->bbone_next = hbone;
+       }
+}
+
 static void rna_Armature_editbone_transform_update(Main *bmain, Scene *scene, PointerRNA *ptr)
 {
        bArmature *arm = (bArmature *)ptr->id.data;
@@ -617,6 +651,13 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
 
 static void rna_def_bone_common(StructRNA *srna, int editbone)
 {
+       static const EnumPropertyItem prop_bbone_handle_type[] = {
+               {BBONE_HANDLE_AUTO, "AUTO", 0, "Automatic", "Use connected parent and children to compute the handle"},
+               {BBONE_HANDLE_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Use the position of the specified bone to compute the handle"},
+               {BBONE_HANDLE_RELATIVE, "RELATIVE", 0, "Relative", "Use the offset of the specified bone from rest pose to compute the handle"},
+               {0, NULL, 0, NULL, NULL}
+       };
+
        PropertyRNA *prop;
 
        /* strings */
@@ -745,6 +786,44 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
        RNA_def_property_range(prop, 0.0f, 1000.0f);
        RNA_def_property_ui_text(prop, "B-Bone Display Z Width", "B-Bone Z size");
        RNA_def_property_update(prop, 0, "rna_Armature_update_data");
+
+       prop = RNA_def_property(srna, "bbone_handle_type_start", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "bbone_prev_type");
+       RNA_def_property_enum_items(prop, prop_bbone_handle_type);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "B-Bone Start Handle Type", "Selects how the start handle of the B-Bone is computed");
+       RNA_def_property_update(prop, 0, "rna_Armature_dependency_update");
+
+       prop = RNA_def_property(srna, "bbone_custom_handle_start", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "bbone_prev");
+       RNA_def_property_struct_type(prop, editbone ? "EditBone" : "Bone");
+       if (editbone) {
+               RNA_def_property_flag(prop, PROP_EDITABLE);
+               RNA_def_property_pointer_funcs(prop, "rna_EditBone_bbone_prev_get", "rna_EditBone_bbone_prev_set", NULL, NULL);
+       }
+       RNA_def_property_flag(prop, PROP_PTR_NO_OWNERSHIP);
+       RNA_def_property_ui_text(prop, "B-Bone Start Handle",
+                                "Bone that serves as the start handle for the B-Bone curve");
+       RNA_def_property_update(prop, 0, "rna_Armature_dependency_update");
+
+       prop = RNA_def_property(srna, "bbone_handle_type_end", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "bbone_next_type");
+       RNA_def_property_enum_items(prop, prop_bbone_handle_type);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "B-Bone End Handle Type", "Selects how the end handle of the B-Bone is computed");
+       RNA_def_property_update(prop, 0, "rna_Armature_dependency_update");
+
+       prop = RNA_def_property(srna, "bbone_custom_handle_end", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "bbone_next");
+       RNA_def_property_struct_type(prop, editbone ? "EditBone" : "Bone");
+       if (editbone) {
+               RNA_def_property_flag(prop, PROP_EDITABLE);
+               RNA_def_property_pointer_funcs(prop, "rna_EditBone_bbone_next_get", "rna_EditBone_bbone_next_set", NULL, NULL);
+       }
+       RNA_def_property_flag(prop, PROP_PTR_NO_OWNERSHIP);
+       RNA_def_property_ui_text(prop, "B-Bone End Handle",
+                                "Bone that serves as the end handle for the B-Bone curve");
+       RNA_def_property_update(prop, 0, "rna_Armature_dependency_update");
 }
 
 /* err... bones should not be directly edited (only editbones should be...) */
index d263e02d3f812186c38e9bcdb99df4e2369b97d8..56ba29d277cd8727dbe5f62ec3396ec73252e6da 100644 (file)
@@ -965,46 +965,22 @@ static void rna_def_pose_channel(BlenderRNA *brna)
        rna_def_bone_curved_common(srna, true);
 
        /* Custom BBone next/prev sources */
-       prop = RNA_def_property(srna, "use_bbone_custom_handles", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_HANDLES);
-       RNA_def_property_ui_text(prop, "Use Custom Handle References",
-                                "Use custom reference bones as handles for B-Bones instead of next/previous bones, "
-                                "leave these blank to use only B-Bone offset properties to control the shape");
-       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, "bbone_custom_handle_start", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "bbone_prev");
        RNA_def_property_struct_type(prop, "PoseBone");
-       RNA_def_property_flag(prop, PROP_EDITABLE | PROP_PTR_NO_OWNERSHIP);
+       RNA_def_property_flag(prop, PROP_PTR_NO_OWNERSHIP);
        RNA_def_property_ui_text(prop, "B-Bone Start Handle",
                                 "Bone that serves as the start handle for the B-Bone curve");
-       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, "use_bbone_relative_start_handle", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_START_REL);
-       RNA_def_property_ui_text(prop, "Relative B-Bone Start Handle",
-                                "Treat custom start handle position as a relative value");
-       RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
-       RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
-
        prop = RNA_def_property(srna, "bbone_custom_handle_end", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "bbone_next");
        RNA_def_property_struct_type(prop, "PoseBone");
-       RNA_def_property_flag(prop, PROP_EDITABLE | PROP_PTR_NO_OWNERSHIP);
+       RNA_def_property_flag(prop, PROP_PTR_NO_OWNERSHIP);
        RNA_def_property_ui_text(prop, "B-Bone End Handle",
                                 "Bone that serves as the end handle for the B-Bone curve");
-       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, "use_bbone_relative_end_handle", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_END_REL);
-       RNA_def_property_ui_text(prop, "Relative B-Bone End Handle",
-                                "Treat custom end handle position as a relative value");
-       RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
-       RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
-
        /* transform matrices - should be read-only since these are set directly by AnimSys evaluation */
        prop = RNA_def_property(srna, "matrix_channel", PROP_FLOAT, PROP_MATRIX);
        RNA_def_property_float_sdna(prop, NULL, "chan_mat");