Speed up the physics engine: hook the SOLID broad phase, so we can either reject...
[blender.git] / source / gameengine / Ketsji / KX_TouchEventManager.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31
32 #include "KX_TouchEventManager.h"
33 #include "SCA_ISensor.h"
34 #include "KX_TouchSensor.h"
35 #include "KX_GameObject.h"
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include "SM_Object.h"
42
43 KX_TouchEventManager::Collision::Collision(SCA_ISensor *sensor, SM_Object *obj1, SM_Object *obj2)
44         : m_id(next_id++),
45           m_sensor(sensor),
46           m_object1(obj1),
47           m_object2(obj2)
48 {
49 }
50
51 bool KX_TouchEventManager::Collision::operator<(const Collision &other) const
52 {
53         if (*this == other)
54                 return true;
55                 
56         return m_id < other.m_id;
57 }
58                 
59 bool KX_TouchEventManager::Collision::operator==(const Collision &other) const
60 {
61         return m_sensor == other.m_sensor && 
62                 ((m_object1 == other.m_object1 && m_object2 == other.m_object2) ||
63                  (m_object1 == other.m_object2 && m_object2 == other.m_object1));
64 }
65
66 int KX_TouchEventManager::Collision::next_id = 0;
67
68 KX_TouchEventManager::KX_TouchEventManager(class SCA_LogicManager* logicmgr,
69         SM_Scene *scene)
70         : SCA_EventManager(TOUCH_EVENTMGR),
71           m_logicmgr(logicmgr),
72           m_scene(scene)
73 {
74         //m_scene->addTouchCallback(STATIC_RESPONSE, KX_TouchEventManager::collisionResponse, this);
75         m_scene->addTouchCallback(OBJECT_RESPONSE, KX_TouchEventManager::collisionResponse, this);
76         m_scene->addTouchCallback(SENSOR_RESPONSE, KX_TouchEventManager::collisionResponse, this);
77 }
78
79 DT_Bool KX_TouchEventManager::HandleCollision(void* object1, void* object2, const DT_CollData *coll_data)
80 {
81         SM_Object * obj1 = static_cast<SM_Object*>(object1);
82         SM_Object * obj2 = static_cast<SM_Object*>(object2);
83         KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo *>(obj1->getClientObject());
84         
85         list<SCA_ISensor*>::iterator it;
86         for ( it = client_info->m_sensors.begin(); it != client_info->m_sensors.end(); ++it)
87                 m_collisions.insert(Collision(*it, obj1, obj2));
88
89         client_info = static_cast<KX_ClientObjectInfo *>(obj2->getClientObject());
90         for ( it = client_info->m_sensors.begin(); it != client_info->m_sensors.end(); ++it)
91                 m_collisions.insert(Collision(*it, obj2, obj1));
92                 
93         return DT_CONTINUE;
94 }
95
96 /*
97 DT_Bool KX_TouchEventManager::HandleCollision(void* object1,void* object2,
98                                                  const DT_CollData * coll_data)
99 {
100         SM_Object * obj1 = (SM_Object *) object1;
101         SM_Object * obj2 = (SM_Object *) object2;
102
103         for ( vector<SCA_ISensor*>::iterator it = m_sensors.begin(); !(it==m_sensors.end()); it++)
104         {
105                 KX_GameObject* gameobj = ((KX_GameObject*)((KX_TouchSensor*)*it)->GetParent());
106                 KX_ClientObjectInfo *client_info = (KX_ClientObjectInfo *) obj1->getClientObject();
107 // Enable these printfs to create excesive debug info
108 //              printf("KX_TEM::HC: Sensor %s\tGO: %p o1: %s (%p)", (const char *) (*it)->GetName(), gameobj, (const char *) ((KX_GameObject *) client_info->m_clientobject)->GetName(), client_info->m_clientobject);
109                 if (client_info && client_info->m_clientobject == gameobj)
110                         ((KX_TouchSensor*)*it)->HandleCollision(object1,object2,coll_data);
111
112                 client_info = (KX_ClientObjectInfo *) obj2->getClientObject();
113 //              printf(" o2: %s (%p)\n", (const char *) ((KX_GameObject *) client_info->m_clientobject)->GetName(), client_info->m_clientobject);
114                 if (client_info && client_info->m_clientobject == gameobj)
115                          ((KX_TouchSensor*)*it)->HandleCollision(object1,object2,coll_data);
116
117         }
118         
119         return DT_CONTINUE;
120 }
121
122 */
123
124 DT_Bool KX_TouchEventManager::collisionResponse(void *client_data, 
125                                                         void *object1,
126                                                         void *object2,
127                                                         const DT_CollData *coll_data)
128 {
129         KX_TouchEventManager *touchmgr = (KX_TouchEventManager *) client_data;
130         touchmgr->HandleCollision(object1, object2, coll_data);
131         return DT_CONTINUE;
132 }
133
134 void KX_TouchEventManager::RegisterSensor(SCA_ISensor* sensor)
135 {
136         KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(sensor);
137         m_sensors.push_back(touchsensor);
138
139         touchsensor->RegisterSumo(this);
140 }
141
142
143
144 void KX_TouchEventManager::EndFrame()
145 {
146         vector<SCA_ISensor*>::iterator it;
147         for ( it = m_sensors.begin();
148         !(it==m_sensors.end());it++)
149         {
150                 ((KX_TouchSensor*)*it)->EndFrame();
151
152         }
153 }
154
155
156
157 void KX_TouchEventManager::NextFrame()
158 {
159         if (m_sensors.size() > 0)
160         {
161                 vector<SCA_ISensor*>::iterator it;
162                 
163                 for (it = m_sensors.begin();!(it==m_sensors.end());++it)
164                         static_cast<KX_TouchSensor*>(*it)->SynchronizeTransform();
165                 
166                 for (std::set<Collision>::iterator cit = m_collisions.begin(); cit != m_collisions.end(); ++cit)
167                         static_cast<KX_TouchSensor*>((*cit).m_sensor)->HandleCollision((*cit).m_object1, (*cit).m_object2, NULL);
168                         
169                 m_collisions.clear();
170                         
171                 for (it = m_sensors.begin();!(it==m_sensors.end());++it)
172                         (*it)->Activate(m_logicmgr,NULL);
173         }
174 }
175
176
177
178 void KX_TouchEventManager::RemoveSensor(class SCA_ISensor* sensor)
179 {
180         std::vector<SCA_ISensor*>::iterator i =
181         std::find(m_sensors.begin(), m_sensors.end(), sensor);
182         if (!(i == m_sensors.end()))
183         {
184                 std::swap(*i, m_sensors.back());
185                 m_sensors.pop_back();
186         }
187         // remove the sensor forever :)
188         SCA_EventManager::RemoveSensor(sensor);
189 }
190