|
Blender
V2.59
|
00001 /* 00002 * Abstract class for sensor logic bricks 00003 * 00004 * $Id: SCA_ISensor.cpp 35169 2011-02-25 13:32:11Z jesterking $ 00005 * 00006 * ***** BEGIN GPL LICENSE BLOCK ***** 00007 * 00008 * This program is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU General Public License 00010 * as published by the Free Software Foundation; either version 2 00011 * of the License, or (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software Foundation, 00020 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00021 * 00022 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00023 * All rights reserved. 00024 * 00025 * The Original Code is: all of this file. 00026 * 00027 * Contributor(s): none yet. 00028 * 00029 * ***** END GPL LICENSE BLOCK ***** 00030 */ 00031 00037 #include <stddef.h> 00038 00039 #include "SCA_ISensor.h" 00040 #include "SCA_EventManager.h" 00041 #include "SCA_LogicManager.h" 00042 // needed for IsTriggered() 00043 #include "SCA_PythonController.h" 00044 00045 #include <stdio.h> 00046 00047 /* Native functions */ 00048 void SCA_ISensor::ReParent(SCA_IObject* parent) 00049 { 00050 SCA_ILogicBrick::ReParent(parent); 00051 // will be done when the sensor is activated 00052 //m_eventmgr->RegisterSensor(this); 00053 //this->SetActive(false); 00054 } 00055 00056 00057 SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj, 00058 class SCA_EventManager* eventmgr) : 00059 SCA_ILogicBrick(gameobj) 00060 { 00061 m_links = 0; 00062 m_suspended = false; 00063 m_invert = false; 00064 m_level = false; 00065 m_tap = false; 00066 m_reset = false; 00067 m_pos_ticks = 0; 00068 m_neg_ticks = 0; 00069 m_pos_pulsemode = false; 00070 m_neg_pulsemode = false; 00071 m_pulse_frequency = 0; 00072 m_state = false; 00073 m_prev_state = false; 00074 00075 m_eventmgr = eventmgr; 00076 } 00077 00078 00079 SCA_ISensor::~SCA_ISensor() 00080 { 00081 // intentionally empty 00082 } 00083 00084 void SCA_ISensor::ProcessReplica() 00085 { 00086 SCA_ILogicBrick::ProcessReplica(); 00087 m_linkedcontrollers.clear(); 00088 } 00089 00090 bool SCA_ISensor::IsPositiveTrigger() { 00091 bool result = false; 00092 00093 if (m_eventval) { 00094 result = (m_eventval->GetNumber() != 0.0); 00095 } 00096 if (m_invert) { 00097 result = !result; 00098 } 00099 00100 return result; 00101 } 00102 00103 void SCA_ISensor::SetPulseMode(bool posmode, 00104 bool negmode, 00105 int freq) { 00106 m_pos_pulsemode = posmode; 00107 m_neg_pulsemode = negmode; 00108 m_pulse_frequency = freq; 00109 } 00110 00111 void SCA_ISensor::SetInvert(bool inv) { 00112 m_invert = inv; 00113 } 00114 00115 void SCA_ISensor::SetLevel(bool lvl) { 00116 m_level = lvl; 00117 } 00118 00119 void SCA_ISensor::SetTap(bool tap) { 00120 m_tap = tap; 00121 } 00122 00123 00124 double SCA_ISensor::GetNumber() { 00125 return GetState(); 00126 } 00127 00128 void SCA_ISensor::Suspend() { 00129 m_suspended = true; 00130 } 00131 00132 bool SCA_ISensor::IsSuspended() { 00133 return m_suspended; 00134 } 00135 00136 void SCA_ISensor::Resume() { 00137 m_suspended = false; 00138 } 00139 00140 void SCA_ISensor::Init() { 00141 printf("Sensor %s has no init function, please report this bug to Blender.org\n", m_name.Ptr()); 00142 } 00143 00144 void SCA_ISensor::DecLink() { 00145 m_links--; 00146 if (m_links < 0) 00147 { 00148 printf("Warning: sensor %s has negative m_links: %d\n", m_name.Ptr(), m_links); 00149 m_links = 0; 00150 } 00151 if (!m_links) 00152 { 00153 // sensor is detached from all controllers, remove it from manager 00154 UnregisterToManager(); 00155 } 00156 } 00157 00158 void SCA_ISensor::RegisterToManager() 00159 { 00160 // sensor is just activated, initialize it 00161 Init(); 00162 m_state = false; 00163 m_eventmgr->RegisterSensor(this); 00164 } 00165 00166 void SCA_ISensor::Replace_EventManager(class SCA_LogicManager* logicmgr) 00167 { 00168 if(m_links) { /* true if we're used currently */ 00169 00170 m_eventmgr->RemoveSensor(this); 00171 m_eventmgr= logicmgr->FindEventManager(m_eventmgr->GetType()); 00172 m_eventmgr->RegisterSensor(this); 00173 } 00174 else { 00175 m_eventmgr= logicmgr->FindEventManager(m_eventmgr->GetType()); 00176 } 00177 } 00178 00179 void SCA_ISensor::LinkToController(SCA_IController* controller) 00180 { 00181 m_linkedcontrollers.push_back(controller); 00182 } 00183 00184 void SCA_ISensor::UnlinkController(SCA_IController* controller) 00185 { 00186 std::vector<class SCA_IController*>::iterator contit; 00187 for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit) 00188 { 00189 if ((*contit) == controller) 00190 { 00191 *contit = m_linkedcontrollers.back(); 00192 m_linkedcontrollers.pop_back(); 00193 return; 00194 } 00195 } 00196 printf("Missing link from sensor %s:%s to controller %s:%s\n", 00197 m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), 00198 controller->GetParent()->GetName().ReadPtr(), controller->GetName().ReadPtr()); 00199 } 00200 00201 void SCA_ISensor::UnlinkAllControllers() 00202 { 00203 std::vector<class SCA_IController*>::iterator contit; 00204 for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit) 00205 { 00206 (*contit)->UnlinkSensor(this); 00207 } 00208 m_linkedcontrollers.clear(); 00209 } 00210 00211 void SCA_ISensor::UnregisterToManager() 00212 { 00213 m_eventmgr->RemoveSensor(this); 00214 m_links = 0; 00215 } 00216 00217 void SCA_ISensor::ActivateControllers(class SCA_LogicManager* logicmgr) 00218 { 00219 for(vector<SCA_IController*>::const_iterator c= m_linkedcontrollers.begin(); 00220 c!=m_linkedcontrollers.end();++c) 00221 { 00222 SCA_IController* contr = *c; 00223 if (contr->IsActive()) 00224 logicmgr->AddTriggeredController(contr, this); 00225 } 00226 } 00227 00228 void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr) 00229 { 00230 00231 // calculate if a __triggering__ is wanted 00232 // don't evaluate a sensor that is not connected to any controller 00233 if (m_links && !m_suspended) { 00234 bool result = this->Evaluate(); 00235 // store the state for the rest of the logic system 00236 m_prev_state = m_state; 00237 m_state = this->IsPositiveTrigger(); 00238 if (result) { 00239 // the sensor triggered this frame 00240 if (m_state || !m_tap) { 00241 ActivateControllers(logicmgr); 00242 // reset these counters so that pulse are synchronized with transition 00243 m_pos_ticks = 0; 00244 m_neg_ticks = 0; 00245 } else 00246 { 00247 result = false; 00248 } 00249 } else 00250 { 00251 /* First, the pulsing behaviour, if pulse mode is 00252 * active. It seems something goes wrong if pulse mode is 00253 * not set :( */ 00254 if (m_pos_pulsemode) { 00255 m_pos_ticks++; 00256 if (m_pos_ticks > m_pulse_frequency) { 00257 if ( m_state ) 00258 { 00259 ActivateControllers(logicmgr); 00260 result = true; 00261 } 00262 m_pos_ticks = 0; 00263 } 00264 } 00265 // negative pulse doesn't make sense in tap mode, skip 00266 if (m_neg_pulsemode && !m_tap) 00267 { 00268 m_neg_ticks++; 00269 if (m_neg_ticks > m_pulse_frequency) { 00270 if (!m_state ) 00271 { 00272 ActivateControllers(logicmgr); 00273 result = true; 00274 } 00275 m_neg_ticks = 0; 00276 } 00277 } 00278 } 00279 if (m_tap) 00280 { 00281 // in tap mode: we send always a negative pulse immediately after a positive pulse 00282 if (!result) 00283 { 00284 // the sensor did not trigger on this frame 00285 if (m_prev_state) 00286 { 00287 // but it triggered on previous frame => send a negative pulse 00288 ActivateControllers(logicmgr); 00289 result = true; 00290 } 00291 // in any case, absence of trigger means sensor off 00292 m_state = false; 00293 } 00294 } 00295 if (!result && m_level) 00296 { 00297 // This level sensor is connected to at least one controller that was just made 00298 // active but it did not generate an event yet, do it now to those controllers only 00299 for(vector<SCA_IController*>::const_iterator c= m_linkedcontrollers.begin(); 00300 c!=m_linkedcontrollers.end();++c) 00301 { 00302 SCA_IController* contr = *c; 00303 if (contr->IsJustActivated()) 00304 logicmgr->AddTriggeredController(contr, this); 00305 } 00306 } 00307 } 00308 } 00309 00310 #ifdef WITH_PYTHON 00311 00312 /* ----------------------------------------------- */ 00313 /* Python Functions */ 00314 /* ----------------------------------------------- */ 00315 00316 KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset, 00317 "reset()\n" 00318 "\tReset sensor internal state, effect depends on the type of sensor and settings.\n" 00319 "\tThe sensor is put in its initial state as if it was just activated.\n") 00320 { 00321 Init(); 00322 m_prev_state = false; 00323 Py_RETURN_NONE; 00324 } 00325 00326 /* ----------------------------------------------- */ 00327 /* Python Integration Hooks */ 00328 /* ----------------------------------------------- */ 00329 00330 PyTypeObject SCA_ISensor::Type = { 00331 PyVarObject_HEAD_INIT(NULL, 0) 00332 "SCA_ISensor", 00333 sizeof(PyObjectPlus_Proxy), 00334 0, 00335 py_base_dealloc, 00336 0, 00337 0, 00338 0, 00339 0, 00340 py_base_repr, 00341 0,0,0,0,0,0,0,0,0, 00342 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 00343 0,0,0,0,0,0,0, 00344 Methods, 00345 0, 00346 0, 00347 &SCA_ILogicBrick::Type, 00348 0,0,0,0,0,0, 00349 py_base_new 00350 }; 00351 00352 PyMethodDef SCA_ISensor::Methods[] = { 00353 KX_PYMETHODTABLE_NOARGS(SCA_ISensor, reset), 00354 {NULL,NULL} //Sentinel 00355 }; 00356 00357 PyAttributeDef SCA_ISensor::Attributes[] = { 00358 KX_PYATTRIBUTE_BOOL_RW("usePosPulseMode",SCA_ISensor,m_pos_pulsemode), 00359 KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode), 00360 KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency), 00361 KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert), 00362 KX_PYATTRIBUTE_BOOL_RW_CHECK("level",SCA_ISensor,m_level,pyattr_check_level), 00363 KX_PYATTRIBUTE_BOOL_RW_CHECK("tap",SCA_ISensor,m_tap,pyattr_check_tap), 00364 KX_PYATTRIBUTE_RO_FUNCTION("triggered", SCA_ISensor, pyattr_get_triggered), 00365 KX_PYATTRIBUTE_RO_FUNCTION("positive", SCA_ISensor, pyattr_get_positive), 00366 KX_PYATTRIBUTE_RO_FUNCTION("status", SCA_ISensor, pyattr_get_status), 00367 KX_PYATTRIBUTE_RO_FUNCTION("pos_ticks", SCA_ISensor, pyattr_get_posTicks), 00368 KX_PYATTRIBUTE_RO_FUNCTION("neg_ticks", SCA_ISensor, pyattr_get_negTicks), 00369 { NULL } //Sentinel 00370 }; 00371 00372 00373 PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00374 { 00375 SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); 00376 int retval = 0; 00377 if (SCA_PythonController::m_sCurrentController) 00378 retval = SCA_PythonController::m_sCurrentController->IsTriggered(self); 00379 return PyLong_FromSsize_t(retval); 00380 } 00381 00382 PyObject* SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00383 { 00384 SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); 00385 return PyLong_FromSsize_t(self->GetState()); 00386 } 00387 00388 PyObject* SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00389 { 00390 SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); 00391 int status = 0; 00392 if (self->GetState()) 00393 { 00394 if (self->GetState() == self->GetPrevState()) 00395 { 00396 status = 2; 00397 } 00398 else 00399 { 00400 status = 1; 00401 } 00402 } 00403 else if (self->GetState() != self->GetPrevState()) 00404 { 00405 status = 3; 00406 } 00407 return PyLong_FromSsize_t(status); 00408 } 00409 00410 PyObject* SCA_ISensor::pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00411 { 00412 SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); 00413 return PyLong_FromLong(self->GetPosTicks()); 00414 } 00415 00416 PyObject* SCA_ISensor::pyattr_get_negTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00417 { 00418 SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); 00419 return PyLong_FromLong(self->GetNegTicks()); 00420 } 00421 00422 int SCA_ISensor::pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00423 { 00424 SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); 00425 if (self->m_level) 00426 self->m_tap = false; 00427 return 0; 00428 } 00429 00430 int SCA_ISensor::pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00431 { 00432 SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); 00433 if (self->m_tap) 00434 self->m_level = false; 00435 return 0; 00436 } 00437 #endif // WITH_PYTHON 00438 00439 /* eof */