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