Speed up the physics engine: hook the SOLID broad phase, so we can either reject...
[blender-staging.git] / source / gameengine / Ketsji / KX_NearSensor.cpp
1 /**
2  * Sense if other objects are near
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL/BL DUAL 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. The Blender
12  * Foundation also sells licenses for use in proprietary software under
13  * the Blender License.  See http://www.blender.org/BL/ for information
14  * about this.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): none yet.
31  *
32  * ***** END GPL/BL DUAL LICENSE BLOCK *****
33  */
34
35 #include "KX_NearSensor.h"
36 #include "SCA_LogicManager.h"
37 #include "KX_GameObject.h"
38 #include "KX_TouchEventManager.h"
39 #include "KX_Scene.h" // needed to create a replica
40
41 #include "SM_Object.h"
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46 KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr,
47                                                          KX_GameObject* gameobj,
48                                                          void *vshape,
49                                                          double margin,
50                                                          double resetmargin,
51                                                          bool bFindMaterial,
52                                                          const STR_String& touchedpropname,
53                                                          class KX_Scene* scene,
54                                                          PyTypeObject* T)
55                          :KX_TouchSensor(eventmgr,
56                                                          gameobj,
57                                                          bFindMaterial,
58                                                          touchedpropname,
59                                                          /* scene, */
60                                                          T),
61                          m_Margin(margin),
62                          m_ResetMargin(resetmargin)
63
64 {
65         gameobj->getClientInfo()->m_sensors.remove(this);
66         m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::NEAR);
67         m_client_info->m_sensors.push_back(this);
68         
69         DT_ShapeHandle shape = (DT_ShapeHandle) vshape;
70         m_sumoObj = new SM_Object(shape,NULL,NULL,NULL);
71         m_sumoObj->setMargin(m_Margin);
72         m_sumoObj->setClientObject(m_client_info);
73         
74         SynchronizeTransform();
75 }
76
77 KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr,
78                                                          KX_GameObject* gameobj,
79                                                          double margin,
80                                                          double resetmargin,
81                                                          bool bFindMaterial,
82                                                          const STR_String& touchedpropname,
83                                                          class KX_Scene* scene,
84                                                          PyTypeObject* T)
85                          :KX_TouchSensor(eventmgr,
86                                                          gameobj,
87                                                          bFindMaterial,
88                                                          touchedpropname,
89                                                          /* scene, */
90                                                          T),
91                          m_Margin(margin),
92                          m_ResetMargin(resetmargin)
93
94 {
95         gameobj->getClientInfo()->m_sensors.remove(this);
96         m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::NEAR);
97         m_client_info->m_sensors.push_back(this);
98         
99         m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL);
100         m_sumoObj->setMargin(m_Margin);
101         m_sumoObj->setClientObject(m_client_info);
102         
103         SynchronizeTransform();
104 }
105
106 void KX_NearSensor::RegisterSumo(KX_TouchEventManager *touchman)
107 {
108         touchman->GetSumoScene()->addSensor(*m_sumoObj);
109 }
110
111 CValue* KX_NearSensor::GetReplica()
112 {
113         KX_NearSensor* replica = new KX_NearSensor(*this);
114         replica->m_colliders = new CListValue();
115         replica->m_bCollision = false;
116         replica->m_bTriggered= false;
117         replica->m_hitObject = NULL;
118         replica->m_bLastTriggered = false;
119         // this will copy properties and so on...
120         CValue::AddDataToReplica(replica);
121         
122         replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::NEAR);
123         
124         replica->m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL);
125         replica->m_sumoObj->setMargin(m_Margin);
126         replica->m_sumoObj->setClientObject(replica->m_client_info);
127         
128         replica->SynchronizeTransform();
129         
130         return replica;
131 }
132
133
134
135 void KX_NearSensor::ReParent(SCA_IObject* parent)
136 {
137         SCA_ISensor::ReParent(parent);
138         
139         m_client_info->m_gameobject = static_cast<KX_GameObject*>(parent); 
140         m_client_info->m_sensors.push_back(this);
141         
142         SynchronizeTransform();
143 }
144
145
146
147 KX_NearSensor::~KX_NearSensor()
148 {
149         // for nearsensor, the sensor is the 'owner' of sumoobj
150         // for touchsensor, it's the parent
151         if (m_sumoObj)
152         {
153                 static_cast<KX_TouchEventManager*>(m_eventmgr)->GetSumoScene()->remove(*m_sumoObj);
154                 delete m_sumoObj;
155                 m_sumoObj = NULL;
156         }
157                 
158         if (m_client_info)
159                 delete m_client_info;
160 }
161
162
163 bool KX_NearSensor::Evaluate(CValue* event)
164 {
165         bool result = false;
166         KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
167
168         if (m_bTriggered != m_bLastTriggered)
169         {
170                 m_bLastTriggered = m_bTriggered;
171                 if (m_bTriggered)
172                 {
173                         if (m_sumoObj)
174                         {
175                                 m_sumoObj->setMargin(m_ResetMargin);
176                         }
177                 } else
178                 {
179                         if (m_sumoObj)
180                         {
181                                 m_sumoObj->setMargin(m_Margin);
182                         }
183
184                 }
185                 result = true;
186         }
187
188         return result;
189 }
190
191
192
193 DT_Bool KX_NearSensor::HandleCollision(void* obj1,void* obj2,const DT_CollData * coll_data)
194 {
195         KX_TouchEventManager* toucheventmgr = static_cast<KX_TouchEventManager*>(m_eventmgr);
196         KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
197         
198         // need the mapping from SM_Objects to gameobjects now
199         
200         KX_ClientObjectInfo* client_info =static_cast<KX_ClientObjectInfo*> (obj1 == m_sumoObj? 
201                                         ((SM_Object*)obj2)->getClientObject() : 
202                                         ((SM_Object*)obj1)->getClientObject());
203
204         KX_GameObject* gameobj = ( client_info ? 
205                         client_info->m_gameobject :
206                         NULL);
207         
208         if (gameobj && (gameobj != parent))
209         {
210                 if (!m_colliders->SearchValue(gameobj))
211                         m_colliders->Add(gameobj->AddRef());
212                 // only take valid colliders
213                 if (client_info->m_type == KX_ClientObjectInfo::ACTOR)
214                 {
215                         if ((m_touchedpropname.Length() == 0) || 
216                                 (gameobj->GetProperty(m_touchedpropname)))
217                         {
218                                 m_bTriggered = true;
219                                 m_hitObject = gameobj;
220                         }
221                 }
222         }
223         
224         return DT_CONTINUE;
225 }
226
227
228
229 // python embedding
230 PyTypeObject KX_NearSensor::Type = {
231         PyObject_HEAD_INIT(&PyType_Type)
232         0,
233         "KX_NearSensor",
234         sizeof(KX_NearSensor),
235         0,
236         PyDestructor,
237         0,
238         __getattr,
239         __setattr,
240         0, //&MyPyCompare,
241         __repr,
242         0, //&cvalue_as_number,
243         0,
244         0,
245         0,
246         0
247 };
248
249
250
251 PyParentObject KX_NearSensor::Parents[] = {
252         &KX_NearSensor::Type,
253         &KX_TouchSensor::Type,
254         &SCA_ISensor::Type,
255         &SCA_ILogicBrick::Type,
256         &CValue::Type,
257         NULL
258 };
259
260
261
262 PyMethodDef KX_NearSensor::Methods[] = {
263         {"setProperty", 
264          (PyCFunction) KX_NearSensor::sPySetProperty,      METH_VARARGS, SetProperty_doc},
265         {"getProperty", 
266          (PyCFunction) KX_NearSensor::sPyGetProperty,      METH_VARARGS, GetProperty_doc},
267         {"getHitObject", 
268          (PyCFunction) KX_NearSensor::sPyGetHitObject,     METH_VARARGS, GetHitObject_doc},
269         {"getHitObjectList", 
270          (PyCFunction) KX_NearSensor::sPyGetHitObjectList, METH_VARARGS, GetHitObjectList_doc},
271         {NULL,NULL} //Sentinel
272 };
273
274
275 PyObject*
276 KX_NearSensor::_getattr(const STR_String& attr)
277 {
278   _getattr_up(KX_TouchSensor);
279 }
280