soc-2008-mxcurioni: merged changes to revision 15705
[blender.git] / source / gameengine / Ketsji / KX_SCA_AddObjectActuator.cpp
1 //
2 // Add an object when this actuator is triggered
3 //
4 // $Id$
5 //
6 // ***** BEGIN GPL LICENSE BLOCK *****
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software Foundation,
20 // Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 //
22 // The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23 // All rights reserved.
24 //
25 // The Original Code is: all of this file.
26 //
27 // Contributor(s): none yet.
28 //
29 // ***** END GPL LICENSE BLOCK *****
30 // Previously existed as:
31
32 // \source\gameengine\GameLogic\SCA_AddObjectActuator.cpp
33
34 // Please look here for revision history.
35
36
37 #include "KX_SCA_AddObjectActuator.h"
38 #include "SCA_IScene.h"
39 #include "KX_GameObject.h"
40 #include "KX_IPhysicsController.h"
41
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45
46 /* ------------------------------------------------------------------------- */
47 /* Native functions                                                          */
48 /* ------------------------------------------------------------------------- */
49
50 KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj,
51                                                                                                    SCA_IObject *original,
52                                                                                                    int time,
53                                                                                                    SCA_IScene* scene,
54                                                                                                    const MT_Vector3& linvel,
55                                                                                                    bool local,
56                                                                                                    PyTypeObject* T)
57         : 
58         SCA_IActuator(gameobj, T),
59         m_OriginalObject(original),
60         m_scene(scene),
61         m_linear_velocity(linvel),
62         m_localFlag(local)
63 {
64         if (m_OriginalObject)
65                 m_OriginalObject->RegisterActuator(this);
66
67         m_lastCreatedObject = NULL;
68         m_timeProp = time;
69
70
71
72
73 KX_SCA_AddObjectActuator::~KX_SCA_AddObjectActuator()
74
75         if (m_OriginalObject)
76                 m_OriginalObject->UnregisterActuator(this);
77         if (m_lastCreatedObject)
78                 m_lastCreatedObject->Release();
79
80
81
82
83 bool KX_SCA_AddObjectActuator::Update()
84 {
85         //bool result = false;  /*unused*/
86         bool bNegativeEvent = IsNegativeEvent();
87         RemoveAllEvents();
88         
89         if (bNegativeEvent) return false; // do nothing on negative events
90
91         InstantAddObject();
92
93         
94         return false;
95 }
96
97
98
99
100 SCA_IObject* KX_SCA_AddObjectActuator::GetLastCreatedObject() const 
101 {
102         return m_lastCreatedObject;
103 }
104
105
106
107 CValue* KX_SCA_AddObjectActuator::GetReplica() 
108 {
109         KX_SCA_AddObjectActuator* replica = new KX_SCA_AddObjectActuator(*this);
110
111         if (replica == NULL)
112                 return NULL;
113
114         // this will copy properties and so on...
115         replica->ProcessReplica();
116         CValue::AddDataToReplica(replica);
117
118         return replica;
119 }
120
121 void KX_SCA_AddObjectActuator::ProcessReplica()
122 {
123         if (m_OriginalObject)
124                 m_OriginalObject->RegisterActuator(this);
125         m_lastCreatedObject=NULL;
126         SCA_IActuator::ProcessReplica();
127 }
128
129 bool KX_SCA_AddObjectActuator::UnlinkObject(SCA_IObject* clientobj)
130 {
131         if (clientobj == m_OriginalObject)
132         {
133                 // this object is being deleted, we cannot continue to track it.
134                 m_OriginalObject = NULL;
135                 return true;
136         }
137         return false;
138 }
139
140 void KX_SCA_AddObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
141 {
142         void **h_obj = (*obj_map)[m_OriginalObject];
143         if (h_obj) {
144                 if (m_OriginalObject)
145                         m_OriginalObject->UnregisterActuator(this);
146                 m_OriginalObject = (SCA_IObject*)(*h_obj);
147                 m_OriginalObject->RegisterActuator(this);
148         }
149 }
150
151
152 /* ------------------------------------------------------------------------- */
153 /* Python functions                                                          */
154 /* ------------------------------------------------------------------------- */
155
156 /* Integration hooks ------------------------------------------------------- */
157 PyTypeObject KX_SCA_AddObjectActuator::Type = {
158         PyObject_HEAD_INIT(&PyType_Type)
159         0,
160         "KX_SCA_AddObjectActuator",
161         sizeof(KX_SCA_AddObjectActuator),
162         0,
163         PyDestructor,
164         0,
165         __getattr,
166         __setattr,
167         0, 
168         __repr,
169         0,
170         0,
171         0,
172         0,
173         0
174 };
175
176 PyParentObject KX_SCA_AddObjectActuator::Parents[] = {
177         &SCA_IActuator::Type,
178         &SCA_ILogicBrick::Type,
179         &CValue::Type,
180         NULL
181 };
182 PyMethodDef KX_SCA_AddObjectActuator::Methods[] = {
183   {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_VARARGS, SetObject_doc},
184   {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_VARARGS, SetTime_doc},
185   {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, GetObject_doc},
186   {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_VARARGS, GetTime_doc},
187   {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_VARARGS, GetLinearVelocity_doc},
188   {"setLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetLinearVelocity, METH_VARARGS, SetLinearVelocity_doc},
189   {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_VARARGS,"getLastCreatedObject() : get the object handle to the last created object\n"},
190   {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_VARARGS,"instantAddObject() : immediately add object without delay\n"},
191   
192   {NULL,NULL} //Sentinel
193 };
194
195
196 PyObject* KX_SCA_AddObjectActuator::_getattr(const STR_String& attr)
197 {
198   _getattr_up(SCA_IActuator);
199 }
200
201 /* 1. setObject */
202 char KX_SCA_AddObjectActuator::SetObject_doc[] = 
203 "setObject(name)\n"
204 "\t- name: string\n"
205 "\tSets the object that will be added. There has to be an object\n"
206 "\tof this name. If not, this function does nothing.\n";
207
208
209
210 PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self,
211                                                                                                 PyObject* args,
212                                                                                                 PyObject* kwds)
213 {    
214         PyObject* gameobj;
215         if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj))
216         {
217                 if (m_OriginalObject != NULL)
218                         m_OriginalObject->UnregisterActuator(this);
219                 m_OriginalObject = (SCA_IObject*)gameobj;
220                 if (m_OriginalObject)
221                         m_OriginalObject->RegisterActuator(this);
222                 Py_Return;
223         }
224         PyErr_Clear();
225         
226         char* objectname;
227         if (PyArg_ParseTuple(args, "s", &objectname))
228         {
229                 if (m_OriginalObject != NULL)
230                         m_OriginalObject->UnregisterActuator(this);
231                 m_OriginalObject = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));;
232                 if (m_OriginalObject)
233                         m_OriginalObject->RegisterActuator(this);
234                 Py_Return;
235         }
236         
237         return NULL;
238 }
239
240
241
242 /* 2. setTime */
243 char KX_SCA_AddObjectActuator::SetTime_doc[] = 
244 "setTime(duration)\n"
245 "\t- duration: integer\n"
246 "\tSets the lifetime of the object that will be added, in frames. \n"
247 "\tIf the duration is negative, it is set to 0.\n";
248
249
250 PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self,
251                                                                                           PyObject* args,
252                                                                                           PyObject* kwds)
253 {
254         int deltatime;
255         
256         if (!PyArg_ParseTuple(args, "i", &deltatime))
257                 return NULL;
258         
259         m_timeProp = deltatime;
260         if (m_timeProp < 0) m_timeProp = 0;
261         
262         Py_Return;
263 }
264
265
266
267 /* 3. getTime */
268 char KX_SCA_AddObjectActuator::GetTime_doc[] = 
269 "GetTime()\n"
270 "\tReturns the lifetime of the object that will be added.\n";
271
272
273 PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self,
274                                                                                           PyObject* args,
275                                                                                           PyObject* kwds)
276 {
277         return PyInt_FromLong(m_timeProp);
278 }
279
280
281 /* 4. getObject */
282 char KX_SCA_AddObjectActuator::GetObject_doc[] = 
283 "getObject()\n"
284 "\tReturns the name of the object that will be added.\n";
285
286
287         
288 PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self,
289                                                                                                 PyObject* args,
290                                                                                                 PyObject* kwds)
291 {
292         if (!m_OriginalObject)
293                 Py_Return;
294
295         return PyString_FromString(m_OriginalObject->GetName());
296 }
297
298
299
300 /* 5. getLinearVelocity */
301 char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] = 
302 "GetLinearVelocity()\n"
303 "\tReturns the linear velocity that will be assigned to \n"
304 "\tthe created object.\n";
305
306
307
308 PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self,
309                                                                                                                 PyObject* args,
310                                                                                                                 PyObject* kwds)
311 {
312         PyObject *retVal = PyList_New(3);
313
314         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
315         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
316         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
317         
318         return retVal;
319 }
320
321
322
323 /* 6. setLinearVelocity                                                 */
324 char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] = 
325 "setLinearVelocity(vx, vy, vz)\n"
326 "\t- vx: float\n"
327 "\t- vy: float\n"
328 "\t- vz: float\n"
329 "\tAssign this velocity to the created object. \n";
330
331
332 PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self,
333                                                                                                                 PyObject* args,
334                                                                                                                 PyObject* kwds)
335 {
336         
337         float vecArg[3];
338         if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2]))
339                 return NULL;
340
341         m_linear_velocity.setValue(vecArg);
342         Py_Return;
343 }
344
345 void    KX_SCA_AddObjectActuator::InstantAddObject()
346 {
347         if (m_OriginalObject)
348         {
349                 // Add an identical object, with properties inherited from the original object  
350                 // Now it needs to be added to the current scene.
351                 SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp );
352                 KX_GameObject * game_obj = static_cast<KX_GameObject *>(replica);
353                 game_obj->setLinearVelocity(m_linear_velocity,m_localFlag);
354                 game_obj->ResolveCombinedVelocities(m_linear_velocity, MT_Vector3(0., 0., 0.), m_localFlag, false);
355
356                 // keep a copy of the last object, to allow python scripters to change it
357                 if (m_lastCreatedObject)
358                 {
359                         //careful with destruction, it might still have outstanding collision callbacks
360                         m_scene->DelayedReleaseObject(m_lastCreatedObject);
361                         m_lastCreatedObject->Release();
362                 }
363                 
364                 m_lastCreatedObject = replica;
365                 m_lastCreatedObject->AddRef();
366                 // finished using replica? then release it
367                 replica->Release();
368         }
369 }
370
371 PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self,
372                                                                                                                    PyObject* args,
373                                                                                                                    PyObject* kwds)
374 {
375         InstantAddObject();
376
377         Py_Return;
378 }
379
380
381
382 /* 7. GetLastCreatedObject                                                */
383 char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] = 
384 "getLastCreatedObject()\n"
385 "\tReturn the last created object. \n";
386
387
388 PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self,
389                                                                                                                    PyObject* args,
390                                                                                                                    PyObject* kwds)
391 {
392         SCA_IObject* result = this->GetLastCreatedObject();
393         if (result)
394         {
395                 result->AddRef();
396                 return result;
397         }
398         // don't return NULL to python anymore, it gives trouble in the scripts
399         Py_Return;
400 }