diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 842b30b4147..0f73843b9fa 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -709,6 +709,7 @@ void berekeny(float f1, float f2, float f3, float f4, float *o, int b) o[a]= c0+t*c1+t*t*c2+t*t*t*c3; } } + void berekenx(float *f, float *o, int b) { float t, c0, c1, c2, c3; @@ -724,83 +725,89 @@ void berekenx(float *f, float *o, int b) } } +/* has to return a float value */ static float eval_driver(IpoDriver *driver) { - Object *ob= driver->ob; - if(ob==NULL) return 0.0f; - - if(driver->blocktype==ID_OB) { - switch(driver->adrcode) { - case OB_LOC_X: - return ob->loc[0]; - case OB_LOC_Y: - return ob->loc[1]; - case OB_LOC_Z: - return ob->loc[2]; - case OB_ROT_X: - return ob->rot[0]/(M_PI_2/9.0); - case OB_ROT_Y: - return ob->rot[1]/(M_PI_2/9.0); - case OB_ROT_Z: - return ob->rot[2]/(M_PI_2/9.0); - case OB_SIZE_X: - return ob->size[0]; - case OB_SIZE_Y: - return ob->size[1]; - case OB_SIZE_Z: - return ob->size[2]; - } + if(driver->flag & IPO_DRIVER_PYTHON) { + printf("Execute %s\n", driver->name); } - else { /* ID_AR */ - bPoseChannel *pchan= get_pose_channel(ob->pose, driver->name); - if(pchan && pchan->bone) { - float pose_mat[3][3]; - float diff_mat[3][3], par_mat[3][3], ipar_mat[3][3]; - float eul[3], size[3]; - - /* we need the local transform = current transform - (parent transform + bone transform) */ - - Mat3CpyMat4(pose_mat, pchan->pose_mat); - - if (pchan->parent) { - Mat3CpyMat4(par_mat, pchan->parent->pose_mat); - Mat3MulMat3(diff_mat, par_mat, pchan->bone->bone_mat); - - Mat3Inv(ipar_mat, diff_mat); - } - else { - Mat3Inv(ipar_mat, pchan->bone->bone_mat); - } - - Mat3MulMat3(diff_mat, ipar_mat, pose_mat); - - Mat3ToEul(diff_mat, eul); - Mat3ToSize(diff_mat, size); - + else { + Object *ob= driver->ob; + + if(ob==NULL) return 0.0f; + + if(driver->blocktype==ID_OB) { switch(driver->adrcode) { case OB_LOC_X: - return pchan->loc[0]; + return ob->loc[0]; case OB_LOC_Y: - return pchan->loc[1]; + return ob->loc[1]; case OB_LOC_Z: - return pchan->loc[2]; + return ob->loc[2]; case OB_ROT_X: - return eul[0]/(M_PI_2/9.0); + return ob->rot[0]/(M_PI_2/9.0); case OB_ROT_Y: - return eul[1]/(M_PI_2/9.0); + return ob->rot[1]/(M_PI_2/9.0); case OB_ROT_Z: - return eul[2]/(M_PI_2/9.0); + return ob->rot[2]/(M_PI_2/9.0); case OB_SIZE_X: - return size[0]; + return ob->size[0]; case OB_SIZE_Y: - return size[1]; + return ob->size[1]; case OB_SIZE_Z: - return size[2]; + return ob->size[2]; } } - } - + else { /* ID_AR */ + bPoseChannel *pchan= get_pose_channel(ob->pose, driver->name); + if(pchan && pchan->bone) { + float pose_mat[3][3]; + float diff_mat[3][3], par_mat[3][3], ipar_mat[3][3]; + float eul[3], size[3]; + + /* we need the local transform = current transform - (parent transform + bone transform) */ + + Mat3CpyMat4(pose_mat, pchan->pose_mat); + + if (pchan->parent) { + Mat3CpyMat4(par_mat, pchan->parent->pose_mat); + Mat3MulMat3(diff_mat, par_mat, pchan->bone->bone_mat); + + Mat3Inv(ipar_mat, diff_mat); + } + else { + Mat3Inv(ipar_mat, pchan->bone->bone_mat); + } + + Mat3MulMat3(diff_mat, ipar_mat, pose_mat); + + Mat3ToEul(diff_mat, eul); + Mat3ToSize(diff_mat, size); + + switch(driver->adrcode) { + case OB_LOC_X: + return pchan->loc[0]; + case OB_LOC_Y: + return pchan->loc[1]; + case OB_LOC_Z: + return pchan->loc[2]; + case OB_ROT_X: + return eul[0]/(M_PI_2/9.0); + case OB_ROT_Y: + return eul[1]/(M_PI_2/9.0); + case OB_ROT_Z: + return eul[2]/(M_PI_2/9.0); + case OB_SIZE_X: + return size[0]; + case OB_SIZE_Y: + return size[1]; + case OB_SIZE_Z: + return size[2]; + } + } + } + } return 0.0f; } diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index ad2d5c1e458..0cc98a3b429 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2170,9 +2170,24 @@ void Mat3ToEul(float tmat[][3], float *eul) cy = (float)sqrt(mat[0][0]*mat[0][0] + mat[0][1]*mat[0][1]); if (cy > 16.0*FLT_EPSILON) { - eul[0] = (float)atan2(mat[1][2], mat[2][2]); - eul[1] = (float)atan2(-mat[0][2], cy); - eul[2] = (float)atan2(mat[0][1], mat[0][0]); + float eul1[3], eul2[3]; + + eul1[0] = (float)atan2(mat[1][2], mat[2][2]); + eul1[1] = (float)atan2(-mat[0][2], cy); + eul1[2] = (float)atan2(mat[0][1], mat[0][0]); + + eul2[0] = (float)atan2(-mat[1][2], -mat[2][2]); + eul2[1] = (float)atan2(-mat[0][2], -cy); + eul2[2] = (float)atan2(-mat[0][1], -mat[0][0]); + + /* return best, which is just the one with lowest values it in */ + if( fabs(eul1[0])+fabs(eul1[1])+fabs(eul1[2]) > fabs(eul2[0])+fabs(eul2[1])+fabs(eul2[2])) { + VecCopyf(eul, eul2); + } + else { + VecCopyf(eul, eul1); + } + } else { eul[0] = (float)atan2(-mat[2][1], mat[1][1]); eul[1] = (float)atan2(-mat[0][2], cy); diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index b5ed8c9102a..18237c2f964 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -174,7 +174,7 @@ typedef struct Curve { typedef struct IpoDriver { struct Object *ob; short blocktype, adrcode, type, flag; - char name[32]; /* bone or constraint(?) name, later we can add python expression here */ + char name[128]; /* bone or constraint(?), or python expression here */ } IpoDriver; typedef struct IpoCurve { @@ -252,6 +252,10 @@ typedef struct IpoCurve { #define CU_UNDERLINE 4 #define CU_WRAP 8 /* wordwrap occured here */ +/* *************** driver ****************** */ + +/* driver->flag */ +#define IPO_DRIVER_PYTHON 1 #endif diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index 3baf2120d66..e6fe76605bc 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -1783,17 +1783,22 @@ void do_ipobuts(unsigned short event) if(ei->icu->driver) { IpoDriver *driver= ei->icu->driver; - if(driver->ob) { - if(ob==driver->ob) { - error("Cannot assign a Driver to own Object"); - driver->ob= NULL; + if(driver->flag & IPO_DRIVER_PYTHON) { + driver->ob= NULL; + } + else { + if(driver->ob) { + if(ob==driver->ob) { + error("Cannot assign a Driver to own Object"); + driver->ob= NULL; + } + else { + /* check if type is still OK */ + if(driver->ob->type==OB_ARMATURE && driver->blocktype==ID_AR); + else driver->blocktype= ID_OB; + } } - else { - /* check if type is still OK */ - if(driver->ob->type==OB_ARMATURE && driver->blocktype==ID_AR); - else driver->blocktype= ID_OB; - } - } + } DAG_scene_sort(G.scene); if(G.sipo->blocktype==ID_KE || G.sipo->blocktype==ID_AC) @@ -1877,27 +1882,35 @@ static void ipo_panel_properties(short cntrl) // IPO_HANDLER_PROPERTIES if(ei->icu && ei->icu->driver) { IpoDriver *driver= ei->icu->driver; - uiDefBut(block, BUT, B_IPO_DRIVER, "Remove", 210,265,100,19, NULL, 0.0f, 0.0f, 0, 0, "Remove Driver for this Ipo Channel"); + uiDefBut(block, BUT, B_IPO_DRIVER, "Remove", 210,265,100,20, NULL, 0.0f, 0.0f, 0, 0, "Remove Driver for this Ipo Channel"); uiBlockBeginAlign(block); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_IPO_DEPCHANGE, "OB:", 10, 240, 150, 20, &(driver->ob), "Driver Object"); - if(driver->ob) { - int icon=ICON_OBJECT; - - if(driver->ob->type==OB_ARMATURE && driver->blocktype==ID_AR) { - icon = ICON_POSE_DEHLT; - uiDefBut(block, TEX, B_IPO_REDR, "BO:", 10,220,150,20, driver->name, 0, 31, 0, 0, "Bone name"); - } - else driver->blocktype= ID_OB; /* safety when switching object button */ - - uiBlockBeginAlign(block); - uiDefIconTextButS(block, MENU, B_IPO_DEPCHANGE, icon, - ipodriver_modeselect_pup(driver->ob), 165,240,145,20, &(driver->blocktype), 0, 0, 0, 0, "Driver type"); - - uiDefButS(block, MENU, B_IPO_REDR, - ipodriver_channelselect_pup(), 165,220,145,20, &(driver->adrcode), 0, 0, 0, 0, "Driver channel"); + uiDefIconButBitS(block, TOG, IPO_DRIVER_PYTHON, B_IPO_DEPCHANGE, ICON_PYTHON, 10,240,25,20, &driver->flag, 0, 0, 0, 0, "Use a one-line Python Expression as Driver"); + + if(driver->flag & IPO_DRIVER_PYTHON) { + uiDefBut(block, TEX, B_IPO_REDR, "", 35,240,275,20, driver->name, 0, 127, 0, 0, "Python Expression"); + uiBlockEndAlign(block); + } + else { + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_IPO_DEPCHANGE, "OB:", 35, 240, 125, 20, &(driver->ob), "Driver Object"); + if(driver->ob) { + int icon=ICON_OBJECT; + + if(driver->ob->type==OB_ARMATURE && driver->blocktype==ID_AR) { + icon = ICON_POSE_DEHLT; + uiDefBut(block, TEX, B_IPO_REDR, "BO:", 10,220,150,20, driver->name, 0, 31, 0, 0, "Bone name"); + } + else driver->blocktype= ID_OB; /* safety when switching object button */ + + uiBlockBeginAlign(block); + uiDefIconTextButS(block, MENU, B_IPO_DEPCHANGE, icon, + ipodriver_modeselect_pup(driver->ob), 165,240,145,20, &(driver->blocktype), 0, 0, 0, 0, "Driver type"); + + uiDefButS(block, MENU, B_IPO_REDR, + ipodriver_channelselect_pup(), 165,220,145,20, &(driver->adrcode), 0, 0, 0, 0, "Driver channel"); + } + uiBlockEndAlign(block); } - uiBlockEndAlign(block); } else { uiDefBut(block, BUT, B_IPO_DRIVER, "Add Driver", 210,265,100,19, NULL, 0.0f, 0.0f, 0, 0, "Create a Driver for this Ipo Channel"); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index a455343c38c..8a23fe7059d 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -3332,12 +3332,9 @@ void compatible_eul(float *eul, float *oldrot) if(dz > 0.0) eul[2] -= 2.0*M_PI; else eul[2]+= 2.0*M_PI; } - /* this return was there from ancient days... i remove it now, - because axis-only rotations then work much nicer (try Y axis rotate - and check Y euler values). - Needed for new locking of transform values. (ton) + /* this return was there from ancient days... but why! probably because the code sucks :) */ - /*return;*/ + return; /* calc again */ dx= eul[0] - oldrot[0];