diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/bad_level_call_stubs/stubs.c | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/constraint.c | 21 | ||||
-rw-r--r-- | source/blender/python/BPY_extern.h | 2 | ||||
-rw-r--r-- | source/blender/python/BPY_interface.c | 116 |
4 files changed, 136 insertions, 8 deletions
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 340ac1ed693..0c81cdfa245 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -125,10 +125,13 @@ int BPY_button_eval(char *expr, double *value) return 0; } -/* constraint.c */ +/* PyConstraints - BPY_interface.c */ void BPY_pyconstraint_eval(struct bPythonConstraint *con, float ownermat[][4], float targetmat[][4]) { } +void BPY_pyconstraint_driver(struct bPythonConstraint *con, struct bConstraintOb *cob, struct Object *target, char subtarget[]) +{ +} int BPY_pyconstraint_targets(struct bPythonConstraint *con, float targetmat[][4]) { return 0; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 7f736a644f9..5ed729fbd37 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2815,16 +2815,29 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) /* value should have been set from IPO's/Constraint Channels already */ enf = con->enforce; - /* move owner into right space */ + /* move owner matrix into right space */ constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace); + Mat4CpyMat4(oldmat, cob->matrix); - /* Get the target matrix - in right space to be used */ + /* get the target matrix - in right space to be used */ ownerdata= ((cob->pchan)? (void *)cob->pchan : (void *)cob->ob); get_constraint_target_matrix(con, cob->type, ownerdata, tarmat, ctime); - Mat4CpyMat4(oldmat, cob->matrix); - /* solve the constraint */ + /* Special Hack for PyConstraints to be able to set settings on the owner and/or + * target. Technically, this violates the design of constraints (as constraints should + * only act on matrices to alter the final transform of an owner), but on the other + * hand, this makes PyConstraints more powerful as it enables certain setups to be created + * and work reliably. + */ + if (con->type == CONSTRAINT_TYPE_PYTHON) { + bPythonConstraint *pycon= (bPythonConstraint *)con->data; + + /* as usual, the function for this is defined in BPY_interface.c */ + BPY_pyconstraint_driver(pycon, cob, pycon->tar, pycon->subtarget); + } + + /* Solve the constraint */ evaluate_constraint(con, cob->matrix, tarmat); /* Interpolate the enforcement, to blend result of constraint into final owner transform */ diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index ee7afe7dcf6..0e662c38d31 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -47,6 +47,7 @@ struct Script; /* BPI_script.h */ struct ScrArea; /* DNA_screen_types.h */ struct bScreen; /* DNA_screen_types.h */ struct bPythonConstraint; /* DNA_constraint_types.h */ +struct bConstraintOb; /* BKE_constraint.h */ #ifdef __cplusplus extern "C" { #endif @@ -71,6 +72,7 @@ extern "C" { void BPy_Free_DrawButtonsList(void); void BPY_pyconstraint_eval(struct bPythonConstraint *con, float ownermat[][4], float targetmat[][4]); + void BPY_pyconstraint_driver(struct bPythonConstraint *con, struct bConstraintOb *cob, struct Object *target, char subtarget[]); void BPY_pyconstraint_settings(void *arg1, void *arg2); int BPY_pyconstraint_targets(struct bPythonConstraint *con, float targetmat[][4]); int BPY_is_pyconstraint(struct Text *text); diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index bcdf5ecee9c..67ad88359a8 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -44,6 +44,7 @@ #include "BKE_library.h" #include "BKE_object.h" /* during_scriptlink() */ #include "BKE_text.h" +#include "BKE_constraint.h" /* for bConstraintOb */ #include "DNA_curve_types.h" /* for struct IpoDriver */ #include "DNA_ID.h" /* ipo driver */ @@ -1163,7 +1164,9 @@ int BPY_is_pyconstraint(Text *text) return 0; } -/* This evals py constraints. It is passed all the arguments the normal constraints recieve */ +/* PyConstraints Evaluation Function (only called from evaluate_constraint) + * This function is responsible for modifying the ownermat that it is passed. + */ void BPY_pyconstraint_eval(bPythonConstraint *con, float ownermat[][4], float targetmat[][4]) { PyObject *srcmat, *tarmat, *idprop; @@ -1290,6 +1293,110 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, float ownermat[][4], float ta Py_XDECREF( retval ); } +/* PyConstraints 'Driver' Function + * This function is responsible for running any code that requires full access to the owner and the target + * It should be used sparringly, and only for doing 'hacks' which are not possible any other way. + */ +void BPY_pyconstraint_driver(bPythonConstraint *con, bConstraintOb *cob, Object *target, char subtarget[]) +{ + PyObject *owner, *subowner, *tar, *subtar; + PyObject *idprop; + PyObject *globals, *gval; + PyObject *pyargs, *retval; + + if ( !con->text ) return; + if ( con->flag & PYCON_SCRIPTERROR) return; + + globals = CreateGlobalDictionary(); + + owner = Object_CreatePyObject( cob->ob ); + subowner = PyPoseBone_FromPosechannel( cob->pchan ); + + tar = Object_CreatePyObject( target ); + if ( (target) && (target->type==OB_ARMATURE) ) { + bPoseChannel *pchan; + pchan = get_pose_channel( target->pose, subtarget ); + subtar = PyPoseBone_FromPosechannel( pchan ); + } + else + subtar = PyString_FromString(subtarget); + + idprop = BPy_Wrap_IDProperty( NULL, con->prop, NULL); + +/* since I can't remember what the armature weakrefs do, I'll just leave this here + commented out. This function was based on pydrivers, and it might still be relevent. + if( !setup_armature_weakrefs()){ + fprintf( stderr, "Oops - weakref dict setup\n"); + return result; + } +*/ + retval = RunPython( con->text, globals ); + + if ( retval == NULL ) { + BPY_Err_Handle(con->text->id.name); + ReleaseGlobalDictionary( globals ); + con->flag |= PYCON_SCRIPTERROR; + + /* free temp objects */ + Py_XDECREF( idprop ); + Py_XDECREF( owner ); + Py_XDECREF( subowner ); + Py_XDECREF( tar ); + Py_XDECREF( subtar ); + return; + } + + if (retval) {Py_XDECREF( retval );} + retval = NULL; + + gval = PyDict_GetItemString(globals, "doDriver"); + if (!gval) { + ReleaseGlobalDictionary( globals ); + + /* free temp objects */ + Py_XDECREF( idprop ); + Py_XDECREF( owner ); + Py_XDECREF( subowner ); + Py_XDECREF( tar ); + Py_XDECREF( subtar ); + return; + } + + /* Now for the fun part! Try and find the functions we need. */ + if (PyFunction_Check(gval) ) { + pyargs = Py_BuildValue("OOOOO", owner, subowner, tar, subtar, idprop); + retval = PyObject_CallObject(gval, pyargs); + Py_XDECREF( pyargs ); + } else { + printf("ERROR: doDriver is supposed to be a function!\n"); + con->flag |= PYCON_SCRIPTERROR; + ReleaseGlobalDictionary( globals ); + + Py_XDECREF( idprop ); + Py_XDECREF( owner ); + Py_XDECREF( subowner ); + Py_XDECREF( tar ); + Py_XDECREF( subtar ); + return; + } + + /* an error occurred while running the function? */ + if (!retval) { + BPY_Err_Handle(con->text->id.name); + con->flag |= PYCON_SCRIPTERROR; + } + + /* clear globals */ + ReleaseGlobalDictionary( globals ); + + /* free temp objects */ + Py_XDECREF( idprop ); + Py_XDECREF( owner ); + Py_XDECREF( subowner ); + Py_XDECREF( tar ); + Py_XDECREF( subtar ); +} + /* This evaluates whether constraint uses targets, and also the target matrix * Return code of 0 = doesn't use targets, 1 = uses targets + matrix set, -1 = uses targets + matrix not set */ @@ -1310,10 +1417,13 @@ int BPY_pyconstraint_targets(bPythonConstraint *con, float targetmat[][4]) globals = CreateGlobalDictionary(); tar = Object_CreatePyObject( con->tar ); - if ( con->tar ) + if ( (con->tar) && (con->tar->type==OB_ARMATURE) ) { + bPoseChannel *pchan; pchan = get_pose_channel( con->tar->pose, con->subtarget ); + subtar = PyPoseBone_FromPosechannel( pchan ); + } else - pchan = NULL; + subtar = PyString_FromString(subtarget); subtar = PyPoseBone_FromPosechannel( pchan ); tarmat = newMatrixObject( (float*)targetmat, 4, 4, Py_NEW ); |