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