-added basic support for GameActuator 'load game', relative paths were broken, just...
[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 #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         replica->SynchronizeTransform();
120         
121         return replica;
122 }
123
124
125
126 void KX_NearSensor::ReParent(SCA_IObject* parent)
127 {
128
129         SCA_ISensor::ReParent(parent);
130         
131         m_client_info->m_gameobject = static_cast<KX_GameObject*>(parent); 
132         m_client_info->m_sensors.push_back(this);
133         
134
135 /*      KX_ClientObjectInfo *client_info = gameobj->getClientInfo();
136         client_info->m_gameobject = gameobj;
137         client_info->m_auxilary_info = NULL;
138         
139         client_info->m_sensors.push_back(this);
140         SCA_ISensor::ReParent(parent);
141 */
142
143         SynchronizeTransform();
144 }
145
146
147
148 KX_NearSensor::~KX_NearSensor()
149 {
150         // for nearsensor, the sensor is the 'owner' of sumoobj
151         // for touchsensor, it's the parent
152         if (m_physCtrl)
153         {
154                 //static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->removeSensor(m_physCtrl);
155                 delete m_physCtrl;
156                 m_physCtrl = NULL;
157         }
158         
159                 
160         if (m_client_info)
161                 delete m_client_info;
162 }
163
164
165 bool KX_NearSensor::Evaluate(CValue* event)
166 {
167         bool result = false;
168 //      KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
169
170         if (m_bTriggered != m_bLastTriggered)
171         {
172                 m_bLastTriggered = m_bTriggered;
173                 if (m_bTriggered)
174                 {
175                         if (m_physCtrl)
176                         {
177                                 m_physCtrl->SetMargin(m_ResetMargin);
178                         }
179                 } else
180                 {
181                         if (m_physCtrl)
182                         {
183                                 m_physCtrl->SetMargin(m_Margin);
184                         }
185
186                 }
187                 result = true;
188         }
189
190         return result;
191 }
192
193
194
195 bool    KX_NearSensor::NewHandleCollision(void* obj1,void* obj2,const PHY_CollData * coll_data)
196 {
197 //      KX_TouchEventManager* toucheventmgr = static_cast<KX_TouchEventManager*>(m_eventmgr);
198         KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
199         
200         // need the mapping from PHY_IPhysicsController to gameobjects now
201         
202         KX_ClientObjectInfo* client_info =static_cast<KX_ClientObjectInfo*> (obj1 == m_physCtrl? 
203                                         ((PHY_IPhysicsController*)obj2)->getNewClientInfo() : 
204                                         ((PHY_IPhysicsController*)obj1)->getNewClientInfo());
205
206         KX_GameObject* gameobj = ( client_info ? 
207                         client_info->m_gameobject :
208                         NULL);
209         
210         if (gameobj && (gameobj != parent))
211         {
212                 if (!m_colliders->SearchValue(gameobj))
213                         m_colliders->Add(gameobj->AddRef());
214                 // only take valid colliders
215                 if (client_info->m_type == KX_ClientObjectInfo::ACTOR)
216                 {
217                         if ((m_touchedpropname.Length() == 0) || 
218                                 (gameobj->GetProperty(m_touchedpropname)))
219                         {
220                                 m_bTriggered = true;
221                                 m_hitObject = gameobj;
222                         }
223                 }
224         }
225         
226         return DT_CONTINUE;
227 }
228
229
230
231 // python embedding
232 PyTypeObject KX_NearSensor::Type = {
233         PyObject_HEAD_INIT(&PyType_Type)
234         0,
235         "KX_NearSensor",
236         sizeof(KX_NearSensor),
237         0,
238         PyDestructor,
239         0,
240         __getattr,
241         __setattr,
242         0, //&MyPyCompare,
243         __repr,
244         0, //&cvalue_as_number,
245         0,
246         0,
247         0,
248         0
249 };
250
251
252
253 PyParentObject KX_NearSensor::Parents[] = {
254         &KX_NearSensor::Type,
255         &KX_TouchSensor::Type,
256         &SCA_ISensor::Type,
257         &SCA_ILogicBrick::Type,
258         &CValue::Type,
259         NULL
260 };
261
262
263
264 PyMethodDef KX_NearSensor::Methods[] = {
265         {"setProperty", 
266          (PyCFunction) KX_NearSensor::sPySetProperty,      METH_VARARGS, SetProperty_doc},
267         {"getProperty", 
268          (PyCFunction) KX_NearSensor::sPyGetProperty,      METH_VARARGS, GetProperty_doc},
269         {"getHitObject", 
270          (PyCFunction) KX_NearSensor::sPyGetHitObject,     METH_VARARGS, GetHitObject_doc},
271         {"getHitObjectList", 
272          (PyCFunction) KX_NearSensor::sPyGetHitObjectList, METH_VARARGS, GetHitObjectList_doc},
273         {NULL,NULL} //Sentinel
274 };
275
276
277 PyObject*
278 KX_NearSensor::_getattr(const STR_String& attr)
279 {
280   _getattr_up(KX_TouchSensor);
281 }
282