Revision: 23141
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23141
Author:   aligorith
Date:     2009-09-12 14:30:23 +0200 (Sat, 12 Sep 2009)

Log Message:
-----------
2.5 - Rotation Locking for Bones

* Added Transform Locks panel. The layout for rotation I'm not satisfied with 
yet, though it is the best alternative so far.

* Rotations can now be locked per-component for quats/axis-angle instead of 
going through eulers. This is currently enabled by the checkbox for the 'label' 
of the Lock Rotation column. 
- The naming of the property in RNA + the way this is presented in the UI can 
get some work done.
- The setting for the 'w' component for quats/axis-angle is currently a 
separate flag in RNA, since I can't figure out how to lump this in under the 
'lock_rotation' property instead (i.e. getting that to be either 3 or 4 
components, depending on whether per-component locking is enabled).
- Editing values directly should not be possible when these locks are set...

* Fixed some tools which made use of this

Modified Paths:
--------------
    branches/blender2.5/blender/release/ui/buttons_data_bone.py
    branches/blender2.5/blender/source/blender/editors/armature/editarmature.c
    branches/blender2.5/blender/source/blender/editors/armature/poseobject.c
    branches/blender2.5/blender/source/blender/editors/transform/transform.c
    branches/blender2.5/blender/source/blender/makesdna/DNA_object_types.h
    branches/blender2.5/blender/source/blender/makesrna/intern/rna_pose.c

