BGE bug fix (good for 2.47): automatic detection that target object of AddObject...
[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
141 /* ------------------------------------------------------------------------- */
142 /* Python functions                                                          */
143 /* ------------------------------------------------------------------------- */
144
145 /* Integration hooks ------------------------------------------------------- */
146 PyTypeObject KX_SCA_AddObjectActuator::Type = {
147         PyObject_HEAD_INIT(&PyType_Type)
148         0,
149         "KX_SCA_AddObjectActuator",
150         sizeof(KX_SCA_AddObjectActuator),
151         0,
152         PyDestructor,
153         0,
154         __getattr,
155         __setattr,
156         0, 
157         __repr,
158         0,
159         0,
160         0,
161         0,
162         0
163 };
164
165 PyParentObject KX_SCA_AddObjectActuator::Parents[] = {
166         &SCA_IActuator::Type,
167         &SCA_ILogicBrick::Type,
168         &CValue::Type,
169         NULL
170 };
171 PyMethodDef KX_SCA_AddObjectActuator::Methods[] = {
172   {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_VARARGS, SetObject_doc},
173   {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_VARARGS, SetTime_doc},
174   {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, GetObject_doc},
175   {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_VARARGS, GetTime_doc},
176   {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_VARARGS, GetLinearVelocity_doc},
177   {"setLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetLinearVelocity, METH_VARARGS, SetLinearVelocity_doc},
178   {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_VARARGS,"getLastCreatedObject() : get the object handle to the last created object\n"},
179   {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_VARARGS,"instantAddObject() : immediately add object without delay\n"},
180   
181   {NULL,NULL} //Sentinel
182 };
183
184
185 PyObject* KX_SCA_AddObjectActuator::_getattr(const STR_String& attr)
186 {
187   _getattr_up(SCA_IActuator);
188 }
189
190 /* 1. setObject */
191 char KX_SCA_AddObjectActuator::SetObject_doc[] = 
192 "setObject(name)\n"
193 "\t- name: string\n"
194 "\tSets the object that will be added. There has to be an object\n"
195 "\tof this name. If not, this function does nothing.\n";
196
197
198
199 PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self,
200                                                                                                 PyObject* args,
201                                                                                                 PyObject* kwds)
202 {    
203         PyObject* gameobj;
204         if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj))
205         {
206                 if (m_OriginalObject != NULL)
207                         m_OriginalObject->UnregisterActuator(this);
208                 m_OriginalObject = (SCA_IObject*)gameobj;
209                 if (m_OriginalObject)
210                         m_OriginalObject->RegisterActuator(this);
211                 Py_Return;
212         }
213         PyErr_Clear();
214         
215         char* objectname;
216         if (PyArg_ParseTuple(args, "s", &objectname))
217         {
218                 if (m_OriginalObject != NULL)
219                         m_OriginalObject->UnregisterActuator(this);
220                 m_OriginalObject = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));;
221                 if (m_OriginalObject)
222                         m_OriginalObject->RegisterActuator(this);
223                 Py_Return;
224         }
225         
226         return NULL;
227 }
228
229
230
231 /* 2. setTime */
232 char KX_SCA_AddObjectActuator::SetTime_doc[] = 
233 "setTime(duration)\n"
234 "\t- duration: integer\n"
235 "\tSets the lifetime of the object that will be added, in frames. \n"
236 "\tIf the duration is negative, it is set to 0.\n";
237
238
239 PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self,
240                                                                                           PyObject* args,
241                                                                                           PyObject* kwds)
242 {
243         int deltatime;
244         
245         if (!PyArg_ParseTuple(args, "i", &deltatime))
246                 return NULL;
247         
248         m_timeProp = deltatime;
249         if (m_timeProp < 0) m_timeProp = 0;
250         
251         Py_Return;
252 }
253
254
255
256 /* 3. getTime */
257 char KX_SCA_AddObjectActuator::GetTime_doc[] = 
258 "GetTime()\n"
259 "\tReturns the lifetime of the object that will be added.\n";
260
261
262 PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self,
263                                                                                           PyObject* args,
264                                                                                           PyObject* kwds)
265 {
266         return PyInt_FromLong(m_timeProp);
267 }
268
269
270 /* 4. getObject */
271 char KX_SCA_AddObjectActuator::GetObject_doc[] = 
272 "getObject()\n"
273 "\tReturns the name of the object that will be added.\n";
274
275
276         
277 PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self,
278                                                                                                 PyObject* args,
279                                                                                                 PyObject* kwds)
280 {
281         if (!m_OriginalObject)
282                 Py_Return;
283
284         return PyString_FromString(m_OriginalObject->GetName());
285 }
286
287
288
289 /* 5. getLinearVelocity */
290 char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] = 
291 "GetLinearVelocity()\n"
292 "\tReturns the linear velocity that will be assigned to \n"
293 "\tthe created object.\n";
294
295
296
297 PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self,
298                                                                                                                 PyObject* args,
299                                                                                                                 PyObject* kwds)
300 {
301         PyObject *retVal = PyList_New(3);
302
303         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
304         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
305         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
306         
307         return retVal;
308 }
309
310
311
312 /* 6. setLinearVelocity                                                 */
313 char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] = 
314 "setLinearVelocity(vx, vy, vz)\n"
315 "\t- vx: float\n"
316 "\t- vy: float\n"
317 "\t- vz: float\n"
318 "\tAssign this velocity to the created object. \n";
319
320
321 PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self,
322                                                                                                                 PyObject* args,
323                                                                                                                 PyObject* kwds)
324 {
325         
326         float vecArg[3];
327         if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2]))
328                 return NULL;
329
330         m_linear_velocity.setValue(vecArg);
331         Py_Return;
332 }
333
334 void    KX_SCA_AddObjectActuator::InstantAddObject()
335 {
336         if (m_OriginalObject)
337         {
338                 // Add an identical object, with properties inherited from the original object  
339                 // Now it needs to be added to the current scene.
340                 SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp );
341                 KX_GameObject * game_obj = static_cast<KX_GameObject *>(replica);
342                 game_obj->setLinearVelocity(m_linear_velocity,m_localFlag);
343                 game_obj->ResolveCombinedVelocities(m_linear_velocity, MT_Vector3(0., 0., 0.), m_localFlag, false);
344
345                 // keep a copy of the last object, to allow python scripters to change it
346                 if (m_lastCreatedObject)
347                 {
348                         //careful with destruction, it might still have outstanding collision callbacks
349                         m_scene->DelayedReleaseObject(m_lastCreatedObject);
350                         m_lastCreatedObject->Release();
351                 }
352                 
353                 m_lastCreatedObject = replica;
354                 m_lastCreatedObject->AddRef();
355                 // finished using replica? then release it
356                 replica->Release();
357         }
358 }
359
360 PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self,
361                                                                                                                    PyObject* args,
362                                                                                                                    PyObject* kwds)
363 {
364         InstantAddObject();
365
366         Py_Return;
367 }
368
369
370
371 /* 7. GetLastCreatedObject                                                */
372 char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] = 
373 "getLastCreatedObject()\n"
374 "\tReturn the last created object. \n";
375
376
377 PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self,
378                                                                                                                    PyObject* args,
379                                                                                                                    PyObject* kwds)
380 {
381         SCA_IObject* result = this->GetLastCreatedObject();
382         if (result)
383         {
384                 result->AddRef();
385                 return result;
386         }
387         // don't return NULL to python anymore, it gives trouble in the scripts
388         Py_Return;
389 }