6 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
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
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.
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.
25 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26 * All rights reserved.
28 * The Original Code is: all of this file.
30 * Contributor(s): none yet.
32 * ***** END GPL/BL DUAL LICENSE BLOCK *****
36 #include "SCA_PropertySensor.h"
37 #include "Operator2Expr.h"
38 #include "ConstExpr.h"
39 #include "InputParser.h"
40 #include "StringValue.h"
41 #include "SCA_EventManager.h"
42 #include "SCA_LogicManager.h"
48 SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr,
50 const STR_String& propname,
51 const STR_String& propval,
52 const STR_String& propmaxval,
53 KX_PROPSENSOR_TYPE checktype,
55 : SCA_ISensor(gameobj,eventmgr,T),
56 m_checktype(checktype),
57 m_checkpropval(propval),
58 m_checkpropmaxval(propmaxval),
59 m_checkpropname(propname),
65 //pars.SetContext(this->AddRef());
66 //CValue* resultval = m_rightexpr->Calculate();
68 CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
71 m_previoustext = orgprop->GetText();
75 if (m_checktype==KX_PROPSENSOR_INTERVAL)
77 PrecalculateRangeExpression();
82 void SCA_PropertySensor::PrecalculateRangeExpression()
85 pars.SetContext(this->AddRef());
86 STR_String checkstr = "(" + m_checkpropval + " <= "
87 + m_checkpropname + ") && ( "
88 + m_checkpropname + " <= "
91 m_range_expr = pars.ProcessText(checkstr);
96 CValue* SCA_PropertySensor::GetReplica()
98 SCA_PropertySensor* replica = new SCA_PropertySensor(*this);
99 // m_range_expr must be recalculated on replica!
100 CValue::AddDataToReplica(replica);
102 replica->m_range_expr = NULL;
103 if (replica->m_checktype==KX_PROPSENSOR_INTERVAL)
105 replica->PrecalculateRangeExpression();
114 bool SCA_PropertySensor::IsPositiveTrigger()
116 bool result = m_recentresult;//CheckPropertyCondition();
125 SCA_PropertySensor::~SCA_PropertySensor()
128 // m_rightexpr->Release();
132 m_range_expr->Release();
140 bool SCA_PropertySensor::Evaluate(CValue* event)
142 bool result = CheckPropertyCondition();
144 if (m_lastresult!=result)
146 m_lastresult = result;
154 bool SCA_PropertySensor::CheckPropertyCondition()
157 m_recentresult=false;
159 bool reverse = false;
162 case KX_PROPSENSOR_NOTEQUAL:
164 case KX_PROPSENSOR_EQUAL:
166 CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
169 STR_String testprop = orgprop->GetText();
170 // Force strings to upper case, to avoid confusion in
171 // bool tests. It's stupid the prop's identity is lost
172 // on the way here...
173 if ((testprop == "TRUE") || (testprop == "FALSE")) {
174 STR_String checkprop = m_checkpropval;
176 result = (testprop == checkprop);
178 result = (orgprop->GetText() == m_checkpropval);
190 case KX_PROPSENSOR_EXPRESSION:
195 CValue* resultval = m_rightexpr->Calculate();
196 if (resultval->IsError())
199 STR_String errortest = resultval->GetText();
204 result = resultval->GetNumber() != 0;
210 case KX_PROPSENSOR_INTERVAL:
212 //CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
217 CValue* vallie = m_range_expr->Calculate();
220 STR_String errtext = vallie->GetText();
221 if (errtext == "TRUE")
226 if (vallie->IsError())
228 //printf (errtext.ReadPtr());
239 //cout << " \nSens:Prop:interval!"; /* need implementation here!!! */
243 case KX_PROPSENSOR_CHANGED:
245 CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
249 if (m_previoustext != orgprop->GetText())
251 m_previoustext = orgprop->GetText();
257 //cout << " \nSens:Prop:changed!"; /* need implementation here!!! */
264 //the concept of Edge and Level triggering has unwanted effect for KX_PROPSENSOR_CHANGED
265 //see Game Engine bugtracker [ #3809 ]
266 if (m_checktype != KX_PROPSENSOR_CHANGED)
268 m_recentresult=result;
271 m_recentresult=result;//true;
276 CValue* SCA_PropertySensor::FindIdentifier(const STR_String& identifiername)
278 return GetParent()->FindIdentifier(identifiername);
281 bool SCA_PropertySensor::validValueForProperty(char *val, STR_String &prop)
284 /* There is no type checking at this moment, unfortunately... */
288 /* ------------------------------------------------------------------------- */
289 /* Python functions */
290 /* ------------------------------------------------------------------------- */
292 /* Integration hooks ------------------------------------------------------- */
293 PyTypeObject SCA_PropertySensor::Type = {
294 PyObject_HEAD_INIT(&PyType_Type)
296 "SCA_PropertySensor",
297 sizeof(SCA_PropertySensor),
305 0, //&cvalue_as_number,
312 PyParentObject SCA_PropertySensor::Parents[] = {
313 &SCA_PropertySensor::Type,
315 &SCA_ILogicBrick::Type,
320 PyMethodDef SCA_PropertySensor::Methods[] = {
321 {"getType", (PyCFunction) SCA_PropertySensor::sPyGetType, METH_VARARGS, GetType_doc},
322 {"setType", (PyCFunction) SCA_PropertySensor::sPySetType, METH_VARARGS, SetType_doc},
323 {"getProperty", (PyCFunction) SCA_PropertySensor::sPyGetProperty, METH_VARARGS, GetProperty_doc},
324 {"setProperty", (PyCFunction) SCA_PropertySensor::sPySetProperty, METH_VARARGS, SetProperty_doc},
325 {"getValue", (PyCFunction) SCA_PropertySensor::sPyGetValue, METH_VARARGS, GetValue_doc},
326 {"setValue", (PyCFunction) SCA_PropertySensor::sPySetValue, METH_VARARGS, SetValue_doc},
327 {NULL,NULL} //Sentinel
330 PyObject* SCA_PropertySensor::_getattr(const STR_String& attr) {
331 _getattr_up(SCA_ISensor); /* implicit return! */
335 char SCA_PropertySensor::GetType_doc[] =
337 "\tReturns the type of check this sensor performs.\n";
338 PyObject* SCA_PropertySensor::PyGetType(PyObject* self, PyObject* args, PyObject* kwds)
340 return PyInt_FromLong(m_checktype);
344 char SCA_PropertySensor::SetType_doc[] =
346 "\t- type: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL,\n"
347 "\t KX_PROPSENSOR_INTERVAL, KX_PROPSENSOR_CHANGED,\n"
348 "\t or KX_PROPSENSOR_EXPRESSION.\n"
349 "\tSet the type of check to perform.\n";
350 PyObject* SCA_PropertySensor::PySetType(PyObject* self, PyObject* args, PyObject* kwds)
354 if (!PyArg_ParseTuple(args, "i", &typeArg)) {
358 if ( (typeArg > KX_PROPSENSOR_NODEF)
359 && (typeArg < KX_PROPSENSOR_MAX) ) {
360 m_checktype = typeArg;
367 char SCA_PropertySensor::GetProperty_doc[] =
369 "\tReturn the property with which the sensor operates.\n";
370 PyObject* SCA_PropertySensor::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds)
372 return PyString_FromString(m_checkpropname);
376 char SCA_PropertySensor::SetProperty_doc[] =
377 "setProperty(name)\n"
379 "\tSets the property with which to operate. If there is no property\n"
380 "\tof this name, the call is ignored.\n";
381 PyObject* SCA_PropertySensor::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds)
383 /* We should query whether the name exists. Or should we create a prop */
385 char *propNameArg = NULL;
387 if (!PyArg_ParseTuple(args, "s", &propNameArg)) {
391 if (FindIdentifier(STR_String(propNameArg))) {
392 m_checkpropname = propNameArg;
394 ; /* error: bad property name */
401 char SCA_PropertySensor::GetValue_doc[] =
403 "\tReturns the value with which the sensor operates.\n";
404 PyObject* SCA_PropertySensor::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds)
406 return PyString_FromString(m_checkpropval);
410 char SCA_PropertySensor::SetValue_doc[] =
412 "\t- value: string\n"
413 "\tSet the value with which the sensor operates. If the value\n"
414 "\tis not compatible with the type of the property, the subsequent\n"
415 "\t action is ignored.\n";
416 PyObject* SCA_PropertySensor::PySetValue(PyObject* self, PyObject* args, PyObject* kwds)
418 /* Here, we need to check whether the value is 'valid' for this property.*/
419 /* We know that the property exists, or is NULL. */
420 char *propValArg = NULL;
422 if(!PyArg_ParseTuple(args, "s", &propValArg)) {
426 if (validValueForProperty(propValArg, m_checkpropname)) {
427 m_checkpropval = propValArg;