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