Blender  V2.59
KX_SCA_AddObjectActuator.cpp
Go to the documentation of this file.
00001 
00004 //
00005 // Add an object when this actuator is triggered
00006 //
00007 // $Id: KX_SCA_AddObjectActuator.cpp 36523 2011-05-06 20:18:42Z blendix $
00008 //
00009 // ***** BEGIN GPL LICENSE BLOCK *****
00010 //
00011 // This program is free software; you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License
00013 // as published by the Free Software Foundation; either version 2
00014 // of the License, or (at your option) any later version.
00015 //
00016 // This program is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU General Public License
00022 // along with this program; if not, write to the Free Software Foundation,
00023 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00024 //
00025 // The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00026 // All rights reserved.
00027 //
00028 // The Original Code is: all of this file.
00029 //
00030 // Contributor(s): none yet.
00031 //
00032 // ***** END GPL LICENSE BLOCK *****
00033 // Previously existed as:
00034 
00035 // \source\gameengine\GameLogic\SCA_AddObjectActuator.cpp
00036 
00037 // Please look here for revision history.
00038 
00039 
00040 #include "KX_SCA_AddObjectActuator.h"
00041 #include "SCA_IScene.h"
00042 #include "KX_GameObject.h"
00043 #include "KX_IPhysicsController.h"
00044 #include "PyObjectPlus.h" 
00045 
00046 /* ------------------------------------------------------------------------- */
00047 /* Native functions                                                          */
00048 /* ------------------------------------------------------------------------- */
00049 
00050 KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj,
00051                                                                                                    SCA_IObject *original,
00052                                                                                                    int time,
00053                                                                                                    SCA_IScene* scene,
00054                                                                                                    const float *linvel,
00055                                                                                                    bool linv_local,
00056                                                                                                    const float *angvel,
00057                                                                                                    bool angv_local)
00058         : 
00059         SCA_IActuator(gameobj, KX_ACT_ADD_OBJECT),
00060         m_OriginalObject(original),
00061         m_scene(scene),
00062         
00063         m_localLinvFlag(linv_local),
00064         m_localAngvFlag(angv_local)
00065 {
00066         m_linear_velocity[0] = linvel[0];
00067         m_linear_velocity[1] = linvel[1];
00068         m_linear_velocity[2] = linvel[2];
00069         m_angular_velocity[0] = angvel[0];
00070         m_angular_velocity[1] = angvel[1];
00071         m_angular_velocity[2] = angvel[2];
00072 
00073         if (m_OriginalObject)
00074                 m_OriginalObject->RegisterActuator(this);
00075 
00076         m_lastCreatedObject = NULL;
00077         m_timeProp = time;
00078 } 
00079 
00080 
00081 
00082 KX_SCA_AddObjectActuator::~KX_SCA_AddObjectActuator()
00083 { 
00084         if (m_OriginalObject)
00085                 m_OriginalObject->UnregisterActuator(this);
00086         if (m_lastCreatedObject)
00087                 m_lastCreatedObject->UnregisterActuator(this);
00088 } 
00089 
00090 
00091 
00092 bool KX_SCA_AddObjectActuator::Update()
00093 {
00094         //bool result = false;  /*unused*/
00095         bool bNegativeEvent = IsNegativeEvent();
00096         RemoveAllEvents();
00097         
00098         if (bNegativeEvent) return false; // do nothing on negative events
00099 
00100         InstantAddObject();
00101 
00102         
00103         return false;
00104 }
00105 
00106 
00107 
00108 
00109 SCA_IObject* KX_SCA_AddObjectActuator::GetLastCreatedObject() const 
00110 {
00111         return m_lastCreatedObject;
00112 }
00113 
00114 
00115 
00116 CValue* KX_SCA_AddObjectActuator::GetReplica() 
00117 {
00118         KX_SCA_AddObjectActuator* replica = new KX_SCA_AddObjectActuator(*this);
00119 
00120         if (replica == NULL)
00121                 return NULL;
00122 
00123         // this will copy properties and so on...
00124         replica->ProcessReplica();
00125 
00126         return replica;
00127 }
00128 
00129 void KX_SCA_AddObjectActuator::ProcessReplica()
00130 {
00131         if (m_OriginalObject)
00132                 m_OriginalObject->RegisterActuator(this);
00133         m_lastCreatedObject=NULL;
00134         SCA_IActuator::ProcessReplica();
00135 }
00136 
00137 bool KX_SCA_AddObjectActuator::UnlinkObject(SCA_IObject* clientobj)
00138 {
00139         if (clientobj == m_OriginalObject)
00140         {
00141                 // this object is being deleted, we cannot continue to track it.
00142                 m_OriginalObject = NULL;
00143                 return true;
00144         }
00145         if (clientobj == m_lastCreatedObject)
00146         {
00147                 // this object is being deleted, we cannot continue to track it.
00148                 m_lastCreatedObject = NULL;
00149                 return true;
00150         }
00151         return false;
00152 }
00153 
00154 void KX_SCA_AddObjectActuator::Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map)
00155 {
00156         void **h_obj = (*obj_map)[m_OriginalObject];
00157         if (h_obj) {
00158                 if (m_OriginalObject)
00159                         m_OriginalObject->UnregisterActuator(this);
00160                 m_OriginalObject = (SCA_IObject*)(*h_obj);
00161                 m_OriginalObject->RegisterActuator(this);
00162         }
00163 }
00164 
00165 #ifdef WITH_PYTHON
00166 
00167 /* ------------------------------------------------------------------------- */
00168 /* Python functions                                                          */
00169 /* ------------------------------------------------------------------------- */
00170 
00171 /* Integration hooks ------------------------------------------------------- */
00172 PyTypeObject KX_SCA_AddObjectActuator::Type = {
00173         PyVarObject_HEAD_INIT(NULL, 0)
00174         "KX_SCA_AddObjectActuator",
00175         sizeof(PyObjectPlus_Proxy),
00176         0,
00177         py_base_dealloc,
00178         0,
00179         0,
00180         0,
00181         0,
00182         py_base_repr,
00183         0,0,0,0,0,0,0,0,0,
00184         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
00185         0,0,0,0,0,0,0,
00186         Methods,
00187         0,
00188         0,
00189         &SCA_IActuator::Type,
00190         0,0,0,0,0,0,
00191         py_base_new
00192 };
00193 
00194 PyMethodDef KX_SCA_AddObjectActuator::Methods[] = {
00195   {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"},
00196   {NULL,NULL} //Sentinel
00197 };
00198 
00199 PyAttributeDef KX_SCA_AddObjectActuator::Attributes[] = {
00200         KX_PYATTRIBUTE_RW_FUNCTION("object",KX_SCA_AddObjectActuator,pyattr_get_object,pyattr_set_object),
00201         KX_PYATTRIBUTE_RO_FUNCTION("objectLastCreated",KX_SCA_AddObjectActuator,pyattr_get_objectLastCreated),
00202         KX_PYATTRIBUTE_INT_RW("time",0,2000,true,KX_SCA_AddObjectActuator,m_timeProp),
00203         KX_PYATTRIBUTE_FLOAT_ARRAY_RW("linearVelocity",-FLT_MAX,FLT_MAX,KX_SCA_AddObjectActuator,m_linear_velocity,3),
00204         KX_PYATTRIBUTE_FLOAT_ARRAY_RW("angularVelocity",-FLT_MAX,FLT_MAX,KX_SCA_AddObjectActuator,m_angular_velocity,3),
00205         { NULL }        //Sentinel
00206 };
00207 
00208 PyObject* KX_SCA_AddObjectActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
00209 {
00210         KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self);
00211         if (!actuator->m_OriginalObject)        
00212                 Py_RETURN_NONE;
00213         else
00214                 return actuator->m_OriginalObject->GetProxy();
00215 }
00216 
00217 int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00218 {
00219         KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self);
00220         KX_GameObject *gameobj;
00221                 
00222         if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SCA_AddObjectActuator"))
00223                 return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
00224                 
00225         if (actuator->m_OriginalObject != NULL)
00226                 actuator->m_OriginalObject->UnregisterActuator(actuator);       
00227 
00228         actuator->m_OriginalObject = (SCA_IObject*)gameobj;
00229                 
00230         if (actuator->m_OriginalObject)
00231                 actuator->m_OriginalObject->RegisterActuator(actuator);
00232                 
00233         return PY_SET_ATTR_SUCCESS;
00234 }
00235 
00236 PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
00237 {
00238         KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self);
00239         if (!actuator->m_lastCreatedObject)
00240                 Py_RETURN_NONE;
00241         else
00242                 return actuator->m_lastCreatedObject->GetProxy();
00243 }
00244 
00245 PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject()
00246 {
00247         InstantAddObject();
00248 
00249         Py_RETURN_NONE;
00250 }
00251 
00252 #endif // WITH_PYTHON
00253 
00254 void    KX_SCA_AddObjectActuator::InstantAddObject()
00255 {
00256         if (m_OriginalObject)
00257         {
00258                 // Add an identical object, with properties inherited from the original object  
00259                 // Now it needs to be added to the current scene.
00260                 SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp );
00261                 KX_GameObject * game_obj = static_cast<KX_GameObject *>(replica);
00262                 game_obj->setLinearVelocity(m_linear_velocity ,m_localLinvFlag);
00263                 game_obj->setAngularVelocity(m_angular_velocity,m_localAngvFlag);
00264                 game_obj->ResolveCombinedVelocities(m_linear_velocity, m_angular_velocity, m_localLinvFlag, m_localAngvFlag);
00265 
00266                 // keep a copy of the last object, to allow python scripters to change it
00267                 if (m_lastCreatedObject)
00268                 {
00269                         //Let's not keep a reference to the object: it's bad, if the object is deleted
00270                         //this will force to keep a "zombie" in the game for no good reason.
00271                         //m_scene->DelayedReleaseObject(m_lastCreatedObject);
00272                         //m_lastCreatedObject->Release();
00273 
00274                         //Instead we use the registration mechanism
00275                         m_lastCreatedObject->UnregisterActuator(this);
00276                         m_lastCreatedObject = NULL;
00277                 }
00278                 
00279                 m_lastCreatedObject = replica;
00280                 // no reference
00281                 //m_lastCreatedObject->AddRef();
00282                 // but registration
00283                 m_lastCreatedObject->RegisterActuator(this);
00284                 // finished using replica? then release it
00285                 replica->Release();
00286         }
00287 }