BGE: allow sound actuators to be converted even when they have invalid samples
[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_O, 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(object)\n"
204 "\t- object: KX_GameObject, string or None\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 PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self, PyObject* value)
208 {
209         KX_GameObject *gameobj;
210         
211         if (!ConvertPythonToGameObject(value, &gameobj, true))
212                 return NULL; // ConvertPythonToGameObject sets the error
213         
214         if (m_OriginalObject != NULL)
215                 m_OriginalObject->UnregisterActuator(this);     
216
217         m_OriginalObject = (SCA_IObject*)gameobj;
218         if (m_OriginalObject)
219                 m_OriginalObject->RegisterActuator(this);
220         
221         Py_RETURN_NONE;
222 }
223
224
225
226 /* 2. setTime */
227 char KX_SCA_AddObjectActuator::SetTime_doc[] = 
228 "setTime(duration)\n"
229 "\t- duration: integer\n"
230 "\tSets the lifetime of the object that will be added, in frames. \n"
231 "\tIf the duration is negative, it is set to 0.\n";
232
233
234 PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self,
235                                                                                           PyObject* args,
236                                                                                           PyObject* kwds)
237 {
238         int deltatime;
239         
240         if (!PyArg_ParseTuple(args, "i", &deltatime))
241                 return NULL;
242         
243         m_timeProp = deltatime;
244         if (m_timeProp < 0) m_timeProp = 0;
245         
246         Py_Return;
247 }
248
249
250
251 /* 3. getTime */
252 char KX_SCA_AddObjectActuator::GetTime_doc[] = 
253 "GetTime()\n"
254 "\tReturns the lifetime of the object that will be added.\n";
255
256
257 PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self,
258                                                                                           PyObject* args,
259                                                                                           PyObject* kwds)
260 {
261         return PyInt_FromLong(m_timeProp);
262 }
263
264
265 /* 4. getObject */
266 char KX_SCA_AddObjectActuator::GetObject_doc[] = 
267 "getObject(name_only = 1)\n"
268 "name_only - optional arg, when true will return the KX_GameObject rather then its name\n"
269 "\tReturns the name of the object that will be added.\n";
270 PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self, PyObject* args)
271 {
272         int ret_name_only = 1;
273         if (!PyArg_ParseTuple(args, "|i", &ret_name_only))
274                 return NULL;
275         
276         if (!m_OriginalObject)
277                 Py_RETURN_NONE;
278         
279         if (ret_name_only)
280                 return PyString_FromString(m_OriginalObject->GetName());
281         else
282                 return m_OriginalObject->AddRef();
283 }
284
285
286
287 /* 5. getLinearVelocity */
288 char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] = 
289 "GetLinearVelocity()\n"
290 "\tReturns the linear velocity that will be assigned to \n"
291 "\tthe created object.\n";
292
293
294
295 PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self,
296                                                                                                                 PyObject* args,
297                                                                                                                 PyObject* kwds)
298 {
299         PyObject *retVal = PyList_New(3);
300
301         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
302         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
303         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
304         
305         return retVal;
306 }
307
308
309
310 /* 6. setLinearVelocity                                                 */
311 char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] = 
312 "setLinearVelocity(vx, vy, vz)\n"
313 "\t- vx: float\n"
314 "\t- vy: float\n"
315 "\t- vz: float\n"
316 "\tAssign this velocity to the created object. \n";
317
318
319 PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self,
320                                                                                                                 PyObject* args,
321                                                                                                                 PyObject* kwds)
322 {
323         
324         float vecArg[3];
325         if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2]))
326                 return NULL;
327
328         m_linear_velocity.setValue(vecArg);
329         Py_Return;
330 }
331
332 void    KX_SCA_AddObjectActuator::InstantAddObject()
333 {
334         if (m_OriginalObject)
335         {
336                 // Add an identical object, with properties inherited from the original object  
337                 // Now it needs to be added to the current scene.
338                 SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp );
339                 KX_GameObject * game_obj = static_cast<KX_GameObject *>(replica);
340                 game_obj->setLinearVelocity(m_linear_velocity,m_localFlag);
341                 game_obj->ResolveCombinedVelocities(m_linear_velocity, MT_Vector3(0., 0., 0.), m_localFlag, false);
342
343                 // keep a copy of the last object, to allow python scripters to change it
344                 if (m_lastCreatedObject)
345                 {
346                         //careful with destruction, it might still have outstanding collision callbacks
347                         m_scene->DelayedReleaseObject(m_lastCreatedObject);
348                         m_lastCreatedObject->Release();
349                 }
350                 
351                 m_lastCreatedObject = replica;
352                 m_lastCreatedObject->AddRef();
353                 // finished using replica? then release it
354                 replica->Release();
355         }
356 }
357
358 PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self,
359                                                                                                                    PyObject* args,
360                                                                                                                    PyObject* kwds)
361 {
362         InstantAddObject();
363
364         Py_Return;
365 }
366
367
368
369 /* 7. GetLastCreatedObject                                                */
370 char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] = 
371 "getLastCreatedObject()\n"
372 "\tReturn the last created object. \n";
373
374
375 PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self,
376                                                                                                                    PyObject* args,
377                                                                                                                    PyObject* kwds)
378 {
379         SCA_IObject* result = this->GetLastCreatedObject();
380         
381         // if result->GetSGNode() is NULL
382         // it means the object has ended, The BGE python api crashes in many places if the object is returned.
383         if (result && (static_cast<KX_GameObject *>(result))->GetSGNode()) 
384         {
385                 result->AddRef();
386                 return result;
387         }
388         // don't return NULL to python anymore, it gives trouble in the scripts
389         Py_Return;
390 }