clear some c++ warnings.
[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 "MT_Matrix3x3.h"
42
43 #include "PyObjectPlus.h" 
44
45 #ifdef WITH_PYTHON
46
47 // nasty glob variable to connect scripting language
48 // if there is a better way (without global), please do so!
49 static PHY_IPhysicsEnvironment* g_CurrentActivePhysicsEnvironment = NULL;
50
51 static char PhysicsConstraints_module_documentation[] =
52 "This is the Python API for the Physics Constraints";
53
54
55 static char gPySetGravity__doc__[] = "setGravity(float x,float y,float z)";
56 static char gPySetDebugMode__doc__[] = "setDebugMode(int mode)";
57
58 static char gPySetNumIterations__doc__[] = "setNumIterations(int numiter) This sets the number of iterations for an iterative constraint solver";
59 static char gPySetNumTimeSubSteps__doc__[] = "setNumTimeSubSteps(int numsubstep) This sets the number of substeps for each physics proceed. Tradeoff quality for performance.";
60
61
62 static char gPySetDeactivationTime__doc__[] = "setDeactivationTime(float time) This sets the time after which a resting rigidbody gets deactived";
63 static char gPySetDeactivationLinearTreshold__doc__[] = "setDeactivationLinearTreshold(float linearTreshold)";
64 static char gPySetDeactivationAngularTreshold__doc__[] = "setDeactivationAngularTreshold(float angularTreshold)";
65 static char gPySetContactBreakingTreshold__doc__[] = "setContactBreakingTreshold(float breakingTreshold) Reasonable default is 0.02 (if units are meters)";
66
67 static char gPySetCcdMode__doc__[] = "setCcdMode(int ccdMode) Very experimental, not recommended";
68 static char gPySetSorConstant__doc__[] = "setSorConstant(float sor) Very experimental, not recommended";
69 static char gPySetSolverTau__doc__[] = "setTau(float tau) Very experimental, not recommended";
70 static char gPySetSolverDamping__doc__[] = "setDamping(float damping) Very experimental, not recommended";
71 static char gPySetLinearAirDamping__doc__[] = "setLinearAirDamping(float damping) Very experimental, not recommended";
72 static char gPySetUseEpa__doc__[] = "setUseEpa(int epa) Very experimental, not recommended";
73 static char gPySetSolverType__doc__[] = "setSolverType(int solverType) Very experimental, not recommended";
74
75
76 static char gPyCreateConstraint__doc__[] = "createConstraint(ob1,ob2,float restLength,float restitution,float damping)";
77 static char gPyGetVehicleConstraint__doc__[] = "getVehicleConstraint(int constraintId)";
78 static char gPyRemoveConstraint__doc__[] = "removeConstraint(int constraintId)";
79 static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId)";
80
81
82
83
84
85
86 static PyObject* gPySetGravity(PyObject* self,
87                                                                                  PyObject* args, 
88                                                                                  PyObject* kwds)
89 {
90         float x,y,z;
91         if (PyArg_ParseTuple(args,"fff",&x,&y,&z))
92         {
93                 if (PHY_GetActiveEnvironment())
94                         PHY_GetActiveEnvironment()->setGravity(x,y,z);
95         }
96         else {
97                 return NULL;
98         }
99         
100         Py_RETURN_NONE;
101 }
102
103 static PyObject* gPySetDebugMode(PyObject* self,
104                                                                                  PyObject* args, 
105                                                                                  PyObject* kwds)
106 {
107         int mode;
108         if (PyArg_ParseTuple(args,"i",&mode))
109         {
110                 if (PHY_GetActiveEnvironment())
111                 {
112                         PHY_GetActiveEnvironment()->setDebugMode(mode);
113                         
114                 }
115                 
116         }
117         else {
118                 return NULL;
119         }
120         
121         Py_RETURN_NONE;
122 }
123
124
125
126 static PyObject* gPySetNumTimeSubSteps(PyObject* self,
127                                                                                  PyObject* args, 
128                                                                                  PyObject* kwds)
129 {
130         int substep;
131         if (PyArg_ParseTuple(args,"i",&substep))
132         {
133                 if (PHY_GetActiveEnvironment())
134                 {
135                         PHY_GetActiveEnvironment()->setNumTimeSubSteps(substep);
136                 }
137         }
138         else {
139                 return NULL;
140         }
141         Py_RETURN_NONE;
142 }
143
144
145 static PyObject* gPySetNumIterations(PyObject* self,
146                                                                                  PyObject* args, 
147                                                                                  PyObject* kwds)
148 {
149         int iter;
150         if (PyArg_ParseTuple(args,"i",&iter))
151         {
152                 if (PHY_GetActiveEnvironment())
153                 {
154                         PHY_GetActiveEnvironment()->setNumIterations(iter);
155                 }
156         }
157         else {
158                 return NULL;
159         }
160         Py_RETURN_NONE;
161 }
162
163
164
165 static PyObject* gPySetDeactivationTime(PyObject* self,
166                                                                                  PyObject* args, 
167                                                                                  PyObject* kwds)
168 {
169         float deactive_time;
170         if (PyArg_ParseTuple(args,"f",&deactive_time))
171         {
172                 if (PHY_GetActiveEnvironment())
173                 {
174                         PHY_GetActiveEnvironment()->setDeactivationTime(deactive_time);
175                 }
176         }
177         else {
178                 return NULL;
179         }
180         Py_RETURN_NONE;
181 }
182
183
184 static PyObject* gPySetDeactivationLinearTreshold(PyObject* self,
185                                                                                  PyObject* args, 
186                                                                                  PyObject* kwds)
187 {
188         float linearDeactivationTreshold;
189         if (PyArg_ParseTuple(args,"f",&linearDeactivationTreshold))
190         {
191                 if (PHY_GetActiveEnvironment())
192                 {
193                         PHY_GetActiveEnvironment()->setDeactivationLinearTreshold( linearDeactivationTreshold);
194                 }
195         }
196         else {
197                 return NULL;
198         }
199         Py_RETURN_NONE;
200 }
201
202
203 static PyObject* gPySetDeactivationAngularTreshold(PyObject* self,
204                                                                                  PyObject* args, 
205                                                                                  PyObject* kwds)
206 {
207         float angularDeactivationTreshold;
208         if (PyArg_ParseTuple(args,"f",&angularDeactivationTreshold))
209         {
210                 if (PHY_GetActiveEnvironment())
211                 {
212                         PHY_GetActiveEnvironment()->setDeactivationAngularTreshold( angularDeactivationTreshold);
213                 }
214         }
215         else {
216                 return NULL;
217         }
218         Py_RETURN_NONE;
219 }
220
221 static PyObject* gPySetContactBreakingTreshold(PyObject* self,
222                                                                                  PyObject* args, 
223                                                                                  PyObject* kwds)
224 {
225         float contactBreakingTreshold;
226         if (PyArg_ParseTuple(args,"f",&contactBreakingTreshold))
227         {
228                 if (PHY_GetActiveEnvironment())
229                 {
230                         PHY_GetActiveEnvironment()->setContactBreakingTreshold( contactBreakingTreshold);
231                 }
232         }
233         else {
234                 return NULL;
235         }
236         Py_RETURN_NONE;
237 }
238
239
240 static PyObject* gPySetCcdMode(PyObject* self,
241                                                                                  PyObject* args, 
242                                                                                  PyObject* kwds)
243 {
244         float ccdMode;
245         if (PyArg_ParseTuple(args,"f",&ccdMode))
246         {
247                 if (PHY_GetActiveEnvironment())
248                 {
249                         PHY_GetActiveEnvironment()->setCcdMode( ccdMode);
250                 }
251         }
252         else {
253                 return NULL;
254         }
255         Py_RETURN_NONE;
256 }
257
258 static PyObject* gPySetSorConstant(PyObject* self,
259                                                                                  PyObject* args, 
260                                                                                  PyObject* kwds)
261 {
262         float sor;
263         if (PyArg_ParseTuple(args,"f",&sor))
264         {
265                 if (PHY_GetActiveEnvironment())
266                 {
267                         PHY_GetActiveEnvironment()->setSolverSorConstant( sor);
268                 }
269         }
270         else {
271                 return NULL;
272         }
273         Py_RETURN_NONE;
274 }
275
276 static PyObject* gPySetSolverTau(PyObject* self,
277                                                                                  PyObject* args, 
278                                                                                  PyObject* kwds)
279 {
280         float tau;
281         if (PyArg_ParseTuple(args,"f",&tau))
282         {
283                 if (PHY_GetActiveEnvironment())
284                 {
285                         PHY_GetActiveEnvironment()->setSolverTau( tau);
286                 }
287         }
288         else {
289                 return NULL;
290         }
291         Py_RETURN_NONE;
292 }
293
294
295 static PyObject* gPySetSolverDamping(PyObject* self,
296                                                                                  PyObject* args, 
297                                                                                  PyObject* kwds)
298 {
299         float damping;
300         if (PyArg_ParseTuple(args,"f",&damping))
301         {
302                 if (PHY_GetActiveEnvironment())
303                 {
304                         PHY_GetActiveEnvironment()->setSolverDamping( damping);
305                 }
306         }
307         else {
308                 return NULL;
309         }
310         Py_RETURN_NONE;
311 }
312
313 static PyObject* gPySetLinearAirDamping(PyObject* self,
314                                                                                  PyObject* args, 
315                                                                                  PyObject* kwds)
316 {
317         float damping;
318         if (PyArg_ParseTuple(args,"f",&damping))
319         {
320                 if (PHY_GetActiveEnvironment())
321                 {
322                         PHY_GetActiveEnvironment()->setLinearAirDamping( damping);
323                 }
324         }
325         else {
326                 return NULL;
327         }
328         Py_RETURN_NONE;
329 }
330
331
332 static PyObject* gPySetUseEpa(PyObject* self,
333                                                                                  PyObject* args, 
334                                                                                  PyObject* kwds)
335 {
336         int     epa;
337         if (PyArg_ParseTuple(args,"i",&epa))
338         {
339                 if (PHY_GetActiveEnvironment())
340                 {
341                         PHY_GetActiveEnvironment()->setUseEpa(epa);
342                 }
343         }
344         else {
345                 return NULL;
346         }
347         Py_RETURN_NONE;
348 }
349 static PyObject* gPySetSolverType(PyObject* self,
350                                                                                  PyObject* args, 
351                                                                                  PyObject* kwds)
352 {
353         int     solverType;
354         if (PyArg_ParseTuple(args,"i",&solverType))
355         {
356                 if (PHY_GetActiveEnvironment())
357                 {
358                         PHY_GetActiveEnvironment()->setSolverType(solverType);
359                 }
360         }
361         else {
362                 return NULL;
363         }
364         Py_RETURN_NONE;
365 }
366
367
368
369 static PyObject* gPyGetVehicleConstraint(PyObject* self,
370                                                                                  PyObject* args, 
371                                                                                  PyObject* kwds)
372 {
373 #if defined(_WIN64)
374         __int64 constraintid;
375         if (PyArg_ParseTuple(args,"L",&constraintid))
376 #else
377         long constraintid;
378         if (PyArg_ParseTuple(args,"l",&constraintid))
379 #endif
380         {
381                 if (PHY_GetActiveEnvironment())
382                 {
383                         
384                         PHY_IVehicle* vehicle = PHY_GetActiveEnvironment()->getVehicleConstraint(constraintid);
385                         if (vehicle)
386                         {
387                                 KX_VehicleWrapper* pyWrapper = new KX_VehicleWrapper(vehicle,PHY_GetActiveEnvironment());
388                                 return pyWrapper->NewProxy(true);
389                         }
390
391                 }
392         }
393         else {
394                 return NULL;
395         }
396
397         Py_RETURN_NONE;
398 }
399
400
401
402
403
404 static PyObject* gPyCreateConstraint(PyObject* self,
405                                                                                  PyObject* args, 
406                                                                                  PyObject* kwds)
407 {
408         /* FIXME - physicsid is an int being cast to a pointer, should at least use PyCapsule */
409         int physicsid=0,physicsid2 = 0,constrainttype=0,extrainfo=0;
410         int len = PyTuple_Size(args);
411         int success = 1;
412         int flag = 0;
413
414         float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1;
415         if (len == 3)
416         {
417                 success = PyArg_ParseTuple(args,"iii",&physicsid,&physicsid2,&constrainttype);
418         }
419         else
420         if (len ==6)
421         {
422                 success = PyArg_ParseTuple(args,"iiifff",&physicsid,&physicsid2,&constrainttype,
423                         &pivotX,&pivotY,&pivotZ);
424         }
425         else if (len == 9)
426         {
427                 success = PyArg_ParseTuple(args,"iiiffffff",&physicsid,&physicsid2,&constrainttype,
428                         &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
429         }
430         else if (len == 10)
431         {
432                 success = PyArg_ParseTuple(args,"iiiffffffi",&physicsid,&physicsid2,&constrainttype,
433                         &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
434         }
435         else if (len==4)
436         {
437                 success = PyArg_ParseTuple(args,"iiii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
438                 pivotX=extrainfo;
439         }
440         
441         if (success)
442         {
443                 if (PHY_GetActiveEnvironment())
444                 {
445                         
446                         PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid;
447                         PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2;
448                         if (physctrl) //TODO:check for existence of this pointer!
449                         {
450                                 PHY_ConstraintType ct = (PHY_ConstraintType) constrainttype;
451                                 int constraintid =0;
452
453                                 if (ct == PHY_GENERIC_6DOF_CONSTRAINT)
454                                 {
455                                         //convert from euler angle into axis
456                                         float radsPerDeg = 6.283185307179586232f / 360.f;
457
458                                         //we need to pass a full constraint frame, not just axis
459                                         //localConstraintFrameBasis
460                                         MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*axisX,radsPerDeg*axisY,radsPerDeg*axisZ));
461                                         MT_Vector3 axis0 = localCFrame.getColumn(0);
462                                         MT_Vector3 axis1 = localCFrame.getColumn(1);
463                                         MT_Vector3 axis2 = localCFrame.getColumn(2);
464                                                 
465                                         constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,
466                                                 pivotX,pivotY,pivotZ,
467                                                 (float)axis0.x(),(float)axis0.y(),(float)axis0.z(),
468                                                 (float)axis1.x(),(float)axis1.y(),(float)axis1.z(),
469                                                 (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag);
470
471                                 } else
472                                 {
473                                         constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ,0);
474                                 }
475                                 
476                                 KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment());
477                                 
478
479                                 return wrap->NewProxy(true);
480                         }
481                         
482                         
483                 }
484         }
485         else {
486                 return NULL;
487         }
488
489         Py_RETURN_NONE;
490 }
491
492
493
494
495 static PyObject* gPyGetAppliedImpulse(PyObject* self,
496                                                                                  PyObject* args, 
497                                                                                  PyObject* kwds)
498 {
499         float   appliedImpulse = 0.f;
500
501 #if defined(_WIN64)
502         __int64 constraintid;
503         if (PyArg_ParseTuple(args,"L",&constraintid))
504 #else
505         long constraintid;
506         if (PyArg_ParseTuple(args,"l",&constraintid))
507 #endif
508         {
509                 if (PHY_GetActiveEnvironment())
510                 {
511                         appliedImpulse = PHY_GetActiveEnvironment()->getAppliedImpulse(constraintid);
512                 }
513         }
514         else {
515                 return NULL;
516         }
517
518         return PyFloat_FromDouble(appliedImpulse);
519 }
520
521
522 static PyObject* gPyRemoveConstraint(PyObject* self,
523                                                                                  PyObject* args, 
524                                                                                  PyObject* kwds)
525 {
526 #if defined(_WIN64)
527         __int64 constraintid;
528         if (PyArg_ParseTuple(args,"L",&constraintid))
529 #else
530         long constraintid;
531         if (PyArg_ParseTuple(args,"l",&constraintid))
532 #endif
533         {
534                 if (PHY_GetActiveEnvironment())
535                 {
536                         PHY_GetActiveEnvironment()->removeConstraint(constraintid);
537                 }
538         }
539         else {
540                 return NULL;
541         }
542         
543         Py_RETURN_NONE;
544 }
545
546 static PyObject* gPyExportBulletFile(PyObject*, PyObject* args)
547 {
548         char* filename;
549         if (!PyArg_ParseTuple(args,"s:exportBulletFile",&filename))
550                 return NULL;
551                 
552         if (PHY_GetActiveEnvironment())
553         {
554                 PHY_GetActiveEnvironment()->exportFile(filename);
555         }
556         Py_RETURN_NONE;
557 }
558
559 static struct PyMethodDef physicsconstraints_methods[] = {
560   {"setGravity",(PyCFunction) gPySetGravity,
561    METH_VARARGS, (const char *)gPySetGravity__doc__},
562   {"setDebugMode",(PyCFunction) gPySetDebugMode,
563    METH_VARARGS, (const char *)gPySetDebugMode__doc__},
564
565    /// settings that influence quality of the rigidbody dynamics
566   {"setNumIterations",(PyCFunction) gPySetNumIterations,
567    METH_VARARGS, (const char *)gPySetNumIterations__doc__},
568
569    {"setNumTimeSubSteps",(PyCFunction) gPySetNumTimeSubSteps,
570    METH_VARARGS, (const char *)gPySetNumTimeSubSteps__doc__},
571
572   {"setDeactivationTime",(PyCFunction) gPySetDeactivationTime,
573    METH_VARARGS, (const char *)gPySetDeactivationTime__doc__},
574
575   {"setDeactivationLinearTreshold",(PyCFunction) gPySetDeactivationLinearTreshold,
576    METH_VARARGS, (const char *)gPySetDeactivationLinearTreshold__doc__},
577   {"setDeactivationAngularTreshold",(PyCFunction) gPySetDeactivationAngularTreshold,
578    METH_VARARGS, (const char *)gPySetDeactivationAngularTreshold__doc__},
579
580    {"setContactBreakingTreshold",(PyCFunction) gPySetContactBreakingTreshold,
581    METH_VARARGS, (const char *)gPySetContactBreakingTreshold__doc__},
582      {"setCcdMode",(PyCFunction) gPySetCcdMode,
583    METH_VARARGS, (const char *)gPySetCcdMode__doc__},
584      {"setSorConstant",(PyCFunction) gPySetSorConstant,
585    METH_VARARGS, (const char *)gPySetSorConstant__doc__},
586        {"setSolverTau",(PyCFunction) gPySetSolverTau,
587    METH_VARARGS, (const char *)gPySetSolverTau__doc__},
588         {"setSolverDamping",(PyCFunction) gPySetSolverDamping,
589    METH_VARARGS, (const char *)gPySetSolverDamping__doc__},
590
591          {"setLinearAirDamping",(PyCFunction) gPySetLinearAirDamping,
592    METH_VARARGS, (const char *)gPySetLinearAirDamping__doc__},
593
594     {"setUseEpa",(PyCFunction) gPySetUseEpa,
595    METH_VARARGS, (const char *)gPySetUseEpa__doc__},
596         {"setSolverType",(PyCFunction) gPySetSolverType,
597    METH_VARARGS, (const char *)gPySetSolverType__doc__},
598
599
600   {"createConstraint",(PyCFunction) gPyCreateConstraint,
601    METH_VARARGS, (const char *)gPyCreateConstraint__doc__},
602      {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint,
603    METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__},
604
605   {"removeConstraint",(PyCFunction) gPyRemoveConstraint,
606    METH_VARARGS, (const char *)gPyRemoveConstraint__doc__},
607         {"getAppliedImpulse",(PyCFunction) gPyGetAppliedImpulse,
608    METH_VARARGS, (const char *)gPyGetAppliedImpulse__doc__},
609
610      {"exportBulletFile",(PyCFunction)gPyExportBulletFile,
611         METH_VARARGS, "export a .bullet file"},
612
613
614    //sentinel
615   { NULL, (PyCFunction) NULL, 0, NULL }
616 };
617
618 static struct PyModuleDef PhysicsConstraints_module_def = {
619         {}, /* m_base */
620         "PhysicsConstraints",  /* m_name */
621         PhysicsConstraints_module_documentation,  /* m_doc */
622         0,  /* m_size */
623         physicsconstraints_methods,  /* m_methods */
624         0,  /* m_reload */
625         0,  /* m_traverse */
626         0,  /* m_clear */
627         0,  /* m_free */
628 };
629
630 PyObject*       initPythonConstraintBinding()
631 {
632
633   PyObject* ErrorObject;
634   PyObject* m;
635   PyObject* d;
636
637         /* Use existing module where possible
638          * be careful not to init any runtime vars after this */
639         m = PyImport_ImportModule( "PhysicsConstraints" );
640         if(m) {
641                 Py_DECREF(m);
642                 return m;
643         }
644         else {
645                 PyErr_Clear();
646                 
647                 m = PyModule_Create(&PhysicsConstraints_module_def);
648                 PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m);
649         }
650
651   // Add some symbolic constants to the module
652   d = PyModule_GetDict(m);
653   ErrorObject = PyUnicode_FromString("PhysicsConstraints.error");
654   PyDict_SetItemString(d, "error", ErrorObject);
655   Py_DECREF(ErrorObject);
656
657   // XXXX Add constants here
658
659   // Check for errors
660   if (PyErr_Occurred())
661     {
662       Py_FatalError("can't initialize module PhysicsConstraints");
663     }
664
665   return d;
666 }
667
668
669 void    KX_RemovePythonConstraintBinding()
670 {
671 }
672
673 void    PHY_SetActiveEnvironment(class  PHY_IPhysicsEnvironment* env)
674 {
675         g_CurrentActivePhysicsEnvironment = env;
676 }
677
678 PHY_IPhysicsEnvironment*        PHY_GetActiveEnvironment()
679 {
680         return g_CurrentActivePhysicsEnvironment;
681 }
682
683
684
685 #endif // WITH_PYTHON
686