Cleanup: style, whitespace, doxy filepaths
[blender-staging.git] / source / gameengine / Ketsji / KX_VehicleWrapper.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file gameengine/Ketsji/KX_VehicleWrapper.cpp
22  *  \ingroup ketsji
23  */
24
25 #include "EXP_PyObjectPlus.h"
26
27 #include "KX_VehicleWrapper.h"
28 #include "PHY_IPhysicsEnvironment.h"
29 #include "PHY_IVehicle.h"
30 #include "KX_PyMath.h"
31 #include "KX_GameObject.h"
32 #include "KX_MotionState.h"
33 #include "KX_PythonInit.h"
34
35 KX_VehicleWrapper::KX_VehicleWrapper(
36                                                 PHY_IVehicle* vehicle,
37                                                 PHY_IPhysicsEnvironment* physenv) :
38                 PyObjectPlus(),
39                 m_vehicle(vehicle),
40                 m_physenv(physenv)
41 {
42 }
43
44 KX_VehicleWrapper::~KX_VehicleWrapper()
45 {
46         int numMotion = m_motionStates.size();
47         for (int i=0;i<numMotion;i++)
48         {
49                 PHY_IMotionState* motionState = m_motionStates[i];
50                 delete motionState;
51         }
52         m_motionStates.clear();
53 }
54
55 #ifdef WITH_PYTHON
56
57
58 static bool raise_exc_wheel(PHY_IVehicle *vehicle, int i, const char *method)
59 {
60         if (i < 0 || i >= vehicle->GetNumWheels()) {
61                 PyErr_Format(PyExc_ValueError,
62                              "%s(...): wheel index %d out of range (0 to %d).", method, i, vehicle->GetNumWheels() - 1);
63                 return true;
64         }
65         else {
66                 return false;
67         }
68 }
69
70 #define WHEEL_INDEX_CHECK_OR_RETURN(i, method) \
71         if (raise_exc_wheel(m_vehicle, i, method)) {return NULL;} (void)0
72
73
74 PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
75 {
76         
77         PyObject *pylistPos,*pylistDir,*pylistAxleDir;
78         PyObject *wheelGameObject;
79         float suspensionRestLength,wheelRadius;
80         int hasSteering;
81
82         
83         if (PyArg_ParseTuple(args,"OOOOffi:addWheel",&wheelGameObject,&pylistPos,&pylistDir,&pylistAxleDir,&suspensionRestLength,&wheelRadius,&hasSteering))
84         {
85                 KX_GameObject *gameOb;
86                 if (!ConvertPythonToGameObject(KX_GetActiveScene()->GetLogicManager(), wheelGameObject, &gameOb, false, "vehicle.addWheel(...): KX_VehicleWrapper (first argument)"))
87                         return NULL;
88
89                 if (gameOb->GetSGNode())
90                 {
91                         MT_Vector3 attachPos,attachDir,attachAxle;
92                         if (!PyVecTo(pylistPos,attachPos)) {
93                                 PyErr_SetString(PyExc_AttributeError,
94                                                 "addWheel(...) Unable to add wheel. attachPos must be a vector with 3 elements.");
95                                 return NULL;
96                         }
97                         if (!PyVecTo(pylistDir,attachDir))  {
98                                 PyErr_SetString(PyExc_AttributeError,
99                                                 "addWheel(...) Unable to add wheel. downDir must be a vector with 3 elements.");
100                                 return NULL;
101                         }
102                         if (!PyVecTo(pylistAxleDir,attachAxle)) {
103                                 PyErr_SetString(PyExc_AttributeError,
104                                                 "addWheel(...) Unable to add wheel. axleDir must be a vector with 3 elements.");
105                                 return NULL;
106                         }
107
108                         //someone reverse some conventions inside Bullet (axle winding)
109                         attachAxle = -attachAxle;
110                         
111                         if (wheelRadius <= 0) {
112                                 PyErr_SetString(PyExc_AttributeError,
113                                                 "addWheel(...) Unable to add wheel. wheelRadius must be positive.");
114                                 return NULL;
115                         }
116
117                         PHY_IMotionState *motionState = new KX_MotionState(gameOb->GetSGNode());
118                         m_vehicle->AddWheel(motionState,attachPos,attachDir,attachAxle,suspensionRestLength,wheelRadius,hasSteering);
119                 }
120                 
121         } else {
122                 return NULL;
123         }
124         Py_RETURN_NONE;
125 }
126
127
128 PyObject *KX_VehicleWrapper::PyGetWheelPosition(PyObject *args)
129 {
130         
131         int wheelIndex;
132
133         if (PyArg_ParseTuple(args,"i:getWheelPosition",&wheelIndex))
134         {
135                 float position[3];
136                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelPosition");
137
138                 m_vehicle->GetWheelPosition(wheelIndex,position[0],position[1],position[2]);
139                 MT_Vector3 pos(position[0],position[1],position[2]);
140                 return PyObjectFrom(pos);
141         }
142         return NULL;
143 }
144
145 PyObject *KX_VehicleWrapper::PyGetWheelRotation(PyObject *args)
146 {
147         int wheelIndex;
148         if (PyArg_ParseTuple(args,"i:getWheelRotation",&wheelIndex))
149         {
150                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelRotation");
151
152                 return PyFloat_FromDouble(m_vehicle->GetWheelRotation(wheelIndex));
153         }
154         return NULL;
155 }
156
157 PyObject *KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject *args)
158 {
159         int wheelIndex;
160         if (PyArg_ParseTuple(args,"i:getWheelOrientationQuaternion",&wheelIndex))
161         {
162                 float orn[4];
163                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelOrientationQuaternion");
164
165                 m_vehicle->GetWheelOrientationQuaternion(wheelIndex,orn[0],orn[1],orn[2],orn[3]);
166                 MT_Quaternion   quatorn(orn[0],orn[1],orn[2],orn[3]);
167                 MT_Matrix3x3 ornmat(quatorn);
168                 return PyObjectFrom(ornmat);
169         }
170         return NULL;
171
172 }
173
174
175 PyObject *KX_VehicleWrapper::PyGetNumWheels(PyObject *args)
176 {
177         return PyLong_FromLong(m_vehicle->GetNumWheels());
178 }
179
180
181 PyObject *KX_VehicleWrapper::PyGetConstraintId(PyObject *args)
182 {
183         return PyLong_FromLong(m_vehicle->GetUserConstraintId());
184 }
185
186
187 PyObject *KX_VehicleWrapper::PyApplyEngineForce(PyObject *args)
188 {
189         float force;
190         int wheelIndex;
191
192         if (PyArg_ParseTuple(args,"fi:applyEngineForce",&force,&wheelIndex))
193         {
194                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "applyEngineForce");
195
196                 force *= -1.f;//someone reverse some conventions inside Bullet (axle winding)
197                 m_vehicle->ApplyEngineForce(force,wheelIndex);
198         }
199         else {
200                 return NULL;
201         }
202         Py_RETURN_NONE;
203 }
204
205 PyObject *KX_VehicleWrapper::PySetTyreFriction(PyObject *args)
206 {
207         float wheelFriction;
208         int wheelIndex;
209
210         if (PyArg_ParseTuple(args,"fi:setTyreFriction",&wheelFriction,&wheelIndex))
211         {
212                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setTyreFriction");
213
214                 m_vehicle->SetWheelFriction(wheelFriction,wheelIndex);
215         }
216         else {
217                 return NULL;
218         }
219         Py_RETURN_NONE;
220 }
221
222 PyObject *KX_VehicleWrapper::PySetSuspensionStiffness(PyObject *args)
223 {
224         float suspensionStiffness;
225         int wheelIndex;
226
227         if (PyArg_ParseTuple(args,"fi:setSuspensionStiffness",&suspensionStiffness,&wheelIndex))
228         {
229                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionStiffness");
230
231                 m_vehicle->SetSuspensionStiffness(suspensionStiffness,wheelIndex);
232         }
233         else {
234                 return NULL;
235         }
236         Py_RETURN_NONE;
237 }
238
239 PyObject *KX_VehicleWrapper::PySetSuspensionDamping(PyObject *args)
240 {
241         float suspensionDamping;
242         int wheelIndex;
243
244         if (PyArg_ParseTuple(args,"fi:setSuspensionDamping",&suspensionDamping,&wheelIndex))
245         {
246                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionDamping");
247
248                 m_vehicle->SetSuspensionDamping(suspensionDamping,wheelIndex);
249         } else {
250                 return NULL;
251         }
252         Py_RETURN_NONE;
253 }
254
255 PyObject *KX_VehicleWrapper::PySetSuspensionCompression(PyObject *args)
256 {
257         float suspensionCompression;
258         int wheelIndex;
259
260         if (PyArg_ParseTuple(args,"fi:setSuspensionCompression",&suspensionCompression,&wheelIndex))
261         {
262                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionCompression");
263
264                 m_vehicle->SetSuspensionCompression(suspensionCompression,wheelIndex);
265         } else {
266                 return NULL;
267         }
268         Py_RETURN_NONE;
269 }
270
271 PyObject *KX_VehicleWrapper::PySetRollInfluence(PyObject *args)
272 {
273         float rollInfluence;
274         int wheelIndex;
275
276         if (PyArg_ParseTuple(args,"fi:setRollInfluence",&rollInfluence,&wheelIndex))
277         {
278                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setRollInfluence");
279
280                 m_vehicle->SetRollInfluence(rollInfluence,wheelIndex);
281         }
282         else {
283                 return NULL;
284         }
285         Py_RETURN_NONE;
286 }
287
288
289 PyObject *KX_VehicleWrapper::PyApplyBraking(PyObject *args)
290 {
291         float braking;
292         int wheelIndex;
293
294         if (PyArg_ParseTuple(args,"fi:applyBraking",&braking,&wheelIndex))
295         {
296                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "applyBraking");
297
298                 m_vehicle->ApplyBraking(braking,wheelIndex);
299         }
300         else {
301                 return NULL;
302         }
303         Py_RETURN_NONE;
304 }
305
306
307 PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args)
308 {
309         float steeringValue;
310         int wheelIndex;
311
312         if (PyArg_ParseTuple(args,"fi:setSteeringValue",&steeringValue,&wheelIndex))
313         {
314                 WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSteeringValue");
315
316                 m_vehicle->SetSteeringValue(steeringValue,wheelIndex);
317         }
318         else {
319                 return NULL;
320         }
321         Py_RETURN_NONE;
322 }
323
324
325 PyObject *KX_VehicleWrapper::PyGetConstraintType(PyObject *args)
326 {
327         return PyLong_FromLong(m_vehicle->GetUserConstraintType());
328 }
329
330
331
332
333
334 //python specific stuff
335 PyTypeObject KX_VehicleWrapper::Type = {
336         PyVarObject_HEAD_INIT(NULL, 0)
337         "KX_VehicleWrapper",
338         sizeof(PyObjectPlus_Proxy),
339         0,
340         py_base_dealloc,
341         0,
342         0,
343         0,
344         0,
345         py_base_repr,
346         0,0,0,0,0,0,0,0,0,
347         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
348         0,0,0,0,0,0,0,
349         Methods,
350         0,
351         0,
352         &PyObjectPlus::Type,
353         0,0,0,0,0,0,
354         py_base_new
355 };
356
357 PyMethodDef KX_VehicleWrapper::Methods[] = {
358         {"addWheel",(PyCFunction) KX_VehicleWrapper::sPyAddWheel, METH_VARARGS},
359         {"getNumWheels",(PyCFunction) KX_VehicleWrapper::sPyGetNumWheels, METH_VARARGS},
360         {"getWheelOrientationQuaternion",(PyCFunction) KX_VehicleWrapper::sPyGetWheelOrientationQuaternion, METH_VARARGS},
361         {"getWheelRotation",(PyCFunction) KX_VehicleWrapper::sPyGetWheelRotation, METH_VARARGS},
362         {"getWheelPosition",(PyCFunction) KX_VehicleWrapper::sPyGetWheelPosition, METH_VARARGS},
363         {"getConstraintId",(PyCFunction) KX_VehicleWrapper::sPyGetConstraintId, METH_VARARGS},
364         {"getConstraintType",(PyCFunction) KX_VehicleWrapper::sPyGetConstraintType, METH_VARARGS},
365         {"setSteeringValue",(PyCFunction) KX_VehicleWrapper::sPySetSteeringValue, METH_VARARGS},
366         {"applyEngineForce",(PyCFunction) KX_VehicleWrapper::sPyApplyEngineForce, METH_VARARGS},
367         {"applyBraking",(PyCFunction) KX_VehicleWrapper::sPyApplyBraking, METH_VARARGS},
368         {"setTyreFriction",(PyCFunction) KX_VehicleWrapper::sPySetTyreFriction, METH_VARARGS},
369         {"setSuspensionStiffness",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionStiffness, METH_VARARGS},
370         {"setSuspensionDamping",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionDamping, METH_VARARGS},
371         {"setSuspensionCompression",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionCompression, METH_VARARGS},
372         {"setRollInfluence",(PyCFunction) KX_VehicleWrapper::sPySetRollInfluence, METH_VARARGS},
373         {NULL,NULL} //Sentinel
374 };
375
376 PyAttributeDef KX_VehicleWrapper::Attributes[] = {
377         { NULL }        //Sentinel
378 };
379
380 #endif // WITH_PYTHON