Ken's 64bit patches weren't merged over to orange for some reason.
[blender-staging.git] / source / gameengine / Ketsji / KX_PyConstraintBinding.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32 #include "KX_PyConstraintBinding.h"
33 #include "PHY_IPhysicsEnvironment.h"
34 #include "KX_ConstraintWrapper.h"
35 #include "KX_PhysicsObjectWrapper.h"
36 #include "PHY_IPhysicsController.h"
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 // nasty glob variable to connect scripting language
43 // if there is a better way (without global), please do so!
44 static PHY_IPhysicsEnvironment* g_CurrentActivePhysicsEnvironment = NULL;
45
46 static char PhysicsConstraints_module_documentation[] =
47 "This is the Python API for the Physics Constraints";
48
49
50 static char gPySetGravity__doc__[] = "setGravity(float x,float y,float z)";
51 static char gPySetDebugMode__doc__[] = "setDebugMode(int mode)";
52
53 static char gPySetNumIterations__doc__[] = "setNumIterations(int numiter) This sets the number of iterations for an iterative constraint solver";
54 static char gPySetDeactivationTime__doc__[] = "setDeactivationTime(float time) This sets the time after which a resting rigidbody gets deactived";
55 static char gPySetDeactivationLinearTreshold__doc__[] = "setDeactivationLinearTreshold(float linearTreshold)";
56 static char gPySetDeactivationAngularTreshold__doc__[] = "setDeactivationAngularTreshold(float angularTreshold)";
57 static char gPySetContactBreakingTreshold__doc__[] = "setContactBreakingTreshold(float breakingTreshold) Reasonable default is 0.02 (if units are meters)";
58
59 static char gPySetCcdMode__doc__[] = "setCcdMode(int ccdMode) Very experimental, not recommended";
60 static char gPySetSorConstant__doc__[] = "setSorConstant(float sor) Very experimental, not recommended";
61 static char gPySetSolverTau__doc__[] = "setTau(float tau) Very experimental, not recommended";
62 static char gPySetSolverDamping__doc__[] = "setDamping(float damping) Very experimental, not recommended";
63 static char gPySetLinearAirDamping__doc__[] = "setLinearAirDamping(float damping) Very experimental, not recommended";
64 static char gPySetUseEpa__doc__[] = "setUseEpa(int epa) Very experimental, not recommended";
65 static char gPySetSolverType__doc__[] = "setSolverType(int solverType) Very experimental, not recommended";
66
67
68 static char gPyCreateConstraint__doc__[] = "createConstraint(ob1,ob2,float restLength,float restitution,float damping)";
69 static char gPyRemoveConstraint__doc__[] = "removeConstraint(constraint id)";
70
71
72
73
74
75 static PyObject* gPySetGravity(PyObject* self,
76                                                                                  PyObject* args, 
77                                                                                  PyObject* kwds)
78 {
79         float x,y,z;
80         int len = PyTuple_Size(args);
81         if ((len == 3) && PyArg_ParseTuple(args,"fff",&x,&y,&z))
82         {
83                 if (PHY_GetActiveEnvironment())
84                         PHY_GetActiveEnvironment()->setGravity(x,y,z);
85         }
86         Py_INCREF(Py_None); return Py_None;
87 }
88
89 static PyObject* gPySetDebugMode(PyObject* self,
90                                                                                  PyObject* args, 
91                                                                                  PyObject* kwds)
92 {
93         int mode;
94         if (PyArg_ParseTuple(args,"i",&mode))
95         {
96                 if (PHY_GetActiveEnvironment())
97                 {
98                         PHY_GetActiveEnvironment()->setDebugMode(mode);
99                         
100                 }
101                 
102         }
103         Py_INCREF(Py_None); return Py_None;
104 }
105
106 static PyObject* gPySetNumIterations(PyObject* self,
107                                                                                  PyObject* args, 
108                                                                                  PyObject* kwds)
109 {
110         int iter;
111         if (PyArg_ParseTuple(args,"i",&iter))
112         {
113                 if (PHY_GetActiveEnvironment())
114                 {
115                         PHY_GetActiveEnvironment()->setNumIterations(iter);
116                 }
117         }
118         Py_INCREF(Py_None); return Py_None;
119 }
120
121
122
123 static PyObject* gPySetDeactivationTime(PyObject* self,
124                                                                                  PyObject* args, 
125                                                                                  PyObject* kwds)
126 {
127         float deactive_time;
128         if (PyArg_ParseTuple(args,"f",&deactive_time))
129         {
130                 if (PHY_GetActiveEnvironment())
131                 {
132                         PHY_GetActiveEnvironment()->setDeactivationTime(deactive_time);
133                 }
134         }
135         Py_INCREF(Py_None); return Py_None;
136 }
137
138
139 static PyObject* gPySetDeactivationLinearTreshold(PyObject* self,
140                                                                                  PyObject* args, 
141                                                                                  PyObject* kwds)
142 {
143         float linearDeactivationTreshold;
144         if (PyArg_ParseTuple(args,"f",&linearDeactivationTreshold))
145         {
146                 if (PHY_GetActiveEnvironment())
147                 {
148                         PHY_GetActiveEnvironment()->setDeactivationLinearTreshold( linearDeactivationTreshold);
149                 }
150         }
151         Py_INCREF(Py_None); return Py_None;
152 }
153
154
155 static PyObject* gPySetDeactivationAngularTreshold(PyObject* self,
156                                                                                  PyObject* args, 
157                                                                                  PyObject* kwds)
158 {
159         float angularDeactivationTreshold;
160         if (PyArg_ParseTuple(args,"f",&angularDeactivationTreshold))
161         {
162                 if (PHY_GetActiveEnvironment())
163                 {
164                         PHY_GetActiveEnvironment()->setDeactivationAngularTreshold( angularDeactivationTreshold);
165                 }
166         }
167         Py_INCREF(Py_None); return Py_None;
168 }
169
170 static PyObject* gPySetContactBreakingTreshold(PyObject* self,
171                                                                                  PyObject* args, 
172                                                                                  PyObject* kwds)
173 {
174         float contactBreakingTreshold;
175         if (PyArg_ParseTuple(args,"f",&contactBreakingTreshold))
176         {
177                 if (PHY_GetActiveEnvironment())
178                 {
179                         PHY_GetActiveEnvironment()->setContactBreakingTreshold( contactBreakingTreshold);
180                 }
181         }
182         Py_INCREF(Py_None); return Py_None;
183 }
184
185
186 static PyObject* gPySetCcdMode(PyObject* self,
187                                                                                  PyObject* args, 
188                                                                                  PyObject* kwds)
189 {
190         float ccdMode;
191         if (PyArg_ParseTuple(args,"f",&ccdMode))
192         {
193                 if (PHY_GetActiveEnvironment())
194                 {
195                         PHY_GetActiveEnvironment()->setCcdMode( ccdMode);
196                 }
197         }
198         Py_INCREF(Py_None); return Py_None;
199 }
200
201 static PyObject* gPySetSorConstant(PyObject* self,
202                                                                                  PyObject* args, 
203                                                                                  PyObject* kwds)
204 {
205         float sor;
206         if (PyArg_ParseTuple(args,"f",&sor))
207         {
208                 if (PHY_GetActiveEnvironment())
209                 {
210                         PHY_GetActiveEnvironment()->setSolverSorConstant( sor);
211                 }
212         }
213         Py_INCREF(Py_None); return Py_None;
214 }
215
216 static PyObject* gPySetSolverTau(PyObject* self,
217                                                                                  PyObject* args, 
218                                                                                  PyObject* kwds)
219 {
220         float tau;
221         if (PyArg_ParseTuple(args,"f",&tau))
222         {
223                 if (PHY_GetActiveEnvironment())
224                 {
225                         PHY_GetActiveEnvironment()->setSolverTau( tau);
226                 }
227         }
228         Py_INCREF(Py_None); return Py_None;
229 }
230
231
232 static PyObject* gPySetSolverDamping(PyObject* self,
233                                                                                  PyObject* args, 
234                                                                                  PyObject* kwds)
235 {
236         float damping;
237         if (PyArg_ParseTuple(args,"f",&damping))
238         {
239                 if (PHY_GetActiveEnvironment())
240                 {
241                         PHY_GetActiveEnvironment()->setSolverDamping( damping);
242                 }
243         }
244         Py_INCREF(Py_None); return Py_None;
245 }
246
247 static PyObject* gPySetLinearAirDamping(PyObject* self,
248                                                                                  PyObject* args, 
249                                                                                  PyObject* kwds)
250 {
251         float damping;
252         if (PyArg_ParseTuple(args,"f",&damping))
253         {
254                 if (PHY_GetActiveEnvironment())
255                 {
256                         PHY_GetActiveEnvironment()->setLinearAirDamping( damping);
257                 }
258         }
259         Py_INCREF(Py_None); return Py_None;
260 }
261
262
263 static PyObject* gPySetUseEpa(PyObject* self,
264                                                                                  PyObject* args, 
265                                                                                  PyObject* kwds)
266 {
267         int     epa;
268         if (PyArg_ParseTuple(args,"i",&epa))
269         {
270                 if (PHY_GetActiveEnvironment())
271                 {
272                         PHY_GetActiveEnvironment()->setUseEpa(epa);
273                 }
274         }
275         Py_INCREF(Py_None); return Py_None;
276 }
277 static PyObject* gPySetSolverType(PyObject* self,
278                                                                                  PyObject* args, 
279                                                                                  PyObject* kwds)
280 {
281         int     solverType;
282         if (PyArg_ParseTuple(args,"i",&solverType))
283         {
284                 if (PHY_GetActiveEnvironment())
285                 {
286                         PHY_GetActiveEnvironment()->setSolverType(solverType);
287                 }
288         }
289         Py_INCREF(Py_None); return Py_None;
290 }
291
292
293
294
295
296
297 static PyObject* gPyCreateConstraint(PyObject* self,
298                                                                                  PyObject* args, 
299                                                                                  PyObject* kwds)
300 {
301         int physicsid=0,physicsid2 = 0,constrainttype=0,extrainfo=0;
302         int len = PyTuple_Size(args);
303         int success = 1;
304         float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1;
305         if (len == 3)
306         {
307                 success = PyArg_ParseTuple(args,"iii",&physicsid,&physicsid2,&constrainttype);
308         }
309         else
310         if (len ==6)
311         {
312                 success = PyArg_ParseTuple(args,"iiifff",&physicsid,&physicsid2,&constrainttype,
313                         &pivotX,&pivotY,&pivotZ);
314         }
315         else if (len == 9)
316         {
317                 success = PyArg_ParseTuple(args,"iiiffffff",&physicsid,&physicsid2,&constrainttype,
318                         &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
319         }
320         else if (len==4)
321         {
322                 success = PyArg_ParseTuple(args,"iiii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
323                 pivotX=extrainfo;
324         }
325         
326         if (success)
327         {
328                 if (PHY_GetActiveEnvironment())
329                 {
330                         
331                         PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid;
332                         PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2;
333                         if (physctrl) //TODO:check for existance of this pointer!
334                         {
335                                 int constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ);
336                                 
337                                 KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment());
338                                 
339
340                                 return wrap;
341                         }
342                         
343                         
344                 }
345         }
346
347         Py_INCREF(Py_None); return Py_None;
348 }
349
350
351 static PyObject* gPyRemoveConstraint(PyObject* self,
352                                                                                  PyObject* args, 
353                                                                                  PyObject* kwds)
354 {
355 #if defined(_WIN64)
356         __int64 constraintid;
357         if (PyArg_ParseTuple(args,"L",&constraintid))
358 #else
359         long constraintid;
360         if (PyArg_ParseTuple(args,"l",&constraintid))
361 #endif
362         {
363                 if (PHY_GetActiveEnvironment())
364                 {
365                         PHY_GetActiveEnvironment()->removeConstraint((void *)constraintid);
366                 }
367         }
368         Py_INCREF(Py_None); return Py_None;
369 }
370
371
372 static struct PyMethodDef physicsconstraints_methods[] = {
373   {"setGravity",(PyCFunction) gPySetGravity,
374    METH_VARARGS, gPySetGravity__doc__},
375   {"setDebugMode",(PyCFunction) gPySetDebugMode,
376    METH_VARARGS, gPySetDebugMode__doc__},
377
378    /// settings that influence quality of the rigidbody dynamics
379   {"setNumIterations",(PyCFunction) gPySetNumIterations,
380    METH_VARARGS, gPySetNumIterations__doc__},
381
382   {"setDeactivationTime",(PyCFunction) gPySetDeactivationTime,
383    METH_VARARGS, gPySetDeactivationTime__doc__},
384
385   {"setDeactivationLinearTreshold",(PyCFunction) gPySetDeactivationLinearTreshold,
386    METH_VARARGS, gPySetDeactivationLinearTreshold__doc__},
387   {"setDeactivationAngularTreshold",(PyCFunction) gPySetDeactivationAngularTreshold,
388    METH_VARARGS, gPySetDeactivationAngularTreshold__doc__},
389
390    {"setContactBreakingTreshold",(PyCFunction) gPySetContactBreakingTreshold,
391    METH_VARARGS, gPySetContactBreakingTreshold__doc__},
392      {"setCcdMode",(PyCFunction) gPySetCcdMode,
393    METH_VARARGS, gPySetCcdMode__doc__},
394      {"setSorConstant",(PyCFunction) gPySetSorConstant,
395    METH_VARARGS, gPySetSorConstant__doc__},
396        {"setSolverTau",(PyCFunction) gPySetSolverTau,
397    METH_VARARGS, gPySetSolverTau__doc__},
398         {"setSolverDamping",(PyCFunction) gPySetSolverDamping,
399    METH_VARARGS, gPySetSolverDamping__doc__},
400
401          {"setLinearAirDamping",(PyCFunction) gPySetLinearAirDamping,
402    METH_VARARGS, gPySetLinearAirDamping__doc__},
403
404     {"setUseEpa",(PyCFunction) gPySetUseEpa,
405    METH_VARARGS, gPySetUseEpa__doc__},
406         {"setSolverType",(PyCFunction) gPySetSolverType,
407    METH_VARARGS, gPySetSolverType__doc__},
408
409
410
411   {"createConstraint",(PyCFunction) gPyCreateConstraint,
412    METH_VARARGS, gPyCreateConstraint__doc__},
413   {"removeConstraint",(PyCFunction) gPyRemoveConstraint,
414    METH_VARARGS, gPyRemoveConstraint__doc__},
415
416    //sentinel
417   { NULL, (PyCFunction) NULL, 0, NULL }
418 };
419
420
421
422 PyObject*       initPythonConstraintBinding()
423 {
424
425   PyObject* ErrorObject;
426   PyObject* m;
427   PyObject* d;
428
429
430   m = Py_InitModule4("PhysicsConstraints", physicsconstraints_methods,
431                      PhysicsConstraints_module_documentation,
432                      (PyObject*)NULL,PYTHON_API_VERSION);
433
434   // Add some symbolic constants to the module
435   d = PyModule_GetDict(m);
436   ErrorObject = PyString_FromString("PhysicsConstraints.error");
437   PyDict_SetItemString(d, "error", ErrorObject);
438
439   // XXXX Add constants here
440
441   // Check for errors
442   if (PyErr_Occurred())
443     {
444       Py_FatalError("can't initialize module PhysicsConstraints");
445     }
446
447   return d;
448 }
449
450
451 void    KX_RemovePythonConstraintBinding()
452 {
453 }
454
455 void    PHY_SetActiveEnvironment(class  PHY_IPhysicsEnvironment* env)
456 {
457         g_CurrentActivePhysicsEnvironment = env;
458 }
459
460 PHY_IPhysicsEnvironment*        PHY_GetActiveEnvironment()
461 {
462         return g_CurrentActivePhysicsEnvironment;
463 }
464