Blender V2.61 - r43446
|
00001 /* 00002 * Sense if other objects are near 00003 * 00004 * 00005 * ***** BEGIN GPL LICENSE BLOCK ***** 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU General Public License 00009 * as published by the Free Software Foundation; either version 2 00010 * of the License, or (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software Foundation, 00019 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 * 00021 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00022 * All rights reserved. 00023 * 00024 * The Original Code is: all of this file. 00025 * 00026 * Contributor(s): none yet. 00027 * 00028 * ***** END GPL LICENSE BLOCK ***** 00029 */ 00030 00036 #include "KX_NearSensor.h" 00037 #include "SCA_LogicManager.h" 00038 #include "KX_GameObject.h" 00039 #include "KX_TouchEventManager.h" 00040 #include "KX_Scene.h" // needed to create a replica 00041 #include "PHY_IPhysicsEnvironment.h" 00042 #include "PHY_IPhysicsController.h" 00043 #include "PHY_IMotionState.h" 00044 00045 KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr, 00046 KX_GameObject* gameobj, 00047 float margin, 00048 float resetmargin, 00049 bool bFindMaterial, 00050 const STR_String& touchedpropname, 00051 PHY_IPhysicsController* ctrl) 00052 :KX_TouchSensor(eventmgr, 00053 gameobj, 00054 bFindMaterial, 00055 false, 00056 touchedpropname), 00057 m_Margin(margin), 00058 m_ResetMargin(resetmargin) 00059 00060 { 00061 00062 gameobj->getClientInfo()->m_sensors.remove(this); 00063 m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::SENSOR); 00064 m_client_info->m_sensors.push_back(this); 00065 00066 //DT_ShapeHandle shape = (DT_ShapeHandle) vshape; 00067 m_physCtrl = ctrl; 00068 if (m_physCtrl) 00069 { 00070 m_physCtrl->SetMargin(m_Margin); 00071 m_physCtrl->setNewClientInfo(m_client_info); 00072 } 00073 SynchronizeTransform(); 00074 } 00075 00076 void KX_NearSensor::SynchronizeTransform() 00077 { 00078 // The near and radar sensors are using a different physical object which is 00079 // not linked to the parent object, must synchronize it. 00080 if (m_physCtrl) 00081 { 00082 PHY_IMotionState* motionState = m_physCtrl->GetMotionState(); 00083 KX_GameObject* parent = ((KX_GameObject*)GetParent()); 00084 const MT_Point3& pos = parent->NodeGetWorldPosition(); 00085 float ori[12]; 00086 parent->NodeGetWorldOrientation().getValue(ori); 00087 motionState->setWorldPosition(pos[0], pos[1], pos[2]); 00088 motionState->setWorldOrientation(ori); 00089 m_physCtrl->WriteMotionStateToDynamics(true); 00090 } 00091 } 00092 00093 CValue* KX_NearSensor::GetReplica() 00094 { 00095 KX_NearSensor* replica = new KX_NearSensor(*this); 00096 replica->ProcessReplica(); 00097 return replica; 00098 } 00099 00100 void KX_NearSensor::ProcessReplica() 00101 { 00102 KX_TouchSensor::ProcessReplica(); 00103 00104 m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::SENSOR); 00105 00106 if (m_physCtrl) 00107 { 00108 m_physCtrl = m_physCtrl->GetReplica(); 00109 if (m_physCtrl) 00110 { 00111 //static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->addSensor(replica->m_physCtrl); 00112 m_physCtrl->SetMargin(m_Margin); 00113 m_physCtrl->setNewClientInfo(m_client_info); 00114 } 00115 00116 } 00117 } 00118 00119 void KX_NearSensor::ReParent(SCA_IObject* parent) 00120 { 00121 SCA_ISensor::ReParent(parent); 00122 m_client_info->m_gameobject = static_cast<KX_GameObject*>(parent); 00123 m_client_info->m_sensors.push_back(this); 00124 //Synchronize here with the actual parent. 00125 SynchronizeTransform(); 00126 } 00127 00128 00129 00130 KX_NearSensor::~KX_NearSensor() 00131 { 00132 // for nearsensor, the sensor is the 'owner' of sumoobj 00133 // for touchsensor, it's the parent 00134 if (m_physCtrl) 00135 { 00136 //static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->removeSensor(m_physCtrl); 00137 delete m_physCtrl; 00138 m_physCtrl = NULL; 00139 } 00140 00141 00142 if (m_client_info) 00143 delete m_client_info; 00144 } 00145 00146 void KX_NearSensor::SetPhysCtrlRadius() 00147 { 00148 if (m_bTriggered) 00149 { 00150 if (m_physCtrl) 00151 { 00152 m_physCtrl->SetRadius(m_ResetMargin); 00153 } 00154 } else 00155 { 00156 if (m_physCtrl) 00157 { 00158 m_physCtrl->SetRadius(m_Margin); 00159 } 00160 } 00161 } 00162 00163 bool KX_NearSensor::Evaluate() 00164 { 00165 bool result = false; 00166 // KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent()); 00167 00168 if (m_bTriggered != m_bLastTriggered) 00169 { 00170 m_bLastTriggered = m_bTriggered; 00171 00172 SetPhysCtrlRadius(); 00173 00174 result = true; 00175 } 00176 00177 return result; 00178 } 00179 00180 // this function is called at broad phase stage to check if the two controller 00181 // need to interact at all. It is used for Near/Radar sensor that don't need to 00182 // check collision with object not included in filter 00183 bool KX_NearSensor::BroadPhaseFilterCollision(void*obj1,void*obj2) 00184 { 00185 KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent()); 00186 00187 // need the mapping from PHY_IPhysicsController to gameobjects now 00188 assert(obj1==m_physCtrl && obj2); 00189 KX_ClientObjectInfo* client_info = static_cast<KX_ClientObjectInfo*>((static_cast<PHY_IPhysicsController*>(obj2))->getNewClientInfo()); 00190 00191 KX_GameObject* gameobj = ( client_info ? 00192 client_info->m_gameobject : 00193 NULL); 00194 00195 if (gameobj && (gameobj != parent)) 00196 { 00197 // only take valid colliders 00198 if (client_info->m_type == KX_ClientObjectInfo::ACTOR) 00199 { 00200 if ((m_touchedpropname.Length() == 0) || 00201 (gameobj->GetProperty(m_touchedpropname))) 00202 { 00203 return true; 00204 } 00205 } 00206 } 00207 00208 return false; 00209 } 00210 00211 bool KX_NearSensor::NewHandleCollision(void* obj1,void* obj2,const PHY_CollData * coll_data) 00212 { 00213 // KX_TouchEventManager* toucheventmgr = static_cast<KX_TouchEventManager*>(m_eventmgr); 00214 // KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent()); 00215 00216 // need the mapping from PHY_IPhysicsController to gameobjects now 00217 00218 KX_ClientObjectInfo* client_info =static_cast<KX_ClientObjectInfo*> (obj1 == m_physCtrl? 00219 ((PHY_IPhysicsController*)obj2)->getNewClientInfo() : 00220 ((PHY_IPhysicsController*)obj1)->getNewClientInfo()); 00221 00222 KX_GameObject* gameobj = ( client_info ? 00223 client_info->m_gameobject : 00224 NULL); 00225 00226 // Add the same check as in SCA_ISensor::Activate(), 00227 // we don't want to record collision when the sensor is not active. 00228 if (m_links && !m_suspended && 00229 gameobj /* done in BroadPhaseFilterCollision() && (gameobj != parent)*/) 00230 { 00231 if (!m_colliders->SearchValue(gameobj)) 00232 m_colliders->Add(gameobj->AddRef()); 00233 // only take valid colliders 00234 // These checks are done already in BroadPhaseFilterCollision() 00235 //if (client_info->m_type == KX_ClientObjectInfo::ACTOR) 00236 //{ 00237 // if ((m_touchedpropname.Length() == 0) || 00238 // (gameobj->GetProperty(m_touchedpropname))) 00239 // { 00240 m_bTriggered = true; 00241 m_hitObject = gameobj; 00242 // } 00243 //} 00244 } 00245 00246 return false; // was DT_CONTINUE; but this was defined in Sumo as false 00247 } 00248 00249 #ifdef WITH_PYTHON 00250 00251 /* ------------------------------------------------------------------------- */ 00252 /* Python Functions */ 00253 /* ------------------------------------------------------------------------- */ 00254 00255 /* ------------------------------------------------------------------------- */ 00256 /* Python Integration Hooks */ 00257 /* ------------------------------------------------------------------------- */ 00258 00259 PyTypeObject KX_NearSensor::Type = { 00260 PyVarObject_HEAD_INIT(NULL, 0) 00261 "KX_NearSensor", 00262 sizeof(PyObjectPlus_Proxy), 00263 0, 00264 py_base_dealloc, 00265 0, 00266 0, 00267 0, 00268 0, 00269 py_base_repr, 00270 0,0,0,0,0,0,0,0,0, 00271 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 00272 0,0,0,0,0,0,0, 00273 Methods, 00274 0, 00275 0, 00276 &KX_TouchSensor::Type, 00277 0,0,0,0,0,0, 00278 py_base_new 00279 }; 00280 00281 PyMethodDef KX_NearSensor::Methods[] = { 00282 //No methods 00283 {NULL,NULL} //Sentinel 00284 }; 00285 00286 PyAttributeDef KX_NearSensor::Attributes[] = { 00287 KX_PYATTRIBUTE_FLOAT_RW_CHECK("distance", 0, 100, KX_NearSensor, m_Margin, CheckResetDistance), 00288 KX_PYATTRIBUTE_FLOAT_RW_CHECK("resetDistance", 0, 100, KX_NearSensor, m_ResetMargin, CheckResetDistance), 00289 {NULL} //Sentinel 00290 }; 00291 00292 #endif // WITH_PYTHON