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