Blender V2.61 - r43446

KX_PyConstraintBinding.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00032 #include "KX_PyConstraintBinding.h"
00033 #include "PHY_IPhysicsEnvironment.h"
00034 #include "KX_ConstraintWrapper.h"
00035 #include "KX_VehicleWrapper.h"
00036 #include "KX_PhysicsObjectWrapper.h"
00037 #include "PHY_IPhysicsController.h"
00038 #include "PHY_IVehicle.h"
00039 #include "PHY_DynamicTypes.h"
00040 #include "MT_Matrix3x3.h"
00041 
00042 #include "PyObjectPlus.h" 
00043 
00044 #ifdef USE_BULLET
00045 #  include "LinearMath/btIDebugDraw.h"
00046 #endif
00047 
00048 #ifdef WITH_PYTHON
00049 
00050 // macro copied from KX_PythonInit.cpp
00051 #define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name2)); Py_DECREF(item)
00052 
00053 // nasty glob variable to connect scripting language
00054 // if there is a better way (without global), please do so!
00055 static PHY_IPhysicsEnvironment* g_CurrentActivePhysicsEnvironment = NULL;
00056 
00057 static char PhysicsConstraints_module_documentation[] =
00058 "This is the Python API for the Physics Constraints";
00059 
00060 
00061 static char gPySetGravity__doc__[] = "setGravity(float x,float y,float z)";
00062 static char gPySetDebugMode__doc__[] = "setDebugMode(int mode)";
00063 
00064 static char gPySetNumIterations__doc__[] = "setNumIterations(int numiter) This sets the number of iterations for an iterative constraint solver";
00065 static char gPySetNumTimeSubSteps__doc__[] = "setNumTimeSubSteps(int numsubstep) This sets the number of substeps for each physics proceed. Tradeoff quality for performance.";
00066 
00067 
00068 static char gPySetDeactivationTime__doc__[] = "setDeactivationTime(float time) This sets the time after which a resting rigidbody gets deactived";
00069 static char gPySetDeactivationLinearTreshold__doc__[] = "setDeactivationLinearTreshold(float linearTreshold)";
00070 static char gPySetDeactivationAngularTreshold__doc__[] = "setDeactivationAngularTreshold(float angularTreshold)";
00071 static char gPySetContactBreakingTreshold__doc__[] = "setContactBreakingTreshold(float breakingTreshold) Reasonable default is 0.02 (if units are meters)";
00072 
00073 static char gPySetCcdMode__doc__[] = "setCcdMode(int ccdMode) Very experimental, not recommended";
00074 static char gPySetSorConstant__doc__[] = "setSorConstant(float sor) Very experimental, not recommended";
00075 static char gPySetSolverTau__doc__[] = "setTau(float tau) Very experimental, not recommended";
00076 static char gPySetSolverDamping__doc__[] = "setDamping(float damping) Very experimental, not recommended";
00077 static char gPySetLinearAirDamping__doc__[] = "setLinearAirDamping(float damping) Very experimental, not recommended";
00078 static char gPySetUseEpa__doc__[] = "setUseEpa(int epa) Very experimental, not recommended";
00079 static char gPySetSolverType__doc__[] = "setSolverType(int solverType) Very experimental, not recommended";
00080 
00081 
00082 static char gPyCreateConstraint__doc__[] = "createConstraint(ob1,ob2,float restLength,float restitution,float damping)";
00083 static char gPyGetVehicleConstraint__doc__[] = "getVehicleConstraint(int constraintId)";
00084 static char gPyRemoveConstraint__doc__[] = "removeConstraint(int constraintId)";
00085 static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId)";
00086 
00087 
00088 
00089 
00090 
00091 
00092 static PyObject* gPySetGravity(PyObject* self,
00093                                PyObject* args,
00094                                PyObject* kwds)
00095 {
00096     float x,y,z;
00097     if (PyArg_ParseTuple(args,"fff",&x,&y,&z))
00098     {
00099         if (PHY_GetActiveEnvironment())
00100             PHY_GetActiveEnvironment()->setGravity(x,y,z);
00101     }
00102     else {
00103         return NULL;
00104     }
00105     
00106     Py_RETURN_NONE;
00107 }
00108 
00109 static PyObject* gPySetDebugMode(PyObject* self,
00110                                  PyObject* args,
00111                                  PyObject* kwds)
00112 {
00113     int mode;
00114     if (PyArg_ParseTuple(args,"i",&mode))
00115     {
00116         if (PHY_GetActiveEnvironment())
00117         {
00118             PHY_GetActiveEnvironment()->setDebugMode(mode);
00119             
00120         }
00121         
00122     }
00123     else {
00124         return NULL;
00125     }
00126     
00127     Py_RETURN_NONE;
00128 }
00129 
00130 
00131 
00132 static PyObject* gPySetNumTimeSubSteps(PyObject* self,
00133                                        PyObject* args,
00134                                        PyObject* kwds)
00135 {
00136     int substep;
00137     if (PyArg_ParseTuple(args,"i",&substep))
00138     {
00139         if (PHY_GetActiveEnvironment())
00140         {
00141             PHY_GetActiveEnvironment()->setNumTimeSubSteps(substep);
00142         }
00143     }
00144     else {
00145         return NULL;
00146     }
00147     Py_RETURN_NONE;
00148 }
00149 
00150 
00151 static PyObject* gPySetNumIterations(PyObject* self,
00152                                      PyObject* args,
00153                                      PyObject* kwds)
00154 {
00155     int iter;
00156     if (PyArg_ParseTuple(args,"i",&iter))
00157     {
00158         if (PHY_GetActiveEnvironment())
00159         {
00160             PHY_GetActiveEnvironment()->setNumIterations(iter);
00161         }
00162     }
00163     else {
00164         return NULL;
00165     }
00166     Py_RETURN_NONE;
00167 }
00168 
00169 
00170 static PyObject* gPySetDeactivationTime(PyObject* self,
00171                                         PyObject* args,
00172                                         PyObject* kwds)
00173 {
00174     float deactive_time;
00175     if (PyArg_ParseTuple(args,"f",&deactive_time))
00176     {
00177         if (PHY_GetActiveEnvironment())
00178         {
00179             PHY_GetActiveEnvironment()->setDeactivationTime(deactive_time);
00180         }
00181     }
00182     else {
00183         return NULL;
00184     }
00185     Py_RETURN_NONE;
00186 }
00187 
00188 
00189 static PyObject* gPySetDeactivationLinearTreshold(PyObject* self,
00190                                                   PyObject* args,
00191                                                   PyObject* kwds)
00192 {
00193     float linearDeactivationTreshold;
00194     if (PyArg_ParseTuple(args,"f",&linearDeactivationTreshold))
00195     {
00196         if (PHY_GetActiveEnvironment())
00197         {
00198             PHY_GetActiveEnvironment()->setDeactivationLinearTreshold( linearDeactivationTreshold);
00199         }
00200     }
00201     else {
00202         return NULL;
00203     }
00204     Py_RETURN_NONE;
00205 }
00206 
00207 
00208 static PyObject* gPySetDeactivationAngularTreshold(PyObject* self,
00209                                                    PyObject* args,
00210                                                    PyObject* kwds)
00211 {
00212     float angularDeactivationTreshold;
00213     if (PyArg_ParseTuple(args,"f",&angularDeactivationTreshold))
00214     {
00215         if (PHY_GetActiveEnvironment())
00216         {
00217             PHY_GetActiveEnvironment()->setDeactivationAngularTreshold( angularDeactivationTreshold);
00218         }
00219     }
00220     else {
00221         return NULL;
00222     }
00223     Py_RETURN_NONE;
00224 }
00225 
00226 static PyObject* gPySetContactBreakingTreshold(PyObject* self,
00227                                                PyObject* args,
00228                                                PyObject* kwds)
00229 {
00230     float contactBreakingTreshold;
00231     if (PyArg_ParseTuple(args,"f",&contactBreakingTreshold))
00232     {
00233         if (PHY_GetActiveEnvironment())
00234         {
00235             PHY_GetActiveEnvironment()->setContactBreakingTreshold( contactBreakingTreshold);
00236         }
00237     }
00238     else {
00239         return NULL;
00240     }
00241     Py_RETURN_NONE;
00242 }
00243 
00244 
00245 static PyObject* gPySetCcdMode(PyObject* self,
00246                                PyObject* args,
00247                                PyObject* kwds)
00248 {
00249     float ccdMode;
00250     if (PyArg_ParseTuple(args,"f",&ccdMode))
00251     {
00252         if (PHY_GetActiveEnvironment())
00253         {
00254             PHY_GetActiveEnvironment()->setCcdMode( ccdMode);
00255         }
00256     }
00257     else {
00258         return NULL;
00259     }
00260     Py_RETURN_NONE;
00261 }
00262 
00263 static PyObject* gPySetSorConstant(PyObject* self,
00264                                    PyObject* args,
00265                                    PyObject* kwds)
00266 {
00267     float sor;
00268     if (PyArg_ParseTuple(args,"f",&sor))
00269     {
00270         if (PHY_GetActiveEnvironment())
00271         {
00272             PHY_GetActiveEnvironment()->setSolverSorConstant( sor);
00273         }
00274     }
00275     else {
00276         return NULL;
00277     }
00278     Py_RETURN_NONE;
00279 }
00280 
00281 static PyObject* gPySetSolverTau(PyObject* self,
00282                                  PyObject* args,
00283                                  PyObject* kwds)
00284 {
00285     float tau;
00286     if (PyArg_ParseTuple(args,"f",&tau))
00287     {
00288         if (PHY_GetActiveEnvironment())
00289         {
00290             PHY_GetActiveEnvironment()->setSolverTau( tau);
00291         }
00292     }
00293     else {
00294         return NULL;
00295     }
00296     Py_RETURN_NONE;
00297 }
00298 
00299 
00300 static PyObject* gPySetSolverDamping(PyObject* self,
00301                                      PyObject* args,
00302                                      PyObject* kwds)
00303 {
00304     float damping;
00305     if (PyArg_ParseTuple(args,"f",&damping))
00306     {
00307         if (PHY_GetActiveEnvironment())
00308         {
00309             PHY_GetActiveEnvironment()->setSolverDamping( damping);
00310         }
00311     }
00312     else {
00313         return NULL;
00314     }
00315     Py_RETURN_NONE;
00316 }
00317 
00318 static PyObject* gPySetLinearAirDamping(PyObject* self,
00319                                         PyObject* args,
00320                                         PyObject* kwds)
00321 {
00322     float damping;
00323     if (PyArg_ParseTuple(args,"f",&damping))
00324     {
00325         if (PHY_GetActiveEnvironment())
00326         {
00327             PHY_GetActiveEnvironment()->setLinearAirDamping( damping);
00328         }
00329     }
00330     else {
00331         return NULL;
00332     }
00333     Py_RETURN_NONE;
00334 }
00335 
00336 
00337 static PyObject* gPySetUseEpa(PyObject* self,
00338                               PyObject* args,
00339                               PyObject* kwds)
00340 {
00341     int epa;
00342     if (PyArg_ParseTuple(args,"i",&epa))
00343     {
00344         if (PHY_GetActiveEnvironment())
00345         {
00346             PHY_GetActiveEnvironment()->setUseEpa(epa);
00347         }
00348     }
00349     else {
00350         return NULL;
00351     }
00352     Py_RETURN_NONE;
00353 }
00354 static PyObject* gPySetSolverType(PyObject* self,
00355                                   PyObject* args,
00356                                   PyObject* kwds)
00357 {
00358     int solverType;
00359     if (PyArg_ParseTuple(args,"i",&solverType))
00360     {
00361         if (PHY_GetActiveEnvironment())
00362         {
00363             PHY_GetActiveEnvironment()->setSolverType(solverType);
00364         }
00365     }
00366     else {
00367         return NULL;
00368     }
00369     Py_RETURN_NONE;
00370 }
00371 
00372 
00373 
00374 static PyObject* gPyGetVehicleConstraint(PyObject* self,
00375                                          PyObject* args,
00376                                          PyObject* kwds)
00377 {
00378 #if defined(_WIN64)
00379     __int64 constraintid;
00380     if (PyArg_ParseTuple(args,"L",&constraintid))
00381 #else
00382     long constraintid;
00383     if (PyArg_ParseTuple(args,"l",&constraintid))
00384 #endif
00385     {
00386         if (PHY_GetActiveEnvironment())
00387         {
00388             
00389             PHY_IVehicle* vehicle = PHY_GetActiveEnvironment()->getVehicleConstraint(constraintid);
00390             if (vehicle)
00391             {
00392                 KX_VehicleWrapper* pyWrapper = new KX_VehicleWrapper(vehicle,PHY_GetActiveEnvironment());
00393                 return pyWrapper->NewProxy(true);
00394             }
00395 
00396         }
00397     }
00398     else {
00399         return NULL;
00400     }
00401 
00402     Py_RETURN_NONE;
00403 }
00404 
00405 
00406 static PyObject* gPyCreateConstraint(PyObject* self,
00407                                          PyObject* args, 
00408                                          PyObject* kwds)
00409 {
00410     /* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */
00411 #if defined(_WIN64)
00412     __int64 physicsid=0,physicsid2 = 0;
00413 #else
00414     long physicsid=0,physicsid2 = 0;
00415 #endif
00416     int constrainttype=0, extrainfo=0;
00417     int len = PyTuple_Size(args);
00418     int success = 1;
00419     int flag = 0;
00420 
00421     float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1;
00422     if (len == 3)
00423     {
00424 #if defined(_WIN64)
00425         success = PyArg_ParseTuple(args,"LLi",&physicsid,&physicsid2,&constrainttype);
00426 #else
00427         success = PyArg_ParseTuple(args,"lli",&physicsid,&physicsid2,&constrainttype);
00428 #endif
00429     }
00430     else if (len == 6)
00431     {
00432 #if defined(_WIN64)
00433         success = PyArg_ParseTuple(args,"LLifff",&physicsid,&physicsid2,&constrainttype,
00434                                    &pivotX,&pivotY,&pivotZ);
00435 #else
00436         success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype,
00437                                    &pivotX,&pivotY,&pivotZ);
00438 #endif  
00439     }
00440     else if (len == 9)
00441     {
00442 #if defined(_WIN64)
00443         success = PyArg_ParseTuple(args,"LLiffffff",&physicsid,&physicsid2,&constrainttype,
00444                                    &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
00445 #else
00446         success = PyArg_ParseTuple(args,"lliffffff",&physicsid,&physicsid2,&constrainttype,
00447                                    &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
00448 #endif
00449     }
00450     else if (len == 10)
00451     {
00452 #if defined(_WIN64)
00453         success = PyArg_ParseTuple(args,"LLiffffffi",&physicsid,&physicsid2,&constrainttype,
00454                                    &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
00455 #else
00456         success = PyArg_ParseTuple(args,"lliffffffi",&physicsid,&physicsid2,&constrainttype,
00457                                    &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
00458 #endif
00459     }
00460 
00461     /* XXX extrainfo seems to be nothing implemented. right now it works as a pivot with [X,0,0] */
00462     else if (len == 4)
00463     {
00464 #if defined(_WIN64)
00465         success = PyArg_ParseTuple(args,"LLii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
00466 #else
00467         success = PyArg_ParseTuple(args,"llii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
00468 #endif
00469         pivotX=extrainfo;
00470     }
00471 
00472     if (success)
00473     {
00474         if (PHY_GetActiveEnvironment())
00475         {
00476             
00477             PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid;
00478             PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2;
00479             if (physctrl) //TODO:check for existence of this pointer!
00480             {
00481                 PHY_ConstraintType ct = (PHY_ConstraintType) constrainttype;
00482                 int constraintid =0;
00483 
00484                 if (ct == PHY_GENERIC_6DOF_CONSTRAINT)
00485                 {
00486                     //convert from euler angle into axis
00487                     float radsPerDeg = 6.283185307179586232f / 360.f;
00488 
00489                     //we need to pass a full constraint frame, not just axis
00490                     //localConstraintFrameBasis
00491                     MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*axisX,radsPerDeg*axisY,radsPerDeg*axisZ));
00492                     MT_Vector3 axis0 = localCFrame.getColumn(0);
00493                     MT_Vector3 axis1 = localCFrame.getColumn(1);
00494                     MT_Vector3 axis2 = localCFrame.getColumn(2);
00495 
00496                     constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,
00497                                                                                 pivotX,pivotY,pivotZ,
00498                                                                                 (float)axis0.x(),(float)axis0.y(),(float)axis0.z(),
00499                                                                                 (float)axis1.x(),(float)axis1.y(),(float)axis1.z(),
00500                                                                                 (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag);
00501                 }
00502                 else {
00503                     constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ,0);
00504                 }
00505                 
00506                 KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment());
00507 
00508                 return wrap->NewProxy(true);
00509             }
00510             
00511             
00512         }
00513     }
00514     else {
00515         return NULL;
00516     }
00517 
00518     Py_RETURN_NONE;
00519 }
00520 
00521 
00522 
00523 
00524 static PyObject* gPyGetAppliedImpulse(PyObject* self,
00525                                       PyObject* args,
00526                                       PyObject* kwds)
00527 {
00528     float   appliedImpulse = 0.f;
00529 
00530 #if defined(_WIN64)
00531     __int64 constraintid;
00532     if (PyArg_ParseTuple(args,"L",&constraintid))
00533 #else
00534     long constraintid;
00535     if (PyArg_ParseTuple(args,"l",&constraintid))
00536 #endif
00537     {
00538         if (PHY_GetActiveEnvironment())
00539         {
00540             appliedImpulse = PHY_GetActiveEnvironment()->getAppliedImpulse(constraintid);
00541         }
00542     }
00543     else {
00544         return NULL;
00545     }
00546 
00547     return PyFloat_FromDouble(appliedImpulse);
00548 }
00549 
00550 
00551 static PyObject* gPyRemoveConstraint(PyObject* self,
00552                                      PyObject* args,
00553                                      PyObject* kwds)
00554 {
00555 #if defined(_WIN64)
00556     __int64 constraintid;
00557     if (PyArg_ParseTuple(args,"L",&constraintid))
00558 #else
00559     long constraintid;
00560     if (PyArg_ParseTuple(args,"l",&constraintid))
00561 #endif
00562     {
00563         if (PHY_GetActiveEnvironment())
00564         {
00565             PHY_GetActiveEnvironment()->removeConstraint(constraintid);
00566         }
00567     }
00568     else {
00569         return NULL;
00570     }
00571     
00572     Py_RETURN_NONE;
00573 }
00574 
00575 static PyObject* gPyExportBulletFile(PyObject*, PyObject* args)
00576 {
00577     char* filename;
00578     if (!PyArg_ParseTuple(args,"s:exportBulletFile",&filename))
00579         return NULL;
00580 
00581     if (PHY_GetActiveEnvironment())
00582     {
00583         PHY_GetActiveEnvironment()->exportFile(filename);
00584     }
00585     Py_RETURN_NONE;
00586 }
00587 
00588 static struct PyMethodDef physicsconstraints_methods[] = {
00589     {"setGravity",(PyCFunction) gPySetGravity,
00590      METH_VARARGS, (const char*)gPySetGravity__doc__},
00591     {"setDebugMode",(PyCFunction) gPySetDebugMode,
00592      METH_VARARGS, (const char *)gPySetDebugMode__doc__},
00593 
00595     {"setNumIterations",(PyCFunction) gPySetNumIterations,
00596      METH_VARARGS, (const char *)gPySetNumIterations__doc__},
00597 
00598     {"setNumTimeSubSteps",(PyCFunction) gPySetNumTimeSubSteps,
00599      METH_VARARGS, (const char *)gPySetNumTimeSubSteps__doc__},
00600 
00601     {"setDeactivationTime",(PyCFunction) gPySetDeactivationTime,
00602      METH_VARARGS, (const char *)gPySetDeactivationTime__doc__},
00603 
00604     {"setDeactivationLinearTreshold",(PyCFunction) gPySetDeactivationLinearTreshold,
00605      METH_VARARGS, (const char *)gPySetDeactivationLinearTreshold__doc__},
00606     {"setDeactivationAngularTreshold",(PyCFunction) gPySetDeactivationAngularTreshold,
00607      METH_VARARGS, (const char *)gPySetDeactivationAngularTreshold__doc__},
00608 
00609     {"setContactBreakingTreshold",(PyCFunction) gPySetContactBreakingTreshold,
00610      METH_VARARGS, (const char *)gPySetContactBreakingTreshold__doc__},
00611     {"setCcdMode",(PyCFunction) gPySetCcdMode,
00612      METH_VARARGS, (const char *)gPySetCcdMode__doc__},
00613     {"setSorConstant",(PyCFunction) gPySetSorConstant,
00614      METH_VARARGS, (const char *)gPySetSorConstant__doc__},
00615     {"setSolverTau",(PyCFunction) gPySetSolverTau,
00616      METH_VARARGS, (const char *)gPySetSolverTau__doc__},
00617     {"setSolverDamping",(PyCFunction) gPySetSolverDamping,
00618      METH_VARARGS, (const char *)gPySetSolverDamping__doc__},
00619 
00620     {"setLinearAirDamping",(PyCFunction) gPySetLinearAirDamping,
00621      METH_VARARGS, (const char *)gPySetLinearAirDamping__doc__},
00622 
00623     {"setUseEpa",(PyCFunction) gPySetUseEpa,
00624      METH_VARARGS, (const char *)gPySetUseEpa__doc__},
00625     {"setSolverType",(PyCFunction) gPySetSolverType,
00626      METH_VARARGS, (const char *)gPySetSolverType__doc__},
00627 
00628 
00629     {"createConstraint",(PyCFunction) gPyCreateConstraint,
00630      METH_VARARGS, (const char *)gPyCreateConstraint__doc__},
00631     {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint,
00632      METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__},
00633 
00634     {"removeConstraint",(PyCFunction) gPyRemoveConstraint,
00635      METH_VARARGS, (const char *)gPyRemoveConstraint__doc__},
00636     {"getAppliedImpulse",(PyCFunction) gPyGetAppliedImpulse,
00637      METH_VARARGS, (const char *)gPyGetAppliedImpulse__doc__},
00638 
00639     {"exportBulletFile",(PyCFunction)gPyExportBulletFile,
00640      METH_VARARGS, "export a .bullet file"},
00641 
00642     //sentinel
00643     { NULL, (PyCFunction) NULL, 0, NULL }
00644 };
00645 
00646 static struct PyModuleDef PhysicsConstraints_module_def = {
00647     {}, /* m_base */
00648     "PhysicsConstraints",  /* m_name */
00649     PhysicsConstraints_module_documentation,  /* m_doc */
00650     0,  /* m_size */
00651     physicsconstraints_methods,  /* m_methods */
00652     0,  /* m_reload */
00653     0,  /* m_traverse */
00654     0,  /* m_clear */
00655     0,  /* m_free */
00656 };
00657 
00658 PyObject* initPythonConstraintBinding()
00659 {
00660 
00661     PyObject* ErrorObject;
00662     PyObject* m;
00663     PyObject* d;
00664     PyObject* item;
00665 
00666     /* Use existing module where possible
00667      * be careful not to init any runtime vars after this */
00668     m = PyImport_ImportModule( "PhysicsConstraints" );
00669     if(m) {
00670         Py_DECREF(m);
00671         return m;
00672     }
00673     else {
00674         PyErr_Clear();
00675         
00676         m = PyModule_Create(&PhysicsConstraints_module_def);
00677         PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m);
00678     }
00679 
00680     // Add some symbolic constants to the module
00681     d = PyModule_GetDict(m);
00682     ErrorObject = PyUnicode_FromString("PhysicsConstraints.error");
00683     PyDict_SetItemString(d, "error", ErrorObject);
00684     Py_DECREF(ErrorObject);
00685 
00686 #ifdef USE_BULLET
00687     //Debug Modes constants to be used with setDebugMode() python function
00688     KX_MACRO_addTypesToDict(d, DBG_NODEBUG, btIDebugDraw::DBG_NoDebug);
00689     KX_MACRO_addTypesToDict(d, DBG_DRAWWIREFRAME, btIDebugDraw::DBG_DrawWireframe);
00690     KX_MACRO_addTypesToDict(d, DBG_DRAWAABB, btIDebugDraw::DBG_DrawAabb);
00691     KX_MACRO_addTypesToDict(d, DBG_DRAWFREATURESTEXT, btIDebugDraw::DBG_DrawFeaturesText);
00692     KX_MACRO_addTypesToDict(d, DBG_DRAWCONTACTPOINTS, btIDebugDraw::DBG_DrawContactPoints);
00693     KX_MACRO_addTypesToDict(d, DBG_NOHELPTEXT, btIDebugDraw::DBG_NoHelpText);
00694     KX_MACRO_addTypesToDict(d, DBG_DRAWTEXT, btIDebugDraw::DBG_DrawText);
00695     KX_MACRO_addTypesToDict(d, DBG_PROFILETIMINGS, btIDebugDraw::DBG_ProfileTimings);
00696     KX_MACRO_addTypesToDict(d, DBG_ENABLESATCOMPARISION, btIDebugDraw::DBG_EnableSatComparison);
00697     KX_MACRO_addTypesToDict(d, DBG_DISABLEBULLETLCP, btIDebugDraw::DBG_DisableBulletLCP);
00698     KX_MACRO_addTypesToDict(d, DBG_ENABLECDD, btIDebugDraw::DBG_EnableCCD);
00699     KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints);
00700     KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits);
00701     KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe);
00702 #endif // USE_BULLET
00703 
00704     //Constraint types to be used with createConstraint() python function
00705     KX_MACRO_addTypesToDict(d, POINTTOPOINT_CONSTRAINT, PHY_POINT2POINT_CONSTRAINT);
00706     KX_MACRO_addTypesToDict(d, LINEHINGE_CONSTRAINT, PHY_LINEHINGE_CONSTRAINT);
00707     KX_MACRO_addTypesToDict(d, ANGULAR_CONSTRAINT, PHY_ANGULAR_CONSTRAINT);
00708     KX_MACRO_addTypesToDict(d, CONETWIST_CONSTRAINT, PHY_CONE_TWIST_CONSTRAINT);
00709     KX_MACRO_addTypesToDict(d, VEHICLE_CONSTRAINT, PHY_VEHICLE_CONSTRAINT);
00710 
00711     // Check for errors
00712     if (PyErr_Occurred()) {
00713         Py_FatalError("can't initialize module PhysicsConstraints");
00714     }
00715 
00716     return d;
00717 }
00718 
00719 
00720 void    KX_RemovePythonConstraintBinding()
00721 {
00722 }
00723 
00724 void    PHY_SetActiveEnvironment(class  PHY_IPhysicsEnvironment* env)
00725 {
00726     g_CurrentActivePhysicsEnvironment = env;
00727 }
00728 
00729 PHY_IPhysicsEnvironment*    PHY_GetActiveEnvironment()
00730 {
00731     return g_CurrentActivePhysicsEnvironment;
00732 }
00733 
00734 #endif // WITH_PYTHON