Blender V2.61 - r43446

KX_SCA_AddObjectActuator.cpp

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