svn merge -r 21041:21301 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[blender.git] / source / gameengine / GameLogic / SCA_IController.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL 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.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "SCA_IController.h"
30 #include "SCA_LogicManager.h"
31 #include "SCA_IActuator.h"
32 #include "SCA_ISensor.h"
33 #include "PyObjectPlus.h"
34 #include "../Ketsji/KX_PythonSeq.h" /* not nice, only need for KX_PythonSeq_CreatePyObject */
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 SCA_IController::SCA_IController(SCA_IObject* gameobj)
41         :
42         SCA_ILogicBrick(gameobj),
43         m_statemask(0),
44         m_justActivated(false)
45 {
46 }
47         
48
49         
50 SCA_IController::~SCA_IController()
51 {
52         //UnlinkAllActuators();
53 }
54
55
56
57 std::vector<class SCA_ISensor*>& SCA_IController::GetLinkedSensors()
58 {
59         return m_linkedsensors;
60 }
61
62
63
64 std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators()
65 {
66         return m_linkedactuators;
67 }
68
69
70
71 void SCA_IController::UnlinkAllSensors()
72 {
73         std::vector<class SCA_ISensor*>::iterator sensit;
74         for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit)
75         {
76                 if (IsActive()) 
77                 {
78                         (*sensit)->DecLink();
79                 }
80                 (*sensit)->UnlinkController(this);
81         }
82         m_linkedsensors.clear();
83 }
84
85
86
87 void SCA_IController::UnlinkAllActuators()
88 {
89         std::vector<class SCA_IActuator*>::iterator actit;
90         for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit)
91         {
92                 if (IsActive()) 
93                 {
94                         (*actit)->DecLink();
95                 }
96                 (*actit)->UnlinkController(this);
97         }
98         m_linkedactuators.clear();
99 }
100
101 void SCA_IController::LinkToActuator(SCA_IActuator* actua)
102 {
103         m_linkedactuators.push_back(actua);
104         if (IsActive())
105         {
106                 actua->IncLink();
107         }
108 }
109
110 void    SCA_IController::UnlinkActuator(class SCA_IActuator* actua)
111 {
112         std::vector<class SCA_IActuator*>::iterator actit;
113         for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit)
114         {
115                 if ((*actit) == actua)
116                 {
117                         if (IsActive())
118                         {
119                                 (*actit)->DecLink();
120                         }
121                         *actit = m_linkedactuators.back();
122                         m_linkedactuators.pop_back();
123                         return;
124                 }
125         }
126         printf("Missing link from controller %s:%s to actuator %s:%s\n", 
127                 m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), 
128                 actua->GetParent()->GetName().ReadPtr(), actua->GetName().ReadPtr());
129 }
130
131 void SCA_IController::LinkToSensor(SCA_ISensor* sensor)
132 {
133         m_linkedsensors.push_back(sensor);
134         if (IsActive())
135         {
136                 sensor->IncLink();
137         }
138 }
139
140 void SCA_IController::UnlinkSensor(class SCA_ISensor* sensor)
141 {
142         std::vector<class SCA_ISensor*>::iterator sensit;
143         for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit)
144         {
145                 if ((*sensit) == sensor)
146                 {
147                         if (IsActive())
148                         {
149                                 sensor->DecLink();
150                         }
151                         *sensit = m_linkedsensors.back();
152                         m_linkedsensors.pop_back();
153                         return;
154                 }
155         }
156         printf("Missing link from controller %s:%s to sensor %s:%s\n", 
157                 m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), 
158                 sensor->GetParent()->GetName().ReadPtr(), sensor->GetName().ReadPtr());
159 }
160
161
162 void SCA_IController::ApplyState(unsigned int state)
163 {
164         std::vector<class SCA_IActuator*>::iterator actit;
165         std::vector<class SCA_ISensor*>::iterator sensit;
166
167         if (m_statemask & state) 
168         {
169                 if (!IsActive()) 
170                 {
171                         // reactive the controller, all the links to actuator are valid again
172                         for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit)
173                         {
174                                 (*actit)->IncLink();
175                         }
176
177                         for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit)
178                         {
179                                 (*sensit)->IncLink();
180                         }
181                         SetActive(true);
182                         m_justActivated = true;
183                 }
184         } else if (IsActive())
185         {
186                 for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit)
187                 {
188                         (*actit)->DecLink();
189                 }
190                 for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit)
191                 {
192                         (*sensit)->DecLink();
193                 }
194                 SetActive(false);
195                 m_justActivated = false;
196         }
197 }
198
199 /* Python api */
200
201 PyTypeObject SCA_IController::Type = {
202 #if (PY_VERSION_HEX >= 0x02060000)
203         PyVarObject_HEAD_INIT(NULL, 0)
204 #else
205         /* python 2.5 and below */
206         PyObject_HEAD_INIT( NULL )  /* required py macro */
207         0,                          /* ob_size */
208 #endif
209                 "SCA_IController",
210                 sizeof(PyObjectPlus_Proxy),
211                 0,
212                 py_base_dealloc,
213                 0,
214                 0,
215                 0,
216                 0,
217                 py_base_repr,
218                 0,0,0,0,0,0,0,0,0,
219                 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
220                 0,0,0,0,0,0,0,
221                 Methods,
222                 0,
223                 0,
224                 &SCA_ILogicBrick::Type,
225                 0,0,0,0,0,0,
226                 py_base_new
227 };
228
229 PyMethodDef SCA_IController::Methods[] = {
230         //Deprecated functions ------>
231         {"getSensor", (PyCFunction) SCA_IController::sPyGetSensor, METH_O},
232         {"getActuator", (PyCFunction) SCA_IController::sPyGetActuator, METH_O},
233         {"getSensors", (PyCFunction) SCA_IController::sPyGetSensors, METH_NOARGS},
234         {"getActuators", (PyCFunction) SCA_IController::sPyGetActuators, METH_NOARGS},
235         {"getState", (PyCFunction) SCA_IController::sPyGetState, METH_NOARGS},
236         //<----- Deprecated
237         {NULL,NULL} //Sentinel
238 };
239
240 PyAttributeDef SCA_IController::Attributes[] = {
241         KX_PYATTRIBUTE_RO_FUNCTION("state", SCA_IController, pyattr_get_state),
242         KX_PYATTRIBUTE_RO_FUNCTION("sensors", SCA_IController, pyattr_get_sensors),
243         KX_PYATTRIBUTE_RO_FUNCTION("actuators", SCA_IController, pyattr_get_actuators),
244         KX_PYATTRIBUTE_BOOL_RW("useHighPriority",SCA_IController,m_bookmark),
245         { NULL }        //Sentinel
246 };
247
248 PyObject* SCA_IController::PyGetActuators()
249 {
250         ShowDeprecationWarning("getActuators()", "the actuators property");
251         
252         PyObject* resultlist = PyList_New(m_linkedactuators.size());
253         for (unsigned int index=0;index<m_linkedactuators.size();index++)
254         {
255                 PyList_SET_ITEM(resultlist,index, m_linkedactuators[index]->GetProxy());
256         }
257
258         return resultlist;
259 }
260
261 PyObject* SCA_IController::PyGetSensor(PyObject* value)
262 {
263         ShowDeprecationWarning("getSensor(string)", "the sensors[string] property");
264         
265         char *scriptArg = _PyUnicode_AsString(value);
266         if (scriptArg==NULL) {
267                 PyErr_SetString(PyExc_TypeError, "controller.getSensor(string): Python Controller, expected a string (sensor name)");
268                 return NULL;
269         }
270         
271         for (unsigned int index=0;index<m_linkedsensors.size();index++)
272         {
273                 SCA_ISensor* sensor = m_linkedsensors[index];
274                 STR_String& realname = sensor->GetName();
275                 if (realname == scriptArg)
276                 {
277                         return sensor->GetProxy();
278                 }
279         }
280         
281         PyErr_Format(PyExc_AttributeError, "controller.getSensor(string): Python Controller, unable to find requested sensor \"%s\"", scriptArg);
282         return NULL;
283 }
284
285 PyObject* SCA_IController::PyGetActuator(PyObject* value)
286 {
287         ShowDeprecationWarning("getActuator(string)", "the actuators[string] property");
288         
289         char *scriptArg = _PyUnicode_AsString(value);
290         if (scriptArg==NULL) {
291                 PyErr_SetString(PyExc_TypeError, "controller.getActuator(string): Python Controller, expected a string (actuator name)");
292                 return NULL;
293         }
294         
295         for (unsigned int index=0;index<m_linkedactuators.size();index++)
296         {
297                 SCA_IActuator* actua = m_linkedactuators[index];
298                 if (actua->GetName() == scriptArg)
299                 {
300                         return actua->GetProxy();
301                 }
302         }
303         
304         PyErr_Format(PyExc_AttributeError, "controller.getActuator(string): Python Controller, unable to find requested actuator \"%s\"", scriptArg);
305         return NULL;
306 }
307
308 PyObject* SCA_IController::PyGetSensors()
309 {
310         ShowDeprecationWarning("getSensors()", "the sensors property");
311         
312         PyObject* resultlist = PyList_New(m_linkedsensors.size());
313         for (unsigned int index=0;index<m_linkedsensors.size();index++)
314         {
315                 PyList_SET_ITEM(resultlist,index, m_linkedsensors[index]->GetProxy());
316         }
317         
318         return resultlist;
319 }
320
321 PyObject* SCA_IController::PyGetState()
322 {
323         ShowDeprecationWarning("getState()", "the state property");
324         return PyLong_FromSsize_t(m_statemask);
325 }
326
327 PyObject* SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
328 {
329         SCA_IController* self= static_cast<SCA_IController*>(self_v);
330         return PyLong_FromSsize_t(self->m_statemask);
331 }
332
333 PyObject* SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
334 {
335         return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_SENSORS);    
336 }
337
338 PyObject* SCA_IController::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
339 {
340         return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_ACTUATORS);  
341 }