Blender V2.61 - r43446

SCA_ISensor.cpp

Go to the documentation of this file.
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 */