Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c5
-rw-r--r--source/blender/blenkernel/intern/constraint.c21
-rw-r--r--source/blender/python/BPY_extern.h2
-rw-r--r--source/blender/python/BPY_interface.c116
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 );