diff options
author | Toni Alatalo <antont@kyperjokki.fi> | 2005-12-18 23:14:22 +0300 |
---|---|---|
committer | Toni Alatalo <antont@kyperjokki.fi> | 2005-12-18 23:14:22 +0300 |
commit | fae20e494e4d5d5f48a8a3c99938796d596537c2 (patch) | |
tree | ddce7c307c1e0b8b7c77ac985382b06dfe1401d4 | |
parent | 3bba3813bde61d2bedfd1a2fa434c929ae12230a (diff) |
orange: animation baking code. also a patch to autokey, to only key the keys made.
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/ipo.c | 6 | ||||
-rw-r--r-- | source/blender/include/BSE_editipo.h | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_userdef_types.h | 1 | ||||
-rw-r--r-- | source/blender/python/SConscript | 1 | ||||
-rw-r--r-- | source/blender/python/api2_2x/NLA.c | 24 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Object.c | 197 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Types.c | 3 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Types.h | 1 | ||||
-rw-r--r-- | source/blender/src/editaction.c | 206 | ||||
-rw-r--r-- | source/blender/src/editipo.c | 82 | ||||
-rw-r--r-- | source/blender/src/editnla.c | 119 | ||||
-rw-r--r-- | source/blender/src/space.c | 5 | ||||
-rwxr-xr-x | source/blender/src/transform_conversions.c | 86 |
14 files changed, 651 insertions, 83 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 0cbccd2a1b4..cee36e06fae 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1078,3 +1078,4 @@ void do_all_object_actions(Object *ob) } } + diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 0f73843b9fa..8aee2c9e785 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1805,7 +1805,11 @@ void execute_action_ipo(bActionChannel *achan, bPoseChannel *pchan) IpoCurve *icu; for(icu= achan->ipo->curve.first; icu; icu= icu->next) { void *poin= get_pchan_ipo_poin(pchan, icu->adrcode); - if(poin) write_ipo_poin(poin, IPO_FLOAT, icu->curval); + if(poin) { + write_ipo_poin(poin, IPO_FLOAT, icu->curval); + //printf("execute_action_ipo wrote_ipo_poin: %f\n", icu->curval); + //printf("%s has poin %p value %f\n", achan->name, poin, icu->curval); + } } } } diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index 38c54d95956..06611ec6dda 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -143,6 +143,8 @@ void duplicate_ipo_keys(struct Ipo *ipo); void borderselect_ipo_key(struct Ipo *ipo, float xmin, float xmax, int val); void borderselect_icu_key(struct IpoCurve *icu, float xmin, float xmax, int (*select_function)(struct BezTriple *)); +void bone2objectspace(float obSpaceBoneMat[][4], float obSpace[][4], float restPos[][4]); +void insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float matrixvalue); void select_ipo_key(struct Ipo *ipo, float selx, int sel); void select_icu_key(struct IpoCurve *icu, float selx, int selectmode); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index aa835780b1a..f1441e7b720 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -207,6 +207,7 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_LOCKAROUND 4096 #define USER_GLOBALUNDO 8192 #define USER_ORBIT_SELECTION 16384 +#define USER_KEYINSERTAVAI 32768 #define USER_HIDE_DOT 65536 /* transopts */ diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index 51d1101e74a..c7a597c62c9 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -34,6 +34,7 @@ source_files = ['BPY_interface.c', 'api2_2x/Noise.c', 'api2_2x/NMesh.c', 'api2_2x/Object.c', + 'api2_2x/Pose.c', 'api2_2x/point.c', 'api2_2x/Registry.c', 'api2_2x/Scene.c', diff --git a/source/blender/python/api2_2x/NLA.c b/source/blender/python/api2_2x/NLA.c index a07f15b3cab..c1ed37bfe43 100644 --- a/source/blender/python/api2_2x/NLA.c +++ b/source/blender/python/api2_2x/NLA.c @@ -79,6 +79,7 @@ static PyObject *Action_getName( BPy_Action * self ); static PyObject *Action_setName( BPy_Action * self, PyObject * args ); static PyObject *Action_setActive( BPy_Action * self, PyObject * args ); static PyObject *Action_getChannelIpo( BPy_Action * self, PyObject * args ); +static PyObject *Action_verifyChannel( BPy_Action * self, PyObject * args ); static PyObject *Action_removeChannel( BPy_Action * self, PyObject * args ); static PyObject *Action_getAllChannelIpos( BPy_Action * self ); @@ -95,6 +96,8 @@ static PyMethodDef BPy_Action_methods[] = { "(str) -set this action as the active action for an object"}, {"getChannelIpo", ( PyCFunction ) Action_getChannelIpo, METH_VARARGS, "(str) -get the Ipo from a named action channel in this action"}, + {"verifyChannel", ( PyCFunction ) Action_verifyChannel, METH_VARARGS, + "(str) -verify the channel in this action"}, {"removeChannel", ( PyCFunction ) Action_removeChannel, METH_VARARGS, "(str) -remove the channel from the action"}, {"getAllChannelIpos", ( PyCFunction ) Action_getAllChannelIpos, @@ -317,6 +320,27 @@ static PyObject *Action_getChannelIpo( BPy_Action * self, PyObject * args ) return Ipo_CreatePyObject( chan->ipo ); } +//---------------------------------------------------------------------- +static PyObject *Action_verifyChannel( BPy_Action * self, PyObject * args ) +{ + char *chanName; + bActionChannel *chan; + + if( !self->action ) + ( EXPP_ReturnPyObjError( PyExc_RuntimeError, + "couldn't create channel for a NULL action" ) ); + + if( !PyArg_ParseTuple( args, "s", &chanName ) ) + return ( EXPP_ReturnPyObjError( PyExc_AttributeError, + "expected string argument" ) ); + + chan = verify_action_channel(self->action, chanName); + + Py_INCREF( Py_None ); + return Py_None; +} + + static PyObject *Action_removeChannel( BPy_Action * self, PyObject * args ) { char *chanName; diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index b8430b3e348..00d948eb7fc 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -77,6 +77,7 @@ struct rctf; #include "Curve.h" #include "Ipo.h" #include "Armature.h" +#include "Pose.h" #include "Camera.h" #include "Lamp.h" #include "Lattice.h" @@ -181,6 +182,7 @@ static PyObject *Object_getTracked( BPy_Object * self ); static PyObject *Object_getType( BPy_Object * self ); static PyObject *Object_getBoundBox( BPy_Object * self ); static PyObject *Object_getAction( BPy_Object * self ); +static PyObject *Object_getPose( BPy_Object * self ); static PyObject *Object_isSelected( BPy_Object * self ); static PyObject *Object_makeDisplayList( BPy_Object * self ); static PyObject *Object_link( BPy_Object * self, PyObject * args ); @@ -198,6 +200,9 @@ static PyObject *Object_setMatrix( BPy_Object * self, PyObject * args ); static PyObject *Object_setIpo( BPy_Object * self, PyObject * args ); static PyObject *Object_insertIpoKey( BPy_Object * self, PyObject * args ); static PyObject *Object_insertPoseKey( BPy_Object * self, PyObject * args ); +static PyObject *Object_insertCurrentPoseKey( BPy_Object * self, PyObject * args ); +static PyObject *Object_insertMatrixKey( BPy_Object * self, PyObject * args ); +static PyObject *Object_bake_to_action( BPy_Object * self, PyObject * args ); static PyObject *Object_setLocation( BPy_Object * self, PyObject * args ); static PyObject *Object_setMaterials( BPy_Object * self, PyObject * args ); static PyObject *Object_setName( BPy_Object * self, PyObject * args ); @@ -295,6 +300,8 @@ If 'name_only' is nonzero or True, only the name of the datablock is returned"}, "Returns the object draw type"}, {"getAction", ( PyCFunction ) Object_getAction, METH_NOARGS, "Returns the active action for this object"}, + {"getPose", ( PyCFunction ) Object_getPose, METH_NOARGS, + "Returns the pose for this object"}, {"isSelected", ( PyCFunction ) Object_isSelected, METH_NOARGS, "Return a 1 or 0 depending on whether the object is selected"}, {"getEuler", ( PyCFunction ) Object_getEuler, METH_NOARGS, @@ -520,6 +527,12 @@ works only if self and the object specified are of the same type."}, "( Object IPO type ) - Inserts a key into IPO"}, {"insertPoseKey", ( PyCFunction ) Object_insertPoseKey, METH_VARARGS, "( Object Pose type ) - Inserts a key into Action"}, + {"insertCurrentPoseKey", ( PyCFunction ) Object_insertCurrentPoseKey, METH_VARARGS, + "( Object Pose type ) - Inserts a key into Action based on current pose"}, + {"insertMatrixKey", ( PyCFunction ) Object_insertMatrixKey, METH_VARARGS, + "( ) - Inserts a key into Action based on current/giventime object matrix"}, + {"bake_to_action", ( PyCFunction ) Object_bake_to_action, METH_VARARGS, + "( ) - creates a new action with the information from object animations"}, {"getAllProperties", ( PyCFunction ) Object_getAllProperties, METH_NOARGS, "() - Get all the properties from this object"}, @@ -1096,6 +1109,15 @@ static PyObject *Object_getAction( BPy_Object * self ) } } +static PyObject *Object_getPose( BPy_Object * self ) +{ + /*BPy_Action *py_action = NULL; */ + + if( !self->object->pose ) + Py_RETURN_NONE; + else + return Pose_CreatePyObject( self->object->pose ); +} static PyObject *Object_isSelected( BPy_Object * self ) { @@ -2060,29 +2082,48 @@ static PyObject *Object_insertIpoKey( BPy_Object * self, PyObject * args ) /* * Object_insertPoseKey() - * inserts Action Pose key (for LOC, ROT, SIZE, LOCROT, or LOCROTSIZE) + * inserts a Action Pose key from a given pose (sourceaction, frame) to the active action to a given framenum */ static PyObject *Object_insertPoseKey( BPy_Object * self, PyObject * args ) { Object *ob= self->object; + BPy_Action *sourceact; char *chanName; + int actframe; + + //for debug prints + bActionChannel *achan; + bPoseChannel *pchan; /* for doing the time trick, similar to editaction bake_action_with_client() */ int oldframe; int curframe; - if( !PyArg_ParseTuple( args, "si", &chanName, &curframe ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected a string and an int argument" ) ); + if( !PyArg_ParseTuple( args, "O!sii", &Action_Type, &sourceact, &chanName, &actframe, &curframe ) ) + return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expects an action to copy poses from, a string for chan/bone name, an int argument for frame-to-extract from the action and finally another int for the frame where to put the new key in the active object.action" ) ); + + printf("%s %s %d %d, ", sourceact->action->id.name, chanName, actframe, curframe); + printf("%s\n", ob->action->id.name); + + /* */ + extract_pose_from_action(ob->pose, sourceact->action, actframe); oldframe = G.scene->r.cfra; G.scene->r.cfra = curframe; - - /* Apply the object ipo */ - /* uses the current action of the object */ - extract_pose_from_action(ob->pose, ob->action, curframe); - where_is_pose(ob); - + + //debug + pchan = get_pose_channel(ob->pose, chanName); + printquat(pchan->name, pchan->quat); + + achan = get_action_channel(sourceact->action, chanName); + if(achan->ipo) { + IpoCurve* icu; + for (icu = achan->ipo->curve.first; icu; icu=icu->next){ + printvecf("bezt", icu->bezt->vec[1]); + } + } + insertkey(&ob->id, ID_PO, chanName, NULL, AC_LOC_X); insertkey(&ob->id, ID_PO, chanName, NULL, AC_LOC_Y); insertkey(&ob->id, ID_PO, chanName, NULL, AC_LOC_Z); @@ -2094,6 +2135,123 @@ static PyObject *Object_insertPoseKey( BPy_Object * self, PyObject * args ) insertkey(&ob->id, ID_PO, chanName, NULL, AC_SIZE_Y); insertkey(&ob->id, ID_PO, chanName, NULL, AC_SIZE_Z); + /* + for (achan = ob->action->chanbase.first; achan; achan=achan->next) { + if(achan->ipo) { + IpoCurve* icu; + for (icu = achan->ipo->curve.first; icu; icu=icu->next){ + printf("result: %f %f %f %f", icu->bp->vec[0], icu->bp->vec[1], icu->bp->vec[2], icu->bp->vec[3]); + } + } + } + */ + + G.scene->r.cfra = oldframe; + + allspace(REMAKEIPO, 0); + EXPP_allqueue(REDRAWIPO, 0); + EXPP_allqueue(REDRAWVIEW3D, 0); + EXPP_allqueue(REDRAWACTION, 0); + EXPP_allqueue(REDRAWNLA, 0); + + /* restore, but now with the new action in place */ + //extract_pose_from_action(ob->pose, ob->action, G.scene->r.cfra); + //where_is_pose(ob); + + allqueue(REDRAWACTION, 1); + + return EXPP_incr_ret( Py_None ); +} + +static PyObject *Object_insertCurrentPoseKey( BPy_Object * self, PyObject * args ) +{ + Object *ob= self->object; + //bPoseChannel *pchan; //for iterating over all channels in object->pose + char *chanName; + + /* for doing the time trick, similar to editaction bake_action_with_client() */ + int oldframe; + int curframe; + + if( !PyArg_ParseTuple( args, "si", &chanName, &curframe ) ) + return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected chan/bone name, and a time (int) argument" ) ); + + oldframe = G.scene->r.cfra; + G.scene->r.cfra = curframe; + + insertkey(&ob->id, ID_PO, chanName, NULL, AC_LOC_X); + insertkey(&ob->id, ID_PO, chanName, NULL, AC_LOC_Y); + insertkey(&ob->id, ID_PO, chanName, NULL, AC_LOC_Z); + insertkey(&ob->id, ID_PO, chanName, NULL, AC_QUAT_X); + insertkey(&ob->id, ID_PO, chanName, NULL, AC_QUAT_Y); + insertkey(&ob->id, ID_PO, chanName, NULL, AC_QUAT_Z); + insertkey(&ob->id, ID_PO, chanName, NULL, AC_QUAT_W); + insertkey(&ob->id, ID_PO, chanName, NULL, AC_SIZE_X); + insertkey(&ob->id, ID_PO, chanName, NULL, AC_SIZE_Y); + insertkey(&ob->id, ID_PO, chanName, NULL, AC_SIZE_Z); + + G.scene->r.cfra = oldframe; + + allspace(REMAKEIPO, 0); + EXPP_allqueue(REDRAWIPO, 0); + EXPP_allqueue(REDRAWVIEW3D, 0); + EXPP_allqueue(REDRAWACTION, 0); + EXPP_allqueue(REDRAWNLA, 0); + + /* restore */ + extract_pose_from_action(ob->pose, ob->action, G.scene->r.cfra); + where_is_pose(ob); + + allqueue(REDRAWACTION, 1); + + return EXPP_incr_ret( Py_None ); +} + +static PyObject *Object_insertMatrixKey( BPy_Object * self, PyObject * args ) +{ + Object *ob= self->object; + char *chanName; + + /* for doing the time trick, similar to editaction bake_action_with_client() */ + int oldframe; + int curframe; + + /* for copying the current object/bone matrices to the new action */ + bPoseChannel *pchan; + float localQuat[4]; + float tmat[4][4], startpos[4][4]; + + //to get the matrix + bArmature *arm; + Bone *bone; + + if( !PyArg_ParseTuple( args, "si", &chanName, &curframe ) ) + return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expects a string for chan/bone name and an int for the frame where to put the new key" ) ); + + oldframe = G.scene->r.cfra; + G.scene->r.cfra = curframe; + + //just to get the armaturespace mat + arm = get_armature(ob); + for (bone = arm->bonebase.first; bone; bone=bone->next) + if (bone->name == chanName) break; + //XXX does not check for if-not-found + + where_is_object(ob); + world2bonespace(tmat, ob->obmat, bone->arm_mat, startpos); + Mat4ToQuat(tmat, localQuat); + + insertmatrixkey(&ob->id, ID_PO, chanName, NULL, AC_LOC_X, tmat[3][0]); + insertmatrixkey(&ob->id, ID_PO, chanName, NULL, AC_LOC_Y, tmat[3][1]); + insertmatrixkey(&ob->id, ID_PO, chanName, NULL, AC_LOC_Z, tmat[3][2]); + insertmatrixkey(&ob->id, ID_PO, chanName, NULL, AC_QUAT_W, localQuat[0]); + insertmatrixkey(&ob->id, ID_PO, chanName, NULL, AC_QUAT_X, localQuat[1]); + insertmatrixkey(&ob->id, ID_PO, chanName, NULL, AC_QUAT_Y, localQuat[2]); + insertmatrixkey(&ob->id, ID_PO, chanName, NULL, AC_QUAT_Z, localQuat[3]); + //insertmatrixkey(&ob->id, ID_PO, chanName, NULL, AC_SIZE_X, ); + //insertmatrixkey(&ob->id, ID_PO, chanName, NULL, AC_SIZE_Y); + //insertmatrixkey(&ob->id, ID_PO, chanName, NULL, AC_SIZE_Z); + allspace(REMAKEIPO, 0); EXPP_allqueue(REDRAWIPO, 0); EXPP_allqueue(REDRAWVIEW3D, 0); @@ -2102,7 +2260,7 @@ static PyObject *Object_insertPoseKey( BPy_Object * self, PyObject * args ) G.scene->r.cfra = oldframe; - /* restore */ + /* restore, but now with the new action in place */ extract_pose_from_action(ob->pose, ob->action, G.scene->r.cfra); where_is_pose(ob); @@ -2111,7 +2269,26 @@ static PyObject *Object_insertPoseKey( BPy_Object * self, PyObject * args ) return EXPP_incr_ret( Py_None ); } +static PyObject *Object_bake_to_action( BPy_Object * self, PyObject * args ) +{ + Object *ob= self->object; + + /* for doing the time trick, similar to editaction bake_action_with_client() */ + //int oldframe; + //int curframe; + + //if( !PyArg_ParseTuple( args, "i", &curframe ) ) + // return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expects an int for the frame where to put the new key" ) ); + + //oldframe = G.scene->r.cfra; + //G.scene->r.cfra = curframe; + + bake_all_to_action(); //ob); + //G.scene->r.cfra = oldframe; + + return EXPP_incr_ret( Py_None ); +} static PyObject *Object_setLocation( BPy_Object * self, PyObject * args ) { diff --git a/source/blender/python/api2_2x/Types.c b/source/blender/python/api2_2x/Types.c index 6f5bbac6a3a..8eb2ed3c2cb 100644 --- a/source/blender/python/api2_2x/Types.c +++ b/source/blender/python/api2_2x/Types.c @@ -48,6 +48,7 @@ struct PyMethodDef Null_methods[] = { {NULL, NULL, 0, NULL} }; void types_InitAll( void ) { Action_Type.ob_type = &PyType_Type; + Pose_Type.ob_type = &PyType_Type; Armature_Type.ob_type = &PyType_Type; BezTriple_Type.ob_type = &PyType_Type; Bone_Type.ob_type = &PyType_Type; @@ -183,6 +184,8 @@ PyObject *Types_Init( void ) ( PyObject * ) &BezTriple_Type ); PyDict_SetItemString( dict, "ActionType", ( PyObject * ) &Action_Type ); + PyDict_SetItemString( dict, "PoseType", + ( PyObject * ) &Pose_Type ); PyDict_SetItemString( dict, "propertyType", ( PyObject * ) &property_Type ); PyDict_SetItemString( dict, "pointType", diff --git a/source/blender/python/api2_2x/Types.h b/source/blender/python/api2_2x/Types.h index ea8a80a1a98..349c4af545b 100644 --- a/source/blender/python/api2_2x/Types.h +++ b/source/blender/python/api2_2x/Types.h @@ -36,6 +36,7 @@ #include <Python.h> extern PyTypeObject Action_Type, Armature_Type; +extern PyTypeObject Pose_Type; extern PyTypeObject BezTriple_Type, Bone_Type, Button_Type; extern PyTypeObject Camera_Type; extern PyTypeObject CurNurb_Type; diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 118bdee813f..42c40205727 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -2148,46 +2148,6 @@ static void numbuts_action(void) } } -static void insert_test(void) -{ - Object *ob= OBACT; - bActionChannel *achan; - int oldframe; - - if(ob==NULL || ob->pose==NULL || ob->action==NULL) return; - printf("In the call\n"); - - /* uses the current action of the object */ - extract_pose_from_action(ob->pose, ob->action, G.scene->r.cfra); - - oldframe = G.scene->r.cfra; - G.scene->r.cfra = G.rt; - - for (achan = ob->action->chanbase.first; achan; achan=achan->next) { - if(achan->ipo) { - printf("inserted %s\n", achan->name); - insertkey(&ob->id, ID_PO, achan->name, NULL, AC_LOC_X); - insertkey(&ob->id, ID_PO, achan->name, NULL, AC_LOC_Y); - insertkey(&ob->id, ID_PO, achan->name, NULL, AC_LOC_Z); - insertkey(&ob->id, ID_PO, achan->name, NULL, AC_QUAT_X); - insertkey(&ob->id, ID_PO, achan->name, NULL, AC_QUAT_Y); - insertkey(&ob->id, ID_PO, achan->name, NULL, AC_QUAT_Z); - insertkey(&ob->id, ID_PO, achan->name, NULL, AC_QUAT_W); - insertkey(&ob->id, ID_PO, achan->name, NULL, AC_SIZE_X); - insertkey(&ob->id, ID_PO, achan->name, NULL, AC_SIZE_Y); - insertkey(&ob->id, ID_PO, achan->name, NULL, AC_SIZE_Z); - } - } - - G.scene->r.cfra = oldframe; - - allspace(REMAKEIPO, 0); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWACTION, 1); -} - void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) { extern void do_actionbuts(unsigned short event); // drawaction.c @@ -2775,3 +2735,169 @@ void bottom_sel_action() allqueue(REDRAWIPO, 0); allqueue(REDRAWNLA, 0); } + +void world2bonespace(float boneSpaceMat[][4], float worldSpace[][4], float restPos[][4], float armPos[][4]) +{ + float imatarm[4][4], imatbone[4][4], tmat[4][4], t2mat[4][4]; + + Mat4Invert(imatarm, armPos); + Mat4Invert(imatbone, restPos); + Mat4MulMat4(tmat, imatarm, worldSpace); + Mat4MulMat4(t2mat, tmat, imatbone); + Mat4MulMat4(boneSpaceMat, restPos, t2mat); +} + + +bAction* bake_obIPO_to_action (Object *ob) +{ + bArmature *arm; + bAction *result=NULL; + bActionChannel *achan; + bAction *temp; + bPoseChannel *pchan; + Bone *bone; + ID *id; + ListBase elems; + float actstart, actend; + int oldframe,testframe; + int curframe; + char newname[64]; + float quat[4],tmat[4][4],startpos[4][4],imat[4][4],mat3[3][3]; + CfraElem *firstcfra, *lastcfra; + + arm = get_armature(ob); + + if (arm) { + + oldframe = CFRA; + result = add_empty_action(ID_PO); + id = (ID *)ob; + + sprintf (newname, "TESTOBBAKE"); + rename_id(&result->id, newname); + + if(ob!=G.obedit) { // make sure object is not in edit mode + if(ob->ipo) { + /* convert the ipo to a list of 'current frame elements' */ + + temp = ob->action; + ob->action = result; + + elems.first= elems.last= NULL; + make_cfra_list(ob->ipo, &elems); + /* set the beginning armature location */ + firstcfra=elems.first; + lastcfra=elems.last; + CFRA=firstcfra->cfra; + + where_is_object(ob); + Mat4CpyMat4(startpos,ob->obmat); + + /* loop from first key to last, sampling every 10 */ + for (testframe = firstcfra->cfra; testframe<=lastcfra->cfra; testframe=testframe+10) { + CFRA=testframe; + where_is_object(ob); + + for (bone = arm->bonebase.first; bone; bone=bone->next) { + if (!bone->parent) { /* this is a root bone, so give it a key! */ + world2bonespace(tmat,ob->obmat,bone->arm_mat,startpos); + Mat4ToQuat(tmat,quat); + printf("Frame: %i %f, %f, %f, %f\n",CFRA,quat[0],quat[1],quat[2],quat[3]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_X,tmat[3][0]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_Y,tmat[3][1]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_Z,tmat[3][2]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_X,quat[1]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_Y,quat[2]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_Z,quat[3]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_W,quat[0]); + //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_X,size[0]); + //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_Y,size[1]); + //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_Z,size[2]); + } + } + } + BLI_freelistN(&elems); + } + } + CFRA = oldframe; + } + return result; +} + +bAction* bake_everything_to_action (Object *ob) +{ + bArmature *arm; + bAction *result=NULL; + bActionChannel *achan; + bAction *temp; + bPoseChannel *pchan; + Bone *bone; + ID *id; + ListBase elems; + float actstart, actend; + int oldframe,testframe; + int curframe; + char newname[64]; + float quat[4],tmat[4][4],startpos[4][4],imat[4][4],mat3[3][3]; + CfraElem *firstcfra, *lastcfra; + + arm = get_armature(ob); + + if (arm) { + + oldframe = CFRA; + result = add_empty_action(ID_PO); + id = (ID *)ob; + + sprintf (newname, "TESTOBBAKE"); + rename_id(&result->id, newname); + + if(ob!=G.obedit) { // make sure object is not in edit mode + if(ob->ipo) { + /* convert the ipo to a list of 'current frame elements' */ + + temp = ob->action; + ob->action = result; + + elems.first= elems.last= NULL; + make_cfra_list(ob->ipo, &elems); + /* set the beginning armature location */ + firstcfra=elems.first; + lastcfra=elems.last; + CFRA=firstcfra->cfra; + + where_is_object(ob); + Mat4CpyMat4(startpos,ob->obmat); + + /* loop from first key to last, sampling every 10 */ + for (testframe = firstcfra->cfra; testframe<=lastcfra->cfra; testframe=testframe+10) { + CFRA=testframe; + + do_all_pose_actions(ob); + where_is_object(ob); + for (bone = arm->bonebase.first; bone; bone=bone->next) { + if (!bone->parent) { /* this is a root bone, so give it a key! */ + world2bonespace(tmat,ob->obmat,bone->arm_mat,startpos); + + Mat4ToQuat(tmat,quat); + printf("Frame: %i %f, %f, %f, %f\n",CFRA,quat[0],quat[1],quat[2],quat[3]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_X,tmat[3][0]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_Y,tmat[3][1]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_Z,tmat[3][2]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_X,quat[1]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_Y,quat[2]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_Z,quat[3]); + insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_W,quat[0]); + //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_X,size[0]); + //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_Y,size[1]); + //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_Z,size[2]); + } + } + } + BLI_freelistN(&elems); + } + } + CFRA = oldframe; + } + return result; +} diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index 9834bdc704c..3fb48fb417f 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -1963,6 +1963,42 @@ void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcod } } +/* For inserting keys based on the object matrix - not on the current IPO value + Generically - it inserts the passed float value into the appropriate IPO */ +void insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float matrixvalue) +{ + IpoCurve *icu; + Object *ob; + void *poin= NULL; + float cfra; + int vartype; + + icu= verify_ipocurve(id, blocktype, actname, constname, adrcode); + + if(icu) { + + poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype); + + if(poin) { + + cfra= frame_to_float(CFRA); + + /* if action is mapped in NLA, it returns a correction */ + if(actname && actname[0] && GS(id->name)==ID_OB) + cfra= get_action_frame((Object *)id, cfra); + + if( GS(id->name)==ID_OB ) { + ob= (Object *)id; + if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { + /* actually frametofloat calc again! */ + cfra-= ob->sf*G.scene->r.framelen; + } + } + insert_vert_ipo(icu, cfra, matrixvalue); + } + } +} + void insertkey_editipo(void) { EditIpo *ei; @@ -2340,7 +2376,7 @@ void common_insertkey(void) ob= OBACT; if (ob && (ob->flag & OB_POSEMODE)) { - strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Avail%x9"); + strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Avail%x9|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13"); } else { base= FIRSTBASE; @@ -2350,7 +2386,7 @@ void common_insertkey(void) } if(base==NULL) return; - strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Layer%x5|Avail%x9"); + strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Layer%x5|Avail%x9|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13"); } if(ob) { @@ -2408,6 +2444,25 @@ void common_insertkey(void) } } } + if(event==11 || event==13) { + float obSpaceBoneMat[4][4]; + + bone2objectspace(obSpaceBoneMat, pchan->pose_mat, pchan->bone->arm_mat); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, obSpaceBoneMat[3][0]); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, obSpaceBoneMat[3][1]); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, obSpaceBoneMat[3][2]); + } + if(event==12 || event==13) { + float obSpaceBoneMat[4][4]; + float localQuat[4]; + + bone2objectspace(obSpaceBoneMat, pchan->pose_mat, pchan->bone->arm_mat); + Mat4ToQuat(obSpaceBoneMat, localQuat); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, localQuat[0]); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, localQuat[1]); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, localQuat[2]); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, localQuat[2]); + } } } if(ob->action) @@ -2460,6 +2515,21 @@ void common_insertkey(void) insertkey(id, ID_OB, actname, NULL, OB_LAY); base->object->lay= tlay; } + if(event==11 || event==13) { + insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_X, ob->obmat[3][0]); + insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Y, ob->obmat[3][1]); + insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Z, ob->obmat[3][2]); + } + if(event==12 || event==13) { + float eul[3]; + float rotMat[3][3]; + + Mat3CpyMat4(rotMat, ob->obmat); + Mat3ToEul(rotMat, eul); + insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_X, eul[0]*(5.72958)); + insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Y, eul[1]*(5.72958)); + insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Z, eul[2]*(5.72958)); + } } base= base->next; } @@ -4454,4 +4524,10 @@ void move_to_frame(void) BIF_undo_push("Set frame to selected Ipo vertex"); } - +void bone2objectspace(float obSpaceBoneMat[][4], float obSpace[][4], float restPos[][4]) +{ + float imat[4][4]; + + Mat4Invert(imat, restPos); + Mat4MulMat4(obSpaceBoneMat, obSpace, imat); +} diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c index 7708b699b52..1679d274d2c 100644 --- a/source/blender/src/editnla.c +++ b/source/blender/src/editnla.c @@ -1577,6 +1577,23 @@ void deselect_nlachannels(int test) } } +static Object *get_object_from_active_strip(void) { + + Base *base; + bActionStrip *strip; + + for (base=G.scene->base.first; base; base=base->next) { + for (strip = base->object->nlastrips.first; + strip; strip=strip->next){ + if (strip->flag & ACTSTRIP_SELECT) { + return base->object; + } + } + } + return NULL; +} + + void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt) { unsigned short event= evt->event; @@ -1587,6 +1604,7 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt) float dx,dy; int cfra; short mousebut = L_MOUSE; + Object *ob; //in shift-B / bake if (curarea->win==0) return; if (!snla) return; @@ -1646,8 +1664,17 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case BKEY: - borderselect_nla(); - break; + if (G.qual & LR_SHIFTKEY){ + bake_all_to_action(); + allqueue (REDRAWNLA, 0); + allqueue (REDRAWVIEW3D, 0); + BIF_undo_push("Bake All To Action"); + ob = get_object_from_active_strip(); + //build_match_caches(ob); + } + else + borderselect_nla(); + break; case CKEY: convert_nla(mval); @@ -1763,3 +1790,91 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(doredraw) scrarea_queue_winredraw(curarea); } +static void add_nla_block_by_name(char name[32], Object *ob, short hold, short add, float repeat) +{ + bAction *act=NULL; + bActionStrip *strip; + int cur; + + if (name){ + for (cur = 1, act=G.main->action.first; act; act=act->id.next, cur++){ + if (strcmp(name,act->id.name)==0) { + break; + } + } + } + + /* Bail out if no action was chosen */ + if (!act){ + return; + } + + /* Initialize the new action block */ + strip = MEM_callocN(sizeof(bActionStrip), "bActionStrip"); + + deselect_nlachannel_keys(0); + + /* Link the action to the strip */ + strip->act = act; + calc_action_range(strip->act, &strip->actstart, &strip->actend); + strip->start = G.scene->r.cfra; /* could be mval[0] another time... */ + strip->end = strip->start + (strip->actend-strip->actstart); + /* simple prevention of zero strips */ + if(strip->start>strip->end-2) + strip->end= strip->start+100; + + strip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION; //|ACTSTRIP_USEMATCH; + + if (hold==1) + strip->flag = strip->flag|ACTSTRIP_HOLDLASTFRAME; + + if (add==1) + strip->mode = ACTSTRIPMODE_ADD; + + find_stridechannel(ob, strip); + + set_active_strip(ob, strip); + + strip->repeat = repeat; + + act->id.us++; + + BLI_addtail(&ob->nlastrips, strip); + + BIF_undo_push("Add NLA strip"); +} + +void bake_all_to_action(void) +{ + Object *ob; + bAction *newAction=NULL; + Ipo *ipo=NULL; + ID *id; + short hold, add; + float repeat; + + /* burn object-level motion into a new action */ + ob = get_object_from_active_strip(); + if (ob) { + if (ob->flag&OB_ARMATURE) { + newAction = bake_obIPO_to_action(ob); + if (newAction) { + /* unlink the object's IPO */ + ipo=ob->ipo; + if (ipo) { + id = &ipo->id; + if (id->us > 0) + id->us--; + ob->ipo = NULL; + } + + /* add the new Action to NLA as a strip */ + hold=1; + add=1; + repeat=1.0; + printf("about to add nla block...\n"); + add_nla_block_by_name(newAction->id.name, ob, hold, add, repeat); + } + } + } +} diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 67517b163de..899acdb4136 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -2678,10 +2678,15 @@ void drawinfospace(ScrArea *sa, void *spacedata) uiDefBut(block, LABEL,0,"Auto keyframe", (xpos+(2*edgsp)+(2*mpref)+midsp),y3label,mpref,buth, 0, 0, 0, 0, 0, ""); + uiDefButBitI(block, TOG, G_RECORDKEYS, REDRAWTIME, "Action and Object", (xpos+edgsp+(2*mpref)+(2*midsp)),y2,mpref, buth, &(G.flags), 0, 0, 0, 0, "Automatic keyframe insertion in Object and Action Ipo curves"); + uiDefButBitI(block, TOG, USER_KEYINSERTAVAI, REDRAWTIME, "Available", + (xpos+edgsp+(2*mpref)+(2*midsp)),y1,mpref, buth, + &(U.uiflag), 0, 0, 0, 0, "Automatic keyframe insertion in available curves"); + // uiDefButBitS(block, TOG, USER_KEYINSERTACT, 0, "Action", // (xpos+edgsp+(2*mpref)+(2*midsp)),y2,(spref+edgsp),buth, // &(U.uiflag), 0, 0, 0, 0, "Automatic keyframe insertion in Action Ipo curve"); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index bb454270d2f..82b5c63d4cb 100755 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -2027,6 +2027,7 @@ void special_aftertrans_update(TransInfo *t) { Object *ob; Base *base; + IpoCurve *icu; int redrawipo=0; int cancelled= (t->state == TRANS_CANCEL); @@ -2073,19 +2074,36 @@ void special_aftertrans_update(TransInfo *t) for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){ if (pchan->bone->flag & BONE_TRANSFORM){ - - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X); - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y); - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z); - - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W); - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X); - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y); - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z); - - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X); - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y); - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z); + + if(U.uiflag & USER_KEYINSERTAVAI) { + bActionChannel *achan; + + for (achan = act->chanbase.first; achan; achan=achan->next){ + + if (achan->ipo && !strcmp (achan->name, pchan->name)){ + for (icu = achan->ipo->curve.first; icu; icu=icu->next){ + insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode); + } + + break; + } + } + } + else{ + + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X); + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y); + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z); + + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W); + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X); + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y); + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z); + + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X); + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y); + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z); + } } } @@ -2122,22 +2140,36 @@ void special_aftertrans_update(TransInfo *t) /* Set autokey if necessary */ if ((G.flags & G_RECORDKEYS) && (!cancelled) && (base->flag & SELECT)){ char *actname=""; - + if(ob->ipoflag & OB_ACTION_OB) actname= "Object"; - - insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_X); - insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_Y); - insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_Z); - - insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_X); - insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_Y); - insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_Z); - - insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_X); - insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_Y); - insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_Z); - + + if(U.uiflag & USER_KEYINSERTAVAI) { + if(base->object->ipo) { + ID* id= (ID *)(base->object); + icu= base->object->ipo->curve.first; + while(icu) { + icu->flag &= ~IPO_SELECT; + insertkey(id, ID_OB, actname, NULL, icu->adrcode); + icu= icu->next; + } + } + } + else { + + insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_X); + insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_Y); + insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_Z); + + insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_X); + insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_Y); + insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_Z); + + insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_X); + insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_Y); + insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_Z); + } + remake_object_ipos (ob); allqueue(REDRAWIPO, 0); allspace(REMAKEIPO, 0); |