Patch #17336: Lock bones in edit mode
authorJoshua Leung <aligorith@gmail.com>
Sun, 27 Jul 2008 04:19:56 +0000 (04:19 +0000)
committerJoshua Leung <aligorith@gmail.com>
Sun, 27 Jul 2008 04:19:56 +0000 (04:19 +0000)
Submitted by: Lorenzo Pierfederici (lento)

This patch adds the ability to lock transformation on bones in edit mode, to protect them from accidental editing.

Bones can be locked from the editing buttons, the transform property panel, the specials popup menu or the python api.

12 files changed:
source/blender/include/BIF_editarmature.h
source/blender/makesdna/DNA_armature_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/python/api2_2x/Armature.c
source/blender/python/api2_2x/Bone.c
source/blender/python/api2_2x/doc/Armature.py
source/blender/src/buttons_editing.c
source/blender/src/drawview.c
source/blender/src/editarmature.c
source/blender/src/editobject.c
source/blender/src/transform_conversions.c
source/blender/src/transform_manipulator.c

index 24112c7f11afd2664d69804428f2748f19aaa5e5..da98eb3d4f1a8beb122345ccf11669cdaf6aad36 100644 (file)
@@ -134,6 +134,7 @@ void        transform_armature_mirror_update(void);
 void   hide_selected_armature_bones(void);
 void   hide_unselected_armature_bones(void);
 void   show_all_armature_bones(void);
+void   set_locks_armature_bones(short lock);
 
 #define        BONESEL_ROOT    0x10000000
 #define        BONESEL_TIP             0x20000000
index 673855a6932009f7c3da12ede50fdc5acdd42260..0648c53535374c2190a9967463c25132924e260e 100644 (file)
@@ -154,7 +154,8 @@ typedef enum eBone_Flag {
        BONE_NO_SCALE                           = (1<<15),      /* No parent scale */
        BONE_HIDDEN_PG                          = (1<<16),      /* hidden bone when drawing PoseChannels (for ghost drawing) */
        BONE_DRAWWIRE                           = (1<<17),      /* bone should be drawn as OB_WIRE, regardless of draw-types of view+armature */
-       BONE_NO_CYCLICOFFSET            = (1<<18)       /* when no parent, bone will not get cyclic offset */
+       BONE_NO_CYCLICOFFSET            = (1<<18),      /* when no parent, bone will not get cyclic offset */
+       BONE_EDITMODE_LOCKED            = (1<<19),      /* bone transforms are locked in EditMode */
 } eBone_Flag;
 
 #endif
index c4e8cb4925b83aeff9bace19c457583f853a626e..85c49a03569b2f8c330dac2b9a8ec6165d4c449a 100644 (file)
@@ -466,9 +466,11 @@ extern Object workob;
 #define OB_LOCK_ROTX   8
 #define OB_LOCK_ROTY   16
 #define OB_LOCK_ROTZ   32
+#define OB_LOCK_ROT            56
 #define OB_LOCK_SCALEX 64
 #define OB_LOCK_SCALEY 128
 #define OB_LOCK_SCALEZ 256
+#define OB_LOCK_SCALE  448
 
 /* ob->softflag in DNA_object_force.h */
 
index e9dff0987738138bbbc088583ecce5e050a03a97..0db87c00dd24c1709544c02f96e1af5bbd09c212 100644 (file)
@@ -1469,6 +1469,8 @@ PyObject *Armature_Init(void)
                PyConstant_NewInt("BONE_SELECTED", BONE_SELECTED));
        PyModule_AddObject(module, "TIP_SELECTED", 
                PyConstant_NewInt("TIP_SELECTED", BONE_TIPSEL));
+       PyModule_AddObject(module, "LOCKED_EDIT", 
+               PyConstant_NewInt("LOCKED_EDIT", BONE_EDITMODE_LOCKED));
 
        PyModule_AddObject(module, "OCTAHEDRON", 
                PyConstant_NewInt("OCTAHEDRON", ARM_OCTA));
