whitespace edits, had odd space/tab mix
[blender.git] / source / gameengine / Ketsji / KX_PyConstraintBinding.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file gameengine/Ketsji/KX_PyConstraintBinding.cpp
31  *  \ingroup ketsji
32  */
33
34 #include "KX_PyConstraintBinding.h"
35 #include "PHY_IPhysicsEnvironment.h"
36 #include "KX_ConstraintWrapper.h"
37 #include "KX_VehicleWrapper.h"
38 #include "KX_PhysicsObjectWrapper.h"
39 #include "PHY_IPhysicsController.h"
40 #include "PHY_IVehicle.h"
41 #include "PHY_DynamicTypes.h"
42 #include "MT_Matrix3x3.h"
43
44 #include "PyObjectPlus.h" 
45
46 #ifdef USE_BULLET
47 #  include "LinearMath/btIDebugDraw.h"
48 #endif
49
50 #ifdef WITH_PYTHON
51
52 // macro copied from KX_PythonInit.cpp
53 #define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name2)); Py_DECREF(item)
54
55 // nasty glob variable to connect scripting language
56 // if there is a better way (without global), please do so!
57 static PHY_IPhysicsEnvironment* g_CurrentActivePhysicsEnvironment = NULL;
58
59 static char PhysicsConstraints_module_documentation[] =
60 "This is the Python API for the Physics Constraints";
61
62
63 static char gPySetGravity__doc__[] = "setGravity(float x,float y,float z)";
64 static char gPySetDebugMode__doc__[] = "setDebugMode(int mode)";
65
66 static char gPySetNumIterations__doc__[] = "setNumIterations(int numiter) This sets the number of iterations for an iterative constraint solver";
67 static char gPySetNumTimeSubSteps__doc__[] = "setNumTimeSubSteps(int numsubstep) This sets the number of substeps for each physics proceed. Tradeoff quality for performance.";
68
69
70 static char gPySetDeactivationTime__doc__[] = "setDeactivationTime(float time) This sets the time after which a resting rigidbody gets deactived";
71 static char gPySetDeactivationLinearTreshold__doc__[] = "setDeactivationLinearTreshold(float linearTreshold)";
72 static char gPySetDeactivationAngularTreshold__doc__[] = "setDeactivationAngularTreshold(float angularTreshold)";
73 static char gPySetContactBreakingTreshold__doc__[] = "setContactBreakingTreshold(float breakingTreshold) Reasonable default is 0.02 (if units are meters)";
74
75 static char gPySetCcdMode__doc__[] = "setCcdMode(int ccdMode) Very experimental, not recommended";
76 static char gPySetSorConstant__doc__[] = "setSorConstant(float sor) Very experimental, not recommended";
77 static char gPySetSolverTau__doc__[] = "setTau(float tau) Very experimental, not recommended";
78 static char gPySetSolverDamping__doc__[] = "setDamping(float damping) Very experimental, not recommended";
79 static char gPySetLinearAirDamping__doc__[] = "setLinearAirDamping(float damping) Very experimental, not recommended";
80 static char gPySetUseEpa__doc__[] = "setUseEpa(int epa) Very experimental, not recommended";
81 static char gPySetSolverType__doc__[] = "setSolverType(int solverType) Very experimental, not recommended";
82
83
84 static char gPyCreateConstraint__doc__[] = "createConstraint(ob1,ob2,float restLength,float restitution,float damping)";
85 static char gPyGetVehicleConstraint__doc__[] = "getVehicleConstraint(int constraintId)";
86 static char gPyRemoveConstraint__doc__[] = "removeConstraint(int constraintId)";
87 static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId)";
88
89
90
91
92
93
94 static PyObject* gPySetGravity(PyObject* self,
95                                PyObject* args,
96                                PyObject* kwds)
97 {
98         float x,y,z;
99         if (PyArg_ParseTuple(args,"fff",&x,&y,&z))
100         {
101                 if (PHY_GetActiveEnvironment())
102                         PHY_GetActiveEnvironment()->setGravity(x,y,z);
103         }
104         else {
105                 return NULL;
106         }
107         
108         Py_RETURN_NONE;
109 }
110
111 static PyObject* gPySetDebugMode(PyObject* self,
112                                  PyObject* args,
113                                  PyObject* kwds)
114 {
115         int mode;
116         if (PyArg_ParseTuple(args,"i",&mode))
117         {
118                 if (PHY_GetActiveEnvironment())
119                 {
120                         PHY_GetActiveEnvironment()->setDebugMode(mode);
121                         
122                 }
123                 
124         }
125         else {
126                 return NULL;
127         }
128         
129         Py_RETURN_NONE;
130 }
131
132
133
134 static PyObject* gPySetNumTimeSubSteps(PyObject* self,
135                                        PyObject* args,
136                                        PyObject* kwds)
137 {
138         int substep;
139         if (PyArg_ParseTuple(args,"i",&substep))
140         {
141                 if (PHY_GetActiveEnvironment())
142                 {
143                         PHY_GetActiveEnvironment()->setNumTimeSubSteps(substep);
144                 }
145         }
146         else {
147                 return NULL;
148         }
149         Py_RETURN_NONE;
150 }
151
152
153 static PyObject* gPySetNumIterations(PyObject* self,
154                                      PyObject* args,
155                                      PyObject* kwds)
156 {
157         int iter;
158         if (PyArg_ParseTuple(args,"i",&iter))
159         {
160                 if (PHY_GetActiveEnvironment())
161                 {
162                         PHY_GetActiveEnvironment()->setNumIterations(iter);
163                 }
164         }
165         else {
166                 return NULL;
167         }
168         Py_RETURN_NONE;
169 }
170
171
172 static PyObject* gPySetDeactivationTime(PyObject* self,
173                                         PyObject* args,
174                                         PyObject* kwds)
175 {
176         float deactive_time;
177         if (PyArg_ParseTuple(args,"f",&deactive_time))
178         {
179                 if (PHY_GetActiveEnvironment())
180                 {
181                         PHY_GetActiveEnvironment()->setDeactivationTime(deactive_time);
182                 }
183         }
184         else {
185                 return NULL;
186         }
187         Py_RETURN_NONE;
188 }
189
190
191 static PyObject* gPySetDeactivationLinearTreshold(PyObject* self,
192                                                   PyObject* args,
193                                                   PyObject* kwds)
194 {
195         float linearDeactivationTreshold;
196         if (PyArg_ParseTuple(args,"f",&linearDeactivationTreshold))
197         {
198                 if (PHY_GetActiveEnvironment())
199                 {
200                         PHY_GetActiveEnvironment()->setDeactivationLinearTreshold( linearDeactivationTreshold);
201                 }
202         }
203         else {
204                 return NULL;
205         }
206         Py_RETURN_NONE;
207 }
208
209
210 static PyObject* gPySetDeactivationAngularTreshold(PyObject* self,
211                                                    PyObject* args,
212                                                    PyObject* kwds)
213 {
214         float angularDeactivationTreshold;
215         if (PyArg_ParseTuple(args,"f",&angularDeactivationTreshold))
216         {
217                 if (PHY_GetActiveEnvironment())
218                 {
219                         PHY_GetActiveEnvironment()->setDeactivationAngularTreshold( angularDeactivationTreshold);
220                 }
221         }
222         else {
223                 return NULL;
224         }
225         Py_RETURN_NONE;
226 }
227
228 static PyObject* gPySetContactBreakingTreshold(PyObject* self,
229                                                PyObject* args,
230                                                PyObject* kwds)
231 {
232         float contactBreakingTreshold;
233         if (PyArg_ParseTuple(args,"f",&contactBreakingTreshold))
234         {
235                 if (PHY_GetActiveEnvironment())
236                 {
237                         PHY_GetActiveEnvironment()->setContactBreakingTreshold( contactBreakingTreshold);
238                 }
239         }
240         else {
241                 return NULL;
242         }
243         Py_RETURN_NONE;
244 }
245
246
247 static PyObject* gPySetCcdMode(PyObject* self,
248                                PyObject* args,
249                                PyObject* kwds)
250 {
251         float ccdMode;
252         if (PyArg_ParseTuple(args,"f",&ccdMode))
253         {
254                 if (PHY_GetActiveEnvironment())
255                 {
256                         PHY_GetActiveEnvironment()->setCcdMode( ccdMode);
257                 }
258         }
259         else {
260                 return NULL;
261         }
262         Py_RETURN_NONE;
263 }
264
265 static PyObject* gPySetSorConstant(PyObject* self,
266                                    PyObject* args,
267                                    PyObject* kwds)
268 {
269         float sor;
270         if (PyArg_ParseTuple(args,"f",&sor))
271         {
272                 if (PHY_GetActiveEnvironment())
273                 {
274                         PHY_GetActiveEnvironment()->setSolverSorConstant( sor);
275                 }
276         }
277         else {
278                 return NULL;
279         }
280         Py_RETURN_NONE;
281 }
282
283 static PyObject* gPySetSolverTau(PyObject* self,
284                                  PyObject* args,
285                                  PyObject* kwds)
286 {
287         float tau;
288         if (PyArg_ParseTuple(args,"f",&tau))
289         {
290                 if (PHY_GetActiveEnvironment())
291                 {
292                         PHY_GetActiveEnvironment()->setSolverTau( tau);
293                 }
294         }
295         else {
296                 return NULL;
297         }
298         Py_RETURN_NONE;
299 }
300
301
302 static PyObject* gPySetSolverDamping(PyObject* self,
303                                      PyObject* args,
304                                      PyObject* kwds)
305 {
306         float damping;
307         if (PyArg_ParseTuple(args,"f",&damping))
308         {
309                 if (PHY_GetActiveEnvironment())
310                 {
311                         PHY_GetActiveEnvironment()->setSolverDamping( damping);
312                 }
313         }
314         else {
315                 return NULL;
316         }
317         Py_RETURN_NONE;
318 }
319
320 static PyObject* gPySetLinearAirDamping(PyObject* self,
321                                         PyObject* args,
322                                         PyObject* kwds)
323 {
324         float damping;
325         if (PyArg_ParseTuple(args,"f",&damping))
326         {
327                 if (PHY_GetActiveEnvironment())
328                 {
329                         PHY_GetActiveEnvironment()->setLinearAirDamping( damping);
330                 }
331         }
332         else {
333                 return NULL;
334         }
335         Py_RETURN_NONE;
336 }
337
338
339 static PyObject* gPySetUseEpa(PyObject* self,
340                               PyObject* args,
341                               PyObject* kwds)
342 {
343         int     epa;
344         if (PyArg_ParseTuple(args,"i",&epa))
345         {
346                 if (PHY_GetActiveEnvironment())
347                 {
348                         PHY_GetActiveEnvironment()->setUseEpa(epa);
349                 }
350         }
351         else {
352                 return NULL;
353         }
354         Py_RETURN_NONE;
355 }
356 static PyObject* gPySetSolverType(PyObject* self,
357                                   PyObject* args,
358                                   PyObject* kwds)
359 {
360         int     solverType;
361         if (PyArg_ParseTuple(args,"i",&solverType))
362         {
363                 if (PHY_GetActiveEnvironment())
364                 {
365                         PHY_GetActiveEnvironment()->setSolverType(solverType);
366                 }
367         }
368         else {
369                 return NULL;
370         }
371         Py_RETURN_NONE;
372 }
373
374
375
376 static PyObject* gPyGetVehicleConstraint(PyObject* self,
377                                          PyObject* args,
378                                          PyObject* kwds)
379 {
380 #if defined(_WIN64)
381         __int64 constraintid;
382         if (PyArg_ParseTuple(args,"L",&constraintid))
383 #else
384         long constraintid;
385         if (PyArg_ParseTuple(args,"l",&constraintid))
386 #endif
387         {
388                 if (PHY_GetActiveEnvironment())
389                 {
390                         
391                         PHY_IVehicle* vehicle = PHY_GetActiveEnvironment()->getVehicleConstraint(constraintid);
392                         if (vehicle)
393                         {
394                                 KX_VehicleWrapper* pyWrapper = new KX_VehicleWrapper(vehicle,PHY_GetActiveEnvironment());
395                                 return pyWrapper->NewProxy(true);
396                         }
397
398                 }
399         }
400         else {
401                 return NULL;
402         }
403
404         Py_RETURN_NONE;
405 }
406
407
408 static PyObject* gPyCreateConstraint(PyObject* self,
409                                                                                  PyObject* args, 
410                                                                                  PyObject* kwds)
411 {
412         /* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */
413 #if defined(_WIN64)
414         __int64 physicsid=0,physicsid2 = 0;
415 #else
416         long physicsid=0,physicsid2 = 0;
417 #endif
418         int constrainttype=0, extrainfo=0;
419         int len = PyTuple_Size(args);
420         int success = 1;
421         int flag = 0;
422
423         float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1;
424         if (len == 3)
425         {
426 #if defined(_WIN64)
427                 success = PyArg_ParseTuple(args,"LLi",&physicsid,&physicsid2,&constrainttype);
428 #else
429                 success = PyArg_ParseTuple(args,"lli",&physicsid,&physicsid2,&constrainttype);
430 #endif
431         }
432         else {
433                 if (len ==6) {
434 #if defined(_WIN64)
435                         success = PyArg_ParseTuple(args,"LLifff",&physicsid,&physicsid2,&constrainttype,
436                                                    &pivotX,&pivotY,&pivotZ);
437 #else
438                         success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype,
439                                                    &pivotX,&pivotY,&pivotZ);
440 #endif  
441                 }
442                 else if (len == 9)
443                 {
444 #if defined(_WIN64)
445                         success = PyArg_ParseTuple(args,"LLiffffff",&physicsid,&physicsid2,&constrainttype,
446                                                    &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
447 #else
448                         success = PyArg_ParseTuple(args,"lliffffff",&physicsid,&physicsid2,&constrainttype,
449                                                    &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
450 #endif
451
452                 }
453                 else if (len == 10)
454                 {
455 #if defined(_WIN64)
456                         success = PyArg_ParseTuple(args,"LLiffffffi",&physicsid,&physicsid2,&constrainttype,
457                                                    &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
458 #else
459                         success = PyArg_ParseTuple(args,"lliffffffi",&physicsid,&physicsid2,&constrainttype,
460                                                    &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
461 #endif
462                 }
463                 else if (len==4)
464                 {
465 #if defined(_WIN64)
466                         success = PyArg_ParseTuple(args,"LLii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
467 #else
468                         success = PyArg_ParseTuple(args,"llii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
469 #endif
470                         pivotX=extrainfo;
471                 }
472         }
473
474         if (success)
475         {
476                 if (PHY_GetActiveEnvironment())
477                 {
478                         
479                         PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid;
480                         PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2;
481                         if (physctrl) //TODO:check for existence of this pointer!
482                         {
483                                 PHY_ConstraintType ct = (PHY_ConstraintType) constrainttype;
484                                 int constraintid =0;
485
486                                 if (ct == PHY_GENERIC_6DOF_CONSTRAINT)
487                                 {
488                                         //convert from euler angle into axis
489                                         float radsPerDeg = 6.283185307179586232f / 360.f;
490
491                                         //we need to pass a full constraint frame, not just axis
492                                         //localConstraintFrameBasis
493                                         MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*axisX,radsPerDeg*axisY,radsPerDeg*axisZ));
494                                         MT_Vector3 axis0 = localCFrame.getColumn(0);
495                                         MT_Vector3 axis1 = localCFrame.getColumn(1);
496                                         MT_Vector3 axis2 = localCFrame.getColumn(2);
497
498                                         constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,
499                                                                                                     pivotX,pivotY,pivotZ,
500                                                                                                     (float)axis0.x(),(float)axis0.y(),(float)axis0.z(),
501                                                                                                     (float)axis1.x(),(float)axis1.y(),(float)axis1.z(),
502                                                                                                     (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag);
503                                 }
504                                 else {
505                                         constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ,0);
506                                 }
507                                 
508                                 KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment());
509
510                                 return wrap->NewProxy(true);
511                         }
512                         
513                         
514                 }
515         }
516         else {
517                 return NULL;
518         }
519
520         Py_RETURN_NONE;
521 }
522
523
524
525
526 static PyObject* gPyGetAppliedImpulse(PyObject* self,
527                                       PyObject* args,
528                                       PyObject* kwds)
529 {
530         float   appliedImpulse = 0.f;
531
532 #if defined(_WIN64)
533         __int64 constraintid;
534         if (PyArg_ParseTuple(args,"L",&constraintid))
535 #else
536         long constraintid;
537         if (PyArg_ParseTuple(args,"l",&constraintid))
538 #endif
539         {
540                 if (PHY_GetActiveEnvironment())
541                 {
542                         appliedImpulse = PHY_GetActiveEnvironment()->getAppliedImpulse(constraintid);
543                 }
544         }
545         else {
546                 return NULL;
547         }
548
549         return PyFloat_FromDouble(appliedImpulse);
550 }
551
552
553 static PyObject* gPyRemoveConstraint(PyObject* self,
554                                      PyObject* args,
555                                      PyObject* kwds)
556 {
557 #if defined(_WIN64)
558         __int64 constraintid;
559         if (PyArg_ParseTuple(args,"L",&constraintid))
560 #else
561         long constraintid;
562         if (PyArg_ParseTuple(args,"l",&constraintid))
563 #endif
564         {
565                 if (PHY_GetActiveEnvironment())
566                 {
567                         PHY_GetActiveEnvironment()->removeConstraint(constraintid);
568                 }
569         }
570         else {
571                 return NULL;
572         }
573         
574         Py_RETURN_NONE;
575 }
576
577 static PyObject* gPyExportBulletFile(PyObject*, PyObject* args)
578 {
579         char* filename;
580         if (!PyArg_ParseTuple(args,"s:exportBulletFile",&filename))
581                 return NULL;
582
583         if (PHY_GetActiveEnvironment())
584         {
585                 PHY_GetActiveEnvironment()->exportFile(filename);
586         }
587         Py_RETURN_NONE;
588 }
589
590 static struct PyMethodDef physicsconstraints_methods[] = {
591         {"setGravity",(PyCFunction) gPySetGravity,
592          METH_VARARGS, (const char*)gPySetGravity__doc__},
593         {"setDebugMode",(PyCFunction) gPySetDebugMode,
594          METH_VARARGS, (const char *)gPySetDebugMode__doc__},
595
596         /// settings that influence quality of the rigidbody dynamics
597         {"setNumIterations",(PyCFunction) gPySetNumIterations,
598          METH_VARARGS, (const char *)gPySetNumIterations__doc__},
599
600         {"setNumTimeSubSteps",(PyCFunction) gPySetNumTimeSubSteps,
601          METH_VARARGS, (const char *)gPySetNumTimeSubSteps__doc__},
602
603         {"setDeactivationTime",(PyCFunction) gPySetDeactivationTime,
604          METH_VARARGS, (const char *)gPySetDeactivationTime__doc__},
605
606         {"setDeactivationLinearTreshold",(PyCFunction) gPySetDeactivationLinearTreshold,
607          METH_VARARGS, (const char *)gPySetDeactivationLinearTreshold__doc__},
608         {"setDeactivationAngularTreshold",(PyCFunction) gPySetDeactivationAngularTreshold,
609          METH_VARARGS, (const char *)gPySetDeactivationAngularTreshold__doc__},
610
611         {"setContactBreakingTreshold",(PyCFunction) gPySetContactBreakingTreshold,
612          METH_VARARGS, (const char *)gPySetContactBreakingTreshold__doc__},
613         {"setCcdMode",(PyCFunction) gPySetCcdMode,
614          METH_VARARGS, (const char *)gPySetCcdMode__doc__},
615         {"setSorConstant",(PyCFunction) gPySetSorConstant,
616          METH_VARARGS, (const char *)gPySetSorConstant__doc__},
617         {"setSolverTau",(PyCFunction) gPySetSolverTau,
618          METH_VARARGS, (const char *)gPySetSolverTau__doc__},
619         {"setSolverDamping",(PyCFunction) gPySetSolverDamping,
620          METH_VARARGS, (const char *)gPySetSolverDamping__doc__},
621
622         {"setLinearAirDamping",(PyCFunction) gPySetLinearAirDamping,
623          METH_VARARGS, (const char *)gPySetLinearAirDamping__doc__},
624
625         {"setUseEpa",(PyCFunction) gPySetUseEpa,
626          METH_VARARGS, (const char *)gPySetUseEpa__doc__},
627         {"setSolverType",(PyCFunction) gPySetSolverType,
628          METH_VARARGS, (const char *)gPySetSolverType__doc__},
629
630
631         {"createConstraint",(PyCFunction) gPyCreateConstraint,
632          METH_VARARGS, (const char *)gPyCreateConstraint__doc__},
633         {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint,
634          METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__},
635
636         {"removeConstraint",(PyCFunction) gPyRemoveConstraint,
637          METH_VARARGS, (const char *)gPyRemoveConstraint__doc__},
638         {"getAppliedImpulse",(PyCFunction) gPyGetAppliedImpulse,
639          METH_VARARGS, (const char *)gPyGetAppliedImpulse__doc__},
640
641         {"exportBulletFile",(PyCFunction)gPyExportBulletFile,
642          METH_VARARGS, "export a .bullet file"},
643
644         //sentinel
645         { NULL, (PyCFunction) NULL, 0, NULL }
646 };
647
648 static struct PyModuleDef PhysicsConstraints_module_def = {
649         {}, /* m_base */
650         "PhysicsConstraints",  /* m_name */
651         PhysicsConstraints_module_documentation,  /* m_doc */
652         0,  /* m_size */
653         physicsconstraints_methods,  /* m_methods */
654         0,  /* m_reload */
655         0,  /* m_traverse */
656         0,  /* m_clear */
657         0,  /* m_free */
658 };
659
660 PyObject* initPythonConstraintBinding()
661 {
662
663         PyObject* ErrorObject;
664         PyObject* m;
665         PyObject* d;
666         PyObject* item;
667
668         /* Use existing module where possible
669          * be careful not to init any runtime vars after this */
670         m = PyImport_ImportModule( "PhysicsConstraints" );
671         if(m) {
672                 Py_DECREF(m);
673                 return m;
674         }
675         else {
676                 PyErr_Clear();
677                 
678                 m = PyModule_Create(&PhysicsConstraints_module_def);
679                 PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m);
680         }
681
682         // Add some symbolic constants to the module
683         d = PyModule_GetDict(m);
684         ErrorObject = PyUnicode_FromString("PhysicsConstraints.error");
685         PyDict_SetItemString(d, "error", ErrorObject);
686         Py_DECREF(ErrorObject);
687
688 #ifdef USE_BULLET
689         //Debug Modes constants to be used with setDebugMode() python function
690         KX_MACRO_addTypesToDict(d, DBG_NODEBUG, btIDebugDraw::DBG_NoDebug);
691         KX_MACRO_addTypesToDict(d, DBG_DRAWWIREFRAME, btIDebugDraw::DBG_DrawWireframe);
692         KX_MACRO_addTypesToDict(d, DBG_DRAWAABB, btIDebugDraw::DBG_DrawAabb);
693         KX_MACRO_addTypesToDict(d, DBG_DRAWFREATURESTEXT, btIDebugDraw::DBG_DrawFeaturesText);
694         KX_MACRO_addTypesToDict(d, DBG_DRAWCONTACTPOINTS, btIDebugDraw::DBG_DrawContactPoints);
695         KX_MACRO_addTypesToDict(d, DBG_NOHELPTEXT, btIDebugDraw::DBG_NoHelpText);
696         KX_MACRO_addTypesToDict(d, DBG_DRAWTEXT, btIDebugDraw::DBG_DrawText);
697         KX_MACRO_addTypesToDict(d, DBG_PROFILETIMINGS, btIDebugDraw::DBG_ProfileTimings);
698         KX_MACRO_addTypesToDict(d, DBG_ENABLESATCOMPARISION, btIDebugDraw::DBG_EnableSatComparison);
699         KX_MACRO_addTypesToDict(d, DBG_DISABLEBULLETLCP, btIDebugDraw::DBG_DisableBulletLCP);
700         KX_MACRO_addTypesToDict(d, DBG_ENABLECDD, btIDebugDraw::DBG_EnableCCD);
701         KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints);
702         KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits);
703         KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe);
704 #endif // USE_BULLET
705
706         //Constraint types to be used with createConstraint() python function
707         KX_MACRO_addTypesToDict(d, POINTTOPOINT_CONSTRAINT, PHY_POINT2POINT_CONSTRAINT);
708         KX_MACRO_addTypesToDict(d, LINEHINGE_CONSTRAINT, PHY_LINEHINGE_CONSTRAINT);
709         KX_MACRO_addTypesToDict(d, ANGULAR_CONSTRAINT, PHY_ANGULAR_CONSTRAINT);
710         KX_MACRO_addTypesToDict(d, CONETWIST_CONSTRAINT, PHY_CONE_TWIST_CONSTRAINT);
711         KX_MACRO_addTypesToDict(d, VEHICLE_CONSTRAINT, PHY_VEHICLE_CONSTRAINT);
712
713         // Check for errors
714         if (PyErr_Occurred()) {
715                 Py_FatalError("can't initialize module PhysicsConstraints");
716         }
717
718         return d;
719 }
720
721
722 void    KX_RemovePythonConstraintBinding()
723 {
724 }
725
726 void    PHY_SetActiveEnvironment(class  PHY_IPhysicsEnvironment* env)
727 {
728         g_CurrentActivePhysicsEnvironment = env;
729 }
730
731 PHY_IPhysicsEnvironment*        PHY_GetActiveEnvironment()
732 {
733         return g_CurrentActivePhysicsEnvironment;
734 }
735
736 #endif // WITH_PYTHON