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