index 84faf416c5f726304138f48f9ea50472272518f7..948eb007803d25bb3e07ac249fe98d04f5f2ab74 100644 (file)
@@ -368,6 +368,10 @@ static PyObject *EditBone_getOptions(BPy_EditBone *self, void *closure)
                        if (PyList_Append(list, 
                                EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
                                goto RuntimeError;
+               if(self->editbone->flag & BONE_EDITMODE_LOCKED)
+                       if (PyList_Append(list, 
+                               EXPP_GetModuleConstant("Blender.Armature", "LOCKED_EDIT")) == -1)
+                               goto RuntimeError;
        }else{
                if(self->flag & BONE_CONNECTED)
                        if (PyList_Append(list, 
@@ -401,6 +405,10 @@ static PyObject *EditBone_getOptions(BPy_EditBone *self, void *closure)
                        if (PyList_Append(list, 
                                EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
                                goto RuntimeError;
+               if(self->flag & BONE_EDITMODE_LOCKED)
+                       if (PyList_Append(list, 
+                               EXPP_GetModuleConstant("Blender.Armature", "LOCKED_EDIT")) == -1)
+                               goto RuntimeError;
        }
 
        return list;
@@ -422,7 +430,7 @@ static int EditBone_CheckValidConstant(PyObject *constant)
                                return 0;
                        if (!STREQ3(PyString_AsString(name), "CONNECTED", "HINGE", "NO_DEFORM") &&
                                !STREQ3(PyString_AsString(name), "ROOT_SELECTED", "BONE_SELECTED", "TIP_SELECTED")      &&
-                               !STREQ2(PyString_AsString(name), "MULTIPLY", "HIDDEN_EDIT"))
+                               !STREQ3(PyString_AsString(name), "MULTIPLY", "HIDDEN_EDIT", "LOCKED_EDIT"))
                                return 0;
                        else
                                return 1;
index 68916af6166e16c944e96abeca49259027b5844d..9aceb0105e36c86adba576d637a0f80687719692 100644 (file)
@@ -89,6 +89,8 @@ Example::
 @type BONE_SELECTED: Constant
 @var TIP_SELECTED: Tip of the Bone is selected
 @type TIP_SELECTED: Constant
+@var LOCKED_EDIT: Prevents the bone from being transformed in editmode
+@type LOCKED_EDIT: Constant
 @var OCTAHEDRON: Bones drawn as octahedrons
 @type OCTAHEDRON: Constant
 @var STICK: Bones drawn as a line
@@ -286,6 +288,7 @@ class Bone:
                         - Armature.ROOT_SELECTED: Selection of root ball of bone
                         - Armature.BONE_SELECTED: Selection of bone
                         - Armature.TIP_SELECTED: Selection of tip ball of bone
+                        - Armature.LOCKED_EDIT: Prevents the bone from being transformed in editmode
        @type options: List of Constants
        @ivar subdivision: The number of bone subdivisions.
        @type subdivision: Int
index 4a4eaf3c81faf0da2c4b50a45ae1364fe3d0a0a4..180fdc852aea68c160bcb28ddf676ad3043f0b0b 100644 (file)
@@ -4371,11 +4371,12 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm)
                        uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", 225, by-19,105, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight");
                        
                        /* bone types */
-                       uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge",         -10,by-38,80,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
-                       uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S",          70,by-38,20,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone");
-                       uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   90, by-38, 80, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
-                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 170,by-38,80,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
-                       uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide",   250,by-38,80,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
+                       uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge",         -10,by-38,60,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
+                       uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S",          50,by-38,20,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone");
+                       uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   70, by-38, 80, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
+                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 150,by-38,60,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
+                       uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide",   210,by-38,60,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
+                       uiDefButBitI(block, TOG, BONE_EDITMODE_LOCKED, REDRAWVIEW3D, "Lock",    270,by-38,60,18, &curBone->flag, 0, 0, 0, 0, "Prevents this bone from being transformed in Edit Mode");
                        
                        /* layers */
                        uiBlockBeginAlign(block);
index 8c7c78de83735b584930676475cbd1678f7baef1..2030eb658dec077dec3cf7a64dc6498f16876bb7 100644 (file)
@@ -1995,6 +1995,8 @@ static void v3d_editarmature_buts(uiBlock *block, Object *ob, float lim)
        tfp->ob_eul[0]= 180.0*ebone->roll/M_PI;
        uiDefButF(block, NUM, B_ARMATUREPANEL1, "Roll:",        10, 100, 140, 19, tfp->ob_eul, -lim, lim, 1000, 3, "");
 
+       uiDefButBitI(block, TOG, BONE_EDITMODE_LOCKED, REDRAWVIEW3D, "Lock", 160, 100, 140, 19, &(ebone->flag), 0, 0, 0, 0, "Prevents bone from being transformed in edit mode");
+       
        uiBlockBeginAlign(block);
        uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailRadius:",  10, 150, 140, 19, &ebone->rad_tail, 0, lim, 10, 3, "");
        if (ebone->parent && ebone->flag & BONE_CONNECTED )
