fix for building without bullet
[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
173 static PyObject* gPySetDeactivationTime(PyObject* self,
174                                                                                  PyObject* args, 
175                                                                                  PyObject* kwds)
176 {
177         float deactive_time;
178         if (PyArg_ParseTuple(args,"f",&deactive_time))
179         {
180                 if (PHY_GetActiveEnvironment())
181                 {
182                         PHY_GetActiveEnvironment()->setDeactivationTime(deactive_time);
183                 }
184         }
185         else {
186                 return NULL;
187         }
188         Py_RETURN_NONE;
189 }
190
191
192 static PyObject* gPySetDeactivationLinearTreshold(PyObject* self,
193                                                                                  PyObject* args, 
194                                                                                  PyObject* kwds)
195 {
196         float linearDeactivationTreshold;
197         if (PyArg_ParseTuple(args,"f",&linearDeactivationTreshold))
198         {
199                 if (PHY_GetActiveEnvironment())
200                 {
201                         PHY_GetActiveEnvironment()->setDeactivationLinearTreshold( linearDeactivationTreshold);
202                 }
203         }
204         else {
205                 return NULL;
206         }
207         Py_RETURN_NONE;
208 }
209
210
211 static PyObject* gPySetDeactivationAngularTreshold(PyObject* self,
212                                                                                  PyObject* args, 
213                                                                                  PyObject* kwds)
214 {
215         float angularDeactivationTreshold;
216         if (PyArg_ParseTuple(args,"f",&angularDeactivationTreshold))
217         {
218                 if (PHY_GetActiveEnvironment())
219                 {
220                         PHY_GetActiveEnvironment()->setDeactivationAngularTreshold( angularDeactivationTreshold);
221                 }
222         }
223         else {
224                 return NULL;
225         }
226         Py_RETURN_NONE;
227 }
228
229 static PyObject* gPySetContactBreakingTreshold(PyObject* self,
230                                                                                  PyObject* args, 
231                                                                                  PyObject* kwds)
232 {
233         float contactBreakingTreshold;
234         if (PyArg_ParseTuple(args,"f",&contactBreakingTreshold))
235         {
236                 if (PHY_GetActiveEnvironment())
237                 {
238                         PHY_GetActiveEnvironment()->setContactBreakingTreshold( contactBreakingTreshold);
239                 }
240         }
241         else {
242                 return NULL;
243         }
244         Py_RETURN_NONE;
245 }
246
247
248 static PyObject* gPySetCcdMode(PyObject* self,
249                                                                                  PyObject* args, 
250                                                                                  PyObject* kwds)
251 {
252         float ccdMode;
253         if (PyArg_ParseTuple(args,"f",&ccdMode))
254         {
255                 if (PHY_GetActiveEnvironment())
256                 {
257                         PHY_GetActiveEnvironment()->setCcdMode( ccdMode);
258                 }
259         }
260         else {
261                 return NULL;
262         }
263         Py_RETURN_NONE;
264 }
265
266 static PyObject* gPySetSorConstant(PyObject* self,
267                                                                                  PyObject* args, 
268                                                                                  PyObject* kwds)
269 {
270         float sor;
271         if (PyArg_ParseTuple(args,"f",&sor))
272         {
273                 if (PHY_GetActiveEnvironment())
274                 {
275                         PHY_GetActiveEnvironment()->setSolverSorConstant( sor);
276                 }
277         }
278         else {
279                 return NULL;
280         }
281         Py_RETURN_NONE;
282 }
283
284 static PyObject* gPySetSolverTau(PyObject* self,
285                                                                                  PyObject* args, 
286                                                                                  PyObject* kwds)
287 {
288         float tau;
289         if (PyArg_ParseTuple(args,"f",&tau))
290         {
291                 if (PHY_GetActiveEnvironment())
292                 {
293                         PHY_GetActiveEnvironment()->setSolverTau( tau);
294                 }
295         }
296         else {
297                 return NULL;
298         }
299         Py_RETURN_NONE;
300 }
301
302
303 static PyObject* gPySetSolverDamping(PyObject* self,
304                                                                                  PyObject* args, 
305                                                                                  PyObject* kwds)
306 {
307         float damping;
308         if (PyArg_ParseTuple(args,"f",&damping))
309         {
310                 if (PHY_GetActiveEnvironment())
311                 {
312                         PHY_GetActiveEnvironment()->setSolverDamping( damping);
313                 }
314         }
315         else {
316                 return NULL;
317         }
318         Py_RETURN_NONE;
319 }
320
321 static PyObject* gPySetLinearAirDamping(PyObject* self,
322                                                                                  PyObject* args, 
323                                                                                  PyObject* kwds)
324 {
325         float damping;
326         if (PyArg_ParseTuple(args,"f",&damping))
327         {
328                 if (PHY_GetActiveEnvironment())
329                 {
330                         PHY_GetActiveEnvironment()->setLinearAirDamping( damping);
331                 }
332         }
333         else {
334                 return NULL;
335         }
336         Py_RETURN_NONE;
337 }
338
339
340 static PyObject* gPySetUseEpa(PyObject* self,
341                                                                                  PyObject* args, 
342                                                                                  PyObject* kwds)
343 {
344         int     epa;
345         if (PyArg_ParseTuple(args,"i",&epa))
346         {
347                 if (PHY_GetActiveEnvironment())
348                 {
349                         PHY_GetActiveEnvironment()->setUseEpa(epa);
350                 }
351         }
352         else {
353                 return NULL;
354         }
355         Py_RETURN_NONE;
356 }
357 static PyObject* gPySetSolverType(PyObject* self,
358                                                                                  PyObject* args, 
359                                                                                  PyObject* kwds)
360 {
361         int     solverType;
362         if (PyArg_ParseTuple(args,"i",&solverType))
363         {
364                 if (PHY_GetActiveEnvironment())
365                 {
366                         PHY_GetActiveEnvironment()->setSolverType(solverType);
367                 }
368         }
369         else {
370                 return NULL;
371         }
372         Py_RETURN_NONE;
373 }
374
375
376
377 static PyObject* gPyGetVehicleConstraint(PyObject* self,
378                                                                                  PyObject* args, 
379                                                                                  PyObject* kwds)
380 {
381 #if defined(_WIN64)
382         __int64 constraintid;
383         if (PyArg_ParseTuple(args,"L",&constraintid))
384 #else
385         long constraintid;
386         if (PyArg_ParseTuple(args,"l",&constraintid))
387 #endif
388         {
389                 if (PHY_GetActiveEnvironment())
390                 {
391                         
392                         PHY_IVehicle* vehicle = PHY_GetActiveEnvironment()->getVehicleConstraint(constraintid);
393                         if (vehicle)
394                         {
395                                 KX_VehicleWrapper* pyWrapper = new KX_VehicleWrapper(vehicle,PHY_GetActiveEnvironment());
396                                 return pyWrapper->NewProxy(true);
397                         }
398
399                 }
400         }
401         else {
402                 return NULL;
403         }
404
405         Py_RETURN_NONE;
406 }
407
408
409
410
411
412 static PyObject* gPyCreateConstraint(PyObject* self,
413                                                                                  PyObject* args, 
414                                                                                  PyObject* kwds)
415 {
416         /* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */
417 #if defined(_WIN64)
418         __int64 physicsid=0,physicsid2 = 0;
419 #else
420         long physicsid=0,physicsid2 = 0;
421 #endif
422         int constrainttype=0, extrainfo=0;
423         int len = PyTuple_Size(args);
424         int success = 1;
425         int flag = 0;
426
427         float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1;
428         if (len == 3)
429         {
430 #if defined(_WIN64)
431                 success = PyArg_ParseTuple(args,"LLi",&physicsid,&physicsid2,&constrainttype);
432 #else
433                 success = PyArg_ParseTuple(args,"lli",&physicsid,&physicsid2,&constrainttype);
434 #endif
435         }
436         else
437         if (len ==6)
438         {
439 #if defined(_WIN64)
440                 success = PyArg_ParseTuple(args,"LLifff",&physicsid,&physicsid2,&constrainttype,
441                         &pivotX,&pivotY,&pivotZ);
442 #else
443                 success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype,
444                                                                    &pivotX,&pivotY,&pivotZ);            
445 #endif  
446         }
447         else if (len == 9)
448         {
449 #if defined(_WIN64)
450                 success = PyArg_ParseTuple(args,"LLiffffff",&physicsid,&physicsid2,&constrainttype,
451                         &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
452 #else
453                 success = PyArg_ParseTuple(args,"lliffffff",&physicsid,&physicsid2,&constrainttype,
454                                                                    &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
455 #endif
456         
457         }
458         else if (len == 10)
459         {
460 #if defined(_WIN64)
461                 success = PyArg_ParseTuple(args,"LLiffffffi",&physicsid,&physicsid2,&constrainttype,
462                         &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
463 #else
464                 success = PyArg_ParseTuple(args,"lliffffffi",&physicsid,&physicsid2,&constrainttype,
465                                                                    &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
466 #endif
467         }
468         else if (len==4)
469         {
470 #if defined(_WIN64)
471                 success = PyArg_ParseTuple(args,"LLii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
472 #else
473                 success = PyArg_ParseTuple(args,"llii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
474 #endif
475                 pivotX=extrainfo;
476         }
477         
478         if (success)
479         {
480                 if (PHY_GetActiveEnvironment())
481                 {
482                         
483                         PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid;
484                         PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2;
485                         if (physctrl) //TODO:check for existence of this pointer!
486                         {
487                                 PHY_ConstraintType ct = (PHY_ConstraintType) constrainttype;
488                                 int constraintid =0;
489
490                                 if (ct == PHY_GENERIC_6DOF_CONSTRAINT)
491                                 {
492                                         //convert from euler angle into axis
493                                         float radsPerDeg = 6.283185307179586232f / 360.f;
494
495                                         //we need to pass a full constraint frame, not just axis
496                                         //localConstraintFrameBasis
497                                         MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*axisX,radsPerDeg*axisY,radsPerDeg*axisZ));
498                                         MT_Vector3 axis0 = localCFrame.getColumn(0);
499                                         MT_Vector3 axis1 = localCFrame.getColumn(1);
500                                         MT_Vector3 axis2 = localCFrame.getColumn(2);
501                                                 
502                                         constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,
503                                                 pivotX,pivotY,pivotZ,
504                                                 (float)axis0.x(),(float)axis0.y(),(float)axis0.z(),
505                                                 (float)axis1.x(),(float)axis1.y(),(float)axis1.z(),
506                                                 (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag);
507
508                                 } else
509                                 {
510                                         constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ,0);
511                                 }
512                                 
513                                 KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment());
514                                 
515
516                                 return wrap->NewProxy(true);
517                         }
518                         
519                         
520                 }
521         }
522         else {
523                 return NULL;
524         }
525
526         Py_RETURN_NONE;
527 }
528
529
530
531
532 static PyObject* gPyGetAppliedImpulse(PyObject* self,
533                                                                                  PyObject* args, 
534                                                                                  PyObject* kwds)
535 {
536         float   appliedImpulse = 0.f;
537
538 #if defined(_WIN64)
539         __int64 constraintid;
540         if (PyArg_ParseTuple(args,"L",&constraintid))
541 #else
542         long constraintid;
543         if (PyArg_ParseTuple(args,"l",&constraintid))
544 #endif
545         {
546                 if (PHY_GetActiveEnvironment())
547                 {
548                         appliedImpulse = PHY_GetActiveEnvironment()->getAppliedImpulse(constraintid);
549                 }
550         }
551         else {
552                 return NULL;
553         }
554
555         return PyFloat_FromDouble(appliedImpulse);
556 }
557
558
559 static PyObject* gPyRemoveConstraint(PyObject* self,
560                                                                                  PyObject* args, 
561                                                                                  PyObject* kwds)
562 {
563 #if defined(_WIN64)
564         __int64 constraintid;
565         if (PyArg_ParseTuple(args,"L",&constraintid))
566 #else
567         long constraintid;
568         if (PyArg_ParseTuple(args,"l",&constraintid))
569 #endif
570         {
571                 if (PHY_GetActiveEnvironment())
572                 {
573                         PHY_GetActiveEnvironment()->removeConstraint(constraintid);
574                 }
575         }
576         else {
577                 return NULL;
578         }
579         
580         Py_RETURN_NONE;
581 }
582
583 static PyObject* gPyExportBulletFile(PyObject*, PyObject* args)
584 {
585         char* filename;
586         if (!PyArg_ParseTuple(args,"s:exportBulletFile",&filename))
587                 return NULL;
588                 
589         if (PHY_GetActiveEnvironment())
590         {
591                 PHY_GetActiveEnvironment()->exportFile(filename);
592         }
593         Py_RETURN_NONE;
594 }
595
596 static struct PyMethodDef physicsconstraints_methods[] = {
597   {"setGravity",(PyCFunction) gPySetGravity,
598    METH_VARARGS, (const char *)gPySetGravity__doc__},
599   {"setDebugMode",(PyCFunction) gPySetDebugMode,
600    METH_VARARGS, (const char *)gPySetDebugMode__doc__},
601
602    /// settings that influence quality of the rigidbody dynamics
603   {"setNumIterations",(PyCFunction) gPySetNumIterations,
604    METH_VARARGS, (const char *)gPySetNumIterations__doc__},
605
606    {"setNumTimeSubSteps",(PyCFunction) gPySetNumTimeSubSteps,
607    METH_VARARGS, (const char *)gPySetNumTimeSubSteps__doc__},
608
609   {"setDeactivationTime",(PyCFunction) gPySetDeactivationTime,
610    METH_VARARGS, (const char *)gPySetDeactivationTime__doc__},
611
612   {"setDeactivationLinearTreshold",(PyCFunction) gPySetDeactivationLinearTreshold,
613    METH_VARARGS, (const char *)gPySetDeactivationLinearTreshold__doc__},
614   {"setDeactivationAngularTreshold",(PyCFunction) gPySetDeactivationAngularTreshold,
615    METH_VARARGS, (const char *)gPySetDeactivationAngularTreshold__doc__},
616
617    {"setContactBreakingTreshold",(PyCFunction) gPySetContactBreakingTreshold,
618    METH_VARARGS, (const char *)gPySetContactBreakingTreshold__doc__},
619      {"setCcdMode",(PyCFunction) gPySetCcdMode,
620    METH_VARARGS, (const char *)gPySetCcdMode__doc__},
621      {"setSorConstant",(PyCFunction) gPySetSorConstant,
622    METH_VARARGS, (const char *)gPySetSorConstant__doc__},
623        {"setSolverTau",(PyCFunction) gPySetSolverTau,
624    METH_VARARGS, (const char *)gPySetSolverTau__doc__},
625         {"setSolverDamping",(PyCFunction) gPySetSolverDamping,
626    METH_VARARGS, (const char *)gPySetSolverDamping__doc__},
627
628          {"setLinearAirDamping",(PyCFunction) gPySetLinearAirDamping,
629    METH_VARARGS, (const char *)gPySetLinearAirDamping__doc__},
630
631     {"setUseEpa",(PyCFunction) gPySetUseEpa,
632    METH_VARARGS, (const char *)gPySetUseEpa__doc__},
633         {"setSolverType",(PyCFunction) gPySetSolverType,
634    METH_VARARGS, (const char *)gPySetSolverType__doc__},
635
636
637   {"createConstraint",(PyCFunction) gPyCreateConstraint,
638    METH_VARARGS, (const char *)gPyCreateConstraint__doc__},
639      {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint,
640    METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__},
641
642   {"removeConstraint",(PyCFunction) gPyRemoveConstraint,
643    METH_VARARGS, (const char *)gPyRemoveConstraint__doc__},
644         {"getAppliedImpulse",(PyCFunction) gPyGetAppliedImpulse,
645    METH_VARARGS, (const char *)gPyGetAppliedImpulse__doc__},
646
647      {"exportBulletFile",(PyCFunction)gPyExportBulletFile,
648         METH_VARARGS, "export a .bullet file"},
649
650
651    //sentinel
652   { NULL, (PyCFunction) NULL, 0, NULL }
653 };
654
655 static struct PyModuleDef PhysicsConstraints_module_def = {
656         {}, /* m_base */
657         "PhysicsConstraints",  /* m_name */
658         PhysicsConstraints_module_documentation,  /* m_doc */
659         0,  /* m_size */
660         physicsconstraints_methods,  /* m_methods */
661         0,  /* m_reload */
662         0,  /* m_traverse */
663         0,  /* m_clear */
664         0,  /* m_free */
665 };
666
667 PyObject*       initPythonConstraintBinding()
668 {
669
670   PyObject* ErrorObject;
671   PyObject* m;
672   PyObject* d;
673   PyObject* item;
674
675         /* Use existing module where possible
676          * be careful not to init any runtime vars after this */
677         m = PyImport_ImportModule( "PhysicsConstraints" );
678         if(m) {
679                 Py_DECREF(m);
680                 return m;
681         }
682         else {
683                 PyErr_Clear();
684                 
685                 m = PyModule_Create(&PhysicsConstraints_module_def);
686                 PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m);
687         }
688
689   // Add some symbolic constants to the module
690   d = PyModule_GetDict(m);
691   ErrorObject = PyUnicode_FromString("PhysicsConstraints.error");
692   PyDict_SetItemString(d, "error", ErrorObject);
693   Py_DECREF(ErrorObject);
694
695 #ifdef USE_BULLET
696   //Debug Modes constants to be used with setDebugMode() python function
697   KX_MACRO_addTypesToDict(d, DBG_NODEBUG, btIDebugDraw::DBG_NoDebug);
698   KX_MACRO_addTypesToDict(d, DBG_DRAWWIREFRAME, btIDebugDraw::DBG_DrawWireframe);
699   KX_MACRO_addTypesToDict(d, DBG_DRAWAABB, btIDebugDraw::DBG_DrawAabb);
700   KX_MACRO_addTypesToDict(d, DBG_DRAWFREATURESTEXT, btIDebugDraw::DBG_DrawFeaturesText);
701   KX_MACRO_addTypesToDict(d, DBG_DRAWCONTACTPOINTS, btIDebugDraw::DBG_DrawContactPoints);
702   KX_MACRO_addTypesToDict(d, DBG_NOHELPTEXT, btIDebugDraw::DBG_NoHelpText);
703   KX_MACRO_addTypesToDict(d, DBG_DRAWTEXT, btIDebugDraw::DBG_DrawText);
704   KX_MACRO_addTypesToDict(d, DBG_PROFILETIMINGS, btIDebugDraw::DBG_ProfileTimings);
705   KX_MACRO_addTypesToDict(d, DBG_ENABLESATCOMPARISION, btIDebugDraw::DBG_EnableSatComparison);
706   KX_MACRO_addTypesToDict(d, DBG_DISABLEBULLETLCP, btIDebugDraw::DBG_DisableBulletLCP);
707   KX_MACRO_addTypesToDict(d, DBG_ENABLECDD, btIDebugDraw::DBG_EnableCCD);
708   KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints);
709   KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits);
710   KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe);
711 #endif // USE_BULLET
712
713   //Constraint types to be used with createConstraint() python function
714   KX_MACRO_addTypesToDict(d, POINTTOPOINT_CONSTRAINT, PHY_POINT2POINT_CONSTRAINT);
715   KX_MACRO_addTypesToDict(d, LINEHINGE_CONSTRAINT, PHY_LINEHINGE_CONSTRAINT);
716   KX_MACRO_addTypesToDict(d, ANGULAR_CONSTRAINT, PHY_ANGULAR_CONSTRAINT);
717   KX_MACRO_addTypesToDict(d, CONETWIST_CONSTRAINT, PHY_CONE_TWIST_CONSTRAINT);
718   KX_MACRO_addTypesToDict(d, VEHICLE_CONSTRAINT, PHY_VEHICLE_CONSTRAINT);
719
720   // Check for errors
721   if (PyErr_Occurred())
722     {
723       Py_FatalError("can't initialize module PhysicsConstraints");
724     }
725
726   return d;
727 }
728
729
730 void    KX_RemovePythonConstraintBinding()
731 {
732 }
733
734 void    PHY_SetActiveEnvironment(class  PHY_IPhysicsEnvironment* env)
735 {
736         g_CurrentActivePhysicsEnvironment = env;
737 }
738
739 PHY_IPhysicsEnvironment*        PHY_GetActiveEnvironment()
740 {
741         return g_CurrentActivePhysicsEnvironment;
742 }
743
744
745
746 #endif // WITH_PYTHON
747