[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [23141] branches/blender2.5/blender: 2. 5 - Rotation Locking for Bones
Joshua Leung
aligorith at gmail.com
Sat Sep 12 14:30:23 CEST 2009
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. @@
More information about the Bf-blender-cvs
mailing list