Reverting some other changes zaghaghi made
[blender.git] / source / gameengine / GameLogic / SCA_ISensor.cpp
1 /**
2  * Abstract class for sensor logic bricks
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 "SCA_ISensor.h"
36 #include "SCA_EventManager.h"
37 #include "SCA_LogicManager.h"
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 /* Native functions */
44 void    SCA_ISensor::ReParent(SCA_IObject* parent)
45 {
46         SCA_ILogicBrick::ReParent(parent);
47         m_eventmgr->RegisterSensor(this);
48         this->SetActive(false);
49 }
50
51
52 SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj,
53                                                  class SCA_EventManager* eventmgr,
54                                                  PyTypeObject* T ) :
55         SCA_ILogicBrick(gameobj,T),
56         m_triggered(false)
57 {
58         m_suspended = false;
59         m_invert = false;
60         m_pos_ticks = 0;
61         m_neg_ticks = 0;
62         m_pos_pulsemode = false;
63         m_neg_pulsemode = false;
64         m_pulse_frequency = 0;
65         
66         m_eventmgr = eventmgr;
67 }
68
69
70 SCA_ISensor::~SCA_ISensor()  
71 {
72         // intentionally empty
73 }
74
75 bool SCA_ISensor::IsPositiveTrigger() { 
76         bool result = false;
77         
78         if (m_eventval) {
79                 result = (m_eventval->GetNumber() != 0.0);
80         }
81         if (m_invert) {
82                 result = !result;
83         }
84         
85         return result;
86 }
87
88 void SCA_ISensor::SetPulseMode(bool posmode, 
89                                                            bool negmode,
90                                                            int freq) {
91         m_pos_pulsemode = posmode;
92         m_neg_pulsemode = negmode;
93         m_pulse_frequency = freq;
94 }
95
96 void SCA_ISensor::SetInvert(bool inv) {
97         m_invert = inv;
98 }
99
100
101 float SCA_ISensor::GetNumber() {
102         return IsPositiveTrigger();
103 }
104
105 void SCA_ISensor::Suspend() {
106         m_suspended = true;
107 }
108
109 bool SCA_ISensor::IsSuspended() {
110         return m_suspended;
111 }
112
113 void SCA_ISensor::Resume() {
114         m_suspended = false;
115 }
116
117 /* python integration */
118
119 PyTypeObject SCA_ISensor::Type = {
120         PyObject_HEAD_INIT(&PyType_Type)
121         0,
122         "SCA_ISensor",
123         sizeof(SCA_ISensor),
124         0,
125         PyDestructor,
126         0,
127         __getattr,
128         __setattr,
129         0, //&MyPyCompare,
130         __repr,
131         0, //&cvalue_as_number,
132         0,
133         0,
134         0,
135         0
136 };
137
138 PyParentObject SCA_ISensor::Parents[] = {
139         &SCA_ISensor::Type,
140         &SCA_ILogicBrick::Type,
141         &CValue::Type,
142         NULL
143 };
144 PyMethodDef SCA_ISensor::Methods[] = {
145         {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, 
146          METH_VARARGS, IsPositive_doc},
147         {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode, 
148          METH_VARARGS, GetUsePosPulseMode_doc},
149         {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode, 
150          METH_VARARGS, SetUsePosPulseMode_doc},
151         {"getFrequency", (PyCFunction) SCA_ISensor::sPyGetFrequency, 
152          METH_VARARGS, GetFrequency_doc},
153         {"setFrequency", (PyCFunction) SCA_ISensor::sPySetFrequency, 
154          METH_VARARGS, SetFrequency_doc},
155         {"getUseNegPulseMode", (PyCFunction) SCA_ISensor::sPyGetUseNegPulseMode, 
156          METH_VARARGS, GetUseNegPulseMode_doc},
157         {"setUseNegPulseMode", (PyCFunction) SCA_ISensor::sPySetUseNegPulseMode, 
158          METH_VARARGS, SetUseNegPulseMode_doc},
159         {"getInvert", (PyCFunction) SCA_ISensor::sPyGetInvert, 
160          METH_VARARGS, GetInvert_doc},
161         {"setInvert", (PyCFunction) SCA_ISensor::sPySetInvert, 
162          METH_VARARGS, SetInvert_doc},
163         {"evaluate", (PyCFunction) SCA_ISensor::sPyEvaluate, 
164          METH_VARARGS, Evaluate_doc},
165         {NULL,NULL} //Sentinel
166 };
167
168
169 PyObject*
170 SCA_ISensor::_getattr(const STR_String& attr)
171 {
172   _getattr_up(SCA_ILogicBrick);
173 }
174
175
176 void SCA_ISensor::RegisterToManager()
177 {
178         m_eventmgr->RegisterSensor(this);
179 }
180
181 void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr,      CValue* event)
182 {
183         
184         // calculate if a __triggering__ is wanted
185         if (!m_suspended) {
186                 bool result = this->Evaluate(event);
187                 if (result) {
188                         logicmgr->AddActivatedSensor(this);     
189                 } else
190                 {
191                         /* First, the pulsing behaviour, if pulse mode is
192                          * active. It seems something goes wrong if pulse mode is
193                          * not set :( */
194                         if (m_pos_pulsemode) {
195                                 m_pos_ticks++;
196                                 if (m_pos_ticks > m_pulse_frequency) {
197                                         if ( this->IsPositiveTrigger() )
198                                         {
199                                                 logicmgr->AddActivatedSensor(this);
200                                         }
201                                         m_pos_ticks = 0;
202                                 } 
203                         }
204                         
205                         if (m_neg_pulsemode)
206                         {
207                                 m_neg_ticks++;
208                                 if (m_neg_ticks > m_pulse_frequency) {
209                                         if (!this->IsPositiveTrigger() )
210                                         {
211                                                 logicmgr->AddActivatedSensor(this);
212                                         }
213                                         m_neg_ticks = 0;
214                                 }
215                         }
216                 }
217         } 
218 }
219
220 /* Python functions: */
221 char SCA_ISensor::IsPositive_doc[] = 
222 "isPositive()\n"
223 "\tReturns whether the sensor is registered a positive event.\n";
224 PyObject* SCA_ISensor::PyIsPositive(PyObject* self, PyObject* args, PyObject* kwds)
225 {
226         int retval = IsPositiveTrigger();
227         return PyInt_FromLong(retval);
228 }
229
230 /**
231  * getUsePulseMode: getter for the pulse mode (KX_TRUE = on)
232  */
233 char SCA_ISensor::GetUsePosPulseMode_doc[] = 
234 "getUsePosPulseMode()\n"
235 "\tReturns whether positive pulse mode is active.\n";
236 PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
237 {
238         return BoolToPyArg(m_pos_pulsemode);
239 }
240
241 /**
242  * setUsePulseMode: setter for the pulse mode (KX_TRUE = on)
243  */
244 char SCA_ISensor::SetUsePosPulseMode_doc[] = 
245 "setUsePosPulseMode(pulse?)\n"
246 "\t - pulse? : Pulse when a positive event occurs?\n"
247 "\t            (KX_TRUE, KX_FALSE)\n"
248 "\tSet whether to do pulsing when positive pulses occur.\n";
249 PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
250 {
251         int pyarg = 0;
252         if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
253         m_pos_pulsemode = PyArgToBool(pyarg);
254         Py_Return;
255 }
256
257 /**
258  * getFrequency: getter for the pulse mode interval
259  */
260 char SCA_ISensor::GetFrequency_doc[] = 
261 "getFrequency()\n"
262 "\tReturns the frequency of the updates in pulse mode.\n" ;
263 PyObject* SCA_ISensor::PyGetFrequency(PyObject* self, PyObject* args, PyObject* kwds)
264 {
265         return PyInt_FromLong(m_pulse_frequency);
266 }
267
268 /**
269  * setFrequency: setter for the pulse mode (KX_TRUE = on)
270  */
271 char SCA_ISensor::SetFrequency_doc[] = 
272 "setFrequency(pulse_frequency)\n"
273 "\t- pulse_frequency: The frequency of the updates in pulse mode (integer)"
274 "\tSet the frequency of the updates in pulse mode.\n"
275 "\tIf the frequency is negative, it is set to 0.\n" ;
276 PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject* kwds)
277 {
278         int pulse_frequencyArg = 0;
279
280         if(!PyArg_ParseTuple(args, "i", &pulse_frequencyArg)) {
281                 return NULL;
282         }
283         
284         /* We can do three things here: clip, ignore and raise an exception.  */
285         /* Exceptions don't work yet, ignoring is not desirable now...        */
286         if (pulse_frequencyArg < 0) {
287                 pulse_frequencyArg = 0;
288         };      
289         m_pulse_frequency = pulse_frequencyArg;
290
291         Py_Return;
292 }
293
294
295 char SCA_ISensor::GetInvert_doc[] = 
296 "getInvert()\n"
297 "\tReturns whether or not pulses from this sensor are inverted.\n" ;
298 PyObject* SCA_ISensor::PyGetInvert(PyObject* self, PyObject* args, PyObject* kwds)
299 {
300         return BoolToPyArg(m_invert);
301 }
302
303 char SCA_ISensor::SetInvert_doc[] = 
304 "setInvert(invert?)\n"
305 "\t- invert?: Invert the event-values? (KX_TRUE, KX_FALSE)\n"
306 "\tSet whether to invert pulses.\n";
307 PyObject* SCA_ISensor::PySetInvert(PyObject* self, PyObject* args, PyObject* kwds)
308 {
309         int pyarg = 0;
310         if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
311         m_invert = PyArgToBool(pyarg);
312         Py_Return;
313 }
314
315 char SCA_ISensor::GetUseNegPulseMode_doc[] = 
316 "getUseNegPulseMode()\n"
317 "\tReturns whether negative pulse mode is active.\n";
318 PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
319 {
320         return BoolToPyArg(m_neg_pulsemode);
321 }
322
323 char SCA_ISensor::SetUseNegPulseMode_doc[] = 
324 "setUseNegPulseMode(pulse?)\n"
325 "\t - pulse? : Pulse when a negative event occurs?\n"
326 "\t            (KX_TRUE, KX_FALSE)\n"
327 "\tSet whether to do pulsing when negative pulses occur.\n";
328 PyObject* SCA_ISensor::PySetUseNegPulseMode(PyObject* self, PyObject* args, PyObject* kwds)
329 {
330         int pyarg = 0;
331         if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
332         m_neg_pulsemode = PyArgToBool(pyarg);
333         Py_Return;
334 }
335
336 char SCA_ISensor::Evaluate_doc[] = 
337 "evaluate()\n"
338 "\tRe-evaluate the sensor so that isPositive() and other methods are up to date\n"
339 "\twith current game conditions. BGE does it automatically on each frame so it's\n"
340 "\tnot usually needed.\n"
341 "\tReturns True or False if the sensor evaluates positively or negatively\n";
342 PyObject* SCA_ISensor::PyEvaluate(PyObject* self, PyObject* args, PyObject* kwds)
343 {
344         return BoolToPyArg(Evaluate(NULL));
345 }
346
347
348 /* eof */