Modified: branches/blender2.5/blender/release/ui/buttons_data_bone.py
===================================================================
--- branches/blender2.5/blender/release/ui/buttons_data_bone.py 2009-09-12 
10:21:55 UTC (rev 23140)
+++ branches/blender2.5/blender/release/ui/buttons_data_bone.py 2009-09-12 
12:30:23 UTC (rev 23141)
@@ -71,6 +71,35 @@
                                col = layout.column(align=True)
                                col.itemL(text="Euler:")
                                col.row().itemR(pchan, "euler_rotation", 
text="")
+                               
+class BONE_PT_transform_locks(BoneButtonsPanel):
+       __label__ = "Transform Locks"
+       
+       def poll(self, context):
+               return context.bone
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               bone = context.bone
+               pchan = ob.pose.pose_channels[context.bone.name]
+               
+               row = layout.row()
+               col = row.column()
+               col.itemR(pchan, "lock_location")
+               col.active = not (bone.parent and bone.connected)
+               
+               col = row.column()
+               if pchan.rotation_mode in ('QUATERNION', 'AXIS_ANGLE'):
+                       col.itemR(pchan, "lock_rotations_4d", text="Lock 
Rotation")
+                       if pchan.lock_rotations_4d:
+                               col.itemR(pchan, "lock_rotation_w", text="W")
+                       col.itemR(pchan, "lock_rotation", text="")
+               else:
+                       col.itemR(pchan, "lock_rotation", text="Rotation")
+               
+               row.column().itemR(pchan, "lock_scale")
 
 class BONE_PT_bone(BoneButtonsPanel):
        __label__ = "Bone"
@@ -243,6 +272,7 @@
 
 bpy.types.register(BONE_PT_context_bone)
 bpy.types.register(BONE_PT_transform)
+bpy.types.register(BONE_PT_transform_locks)
 bpy.types.register(BONE_PT_bone)
 bpy.types.register(BONE_PT_deform)
 bpy.types.register(BONE_PT_inverse_kinematics)

Modified: 
branches/blender2.5/blender/source/blender/editors/armature/editarmature.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/armature/editarmature.c  
2009-09-12 10:21:55 UTC (rev 23140)
+++ branches/blender2.5/blender/source/blender/editors/armature/editarmature.c  
2009-09-12 12:30:23 UTC (rev 23141)
@@ -4849,43 +4849,57 @@
        
        /* only clear those channels that are not locked */
        CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
-               if (pchan->protectflag & 
(OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ)) {
-                       float eul[3], oldeul[3], quat1[4];
-                       
-                       if (pchan->rotmode == PCHAN_ROT_QUAT) {
-                               QUATCOPY(quat1, pchan->quat);
-                               QuatToEul(pchan->quat, oldeul);
+               if (pchan->protectflag & 
(OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) {
+                       /* check if convert to eulers for locking... */
+                       if (pchan->protectflag & OB_LOCK_ROT4D) {
+                               /* perform clamping on a component by component 
basis */
+                               if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+                                       pchan->quat[0]= (pchan->rotmode == 
PCHAN_ROT_AXISANGLE) ? 0.0f : 1.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+                                       pchan->quat[1]= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+                                       pchan->quat[2]= 0.0f;
+                               if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+                                       pchan->quat[3]= 0.0f;
                        }
-                       else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
-                               continue; // XXX
-                       }
                        else {
-                               VECCOPY(oldeul, pchan->eul);
-                       }
-                       
-                       eul[0]= eul[1]= eul[2]= 0.0f;
-                       
-                       // TODO: for 4 channel rotations, we need special flags 
for those too...
-                       if (pchan->protectflag & OB_LOCK_ROTX)
-                               eul[0]= oldeul[0];
-                       if (pchan->protectflag & OB_LOCK_ROTY)
-                               eul[1]= oldeul[1];
-                       if (pchan->protectflag & OB_LOCK_ROTZ)
-                               eul[2]= oldeul[2];
-                       
-                       if (pchan->rotmode == PCHAN_ROT_QUAT) {
-                               EulToQuat(eul, pchan->quat);
-                               /* quaternions flip w sign to accumulate 
rotations correctly */
-                               if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || 
(quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
-                                       QuatMulf(pchan->quat, -1.0f);
+                               /* perform clamping using euler form 
(3-components) */
+                               float eul[3], oldeul[3], quat1[4];
+                               
+                               if (pchan->rotmode == PCHAN_ROT_QUAT) {
+                                       QUATCOPY(quat1, pchan->quat);
+                                       QuatToEul(pchan->quat, oldeul);
                                }
+                               else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) 
{
+                                       AxisAngleToEulO(&pchan->quat[1], 
pchan->quat[0], oldeul, EULER_ORDER_DEFAULT);
+                               }
+                               else {
+                                       VECCOPY(oldeul, pchan->eul);
+                               }
+                               
+                               eul[0]= eul[1]= eul[2]= 0.0f;
+                               
+                               if (pchan->protectflag & OB_LOCK_ROTX)
+                                       eul[0]= oldeul[0];
+                               if (pchan->protectflag & OB_LOCK_ROTY)
+                                       eul[1]= oldeul[1];
+                               if (pchan->protectflag & OB_LOCK_ROTZ)
+                                       eul[2]= oldeul[2];
+                               
+                               if (pchan->rotmode == PCHAN_ROT_QUAT) {
+                                       EulToQuat(eul, pchan->quat);
+                                       /* quaternions flip w sign to 
accumulate rotations correctly */
+                                       if ((quat1[0]<0.0f && 
pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
+                                               QuatMulf(pchan->quat, -1.0f);
+                                       }
+                               }
+                               else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) 
{
+                                       AxisAngleToEulO(&pchan->quat[1], 
pchan->quat[0], oldeul, EULER_ORDER_DEFAULT);
+                               }
+                               else {
+                                       VECCOPY(pchan->eul, eul);
+                               }
                        }
-                       else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
-                               // TODO...
-                       }
-                       else {
-                               VECCOPY(pchan->eul, eul);
-                       }
                }                                               
                else { 
                        if (pchan->rotmode == PCHAN_ROT_QUAT) {

Modified: 
branches/blender2.5/blender/source/blender/editors/armature/poseobject.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/armature/poseobject.c    
2009-09-12 10:21:55 UTC (rev 23140)
+++ branches/blender2.5/blender/source/blender/editors/armature/poseobject.c    
2009-09-12 12:30:23 UTC (rev 23141)
@@ -998,7 +998,6 @@
                                pchan->flag= chan->flag;
                                
                                /* check if rotation modes are compatible (i.e. 
do they need any conversions) */
-                               // FIXME: add axis-angle here too...
                                if (pchan->rotmode == chan->rotmode) {
                                        /* copy the type of rotation in use */
                                        if (pchan->rotmode > 0) {

Modified: 
branches/blender2.5/blender/source/blender/editors/transform/transform.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/transform/transform.c    
2009-09-12 10:21:55 UTC (rev 23140)
+++ branches/blender2.5/blender/source/blender/editors/transform/transform.c    
2009-09-12 12:30:23 UTC (rev 23141)
@@ -1610,29 +1610,88 @@
                eul[2]= oldeul[2];
 }
 
+
+/* this function only does the delta rotation */
+/* axis-angle is usually internally stored as quats... */
+static void protectedAxisAngleBits(short protectflag, float *quat, float 
*oldquat)
+{
+       /* check that protection flags are set */
+       if ((protectflag & 
(OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) == 0)
+               return;
+       
+       if (protectflag & OB_LOCK_ROT4D) {
+               /* axis-angle getting limited as 4D entities that they are... */
+               if (protectflag & OB_LOCK_ROTW)
+                       quat[0]= oldquat[0];
+               if (protectflag & OB_LOCK_ROTX)
+                       quat[1]= oldquat[1];
+               if (protectflag & OB_LOCK_ROTY)
+                       quat[2]= oldquat[2];
+               if (protectflag & OB_LOCK_ROTZ)
+                       quat[3]= oldquat[3];
+       }
+       else {
+               /* axis-angle get limited with euler... */
+               float eul[3], oldeul[3], quat1[4];
+               
+               QUATCOPY(quat1, quat);
+               AxisAngleToEulO(quat+1, quat[0], eul, EULER_ORDER_DEFAULT);
+               AxisAngleToEulO(oldquat+1, oldquat[0], oldeul, 
EULER_ORDER_DEFAULT);
+               
+               if (protectflag & OB_LOCK_ROTX)
+                       eul[0]= oldeul[0];
+               if (protectflag & OB_LOCK_ROTY)
+                       eul[1]= oldeul[1];
+               if (protectflag & OB_LOCK_ROTZ)
+                       eul[2]= oldeul[2];
+               
+               EulOToAxisAngle(eul, EULER_ORDER_DEFAULT, quat+1, quat);
+               
+               /* when converting to axis-angle, we need a special exception 
for the case when there is no axis */
+               if (IS_EQ(quat[1], quat[2]) && IS_EQ(quat[2], quat[3])) {
+                       /* for now, rotate around y-axis then (so that it 
simply becomes the roll) */
+                       quat[2]= 1.0f;
+               }
+       }
+}
+
+/* this function only does the delta rotation */
 static void protectedQuaternionBits(short protectflag, float *quat, float 
*oldquat)
 {
-       /* quaternions get limited with euler... */
-       /* this function only does the delta rotation */
+       /* check that protection flags are set */
+       if ((protectflag & 
(OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) == 0)
+               return;
        
-       // FIXME: need special checks for quality here...
-       if(protectflag) {
+       if (protectflag & OB_LOCK_ROT4D) {
+               /* quaternions getting limited as 4D entities that they are... 
*/
+               if (protectflag & OB_LOCK_ROTW)
+                       quat[0]= oldquat[0];
+               if (protectflag & OB_LOCK_ROTX)
+                       quat[1]= oldquat[1];
+               if (protectflag & OB_LOCK_ROTY)
+                       quat[2]= oldquat[2];
+               if (protectflag & OB_LOCK_ROTZ)
+                       quat[3]= oldquat[3];
+       }
+       else {
+               /* quaternions get limited with euler... (compatability mode) */
                float eul[3], oldeul[3], quat1[4];
-
+               
                QUATCOPY(quat1, quat);
                QuatToEul(quat, eul);
                QuatToEul(oldquat, oldeul);
-
-               if(protectflag & OB_LOCK_ROTX)
+               
+               if (protectflag & OB_LOCK_ROTX)
                        eul[0]= oldeul[0];
-               if(protectflag & OB_LOCK_ROTY)
+               if (protectflag & OB_LOCK_ROTY)
                        eul[1]= oldeul[1];
-               if(protectflag & OB_LOCK_ROTZ)
+               if (protectflag & OB_LOCK_ROTZ)
                        eul[2]= oldeul[2];
-
+               
                EulToQuat(eul, quat);
+               
                /* quaternions flip w sign to accumulate rotations correctly */
-               if( (quat1[0]<0.0f && quat[0]>0.0f) || (quat1[0]>0.0f && 
quat[0]<0.0f) ) {
+               if ( (quat1[0]<0.0f && quat[0]>0.0f) || (quat1[0]>0.0f && 
quat[0]<0.0f) ) {
                        QuatMulf(quat, -1.0f);
                }
        }
@@ -1733,17 +1792,24 @@
                        else
                                return;
                }
-               else if (td->tdi) {
+               else if (td->tdi) { // XXX depreceated
                        /* ipo-keys eulers */
                        TransDataIpokey *tdi= td->tdi;
                        float eul[3];
-
+                       
                        eul[0]= tdi->rotx[0];
                        eul[1]= tdi->roty[0];
                        eul[2]= tdi->rotz[0];
-
+                       
                        EulOToMat4(eul, td->rotOrder, cob.matrix);
                }
+               else if (td->rotOrder == PCHAN_ROT_AXISANGLE) {
+                       /* axis angle */
+                       if (td->ext)
+                               AxisAngleToMat4(&td->ext->quat[1], 
td->ext->quat[0], cob.matrix);
+                       else
+                               return;
+               }
                else {
                        /* eulers */
                        if (td->ext)
@@ -1751,22 +1817,22 @@
                        else
                                return;
                }
-
+               
                /* Evaluate valid constraints */
                for (con= td->con; con; con= con->next) {
                        /* only consider constraint if enabled */
                        if (con->flag & CONSTRAINT_DISABLE) continue;
                        if (con->enforce == 0.0f) continue;
-
+                       
                        /* we're only interested in Limit-Rotation constraints 
*/
                        if (con->type == CONSTRAINT_TYPE_ROTLIMIT) {
                                bRotLimitConstraint *data= con->data;
                                float tmat[4][4];
-
+                               
                                /* only use it if it's tagged for this purpose 
*/
                                if ((data->flag2 & LIMIT_TRANSFORM)==0)
                                        continue;
-
+                               
                                /* do space conversions */
                                if (con->ownspace == CONSTRAINT_SPACE_WORLD) {

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to