Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[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 #include "PyObjectPlus.h" 
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46
47 /* ------------------------------------------------------------------------- */
48 /* Native functions                                                          */
49 /* ------------------------------------------------------------------------- */
50
51 KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj,
52                                                                                                    SCA_IObject *original,
53                                                                                                    int time,
54                                                                                                    SCA_IScene* scene,
55                                                                                                    const float *linvel,
56                                                                                                    bool linv_local,
57                                                                                                    const float *angvel,
58                                                                                                    bool angv_local)
59         : 
60         SCA_IActuator(gameobj, KX_ACT_ADD_OBJECT),
61         m_OriginalObject(original),
62         m_scene(scene),
63         
64         m_localLinvFlag(linv_local),
65         m_localAngvFlag(angv_local)
66 {
67         m_linear_velocity[0] = linvel[0];
68         m_linear_velocity[1] = linvel[1];
69         m_linear_velocity[2] = linvel[2];
70         m_angular_velocity[0] = angvel[0];
71         m_angular_velocity[1] = angvel[1];
72         m_angular_velocity[2] = angvel[2];
73
74         if (m_OriginalObject)
75                 m_OriginalObject->RegisterActuator(this);
76
77         m_lastCreatedObject = NULL;
78         m_timeProp = time;
79
80
81
82
83 KX_SCA_AddObjectActuator::~KX_SCA_AddObjectActuator()
84
85         if (m_OriginalObject)
86                 m_OriginalObject->UnregisterActuator(this);
87         if (m_lastCreatedObject)
88                 m_lastCreatedObject->UnregisterActuator(this);
89
90
91
92
93 bool KX_SCA_AddObjectActuator::Update()
94 {
95         //bool result = false;  /*unused*/
96         bool bNegativeEvent = IsNegativeEvent();
97         RemoveAllEvents();
98         
99         if (bNegativeEvent) return false; // do nothing on negative events
100
101         InstantAddObject();
102
103         
104         return false;
105 }
106
107
108
109
110 SCA_IObject* KX_SCA_AddObjectActuator::GetLastCreatedObject() const 
111 {
112         return m_lastCreatedObject;
113 }
114
115
116
117 CValue* KX_SCA_AddObjectActuator::GetReplica() 
118 {
119         KX_SCA_AddObjectActuator* replica = new KX_SCA_AddObjectActuator(*this);
120
121         if (replica == NULL)
122                 return NULL;
123
124         // this will copy properties and so on...
125         replica->ProcessReplica();
126
127         return replica;
128 }
129
130 void KX_SCA_AddObjectActuator::ProcessReplica()
131 {
132         if (m_OriginalObject)
133                 m_OriginalObject->RegisterActuator(this);
134         m_lastCreatedObject=NULL;
135         SCA_IActuator::ProcessReplica();
136 }
137
138 bool KX_SCA_AddObjectActuator::UnlinkObject(SCA_IObject* clientobj)
139 {
140         if (clientobj == m_OriginalObject)
141         {
142                 // this object is being deleted, we cannot continue to track it.
143                 m_OriginalObject = NULL;
144                 return true;
145         }
146         if (clientobj == m_lastCreatedObject)
147         {
148                 // this object is being deleted, we cannot continue to track it.
149                 m_lastCreatedObject = NULL;
150                 return true;
151         }
152         return false;
153 }
154
155 void KX_SCA_AddObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
156 {
157         void **h_obj = (*obj_map)[m_OriginalObject];
158         if (h_obj) {
159                 if (m_OriginalObject)
160                         m_OriginalObject->UnregisterActuator(this);
161                 m_OriginalObject = (SCA_IObject*)(*h_obj);
162                 m_OriginalObject->RegisterActuator(this);
163         }
164 }
165
166
167 /* ------------------------------------------------------------------------- */
168 /* Python functions                                                          */
169 /* ------------------------------------------------------------------------- */
170
171 /* Integration hooks ------------------------------------------------------- */
172 PyTypeObject KX_SCA_AddObjectActuator::Type = {
173         PyVarObject_HEAD_INIT(NULL, 0)
174         "KX_SCA_AddObjectActuator",
175         sizeof(PyObjectPlus_Proxy),
176         0,
177         py_base_dealloc,
178         0,
179         0,
180         0,
181         0,
182         py_base_repr,
183         0,0,0,0,0,0,0,0,0,
184         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
185         0,0,0,0,0,0,0,
186         Methods,
187         0,
188         0,
189         &SCA_IActuator::Type,
190         0,0,0,0,0,0,
191         py_base_new
192 };
193
194 PyMethodDef KX_SCA_AddObjectActuator::Methods[] = {
195   {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"},
196   {NULL,NULL} //Sentinel
197 };
198
199 PyAttributeDef KX_SCA_AddObjectActuator::Attributes[] = {
200         KX_PYATTRIBUTE_RW_FUNCTION("object",KX_SCA_AddObjectActuator,pyattr_get_object,pyattr_set_object),
201         KX_PYATTRIBUTE_RO_FUNCTION("objectLastCreated",KX_SCA_AddObjectActuator,pyattr_get_objectLastCreated),
202         KX_PYATTRIBUTE_INT_RW("time",0,2000,true,KX_SCA_AddObjectActuator,m_timeProp),
203         KX_PYATTRIBUTE_FLOAT_ARRAY_RW("linearVelocity",-FLT_MAX,FLT_MAX,KX_SCA_AddObjectActuator,m_linear_velocity,3),
204         KX_PYATTRIBUTE_FLOAT_ARRAY_RW("angularVelocity",-FLT_MAX,FLT_MAX,KX_SCA_AddObjectActuator,m_angular_velocity,3),
205         { NULL }        //Sentinel
206 };
207
208 PyObject* KX_SCA_AddObjectActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
209 {
210         KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self);
211         if (!actuator->m_OriginalObject)        
212                 Py_RETURN_NONE;
213         else
214                 return actuator->m_OriginalObject->GetProxy();
215 }
216
217 int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
218 {
219         KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self);
220         KX_GameObject *gameobj;
221                 
222         if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SCA_AddObjectActuator"))
223                 return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
224                 
225         if (actuator->m_OriginalObject != NULL)
226                 actuator->m_OriginalObject->UnregisterActuator(actuator);       
227
228         actuator->m_OriginalObject = (SCA_IObject*)gameobj;
229                 
230         if (actuator->m_OriginalObject)
231                 actuator->m_OriginalObject->RegisterActuator(actuator);
232                 
233         return PY_SET_ATTR_SUCCESS;
234 }
235
236 PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
237 {
238         KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self);
239         if (!actuator->m_lastCreatedObject)
240                 Py_RETURN_NONE;
241         else
242                 return actuator->m_lastCreatedObject->GetProxy();
243 }
244
245
246 void    KX_SCA_AddObjectActuator::InstantAddObject()
247 {
248         if (m_OriginalObject)
249         {
250                 // Add an identical object, with properties inherited from the original object  
251                 // Now it needs to be added to the current scene.
252                 SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp );
253                 KX_GameObject * game_obj = static_cast<KX_GameObject *>(replica);
254                 game_obj->setLinearVelocity(m_linear_velocity ,m_localLinvFlag);
255                 game_obj->setAngularVelocity(m_angular_velocity,m_localAngvFlag);
256                 game_obj->ResolveCombinedVelocities(m_linear_velocity, m_angular_velocity, m_localLinvFlag, m_localAngvFlag);
257
258                 // keep a copy of the last object, to allow python scripters to change it
259                 if (m_lastCreatedObject)
260                 {
261                         //Let's not keep a reference to the object: it's bad, if the object is deleted
262                         //this will force to keep a "zombie" in the game for no good reason.
263                         //m_scene->DelayedReleaseObject(m_lastCreatedObject);
264                         //m_lastCreatedObject->Release();
265
266                         //Instead we use the registration mechanism
267                         m_lastCreatedObject->UnregisterActuator(this);
268                         m_lastCreatedObject = NULL;
269                 }
270                 
271                 m_lastCreatedObject = replica;
272                 // no reference
273                 //m_lastCreatedObject->AddRef();
274                 // but registration
275                 m_lastCreatedObject->RegisterActuator(this);
276                 // finished using replica? then release it
277                 replica->Release();
278         }
279 }
280
281 PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject()
282 {
283         InstantAddObject();
284
285         Py_RETURN_NONE;
286 }