index 6310dd0a262c8e6a85bd0139af08c004d19b36f3..d0f44263fb7fca4b026fc4c2cc3e6747ab1d3056 100644 (file)
@@ -2709,6 +2709,32 @@ void show_all_armature_bones(void)
        BIF_undo_push("Reveal Bones");
 }
 
+/* Sets editmode transform locks for bones (adds if lock==1, clears otherwise) */
+void set_locks_armature_bones(short lock)
+{
+       bArmature *arm= G.obedit->data;
+       EditBone *ebone;
+       
+       for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
+               if (arm->layer & ebone->layer) {
+                       if (ebone->flag & (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL)) {
+                               if (lock)
+                                       ebone->flag |= BONE_EDITMODE_LOCKED;
+                               else    
+                                       ebone->flag &= ~BONE_EDITMODE_LOCKED;
+                       }
+               }
+       }
+       countall();
+       allqueue(REDRAWVIEW3D, 0);
+       allqueue(REDRAWBUTSEDIT, 0);
+       
+       if (lock)
+               BIF_undo_push("Lock Bones");
+       else
+               BIF_undo_push("Unlock Bones");
+}
+
 /* check for null, before calling! */
 static void bone_connect_to_existing_parent(EditBone *bone)
 {
index 6af4f47ed11cdbc91e0a55b4087716014eec7444..2f9addb106ea77bb380fc3744ecdf3311b10d91c 100644 (file)
@@ -2760,7 +2760,7 @@ void special_editmenu(void)
                DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
        }
        else if(G.obedit->type==OB_ARMATURE) {
-               nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Flip Left-Right Names%x3|%l|AutoName Left-Right%x4|AutoName Front-Back%x5|AutoName Top-Bottom%x6");
+               nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Flip Left-Right Names%x3|%l|AutoName Left-Right%x4|AutoName Front-Back%x5|AutoName Top-Bottom%x6|%l|Lock%x7|Unlock%x8");
                if(nr==1)
                        subdivide_armature(1);
                if(nr==2) {
@@ -2773,6 +2773,10 @@ void special_editmenu(void)
                else if(ELEM3(nr, 4, 5, 6)) {
                        armature_autoside_names(nr-4);
                }
+               else if(nr==7)
+                       set_locks_armature_bones(1);
+               else if(nr==8)
+                       set_locks_armature_bones(0);
        }
        else if(G.obedit->type==OB_LATTICE) {
                static float weight= 1.0f;
index 706b079432cfb000b2e7ca178de36d3db1a8e1b8..8f83434e52873883e2031ac21dd49e4fe7a4c8e7 100644 (file)
@@ -1089,6 +1089,8 @@ static void createTransArmatureVerts(TransInfo *t)
                                        VECCOPY (td->center, td->iloc);
                                        td->loc= ebo->tail;
                                        td->flag= TD_SELECTED;
+                                       if (ebo->flag & BONE_EDITMODE_LOCKED)
+                                               td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
 
                                        Mat3CpyMat3(td->smtx, smtx);
                                        Mat3CpyMat3(td->mtx, mtx);
@@ -1104,6 +1106,8 @@ static void createTransArmatureVerts(TransInfo *t)
                                        VECCOPY (td->center, td->iloc);
                                        td->loc= ebo->head;
                                        td->flag= TD_SELECTED;
+                                       if (ebo->flag & BONE_EDITMODE_LOCKED)
+                                               td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
 
                                        Mat3CpyMat3(td->smtx, smtx);
                                        Mat3CpyMat3(td->mtx, mtx);
index 050360887b4d1f3a73d1ec0880d774b4805f2842..709879f142bb552fe23418453ceba66e1f716359 100644 (file)
@@ -170,6 +170,13 @@ static void stats_pose(View3D *v3d, bPoseChannel *pchan)
        }
 }
 
+/* for editmode*/
+static void stats_editbone(View3D *v3d, EditBone *ebo)
+{
+       if (ebo->flag & BONE_EDITMODE_LOCKED)
+               protectflag_to_drawflags(OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE, &v3d->twdrawflag);
+}
+
 /* only counts the parent selection, and tags transform flag */
 /* bad call... should re-use method from transform_conversion once */
 static void count_bone_select(TransInfo *t, bArmature *arm, ListBase *lb, int do_it) 
@@ -258,6 +265,9 @@ int calc_manipulator_stats(ScrArea *sa)
                                                calc_tw_center(ebo->head);
                                                totsel++;
                                        }
+                                       if (ebo->flag & BONE_SELECTED) {
+                                               stats_editbone(v3d, ebo);
+                                       }
                                }
                        }
                }