resolved conflict state with HEAD r14096
[blender.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 #include "PHY_IPhysicsEnvironment.h"
41 #include "PHY_IPhysicsController.h"
42
43
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif
47 KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr,
48                                                          KX_GameObject* gameobj,
49                                                          double margin,
50                                                          double resetmargin,
51                                                          bool bFindMaterial,
52                                                          const STR_String& touchedpropname,
53                                                          class KX_Scene* scene,
54                                                          PHY_IPhysicsController*        ctrl,
55                                                          PyTypeObject* T)
56                          :KX_TouchSensor(eventmgr,
57                                                          gameobj,
58                                                          bFindMaterial,
59                                                          touchedpropname,
60                                                          /* scene, */
61                                                          T),
62                          m_Margin(margin),
63                          m_ResetMargin(resetmargin)
64
65 {
66
67         gameobj->getClientInfo()->m_sensors.remove(this);
68         m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::NEAR);
69         m_client_info->m_sensors.push_back(this);
70         
71         //DT_ShapeHandle shape = (DT_ShapeHandle) vshape;
72         m_physCtrl = ctrl;
73         if (m_physCtrl)
74         {
75                 m_physCtrl->SetMargin(m_Margin);
76                 m_physCtrl->setNewClientInfo(m_client_info);
77         }
78         SynchronizeTransform();
79 }
80
81 void KX_NearSensor::RegisterSumo(KX_TouchEventManager *touchman)
82 {
83         if (m_physCtrl)
84         {
85                 touchman->GetPhysicsEnvironment()->addSensor(m_physCtrl);
86         }
87 }
88
89 CValue* KX_NearSensor::GetReplica()
90 {
91         KX_NearSensor* replica = new KX_NearSensor(*this);
92         replica->m_colliders = new CListValue();
93         replica->m_bCollision = false;
94         replica->m_bTriggered= false;
95         replica->m_hitObject = NULL;
96         replica->m_bLastTriggered = false;
97         // this will copy properties and so on...
98         CValue::AddDataToReplica(replica);
99         
100         replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::NEAR);
101         
102         if (replica->m_physCtrl)
103         {
104                 replica->m_physCtrl = replica->m_physCtrl->GetReplica();
105                 if (replica->m_physCtrl)
106                 {
107                         //static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->addSensor(replica->m_physCtrl);
108                         replica->m_physCtrl->SetMargin(m_Margin);
109                         replica->m_physCtrl->setNewClientInfo(replica->m_client_info);
110                 }
111                 
112         }
113         //static_cast<KX_TouchEventManager*>(m_eventmgr)->RegisterSensor(this);
114         //todo: make sure replication works fine
115         //>m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL);
116         //replica->m_sumoObj->setMargin(m_Margin);
117         //replica->m_sumoObj->setClientObject(replica->m_client_info);
118         
119         ((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL);
120         replica->SynchronizeTransform();
121         
122         return replica;
123 }
124
125
126
127 void KX_NearSensor::ReParent(SCA_IObject* parent)
128 {
129
130         SCA_ISensor::ReParent(parent);
131         
132         m_client_info->m_gameobject = static_cast<KX_GameObject*>(parent); 
133         m_client_info->m_sensors.push_back(this);
134         
135
136 /*      KX_ClientObjectInfo *client_info = gameobj->getClientInfo();
137         client_info->m_gameobject = gameobj;
138         client_info->m_auxilary_info = NULL;
139         
140         client_info->m_sensors.push_back(this);
141         SCA_ISensor::ReParent(parent);
142 */
143         ((KX_GameObject*)GetParent())->GetSGNode()->ComputeWorldTransforms(NULL);
144         SynchronizeTransform();
145 }
146
147
148
149 KX_NearSensor::~KX_NearSensor()
150 {
151         // for nearsensor, the sensor is the 'owner' of sumoobj
152         // for touchsensor, it's the parent
153         if (m_physCtrl)
154         {
155                 //static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->removeSensor(m_physCtrl);
156                 delete m_physCtrl;
157                 m_physCtrl = NULL;
158         }
159         
160                 
161         if (m_client_info)
162                 delete m_client_info;
163 }
164
165
166 bool KX_NearSensor::Evaluate(CValue* event)
167 {
168         bool result = false;
169 //      KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
170
171         if (m_bTriggered != m_bLastTriggered)
172         {
173                 m_bLastTriggered = m_bTriggered;
174                 if (m_bTriggered)
175                 {
176                         if (m_physCtrl)
177                         {
178                                 m_physCtrl->SetMargin(m_ResetMargin);
179                         }
180                 } else
181                 {
182                         if (m_physCtrl)
183                         {
184                                 m_physCtrl->SetMargin(m_Margin);
185                         }
186
187                 }
188                 result = true;
189         }
190
191         return result;
192 }
193
194 // this function is called at broad phase stage to check if the two controller
195 // need to interact at all. It is used for Near/Radar sensor that don't need to
196 // check collision with object not included in filter
197 bool    KX_NearSensor::BroadPhaseFilterCollision(void*obj1,void*obj2)
198 {
199         KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
200         
201         // need the mapping from PHY_IPhysicsController to gameobjects now
202         assert(obj1==m_physCtrl && obj2);
203         KX_ClientObjectInfo* client_info = static_cast<KX_ClientObjectInfo*>((static_cast<PHY_IPhysicsController*>(obj2))->getNewClientInfo());
204
205         KX_GameObject* gameobj = ( client_info ? 
206                         client_info->m_gameobject :
207                         NULL);
208         
209         if (gameobj && (gameobj != parent))
210         {
211                 // only take valid colliders
212                 if (client_info->m_type == KX_ClientObjectInfo::ACTOR)
213                 {
214                         if ((m_touchedpropname.Length() == 0) || 
215                                 (gameobj->GetProperty(m_touchedpropname)))
216                         {
217                                 return true;
218                         }
219                 }
220         }
221
222         return false;
223 }
224
225 bool    KX_NearSensor::NewHandleCollision(void* obj1,void* obj2,const PHY_CollData * coll_data)
226 {
227 //      KX_TouchEventManager* toucheventmgr = static_cast<KX_TouchEventManager*>(m_eventmgr);
228         KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
229         
230         // need the mapping from PHY_IPhysicsController to gameobjects now
231         
232         KX_ClientObjectInfo* client_info =static_cast<KX_ClientObjectInfo*> (obj1 == m_physCtrl? 
233                                         ((PHY_IPhysicsController*)obj2)->getNewClientInfo() : 
234                                         ((PHY_IPhysicsController*)obj1)->getNewClientInfo());
235
236         KX_GameObject* gameobj = ( client_info ? 
237                         client_info->m_gameobject :
238                         NULL);
239         
240         // these checks are done already in BroadPhaseFilterCollision()
241         if (gameobj /*&& (gameobj != parent)*/)
242         {
243                 if (!m_colliders->SearchValue(gameobj))
244                         m_colliders->Add(gameobj->AddRef());
245                 // only take valid colliders
246                 // These checks are done already in BroadPhaseFilterCollision()
247                 //if (client_info->m_type == KX_ClientObjectInfo::ACTOR)
248                 //{
249                 //      if ((m_touchedpropname.Length() == 0) || 
250                 //              (gameobj->GetProperty(m_touchedpropname)))
251                 //      {
252                                 m_bTriggered = true;
253                                 m_hitObject = gameobj;
254                 //      }
255                 //}
256         }
257         
258         return DT_CONTINUE;
259 }
260
261
262
263 // python embedding
264 PyTypeObject KX_NearSensor::Type = {
265         PyObject_HEAD_INIT(&PyType_Type)
266         0,
267         "KX_NearSensor",
268         sizeof(KX_NearSensor),
269         0,
270         PyDestructor,
271         0,
272         __getattr,
273         __setattr,
274         0, //&MyPyCompare,
275         __repr,
276         0, //&cvalue_as_number,
277         0,
278         0,
279         0,
280         0
281 };
282
283
284
285 PyParentObject KX_NearSensor::Parents[] = {
286         &KX_NearSensor::Type,
287         &KX_TouchSensor::Type,
288         &SCA_ISensor::Type,
289         &SCA_ILogicBrick::Type,
290         &CValue::Type,
291         NULL
292 };
293
294
295
296 PyMethodDef KX_NearSensor::Methods[] = {
297         {"setProperty", 
298          (PyCFunction) KX_NearSensor::sPySetProperty,      METH_VARARGS, SetProperty_doc},
299         {"getProperty", 
300          (PyCFunction) KX_NearSensor::sPyGetProperty,      METH_VARARGS, GetProperty_doc},
301         {"getHitObject", 
302          (PyCFunction) KX_NearSensor::sPyGetHitObject,     METH_VARARGS, GetHitObject_doc},
303         {"getHitObjectList", 
304          (PyCFunction) KX_NearSensor::sPyGetHitObjectList, METH_VARARGS, GetHitObjectList_doc},
305         {NULL,NULL} //Sentinel
306 };
307
308
309 PyObject*
310 KX_NearSensor::_getattr(const STR_String& attr)
311 {
312   _getattr_up(KX_TouchSensor);
313 }
314