diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-06-09 00:08:19 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-06-09 00:08:19 +0400 |
commit | c8b4cf92067ffeb625aa39003baf5d8f7c3f0025 (patch) | |
tree | c6c50dbc3d90a65fca6c1ca56a93e4a57cf7e154 /source/gameengine/GameLogic | |
parent | e93db433a086a3e739c0f4026cd500f0b595b0f1 (diff) | |
parent | d76a6f5231c015c35123d22e1f5c3ffcdfbf9bbd (diff) |
2.50:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r19820:HEAD
Notes:
* Game and sequencer RNA, and sequencer header are now out of date
a bit after changes in trunk.
* I didn't know how to port these bugfixes, most likely they are
not needed anymore.
* Fix "duplicate strip" always increase the user count for ipo.
* IPO pinning on sequencer strips was lost during Undo.
Diffstat (limited to 'source/gameengine/GameLogic')
72 files changed, 1494 insertions, 1098 deletions
diff --git a/source/gameengine/GameLogic/CMakeLists.txt b/source/gameengine/GameLogic/CMakeLists.txt index a7519196d50..7e2bc85bd1f 100644 --- a/source/gameengine/GameLogic/CMakeLists.txt +++ b/source/gameengine/GameLogic/CMakeLists.txt @@ -31,6 +31,7 @@ SET(INC ../../../source/kernel/gen_system ../../../intern/string ../../../source/gameengine/Expressions + ../../../source/gameengine/SceneGraph ../../../intern/moto/include ../../../source/gameengine/Rasterizer ${PYTHON_INC} diff --git a/source/gameengine/GameLogic/Joystick/Makefile b/source/gameengine/GameLogic/Joystick/Makefile index 7016f1ed16f..02def1cec62 100644 --- a/source/gameengine/GameLogic/Joystick/Makefile +++ b/source/gameengine/GameLogic/Joystick/Makefile @@ -40,5 +40,5 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) CPPFLAGS += $(NAN_SDLCFLAGS) - +CPPFLAGS += -I../../SceneGraph CPPFLAGS += -I../../../kernel/gen_system diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp index c300baa9bd4..d83179d4f80 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp @@ -38,11 +38,9 @@ SCA_Joystick::SCA_Joystick(short int index) : m_joyindex(index), m_prec(3200), - m_buttonnum(-2), m_axismax(-1), m_buttonmax(-1), m_hatmax(-1), - m_hatdir(-2), m_isinit(0), m_istrig_axis(0), m_istrig_button(0), @@ -50,6 +48,10 @@ SCA_Joystick::SCA_Joystick(short int index) { for(int i=0; i<JOYAXIS_MAX; i++) m_axis_array[i]= 0; + + for(int i=0; i<JOYHAT_MAX; i++) + m_hat_array[i]= 0; + #ifndef DISABLE_SDL m_private = new PrivateData(); #endif @@ -65,6 +67,7 @@ SCA_Joystick::~SCA_Joystick() } SCA_Joystick *SCA_Joystick::m_instance[JOYINDEX_MAX]; +int SCA_Joystick::m_joynum = 0; int SCA_Joystick::m_refCount = 0; SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) @@ -85,6 +88,9 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) echo("Error-Initializing-SDL: " << SDL_GetError()); return NULL; } + + m_joynum = SDL_NumJoysticks(); + for (i=0; i<JOYINDEX_MAX; i++) { m_instance[i] = new SCA_Joystick(i); m_instance[i]->CreateJoystickDevice(); @@ -152,12 +158,13 @@ bool SCA_Joystick::aAxisIsPositive(int axis_single) bool SCA_Joystick::aAnyButtonPressIsPositive(void) { - return (m_buttonnum==-2) ? false : true; -} - -bool SCA_Joystick::aAnyButtonReleaseIsPositive(void) -{ - return (m_buttonnum==-2) ? true : false; + /* this is needed for the "all events" option + * so we know if there are no buttons pressed */ + for (int i=0; i<m_buttonmax; i++) + if (SDL_JoystickGetButton(m_private->m_joystick, i)) + return true; + + return false; } bool SCA_Joystick::aButtonPressIsPositive(int button) @@ -184,20 +191,9 @@ bool SCA_Joystick::aButtonReleaseIsPositive(int button) } -bool SCA_Joystick::aHatIsPositive(int dir) +bool SCA_Joystick::aHatIsPositive(int hatnum, int dir) { - bool result; - int res = pGetHat(dir); - res == dir? result = true : result = false; - return result; -} - -int SCA_Joystick::pGetHat(int direction) -{ - if(direction == m_hatdir){ - return m_hatdir; - } - return 0; + return (GetHat(hatnum)==dir) ? true : false; } int SCA_Joystick::GetNumberOfAxes() @@ -220,12 +216,17 @@ int SCA_Joystick::GetNumberOfHats() bool SCA_Joystick::CreateJoystickDevice(void) { #ifdef DISABLE_SDL + m_isinit = true; + m_axismax = m_buttonmax = m_hatmax = 0; return false; #else if(m_isinit == false){ - if (m_joyindex>=SDL_NumJoysticks()) { + if (m_joyindex>=m_joynum) { // don't print a message, because this is done anyway //echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); + + // Need this so python args can return empty lists + m_axismax = m_buttonmax = m_hatmax = 0; return false; } @@ -237,11 +238,16 @@ bool SCA_Joystick::CreateJoystickDevice(void) /* must run after being initialized */ m_axismax = SDL_JoystickNumAxes(m_private->m_joystick); - if (m_axismax > JOYAXIS_MAX) m_axismax= JOYAXIS_MAX; /* very unlikely */ - m_buttonmax = SDL_JoystickNumButtons(m_private->m_joystick); m_hatmax = SDL_JoystickNumHats(m_private->m_joystick); + if (m_axismax > JOYAXIS_MAX) m_axismax= JOYAXIS_MAX; /* very unlikely */ + else if (m_axismax < 0) m_axismax = 0; + + if (m_hatmax > JOYHAT_MAX) m_hatmax= JOYHAT_MAX; /* very unlikely */ + else if(m_hatmax<0) m_hatmax= 0; + + if(m_buttonmax<0) m_buttonmax= 0; } return true; @@ -271,15 +277,6 @@ int SCA_Joystick::Connected(void) return 0; } -void SCA_Joystick::pFillAxes() -{ -#ifndef DISABLE_SDL - for(int i=0; i<m_axismax; i++) - m_axis_array[i]= SDL_JoystickGetAxis(m_private->m_joystick, i); -#endif -} - - int SCA_Joystick::pGetAxis(int axisnum, int udlr) { #ifndef DISABLE_SDL diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h index 53cd65cd495..6324b898247 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h @@ -44,6 +44,7 @@ class SCA_Joystick { static SCA_Joystick *m_instance[JOYINDEX_MAX]; + static int m_joynum; static int m_refCount; class PrivateData; @@ -53,9 +54,14 @@ class SCA_Joystick int m_joyindex; /* - *support for 2 axes + *support for JOYAXIS_MAX axes (in pairs) */ int m_axis_array[JOYAXIS_MAX]; + + /* + *support for JOYHAT_MAX hats (each is a direction) + */ + int m_hat_array[JOYHAT_MAX]; /* * Precision or range of the axes @@ -63,24 +69,6 @@ class SCA_Joystick int m_prec; /* - * multiple axis values stored here - */ - int m_axisnum; - int m_axisvalue; - - /* - * max # of axes avail - */ - /*disabled - int m_axismax; - */ - - /* - * button values stored here - */ - int m_buttonnum; - - /* * max # of buttons avail */ @@ -88,18 +76,6 @@ class SCA_Joystick int m_buttonmax; int m_hatmax; - /* - * hat values stored here - */ - int m_hatnum; - int m_hatdir; - - /* - - * max # of hats avail - disabled - int m_hatmax; - */ /* is the joystick initialized ?*/ bool m_isinit; @@ -136,7 +112,6 @@ class SCA_Joystick /* * fills the axis mnember values */ - void pFillAxes(void); void pFillButtons(void); /* @@ -149,11 +124,6 @@ class SCA_Joystick */ int pGetAxis(int axisnum, int udlr); - /* - * gets the current hat direction - */ - int pGetHat(int direction); - SCA_Joystick(short int index); ~SCA_Joystick(); @@ -172,10 +142,9 @@ public: bool aAxisIsPositive(int axis_single); /* check a single axis only */ bool aAnyButtonPressIsPositive(void); - bool aAnyButtonReleaseIsPositive(void); bool aButtonPressIsPositive(int button); bool aButtonReleaseIsPositive(int button); - bool aHatIsPositive(int dir); + bool aHatIsPositive(int hatnum, int dir); /* * precision is default '3200' which is overridden by input @@ -186,13 +155,9 @@ public: int GetAxisPosition(int index){ return m_axis_array[index]; } - - int GetButton(void){ - return m_buttonnum; - } - int GetHat(void){ - return m_hatdir; + int GetHat(int index){ + return m_hat_array[index]; } int GetThreshold(void){ diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h index 636c4dd5a42..70619ff337a 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h @@ -40,6 +40,8 @@ #define JOYINDEX_MAX 8 #define JOYAXIS_MAX 16 +#define JOYBUT_MAX 18 +#define JOYHAT_MAX 4 #define JOYAXIS_RIGHT 0 #define JOYAXIS_UP 1 diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp index 8e190060e95..53d3be35f92 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp @@ -35,44 +35,37 @@ #ifndef DISABLE_SDL void SCA_Joystick::OnAxisMotion(SDL_Event* sdl_event) { - pFillAxes(); - m_axisnum = sdl_event->jaxis.axis; - m_axisvalue = sdl_event->jaxis.value; + if(sdl_event->jaxis.axis >= JOYAXIS_MAX) + return; + + m_axis_array[sdl_event->jaxis.axis]= sdl_event->jaxis.value; m_istrig_axis = 1; } - +/* See notes below in the event loop */ void SCA_Joystick::OnHatMotion(SDL_Event* sdl_event) { - m_hatdir = sdl_event->jhat.value; - m_hatnum = sdl_event->jhat.hat; + if(sdl_event->jhat.hat >= JOYHAT_MAX) + return; + + m_hat_array[sdl_event->jhat.hat]= sdl_event->jhat.value; m_istrig_hat = 1; } +/* See notes below in the event loop */ void SCA_Joystick::OnButtonUp(SDL_Event* sdl_event) { m_istrig_button = 1; - - /* this is needed for the "all events" option - * so we know if there are no buttons pressed */ - int i; - for (i=0; i<m_buttonmax; i++) { - if (SDL_JoystickGetButton(m_private->m_joystick, i)) { - m_buttonnum = i; - return; - } - } - m_buttonnum = -2; } void SCA_Joystick::OnButtonDown(SDL_Event* sdl_event) { - if(sdl_event->jbutton.button <= m_buttonmax) /* unsigned int so always above 0 */ - { - m_istrig_button = 1; - m_buttonnum = sdl_event->jbutton.button; - } + //if(sdl_event->jbutton.button > m_buttonmax) /* unsigned int so always above 0 */ + // return; + // sdl_event->jbutton.button; + + m_istrig_button = 1; } @@ -81,22 +74,27 @@ void SCA_Joystick::OnNothing(SDL_Event* sdl_event) m_istrig_axis = m_istrig_button = m_istrig_hat = 0; } -/* only handle events for 1 joystick */ - void SCA_Joystick::HandleEvents(void) { SDL_Event sdl_event; int i; - for (i=0; i<JOYINDEX_MAX; i++) { + for (i=0; i<m_joynum; i++) { /* could use JOYINDEX_MAX but no reason to */ if(SCA_Joystick::m_instance[i]) SCA_Joystick::m_instance[i]->OnNothing(&sdl_event); } - if(SDL_PollEvent(&sdl_event)) + while(SDL_PollEvent(&sdl_event)) { /* Note! m_instance[sdl_event.jaxis.which] * will segfault if over JOYINDEX_MAX, not too nice but what are the chances? */ + + /* Note!, with buttons, this wont care which button is pressed, + * only to set 'm_istrig_button', actual pressed buttons are detected by SDL_JoystickGetButton */ + + /* Note!, if you manage to press and release a button within 1 logic tick + * it wont work as it should */ + switch(sdl_event.type) { case SDL_JOYAXISMOTION: diff --git a/source/gameengine/GameLogic/Makefile b/source/gameengine/GameLogic/Makefile index 355ece6e8bd..a1794a60452 100644 --- a/source/gameengine/GameLogic/Makefile +++ b/source/gameengine/GameLogic/Makefile @@ -39,6 +39,7 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I../Expressions +CPPFLAGS += -I../SceneGraph CPPFLAGS += -I../Rasterizer CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index 251a586308e..caed85b9938 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -64,8 +64,6 @@ CValue* SCA_2DFilterActuator::GetReplica() { SCA_2DFilterActuator* replica = new SCA_2DFilterActuator(*this); replica->ProcessReplica(); - CValue::AddDataToReplica(replica); - return replica; } @@ -97,7 +95,7 @@ bool SCA_2DFilterActuator::Update() } -void SCA_2DFilterActuator::SetShaderText(STR_String text) +void SCA_2DFilterActuator::SetShaderText(const char *text) { m_shaderText = text; } @@ -110,8 +108,13 @@ void SCA_2DFilterActuator::SetShaderText(STR_String text) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_2DFilterActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_2DFilterActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -146,8 +149,8 @@ PyMethodDef SCA_2DFilterActuator::Methods[] = { PyAttributeDef SCA_2DFilterActuator::Attributes[] = { KX_PYATTRIBUTE_STRING_RW("shaderText", 0, 64000, false, SCA_2DFilterActuator, m_shaderText), KX_PYATTRIBUTE_SHORT_RW("disableMotionBlur", 0, 1, true, SCA_2DFilterActuator, m_disableMotionBlur), - KX_PYATTRIBUTE_ENUM_RW("type",RAS_2DFilterManager::RAS_2DFILTER_ENABLED,RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS,false,SCA_2DFilterActuator,m_type), - KX_PYATTRIBUTE_INT_RW("passNb", 0, 100, true, SCA_2DFilterActuator, m_int_arg), + KX_PYATTRIBUTE_ENUM_RW("mode",RAS_2DFilterManager::RAS_2DFILTER_ENABLED,RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS,false,SCA_2DFilterActuator,m_type), + KX_PYATTRIBUTE_INT_RW("passNumber", 0, 100, true, SCA_2DFilterActuator, m_int_arg), KX_PYATTRIBUTE_FLOAT_RW("value", 0.0, 100.0, SCA_2DFilterActuator, m_float_arg), { NULL } //Sentinel }; @@ -157,6 +160,10 @@ PyObject* SCA_2DFilterActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* SCA_2DFilterActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int SCA_2DFilterActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h index de0201a4b19..13b9997a010 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h @@ -60,7 +60,7 @@ public: PyTypeObject* T=&Type ); - void SetShaderText(STR_String text); + void SetShaderText(const char *text); virtual ~SCA_2DFilterActuator(); virtual bool Update(); @@ -71,6 +71,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); }; diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp index 1cb03f375cb..87f7c612e7c 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.cpp +++ b/source/gameengine/GameLogic/SCA_ANDController.cpp @@ -66,26 +66,19 @@ void SCA_ANDController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (!sensor->IsPositiveTrigger()) + if (!sensor->GetState()) { sensorresult = false; break; } } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); - } @@ -94,7 +87,7 @@ CValue* SCA_ANDController::GetReplica() { CValue* replica = new SCA_ANDController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -107,8 +100,13 @@ CValue* SCA_ANDController::GetReplica() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_ANDController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_ANDController", sizeof(PyObjectPlus_Proxy), 0, @@ -145,4 +143,8 @@ PyObject* SCA_ANDController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_ANDController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ANDController.h b/source/gameengine/GameLogic/SCA_ANDController.h index fdb93d0fc42..9a359d57cb4 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.h +++ b/source/gameengine/GameLogic/SCA_ANDController.h @@ -49,6 +49,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp b/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp index 768a3a45937..a80b2af55c8 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp @@ -51,17 +51,19 @@ SCA_ActuatorEventManager::~SCA_ActuatorEventManager() void SCA_ActuatorEventManager::NextFrame() { // check for changed actuator - for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*it)->Activate(m_logicmgr,NULL); + (*it)->Activate(m_logicmgr); } } void SCA_ActuatorEventManager::UpdateFrame() { // update the state of actuator before executing them - for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + SG_DList::iterator<SCA_ActuatorSensor> it(m_sensors); + for (it.begin();!it.end();++it) { - ((SCA_ActuatorSensor*)(*it))->Update(); + (*it)->Update(); } }
\ No newline at end of file diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index acd906ef9dd..4dad65c5a25 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -60,7 +60,7 @@ CValue* SCA_ActuatorSensor::GetReplica() { SCA_ActuatorSensor* replica = new SCA_ActuatorSensor(*this); // m_range_expr must be recalculated on replica! - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); return replica; @@ -89,7 +89,7 @@ SCA_ActuatorSensor::~SCA_ActuatorSensor() -bool SCA_ActuatorSensor::Evaluate(CValue* event) +bool SCA_ActuatorSensor::Evaluate() { if (m_actuator) { @@ -122,8 +122,13 @@ void SCA_ActuatorSensor::Update() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_ActuatorSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_ActuatorSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -165,6 +170,10 @@ PyObject* SCA_ActuatorSensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_ActuatorSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_ActuatorSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); } diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h index 21960993497..6655e08dc70 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h @@ -52,7 +52,7 @@ public: virtual ~SCA_ActuatorSensor(); virtual CValue* GetReplica(); virtual void Init(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void ReParent(SCA_IObject* parent); void Update(); @@ -62,6 +62,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* 3. setProperty */ diff --git a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp index 4cd2dfba994..dd3b55abcc9 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp @@ -51,9 +51,10 @@ SCA_AlwaysEventManager::SCA_AlwaysEventManager(class SCA_LogicManager* logicmgr) void SCA_AlwaysEventManager::NextFrame() { - for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*i)->Activate(m_logicmgr, NULL); + (*it)->Activate(m_logicmgr); } } diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp index b7ecb0233a1..ff02680f191 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp @@ -72,7 +72,7 @@ CValue* SCA_AlwaysSensor::GetReplica() { CValue* replica = new SCA_AlwaysSensor(*this);//m_float,GetName()); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -86,7 +86,7 @@ bool SCA_AlwaysSensor::IsPositiveTrigger() -bool SCA_AlwaysSensor::Evaluate(CValue* event) +bool SCA_AlwaysSensor::Evaluate() { /* Nice! :) */ //return true; @@ -105,8 +105,13 @@ bool SCA_AlwaysSensor::Evaluate(CValue* event) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_AlwaysSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_AlwaysSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -143,4 +148,8 @@ PyObject* SCA_AlwaysSensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_AlwaysSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h index 87949babf59..0f85a641ef1 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.h +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h @@ -43,7 +43,7 @@ public: PyTypeObject* T =&Type); virtual ~SCA_AlwaysSensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); @@ -53,7 +53,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); - + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index 44a0175d916..dcdae0b4e75 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -77,7 +77,7 @@ CValue* SCA_DelaySensor::GetReplica() { CValue* replica = new SCA_DelaySensor(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -89,7 +89,7 @@ bool SCA_DelaySensor::IsPositiveTrigger() return (m_invert ? !m_lastResult : m_lastResult); } -bool SCA_DelaySensor::Evaluate(CValue* event) +bool SCA_DelaySensor::Evaluate() { bool trigger = false; bool result; @@ -131,8 +131,13 @@ bool SCA_DelaySensor::Evaluate(CValue* event) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_DelaySensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_DelaySensor", sizeof(PyObjectPlus_Proxy), 0, @@ -182,6 +187,10 @@ PyObject* SCA_DelaySensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_DelaySensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_DelaySensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); } diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h index 8da76ff7189..5ccb33f8a16 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.h +++ b/source/gameengine/GameLogic/SCA_DelaySensor.h @@ -51,7 +51,7 @@ public: PyTypeObject* T =&Type); virtual ~SCA_DelaySensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); @@ -61,6 +61,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* setProperty */ diff --git a/source/gameengine/GameLogic/SCA_EventManager.cpp b/source/gameengine/GameLogic/SCA_EventManager.cpp index e4fd0379597..d1301541a0a 100644 --- a/source/gameengine/GameLogic/SCA_EventManager.cpp +++ b/source/gameengine/GameLogic/SCA_EventManager.cpp @@ -28,6 +28,7 @@ #include <assert.h> #include "SCA_EventManager.h" +#include "SCA_ISensor.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -43,16 +44,18 @@ SCA_EventManager::SCA_EventManager(EVENT_MANAGER_TYPE mgrtype) SCA_EventManager::~SCA_EventManager() { + // all sensors should be removed + assert(m_sensors.Empty()); } void SCA_EventManager::RegisterSensor(class SCA_ISensor* sensor) { - m_sensors.insert(sensor); + m_sensors.AddBack(sensor); } void SCA_EventManager::RemoveSensor(class SCA_ISensor* sensor) { - m_sensors.erase(sensor); + sensor->Delink(); } void SCA_EventManager::NextFrame(double curtime, double fixedtime) diff --git a/source/gameengine/GameLogic/SCA_EventManager.h b/source/gameengine/GameLogic/SCA_EventManager.h index 9dbb5a6d24f..5ff55849bfe 100644 --- a/source/gameengine/GameLogic/SCA_EventManager.h +++ b/source/gameengine/GameLogic/SCA_EventManager.h @@ -33,11 +33,14 @@ #include <set> #include <algorithm> +#include "SG_DList.h" + class SCA_EventManager { protected: // use a set to speed-up insertion/removal - std::set <class SCA_ISensor*> m_sensors; + //std::set <class SCA_ISensor*> m_sensors; + SG_DList m_sensors; public: enum EVENT_MANAGER_TYPE { diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp index 352a39a6fea..8e044b89c71 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.cpp +++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp @@ -70,7 +70,7 @@ CValue* SCA_ExpressionController::GetReplica() replica->m_exprText = m_exprText; replica->m_exprCache = NULL; // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -115,37 +115,14 @@ void SCA_ExpressionController::Trigger(SCA_LogicManager* logicmgr) value->Release(); } - //m_exprCache->Release(); - //m_exprCache = NULL; } - /* - - for (vector<SCA_ISensor*>::const_iterator is=m_linkedsensors.begin(); - !(is==m_linkedsensors.end());is++) - { - SCA_ISensor* sensor = *is; - if (!sensor->IsPositiveTrigger()) - { - sensorresult = false; - break; - } - } - - */ - - CValue* newevent = new CBoolValue(expressionresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { SCA_IActuator* actua = *i; - logicmgr->AddActiveActuator(actua,newevent); + logicmgr->AddActiveActuator(actua,expressionresult); } - //printf("expr %d.",expressionresult); - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); } @@ -161,7 +138,7 @@ CValue* SCA_ExpressionController::FindIdentifier(const STR_String& identifiernam SCA_ISensor* sensor = *is; if (sensor->GetName() == identifiername) { - identifierval = new CBoolValue(sensor->IsPositiveTrigger()); + identifierval = new CBoolValue(sensor->GetState()); //identifierval = sensor->AddRef(); } diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h index 2936742be19..6a34d7b2dff 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.h +++ b/source/gameengine/GameLogic/SCA_ExpressionController.h @@ -60,6 +60,7 @@ public: /* --------------------------------------------------------------------- */ // virtual PyObject* py_getattro(PyObject *attr); +// virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_IActuator.cpp b/source/gameengine/GameLogic/SCA_IActuator.cpp index 309f3108418..be7c2651686 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.cpp +++ b/source/gameengine/GameLogic/SCA_IActuator.cpp @@ -37,53 +37,13 @@ using namespace std; SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj, PyTypeObject* T) : SCA_ILogicBrick(gameobj,T), - m_links(0) + m_links(0), + m_posevent(false), + m_negevent(false) { // nothing to do } - - -void SCA_IActuator::AddEvent(CValue* event) -{ - m_events.push_back(event); -} - - - -void SCA_IActuator::RemoveAllEvents() -{ // remove event queue! - for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++) - { - (*i)->Release(); - } - m_events.clear(); -} - - - - - -bool SCA_IActuator::IsNegativeEvent() const -{ - bool bPositiveEvent(false); - bool bNegativeEvent(false); - - for (vector<CValue*>::const_iterator i=m_events.begin(); i!=m_events.end();++i) - { - if ((*i)->GetNumber() == 0.0f) - { - bNegativeEvent = true; - } else { - bPositiveEvent = true; - } - } - - // if at least 1 positive event, return false - - return !bPositiveEvent && bNegativeEvent; -} - bool SCA_IActuator::Update(double curtime, bool frame) { if (frame) @@ -98,9 +58,34 @@ bool SCA_IActuator::Update() return false; } +void SCA_IActuator::Activate(SG_DList& head) +{ + if (QEmpty()) + { + InsertActiveQList(m_gameobj->m_activeActuators); + head.AddBack(&m_gameobj->m_activeActuators); + } +} + +// this function is only used to deactivate actuators outside the logic loop +// e.g. when an object is deleted. +void SCA_IActuator::Deactivate() +{ + if (QDelink()) + { + // the actuator was in the active list + if (m_gameobj->m_activeActuators.QEmpty()) + // the owner object has no more active actuators, remove it from the global list + m_gameobj->m_activeActuators.Delink(); + } +} + + void SCA_IActuator::ProcessReplica() { - m_events.clear(); + SCA_ILogicBrick::ProcessReplica(); + RemoveAllEvents(); + m_linkedcontrollers.clear(); } @@ -119,3 +104,36 @@ void SCA_IActuator::DecLink() m_links = 0; } } + +void SCA_IActuator::LinkToController(SCA_IController* controller) +{ + m_linkedcontrollers.push_back(controller); +} + +void SCA_IActuator::UnlinkController(SCA_IController* controller) +{ + std::vector<class SCA_IController*>::iterator contit; + for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit) + { + if ((*contit) == controller) + { + *contit = m_linkedcontrollers.back(); + m_linkedcontrollers.pop_back(); + return; + } + } + printf("Missing link from actuator %s:%s to controller %s:%s\n", + m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), + controller->GetParent()->GetName().ReadPtr(), controller->GetName().ReadPtr()); +} + +void SCA_IActuator::UnlinkAllControllers() +{ + std::vector<class SCA_IController*>::iterator contit; + for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit) + { + (*contit)->UnlinkActuator(this); + } + m_linkedcontrollers.clear(); +} + diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h index 51bd6454d92..27afcbc386b 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.h +++ b/source/gameengine/GameLogic/SCA_IActuator.h @@ -29,17 +29,32 @@ #ifndef __KX_IACTUATOR #define __KX_IACTUATOR -#include "SCA_ILogicBrick.h" +#include "SCA_IController.h" #include <vector> +/* + * Use of SG_DList : None + * Use of SG_QList : element of activated actuator list of their owner + * Head: SCA_IObject::m_activeActuators + */ class SCA_IActuator : public SCA_ILogicBrick { friend class SCA_LogicManager; protected: int m_links; // number of active links to controllers // when 0, the actuator is automatically stopped - std::vector<CValue*> m_events; - void RemoveAllEvents(); + //std::vector<CValue*> m_events; + bool m_posevent; + bool m_negevent; + + std::vector<class SCA_IController*> m_linkedcontrollers; + + void RemoveAllEvents() + { + m_posevent = false; + m_negevent = false; + } + public: /** @@ -75,7 +90,15 @@ public: /** * Add an event to an actuator. */ - void AddEvent(CValue* event); + //void AddEvent(CValue* event) + void AddEvent(bool event) + { + if (event) + m_posevent = true; + else + m_negevent = true; + } + virtual void ProcessReplica(); /** @@ -84,9 +107,23 @@ public: * not immediately clear. But usually refers to key-up events * or events where no action is required. */ - bool IsNegativeEvent() const; + bool IsNegativeEvent() const + { + return !m_posevent && m_negevent; + } + virtual ~SCA_IActuator(); + /** + * remove this actuator from the list of active actuators + */ + virtual void Deactivate(); + virtual void Activate(SG_DList& head); + + void LinkToController(SCA_IController* controller); + void UnlinkController(class SCA_IController* cont); + void UnlinkAllControllers(); + void ClrLink() { m_links=0; } void IncLink() { m_links++; } void DecLink(); diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index f9c192cae5c..f2c3c83a2d9 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -30,6 +30,8 @@ #include "SCA_LogicManager.h" #include "SCA_IActuator.h" #include "SCA_ISensor.h" +#include "PyObjectPlus.h" +#include "../Ketsji/KX_PythonSeq.h" /* not nice, only need for KX_PythonSeq_CreatePyObject */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -39,7 +41,8 @@ SCA_IController::SCA_IController(SCA_IObject* gameobj, PyTypeObject* T) : SCA_ILogicBrick(gameobj,T), - m_statemask(0) + m_statemask(0), + m_justActivated(false) { } @@ -47,19 +50,19 @@ SCA_IController::SCA_IController(SCA_IObject* gameobj, SCA_IController::~SCA_IController() { - UnlinkAllActuators(); + //UnlinkAllActuators(); } -const std::vector<class SCA_ISensor*>& SCA_IController::GetLinkedSensors() +std::vector<class SCA_ISensor*>& SCA_IController::GetLinkedSensors() { return m_linkedsensors; } -const std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators() +std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators() { return m_linkedactuators; } @@ -68,13 +71,14 @@ const std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators() void SCA_IController::UnlinkAllSensors() { - if (IsActive()) + std::vector<class SCA_ISensor*>::iterator sensit; + for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) { - std::vector<class SCA_ISensor*>::iterator sensit; - for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) + if (IsActive()) { (*sensit)->DecLink(); } + (*sensit)->UnlinkController(this); } m_linkedsensors.clear(); } @@ -83,34 +87,18 @@ void SCA_IController::UnlinkAllSensors() void SCA_IController::UnlinkAllActuators() { - if (IsActive()) + std::vector<class SCA_IActuator*>::iterator actit; + for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit) { - std::vector<class SCA_IActuator*>::iterator actit; - for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit) + if (IsActive()) { (*actit)->DecLink(); } + (*actit)->UnlinkController(this); } m_linkedactuators.clear(); } - - -/* -void SCA_IController::Trigger(SCA_LogicManager* logicmgr) -{ - //for (int i=0;i<m_linkedactuators.size();i++) - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); - !(i==m_linkedactuators.end());i++) - { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - - logicmgr->AddActiveActuator(actua); - } - -} -*/ - void SCA_IController::LinkToActuator(SCA_IActuator* actua) { m_linkedactuators.push_back(actua); @@ -127,18 +115,18 @@ void SCA_IController::UnlinkActuator(class SCA_IActuator* actua) { if ((*actit) == actua) { - break; - } - - } - if (!(actit==m_linkedactuators.end())) - { - if (IsActive()) - { - (*actit)->DecLink(); + if (IsActive()) + { + (*actit)->DecLink(); + } + *actit = m_linkedactuators.back(); + m_linkedactuators.pop_back(); + return; } - m_linkedactuators.erase(actit); } + printf("Missing link from controller %s:%s to actuator %s:%s\n", + m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), + actua->GetParent()->GetName().ReadPtr(), actua->GetName().ReadPtr()); } void SCA_IController::LinkToSensor(SCA_ISensor* sensor) @@ -157,20 +145,21 @@ void SCA_IController::UnlinkSensor(class SCA_ISensor* sensor) { if ((*sensit) == sensor) { - break; - } - - } - if (!(sensit==m_linkedsensors.end())) - { - if (IsActive()) - { - (*sensit)->DecLink(); + if (IsActive()) + { + sensor->DecLink(); + } + *sensit = m_linkedsensors.back(); + m_linkedsensors.pop_back(); + return; } - m_linkedsensors.erase(sensit); } + printf("Missing link from controller %s:%s to sensor %s:%s\n", + m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), + sensor->GetParent()->GetName().ReadPtr(), sensor->GetName().ReadPtr()); } + void SCA_IController::ApplyState(unsigned int state) { std::vector<class SCA_IActuator*>::iterator actit; @@ -185,13 +174,13 @@ void SCA_IController::ApplyState(unsigned int state) { (*actit)->IncLink(); } + for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) { (*sensit)->IncLink(); - // remember that this controller just activated that sensor - (*sensit)->AddNewController(this); } SetActive(true); + m_justActivated = true; } } else if (IsActive()) { @@ -204,6 +193,168 @@ void SCA_IController::ApplyState(unsigned int state) (*sensit)->DecLink(); } SetActive(false); + m_justActivated = false; } } +/* Python api */ + +PyTypeObject SCA_IController::Type = { +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif + "SCA_IController", + sizeof(PyObjectPlus_Proxy), + 0, + py_base_dealloc, + 0, + 0, + 0, + 0, + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods +}; + +PyParentObject SCA_IController::Parents[] = { + &SCA_IController::Type, + &CValue::Type, + NULL +}; + +PyMethodDef SCA_IController::Methods[] = { + //Deprecated functions ------> + {"getSensor", (PyCFunction) SCA_IController::sPyGetSensor, METH_O}, + {"getActuator", (PyCFunction) SCA_IController::sPyGetActuator, METH_O}, + {"getSensors", (PyCFunction) SCA_IController::sPyGetSensors, METH_NOARGS}, + {"getActuators", (PyCFunction) SCA_IController::sPyGetActuators, METH_NOARGS}, + {"getState", (PyCFunction) SCA_IController::sPyGetState, METH_NOARGS}, + //<----- Deprecated + {NULL,NULL} //Sentinel +}; + +PyAttributeDef SCA_IController::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("state", SCA_IController, pyattr_get_state), + KX_PYATTRIBUTE_RO_FUNCTION("sensors", SCA_IController, pyattr_get_sensors), + KX_PYATTRIBUTE_RO_FUNCTION("actuators", SCA_IController, pyattr_get_actuators), + KX_PYATTRIBUTE_BOOL_RW("useHighPriority",SCA_IController,m_bookmark), + { NULL } //Sentinel +}; + +PyObject* SCA_IController::py_getattro(PyObject *attr) +{ + py_getattro_up(SCA_ILogicBrick); +} + +PyObject* SCA_IController::py_getattro_dict() { + py_getattro_dict_up(SCA_ILogicBrick); +} + +int SCA_IController::py_setattro(PyObject *attr, PyObject *value) +{ + py_setattro_up(SCA_ILogicBrick); +} + + + +PyObject* SCA_IController::PyGetActuators() +{ + ShowDeprecationWarning("getActuators()", "the actuators property"); + + PyObject* resultlist = PyList_New(m_linkedactuators.size()); + for (unsigned int index=0;index<m_linkedactuators.size();index++) + { + PyList_SET_ITEM(resultlist,index, m_linkedactuators[index]->GetProxy()); + } + + return resultlist; +} + +PyObject* SCA_IController::PyGetSensor(PyObject* value) +{ + ShowDeprecationWarning("getSensor(string)", "the sensors[string] property"); + + char *scriptArg = PyString_AsString(value); + if (scriptArg==NULL) { + PyErr_SetString(PyExc_TypeError, "controller.getSensor(string): Python Controller, expected a string (sensor name)"); + return NULL; + } + + for (unsigned int index=0;index<m_linkedsensors.size();index++) + { + SCA_ISensor* sensor = m_linkedsensors[index]; + STR_String& realname = sensor->GetName(); + if (realname == scriptArg) + { + return sensor->GetProxy(); + } + } + + PyErr_Format(PyExc_AttributeError, "controller.getSensor(string): Python Controller, unable to find requested sensor \"%s\"", scriptArg); + return NULL; +} + +PyObject* SCA_IController::PyGetActuator(PyObject* value) +{ + ShowDeprecationWarning("getActuator(string)", "the actuators[string] property"); + + char *scriptArg = PyString_AsString(value); + if (scriptArg==NULL) { + PyErr_SetString(PyExc_TypeError, "controller.getActuator(string): Python Controller, expected a string (actuator name)"); + return NULL; + } + + for (unsigned int index=0;index<m_linkedactuators.size();index++) + { + SCA_IActuator* actua = m_linkedactuators[index]; + if (actua->GetName() == scriptArg) + { + return actua->GetProxy(); + } + } + + PyErr_Format(PyExc_AttributeError, "controller.getActuator(string): Python Controller, unable to find requested actuator \"%s\"", scriptArg); + return NULL; +} + +PyObject* SCA_IController::PyGetSensors() +{ + ShowDeprecationWarning("getSensors()", "the sensors property"); + + PyObject* resultlist = PyList_New(m_linkedsensors.size()); + for (unsigned int index=0;index<m_linkedsensors.size();index++) + { + PyList_SET_ITEM(resultlist,index, m_linkedsensors[index]->GetProxy()); + } + + return resultlist; +} + +PyObject* SCA_IController::PyGetState() +{ + ShowDeprecationWarning("getState()", "the state property"); + return PyInt_FromLong(m_statemask); +} + +PyObject* SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_IController* self= static_cast<SCA_IController*>(self_v); + return PyInt_FromLong(self->m_statemask); +} + +PyObject* SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_SENSORS); +} + +PyObject* SCA_IController::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_ACTUATORS); +} diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h index f67c0942eb4..a52c57ab3ed 100644 --- a/source/gameengine/GameLogic/SCA_IController.h +++ b/source/gameengine/GameLogic/SCA_IController.h @@ -30,28 +30,87 @@ #define __KX_ICONTROLLER #include "SCA_ILogicBrick.h" +#include "PyObjectPlus.h" +/* + * Use of SG_DList element: none + * Use of SG_QList element: build ordered list of activated controller on the owner object + * Head: SCA_IObject::m_activeControllers + */ class SCA_IController : public SCA_ILogicBrick { + Py_Header; protected: std::vector<class SCA_ISensor*> m_linkedsensors; std::vector<class SCA_IActuator*> m_linkedactuators; unsigned int m_statemask; + bool m_justActivated; + bool m_bookmark; public: SCA_IController(SCA_IObject* gameobj,PyTypeObject* T); virtual ~SCA_IController(); virtual void Trigger(class SCA_LogicManager* logicmgr)=0; void LinkToSensor(SCA_ISensor* sensor); void LinkToActuator(SCA_IActuator*); - const std::vector<class SCA_ISensor*>& GetLinkedSensors(); - const std::vector<class SCA_IActuator*>& GetLinkedActuators(); + std::vector<class SCA_ISensor*>& GetLinkedSensors(); + std::vector<class SCA_IActuator*>& GetLinkedActuators(); + void ReserveActuator(int num) + { + m_linkedactuators.reserve(num); + } void UnlinkAllSensors(); void UnlinkAllActuators(); void UnlinkActuator(class SCA_IActuator* actua); void UnlinkSensor(class SCA_ISensor* sensor); void SetState(unsigned int state) { m_statemask = state; } void ApplyState(unsigned int state); + void Deactivate() + { + // the controller can only be part of a sensor m_newControllers list + Delink(); + } + bool IsJustActivated() + { + return m_justActivated; + } + void ClrJustActivated() + { + m_justActivated = false; + } + void SetBookmark(bool bookmark) + { + m_bookmark = bookmark; + } + void Activate(SG_DList& head) + { + if (QEmpty()) + { + if (m_bookmark) + { + m_gameobj->m_activeBookmarkedControllers.QAddBack(this); + head.AddFront(&m_gameobj->m_activeBookmarkedControllers); + } + else + { + InsertActiveQList(m_gameobj->m_activeControllers); + head.AddBack(&m_gameobj->m_activeControllers); + } + } + } + virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); + virtual int py_setattro(PyObject *attr, PyObject *value); + + KX_PYMETHOD_NOARGS(SCA_IController,GetSensors); + KX_PYMETHOD_NOARGS(SCA_IController,GetActuators); + KX_PYMETHOD_O(SCA_IController,GetSensor); + KX_PYMETHOD_O(SCA_IController,GetActuator); + KX_PYMETHOD_NOARGS(SCA_IController,GetState); + + static PyObject* pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); }; diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 3cd750ff63b..2dc80f54568 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -71,13 +71,6 @@ void SCA_ILogicBrick::SetUeberExecutePriority(int execute_Priority) -SCA_IObject* SCA_ILogicBrick::GetParent() -{ - return m_gameobj; -} - - - void SCA_ILogicBrick::ReParent(SCA_IObject* parent) { m_gameobj = parent; @@ -130,33 +123,17 @@ double SCA_ILogicBrick::GetNumber() -STR_String SCA_ILogicBrick::GetName() +STR_String& SCA_ILogicBrick::GetName() { return m_name; } -void SCA_ILogicBrick::SetName(STR_String name) -{ - m_name = name; -} - - - -void SCA_ILogicBrick::ReplicaSetName(STR_String name) +void SCA_ILogicBrick::SetName(const char *name) { m_name = name; } - - - -bool SCA_ILogicBrick::IsActive() -{ - return m_bActive; -} - - bool SCA_ILogicBrick::LessComparedTo(SCA_ILogicBrick* other) { @@ -165,22 +142,6 @@ bool SCA_ILogicBrick::LessComparedTo(SCA_ILogicBrick* other) (this->m_Execute_Priority < other->m_Execute_Priority)); } - - -void SCA_ILogicBrick::SetActive(bool active) -{ - m_bActive=active; - if (active) - { - //m_gameobj->SetDebugColor(GetDrawColor()); - } else - { - //m_gameobj->ResetDebugColor(); - } -} - - - void SCA_ILogicBrick::RegisterEvent(CValue* eventval) { if (m_eventval) @@ -217,8 +178,13 @@ CValue* SCA_ILogicBrick::GetEvent() /* python stuff */ PyTypeObject SCA_ILogicBrick::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_ILogicBrick", sizeof(PyObjectPlus_Proxy), 0, @@ -256,7 +222,8 @@ PyMethodDef SCA_ILogicBrick::Methods[] = { PyAttributeDef SCA_ILogicBrick::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("owner", SCA_ILogicBrick, pyattr_get_owner), - KX_PYATTRIBUTE_INT_RW("executePriority",0,100000,false,SCA_ILogicBrick,m_Execute_Ueber_Priority), + KX_PYATTRIBUTE_INT_RW("executePriority",0,100000,false,SCA_ILogicBrick,m_Execute_Priority), + KX_PYATTRIBUTE_STRING_RO("name", SCA_ILogicBrick, m_name), {NULL} //Sentinel }; @@ -278,12 +245,15 @@ int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) return 0; } -PyObject* -SCA_ILogicBrick::py_getattro(PyObject *attr) +PyObject* SCA_ILogicBrick::py_getattro(PyObject *attr) { py_getattro_up(CValue); } +PyObject* SCA_ILogicBrick::py_getattro_dict() { + py_getattro_dict_up(CValue); +} + int SCA_ILogicBrick::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(CValue); @@ -316,7 +286,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* args) return NULL; } - m_Execute_Ueber_Priority = priority; + m_Execute_Priority = priority; Py_RETURN_NONE; } @@ -326,7 +296,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* args) PyObject* SCA_ILogicBrick::PyGetExecutePriority() { ShowDeprecationWarning("getExecutePriority()", "the executePriority property"); - return PyInt_FromLong(m_Execute_Ueber_Priority); + return PyInt_FromLong(m_Execute_Priority); } diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index e59d05ea051..779e5397a6a 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -59,7 +59,8 @@ public: void SetExecutePriority(int execute_Priority); void SetUeberExecutePriority(int execute_Priority); - SCA_IObject* GetParent(); + SCA_IObject* GetParent() { return m_gameobj; } + virtual void ReParent(SCA_IObject* parent); virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); virtual void Delete() { Release(); } @@ -70,16 +71,59 @@ public: virtual const STR_String & GetText(); virtual double GetNumber(); - virtual STR_String GetName(); - virtual void SetName(STR_String name); - virtual void ReplicaSetName(STR_String name); + virtual STR_String& GetName(); + virtual void SetName(const char *); - bool IsActive(); - void SetActive(bool active) ; + bool IsActive() + { + return m_bActive; + } + + void SetActive(bool active) + { + m_bActive=active; + } + + // insert in a QList at position corresponding to m_Execute_Priority + void InsertActiveQList(SG_QList& head) + { + SG_QList::iterator<SCA_ILogicBrick> it(head); + for(it.begin(); !it.end() && m_Execute_Priority > (*it)->m_Execute_Priority; ++it); + it.add_back(this); + } + + // insert in a QList at position corresponding to m_Execute_Priority + // inside a longer list that contains elements of other objects. + // Sorting is done only between the elements of the same object. + // head is the head of the combined list + // current points to the first element of the object in the list, NULL if none yet + void InsertSelfActiveQList(SG_QList& head, SG_QList** current) + { + if (!*current) + { + // first element can be put anywhere + head.QAddBack(this); + *current = this; + return; + } + // note: we assume current points actually to one o our element, skip the tests + SG_QList::iterator<SCA_ILogicBrick> it(head,*current); + if (m_Execute_Priority <= (*it)->m_Execute_Priority) + { + // this element comes before the first + *current = this; + } + else + { + for(++it; !it.end() && (*it)->m_gameobj == m_gameobj && m_Execute_Priority > (*it)->m_Execute_Priority; ++it); + } + it.add_back(this); + } virtual bool LessComparedTo(SCA_ILogicBrick* other); virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); static class SCA_LogicManager* m_sCurrentLogicManager; diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index 75804525e7a..9876f2512c0 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -39,13 +39,13 @@ #endif MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0); +SG_QList SCA_IObject::m_activeBookmarkedControllers; + +SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T), m_initState(0), m_state(0), m_firstState(NULL) -SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T), m_initState(0), m_state(0) { m_suspended = false; } - - SCA_IObject::~SCA_IObject() { @@ -70,7 +70,7 @@ SCA_IObject::~SCA_IObject() } for (ita = m_actuators.begin(); !(ita==m_actuators.end()); ++ita) { - ((CValue*)(*ita))->Release(); + (*ita)->Delete(); } //T_InterpolatorList::iterator i; @@ -79,29 +79,6 @@ SCA_IObject::~SCA_IObject() //} } - - -SCA_ControllerList& SCA_IObject::GetControllers() -{ - return m_controllers; -} - - - -SCA_SensorList& SCA_IObject::GetSensors() -{ - return m_sensors; -} - - - -SCA_ActuatorList& SCA_IObject::GetActuators() -{ - return m_actuators; -} - - - void SCA_IObject::AddSensor(SCA_ISensor* act) { act->AddRef(); @@ -133,7 +110,7 @@ void SCA_IObject::RegisterActuator(SCA_IActuator* act) void SCA_IObject::UnregisterActuator(SCA_IActuator* act) { SCA_ActuatorList::iterator ita; - for (ita = m_registeredActuators.begin(); ita != m_registeredActuators.end(); ita++) + for (ita = m_registeredActuators.begin(); ita != m_registeredActuators.end(); ++ita) { if ((*ita) == act) { (*ita) = m_registeredActuators.back(); @@ -143,20 +120,6 @@ void SCA_IObject::UnregisterActuator(SCA_IActuator* act) } } -void SCA_IObject::SetIgnoreActivityCulling(bool b) -{ - m_ignore_activity_culling = b; -} - - - -bool SCA_IObject::GetIgnoreActivityCulling() -{ - return m_ignore_activity_culling; -} - - - void SCA_IObject::ReParentLogic() { SCA_ActuatorList& oldactuators = GetActuators(); @@ -208,7 +171,7 @@ SCA_ISensor* SCA_IObject::FindSensor(const STR_String& sensorname) { SCA_ISensor* foundsensor = NULL; - for (SCA_SensorList::iterator its = m_sensors.begin();!(its==m_sensors.end());its++) + for (SCA_SensorList::iterator its = m_sensors.begin();!(its==m_sensors.end());++its) { if ((*its)->GetName() == sensorname) { @@ -225,7 +188,7 @@ SCA_IController* SCA_IObject::FindController(const STR_String& controllername) { SCA_IController* foundcontroller = NULL; - for (SCA_ControllerList::iterator itc = m_controllers.begin();!(itc==m_controllers.end());itc++) + for (SCA_ControllerList::iterator itc = m_controllers.begin();!(itc==m_controllers.end());++itc) { if ((*itc)->GetName() == controllername) { @@ -242,7 +205,7 @@ SCA_IActuator* SCA_IObject::FindActuator(const STR_String& actuatorname) { SCA_IActuator* foundactuator = NULL; - for (SCA_ActuatorList::iterator ita = m_actuators.begin();!(ita==m_actuators.end());ita++) + for (SCA_ActuatorList::iterator ita = m_actuators.begin();!(ita==m_actuators.end());++ita) { if ((*ita)->GetName() == actuatorname) { @@ -256,14 +219,6 @@ SCA_IActuator* SCA_IObject::FindActuator(const STR_String& actuatorname) -void SCA_IObject::SetCurrentTime(float currentTime) { - //T_InterpolatorList::iterator i; - //for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { - // (*i)->Execute(currentTime); - //} -} - - #if 0 const MT_Point3& SCA_IObject::ConvertPythonPylist(PyObject* pylist) { @@ -317,7 +272,7 @@ void SCA_IObject::Suspend() SCA_SensorList::iterator i = m_sensors.begin(); while (i != m_sensors.end()) { (*i)->Suspend(); - i++; + ++i; } } } @@ -332,7 +287,7 @@ void SCA_IObject::Resume(void) SCA_SensorList::iterator i = m_sensors.begin(); while (i != m_sensors.end()) { (*i)->Resume(); - i++; + ++i; } } } @@ -352,7 +307,7 @@ void SCA_IObject::SetState(unsigned int state) if (tmpstate != m_state) { // update the status of the controllers - for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + for (contit = m_controllers.begin(); contit != m_controllers.end(); ++contit) { (*contit)->ApplyState(tmpstate); } @@ -360,7 +315,7 @@ void SCA_IObject::SetState(unsigned int state) m_state = state; if (m_state != tmpstate) { - for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + for (contit = m_controllers.begin(); contit != m_controllers.end(); ++contit) { (*contit)->ApplyState(m_state); } @@ -375,8 +330,13 @@ void SCA_IObject::SetState(unsigned int state) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_IObject::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_IObject", sizeof(PyObjectPlus_Proxy), 0, @@ -418,3 +378,6 @@ PyObject* SCA_IObject::py_getattro(PyObject *attr) { py_getattro_up(CValue); } +PyObject* SCA_IObject::py_getattro_dict() { + py_getattro_dict_up(CValue); +} diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index 44ed3c8f3fe..eae427741ca 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -52,10 +52,30 @@ class SCA_IObject : public CValue Py_Header; protected: + friend class KX_StateActuator; + friend class SCA_IActuator; + friend class SCA_IController; SCA_SensorList m_sensors; SCA_ControllerList m_controllers; SCA_ActuatorList m_actuators; SCA_ActuatorList m_registeredActuators; // actuators that use a pointer to this object + + // SG_Dlist: element of objects with active actuators + // Head: SCA_LogicManager::m_activeActuators + // SG_QList: Head of active actuators list on this object + // Elements: SCA_IActuator + SG_QList m_activeActuators; + // SG_Dlist: element of list os lists with active controllers + // Head: SCA_LogicManager::m_activeControllers + // SG_QList: Head of active controller list on this object + // Elements: SCA_IController + SG_QList m_activeControllers; + // SG_Dlist: element of list of lists of active controllers + // Head: SCA_LogicManager::m_activeControllers + // SG_QList: Head of active bookmarked controller list globally + // Elements: SCA_IController with bookmark option + static SG_QList m_activeBookmarkedControllers; + static class MT_Point3 m_sDummy; /** @@ -78,18 +98,48 @@ protected: */ unsigned int m_state; + /** + * pointer inside state actuator list for sorting + */ + SG_QList* m_firstState; + public: SCA_IObject(PyTypeObject* T=&Type); virtual ~SCA_IObject(); - SCA_ControllerList& GetControllers(); - SCA_SensorList& GetSensors(); - SCA_ActuatorList& GetActuators(); + SCA_ControllerList& GetControllers() + { + return m_controllers; + } + SCA_SensorList& GetSensors() + { + return m_sensors; + } + SCA_ActuatorList& GetActuators() + { + return m_actuators; + } + SG_QList& GetActiveActuators() + { + return m_activeActuators; + } void AddSensor(SCA_ISensor* act); + void ReserveSensor(int num) + { + m_sensors.reserve(num); + } void AddController(SCA_IController* act); + void ReserveController(int num) + { + m_controllers.reserve(num); + } void AddActuator(SCA_IActuator* act); + void ReserveActuator(int num) + { + m_actuators.reserve(num); + } void RegisterActuator(SCA_IActuator* act); void UnregisterActuator(SCA_IActuator* act); @@ -97,20 +147,26 @@ public: SCA_IActuator* FindActuator(const STR_String& actuatorname); SCA_IController* FindController(const STR_String& controllername); - void SetCurrentTime(float currentTime); + void SetCurrentTime(float currentTime) {} void ReParentLogic(); /** * Set whether or not to ignore activity culling requests */ - void SetIgnoreActivityCulling(bool b); + void SetIgnoreActivityCulling(bool b) + { + m_ignore_activity_culling = b; + } /** * Set whether or not this object wants to ignore activity culling * requests */ - bool GetIgnoreActivityCulling(); + bool GetIgnoreActivityCulling() + { + return m_ignore_activity_culling; + } /** * Suspend all progress. @@ -146,6 +202,7 @@ public: // here come the python forwarded methods virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int GetGameObjectType() {return -1;} diff --git a/source/gameengine/GameLogic/SCA_IScene.cpp b/source/gameengine/GameLogic/SCA_IScene.cpp index 9fbeb706910..86b176a38b0 100644 --- a/source/gameengine/GameLogic/SCA_IScene.cpp +++ b/source/gameengine/GameLogic/SCA_IScene.cpp @@ -50,7 +50,7 @@ SCA_IScene::SCA_IScene() void SCA_IScene::RemoveAllDebugProperties() { for (std::vector<SCA_DebugProp*>::iterator it = m_debugList.begin(); - !(it==m_debugList.end());it++) + !(it==m_debugList.end());++it) { delete (*it); } diff --git a/source/gameengine/GameLogic/SCA_IScene.h b/source/gameengine/GameLogic/SCA_IScene.h index d18778a37c2..b641efc6ee1 100644 --- a/source/gameengine/GameLogic/SCA_IScene.h +++ b/source/gameengine/GameLogic/SCA_IScene.h @@ -52,7 +52,7 @@ public: int lifespan=0)=0; virtual void RemoveObject(class CValue* gameobj)=0; virtual void DelayedRemoveObject(class CValue* gameobj)=0; - virtual void DelayedReleaseObject(class CValue* gameobj)=0; + //virtual void DelayedReleaseObject(class CValue* gameobj)=0; virtual void ReplaceMesh(class CValue* gameobj, void* meshobj)=0; diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 68f5653d53a..2783bf14600 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -45,26 +45,28 @@ void SCA_ISensor::ReParent(SCA_IObject* parent) SCA_ILogicBrick::ReParent(parent); // will be done when the sensor is activated //m_eventmgr->RegisterSensor(this); - this->SetActive(false); + //this->SetActive(false); } SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj, class SCA_EventManager* eventmgr, PyTypeObject* T ) : - SCA_ILogicBrick(gameobj,T), - m_triggered(false) + SCA_ILogicBrick(gameobj,T) { m_links = 0; m_suspended = false; m_invert = false; m_level = false; + m_tap = false; m_reset = false; m_pos_ticks = 0; m_neg_ticks = 0; m_pos_pulsemode = false; m_neg_pulsemode = false; m_pulse_frequency = 0; + m_state = false; + m_prev_state = false; m_eventmgr = eventmgr; } @@ -75,6 +77,12 @@ SCA_ISensor::~SCA_ISensor() // intentionally empty } +void SCA_ISensor::ProcessReplica() +{ + SCA_ILogicBrick::ProcessReplica(); + m_linkedcontrollers.clear(); +} + bool SCA_ISensor::IsPositiveTrigger() { bool result = false; @@ -104,9 +112,13 @@ void SCA_ISensor::SetLevel(bool lvl) { m_level = lvl; } +void SCA_ISensor::SetTap(bool tap) { + m_tap = tap; +} + double SCA_ISensor::GetNumber() { - return IsPositiveTrigger(); + return GetState(); } void SCA_ISensor::Suspend() { @@ -143,27 +155,80 @@ void SCA_ISensor::RegisterToManager() { // sensor is just activated, initialize it Init(); - m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); + m_state = false; m_eventmgr->RegisterSensor(this); } +void SCA_ISensor::LinkToController(SCA_IController* controller) +{ + m_linkedcontrollers.push_back(controller); +} + +void SCA_ISensor::UnlinkController(SCA_IController* controller) +{ + std::vector<class SCA_IController*>::iterator contit; + for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit) + { + if ((*contit) == controller) + { + *contit = m_linkedcontrollers.back(); + m_linkedcontrollers.pop_back(); + return; + } + } + printf("Missing link from sensor %s:%s to controller %s:%s\n", + m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), + controller->GetParent()->GetName().ReadPtr(), controller->GetName().ReadPtr()); +} + +void SCA_ISensor::UnlinkAllControllers() +{ + std::vector<class SCA_IController*>::iterator contit; + for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit) + { + (*contit)->UnlinkSensor(this); + } + m_linkedcontrollers.clear(); +} + void SCA_ISensor::UnregisterToManager() { m_eventmgr->RemoveSensor(this); + m_links = 0; +} + +void SCA_ISensor::ActivateControllers(class SCA_LogicManager* logicmgr) +{ + for(vector<SCA_IController*>::const_iterator c= m_linkedcontrollers.begin(); + c!=m_linkedcontrollers.end();++c) + { + SCA_IController* contr = *c; + if (contr->IsActive()) + logicmgr->AddTriggeredController(contr, this); + } } -void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) +void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr) { // calculate if a __triggering__ is wanted // don't evaluate a sensor that is not connected to any controller if (m_links && !m_suspended) { - bool result = this->Evaluate(event); + bool result = this->Evaluate(); + // store the state for the rest of the logic system + m_prev_state = m_state; + m_state = this->IsPositiveTrigger(); if (result) { - logicmgr->AddActivatedSensor(this); - // reset these counters so that pulse are synchronized with transition - m_pos_ticks = 0; - m_neg_ticks = 0; + // the sensor triggered this frame + if (m_state || !m_tap) { + ActivateControllers(logicmgr); + // reset these counters so that pulse are synchronized with transition + m_pos_ticks = 0; + m_neg_ticks = 0; + } else + { + result = false; + } } else { /* First, the pulsing behaviour, if pulse mode is @@ -172,41 +237,55 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) if (m_pos_pulsemode) { m_pos_ticks++; if (m_pos_ticks > m_pulse_frequency) { - if ( this->IsPositiveTrigger() ) + if ( m_state ) { - logicmgr->AddActivatedSensor(this); + ActivateControllers(logicmgr); + result = true; } m_pos_ticks = 0; } } - - if (m_neg_pulsemode) + // negative pulse doesn't make sense in tap mode, skip + if (m_neg_pulsemode && !m_tap) { m_neg_ticks++; if (m_neg_ticks > m_pulse_frequency) { - if (!this->IsPositiveTrigger() ) + if (!m_state ) { - logicmgr->AddActivatedSensor(this); + ActivateControllers(logicmgr); + result = true; } m_neg_ticks = 0; } } } - if (!m_newControllers.empty()) + if (m_tap) { - if (!IsActive() && m_level) + // in tap mode: we send always a negative pulse immediately after a positive pulse + if (!result) { - // This level sensor is connected to at least one controller that was just made - // active but it did not generate an event yet, do it now to those controllers only - for (std::vector<SCA_IController*>::iterator ci=m_newControllers.begin(); - ci != m_newControllers.end(); ci++) + // the sensor did not trigger on this frame + if (m_prev_state) { - logicmgr->AddTriggeredController(*ci, this); + // but it triggered on previous frame => send a negative pulse + ActivateControllers(logicmgr); + result = true; } + // in any case, absence of trigger means sensor off + m_state = false; + } + } + if (!result && m_level) + { + // This level sensor is connected to at least one controller that was just made + // active but it did not generate an event yet, do it now to those controllers only + for(vector<SCA_IController*>::const_iterator c= m_linkedcontrollers.begin(); + c!=m_linkedcontrollers.end();++c) + { + SCA_IController* contr = *c; + if (contr->IsJustActivated()) + logicmgr->AddTriggeredController(contr, this); } - // clear the list. Instead of using clear, which also release the memory, - // use erase, which keeps the memory available for next time. - m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); } } } @@ -221,7 +300,7 @@ const char SCA_ISensor::IsPositive_doc[] = PyObject* SCA_ISensor::PyIsPositive() { ShowDeprecationWarning("isPositive()", "the read-only positive property"); - int retval = IsPositiveTrigger(); + int retval = GetState(); return PyInt_FromLong(retval); } @@ -385,6 +464,7 @@ KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset, "\tThe sensor is put in its initial state as if it was just activated.\n") { Init(); + m_prev_state = false; Py_RETURN_NONE; } @@ -393,8 +473,13 @@ KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset, /* ----------------------------------------------- */ PyTypeObject SCA_ISensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_ISensor", sizeof(PyObjectPlus_Proxy), 0, @@ -453,18 +538,25 @@ PyAttributeDef SCA_ISensor::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode), KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency), KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert), - KX_PYATTRIBUTE_BOOL_RW("level",SCA_ISensor,m_level), + KX_PYATTRIBUTE_BOOL_RW_CHECK("level",SCA_ISensor,m_level,pyattr_check_level), + KX_PYATTRIBUTE_BOOL_RW_CHECK("tap",SCA_ISensor,m_tap,pyattr_check_tap), KX_PYATTRIBUTE_RO_FUNCTION("triggered", SCA_ISensor, pyattr_get_triggered), KX_PYATTRIBUTE_RO_FUNCTION("positive", SCA_ISensor, pyattr_get_positive), + //KX_PYATTRIBUTE_TODO("links"), + //KX_PYATTRIBUTE_TODO("posTicks"), + //KX_PYATTRIBUTE_TODO("negTicks"), { NULL } //Sentinel }; -PyObject* -SCA_ISensor::py_getattro(PyObject *attr) +PyObject* SCA_ISensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ILogicBrick); } +PyObject* SCA_ISensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ILogicBrick); +} + int SCA_ISensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ILogicBrick); @@ -482,7 +574,23 @@ PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_D PyObject* SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); - return PyInt_FromLong(self->IsPositiveTrigger()); + return PyInt_FromLong(self->GetState()); +} + +int SCA_ISensor::pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); + if (self->m_level) + self->m_tap = false; + return 0; +} + +int SCA_ISensor::pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); + if (self->m_tap) + self->m_level = false; + return 0; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 6b1c8cca104..9bbd6ed41e4 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -32,18 +32,22 @@ #ifndef __SCA_ISENSOR #define __SCA_ISENSOR -#include "SCA_ILogicBrick.h" +#include "SCA_IController.h" #include <vector> /** * Interface Class for all logic Sensors. Implements - * pulsemode,pulsefrequency */ + * pulsemode,pulsefrequency + * Use of SG_DList element: link sensors to their respective event manager + * Head: SCA_EventManager::m_sensors + * Use of SG_QList element: not used + */ class SCA_ISensor : public SCA_ILogicBrick { Py_Header; +protected: class SCA_EventManager* m_eventmgr; - bool m_triggered; /** Pulse positive pulses? */ bool m_pos_pulsemode; @@ -66,6 +70,9 @@ class SCA_ISensor : public SCA_ILogicBrick /** detect level instead of edge*/ bool m_level; + /** tap mode */ + bool m_tap; + /** sensor has been reset */ bool m_reset; @@ -75,10 +82,24 @@ class SCA_ISensor : public SCA_ILogicBrick /** number of connections to controller */ int m_links; - /** list of controllers that have just activated this sensor because of a state change */ - std::vector<class SCA_IController*> m_newControllers; + /** current sensor state */ + bool m_state; + + /** previous state (for tap option) */ + bool m_prev_state; + + std::vector<class SCA_IController*> m_linkedcontrollers; public: + + enum sensortype { + ST_NONE = 0, + ST_TOUCH, + ST_NEAR, + ST_RADAR, + // to be updated as needed + }; + SCA_ISensor(SCA_IObject* gameobj, class SCA_EventManager* eventmgr, PyTypeObject* T );; @@ -89,8 +110,8 @@ public: /* an implementation on this level. It requires an evaluate on the lower */ /* level of individual sensors. Mapping the old activate()s is easy. */ /* The IsPosTrig() also has to change, to keep things consistent. */ - void Activate(class SCA_LogicManager* logicmgr,CValue* event); - virtual bool Evaluate(CValue* event) = 0; + void Activate(class SCA_LogicManager* logicmgr); + virtual bool Evaluate() = 0; virtual bool IsPositiveTrigger(); virtual void Init(); @@ -109,23 +130,40 @@ public: void SetInvert(bool inv); /** set the level detection on or off */ void SetLevel(bool lvl); + void SetTap(bool tap); virtual void RegisterToManager(); virtual void UnregisterToManager(); + void ReserveController(int num) + { + m_linkedcontrollers.reserve(num); + } + void LinkToController(SCA_IController* controller); + void UnlinkController(SCA_IController* controller); + void UnlinkAllControllers(); + void ActivateControllers(class SCA_LogicManager* logicmgr); + + virtual void ProcessReplica(); virtual double GetNumber(); + virtual sensortype GetSensorType() { return ST_NONE; } + /** Stop sensing for a while. */ void Suspend(); /** Is this sensor switched off? */ bool IsSuspended(); + /** get the state of the sensor: positive or negative */ + bool GetState() + { + return m_state; + } + /** Resume sensing. */ void Resume(); - void AddNewController(class SCA_IController* controller) - { m_newControllers.push_back(controller); } void ClrLink() { m_links = 0; } void IncLink() @@ -137,6 +175,7 @@ public: /* Python functions: */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated functions -----> @@ -157,6 +196,8 @@ public: static PyObject* pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); }; #endif //__SCA_ISENSOR diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.cpp b/source/gameengine/GameLogic/SCA_JoystickManager.cpp index f3ce549a637..ff8f3b1c81f 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickManager.cpp @@ -59,20 +59,21 @@ SCA_JoystickManager::~SCA_JoystickManager() void SCA_JoystickManager::NextFrame(double curtime,double deltatime) { - if (m_sensors.size()==0) { + if (m_sensors.Empty()) { return; } else { - set<SCA_ISensor*>::iterator it; + ; #ifndef DISABLE_SDL SCA_Joystick::HandleEvents(); /* Handle all SDL Joystick events */ #endif - for (it = m_sensors.begin(); it != m_sensors.end(); it++) + SG_DList::iterator<SCA_JoystickSensor> it(m_sensors); + for (it.begin();!it.end();++it) { - SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it); + SCA_JoystickSensor* joysensor = *it; if(!joysensor->IsSuspended()) { - joysensor->Activate(m_logicmgr, NULL); + joysensor->Activate(m_logicmgr); } } } diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 1c601eded81..336529667d7 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -87,7 +87,7 @@ CValue* SCA_JoystickSensor::GetReplica() { SCA_JoystickSensor* replica = new SCA_JoystickSensor(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); return replica; } @@ -102,7 +102,7 @@ bool SCA_JoystickSensor::IsPositiveTrigger() } -bool SCA_JoystickSensor::Evaluate(CValue* event) +bool SCA_JoystickSensor::Evaluate() { SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(m_joyindex); bool result = false; @@ -198,33 +198,20 @@ bool SCA_JoystickSensor::Evaluate(CValue* event) case KX_JOYSENSORMODE_HAT: { /* what is what! - numberof = m_hat -- max 2 + numberof = m_hat -- max 4 direction= m_hatf -- max 12 */ if (!js->IsTrigHat() && !reset) /* No events from SDL? - dont bother */ return false; - if(m_hat == 1){ - if(js->aHatIsPositive(m_hatf)){ - m_istrig = 1; - result = true; - }else{ - if(m_istrig){ - m_istrig = 0; - result = true; - } - } - } - if(m_hat == 2){ - if(js->aHatIsPositive(m_hatf)){ - m_istrig = 1; + if((m_bAllEvents && js->GetHat(m_hat-1)) || js->aHatIsPositive(m_hat-1, m_hatf)) { + m_istrig = 1; + result = true; + }else{ + if(m_istrig){ + m_istrig = 0; result = true; - }else{ - if(m_istrig){ - m_istrig = 0; - result = true; - } } } break; @@ -266,8 +253,13 @@ bool SCA_JoystickSensor::isValid(SCA_JoystickSensor::KX_JOYSENSORMODE m) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_JoystickSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_JoystickSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -326,11 +318,13 @@ PyAttributeDef SCA_JoystickSensor::Attributes[] = { KX_PYATTRIBUTE_INT_LIST_RW_CHECK("hat",0,12,true,SCA_JoystickSensor,m_hat,2,CheckHat), KX_PYATTRIBUTE_RO_FUNCTION("axisValues", SCA_JoystickSensor, pyattr_get_axis_values), KX_PYATTRIBUTE_RO_FUNCTION("axisSingle", SCA_JoystickSensor, pyattr_get_axis_single), + KX_PYATTRIBUTE_RO_FUNCTION("hatValues", SCA_JoystickSensor, pyattr_get_hat_values), + KX_PYATTRIBUTE_RO_FUNCTION("hatSingle", SCA_JoystickSensor, pyattr_get_hat_single), KX_PYATTRIBUTE_RO_FUNCTION("numAxis", SCA_JoystickSensor, pyattr_get_num_axis), KX_PYATTRIBUTE_RO_FUNCTION("numButtons", SCA_JoystickSensor, pyattr_get_num_buttons), KX_PYATTRIBUTE_RO_FUNCTION("numHats", SCA_JoystickSensor, pyattr_get_num_hats), KX_PYATTRIBUTE_RO_FUNCTION("connected", SCA_JoystickSensor, pyattr_get_connected), - + //KX_PYATTRIBUTE_TODO("events"), { NULL } //Sentinel }; @@ -339,6 +333,10 @@ PyObject* SCA_JoystickSensor::py_getattro(PyObject *attr) py_getattro_up(SCA_ISensor); } +PyObject* SCA_JoystickSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_JoystickSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); @@ -394,6 +392,8 @@ PyObject* SCA_JoystickSensor::PySetAxis( PyObject* args ) { } m_axis = axis; m_axisf = axisflag; + + CheckAxis((void *)this, NULL); /* clamp values */ Py_RETURN_NONE; } @@ -535,6 +535,8 @@ PyObject* SCA_JoystickSensor::PySetHat( PyObject* args ) { } m_hat = hat; m_hatf = hatflag; + + CheckHat((void *)this, NULL); /* clamp values */ Py_RETURN_NONE; } @@ -608,6 +610,29 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT return PyInt_FromLong(joy->GetAxisPosition(self->m_axis-1)); } +PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v); + SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); + + int hat_index= joy->GetNumberOfHats(); + PyObject *list= PyList_New(hat_index); + + while(hat_index--) { + PyList_SET_ITEM(list, hat_index, PyInt_FromLong(joy->GetHat(hat_index))); + } + + return list; +} + +PyObject* SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v); + SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); + + return PyInt_FromLong(joy->GetHat(self->m_hat-1)); +} + PyObject* SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v); diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index cf3e7e74414..e6a1d2eef32 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -30,6 +30,7 @@ #define __JOYSENSOR_H #include "SCA_ISensor.h" +#include "./Joystick/SCA_JoystickDefines.h" class SCA_JoystickSensor :public SCA_ISensor { @@ -37,7 +38,7 @@ class SCA_JoystickSensor :public SCA_ISensor class SCA_JoystickManager* m_pJoystickMgr; /** - * Axis 1-or-2, MUST be followed by m_axisf + * Axis 1-JOYAXIS_MAX, MUST be followed by m_axisf */ int m_axis; /** @@ -53,11 +54,11 @@ class SCA_JoystickSensor :public SCA_ISensor */ int m_buttonf; /** - * The actual hat. MUST be followed by m_hatf + * The actual hat 1-JOYHAT_MAX. MUST be followed by m_hatf */ int m_hat; /** - * Flag to find direction 0-11, MUST be an int + * Flag to find direction 1-12, MUST be an int */ int m_hatf; /** @@ -110,7 +111,7 @@ public: virtual ~SCA_JoystickSensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); @@ -123,6 +124,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* Joystick Index */ @@ -151,6 +153,8 @@ public: static PyObject* pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_axis_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_hat_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); @@ -163,8 +167,8 @@ public: SCA_JoystickSensor* sensor = reinterpret_cast<SCA_JoystickSensor*>(self); if (sensor->m_axis < 1) sensor->m_axis = 1; - else if (sensor->m_axis > 2) - sensor->m_axis = 2; + else if (sensor->m_axis > JOYAXIS_MAX) + sensor->m_axis = JOYAXIS_MAX; return 0; } static int CheckHat(void *self, const PyAttributeDef*) @@ -172,8 +176,8 @@ public: SCA_JoystickSensor* sensor = reinterpret_cast<SCA_JoystickSensor*>(self); if (sensor->m_hat < 1) sensor->m_hat = 1; - else if (sensor->m_hat > 2) - sensor->m_hat = 2; + else if (sensor->m_hat > JOYHAT_MAX) + sensor->m_hat = JOYHAT_MAX; return 0; } diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp index 6a96442b124..279adab94d8 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp @@ -62,12 +62,11 @@ void SCA_KeyboardManager::NextFrame() { //const SCA_InputEvent& event = GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode)=0; // cerr << "SCA_KeyboardManager::NextFrame"<< endl; - set<SCA_ISensor*>::iterator it; - for (it=m_sensors.begin(); it != m_sensors.end(); it++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*it)->Activate(m_logicmanager,NULL); + (*it)->Activate(m_logicmanager); } - } bool SCA_KeyboardManager::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode) diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index c946156283f..f8ee8ed8b41 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -85,7 +85,7 @@ CValue* SCA_KeyboardSensor::GetReplica() { SCA_KeyboardSensor* replica = new SCA_KeyboardSensor(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); return replica; } @@ -118,7 +118,7 @@ bool SCA_KeyboardSensor::TriggerOnAllKeys() -bool SCA_KeyboardSensor::Evaluate(CValue* eventval) +bool SCA_KeyboardSensor::Evaluate() { bool result = false; bool reset = m_reset && m_level; @@ -195,6 +195,9 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval) } } } + if (m_tap) + // special case for tap mode: only generate event for new activation + result = false; } @@ -612,8 +615,13 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, /* ------------------------------------------------------------------------- */ PyTypeObject SCA_KeyboardSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_KeyboardSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -664,12 +672,15 @@ PyAttributeDef SCA_KeyboardSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* -SCA_KeyboardSensor::py_getattro(PyObject *attr) +PyObject* SCA_KeyboardSensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_KeyboardSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_KeyboardSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); @@ -691,7 +702,7 @@ PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBU { PyObject* keypair = PyList_New(2); PyList_SET_ITEM(keypair,0,PyInt_FromLong(i)); - PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status)); + PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status)); PyList_Append(resultlist,keypair); } } diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index 073b3e6dbe0..033225cd9be 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -102,7 +102,7 @@ public: short int GetHotkey(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); bool TriggerOnAllKeys(); @@ -111,6 +111,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated functions -----> diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index b584b37180f..83271288154 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -49,37 +49,14 @@ SCA_LogicManager::SCA_LogicManager() SCA_LogicManager::~SCA_LogicManager() { - /* AddRef() is not used when the objects are added to m_mapStringToGameObjects - so Release() should not be used either. The memory leak big is fixed - in BL_ConvertBlenderObjects() - - int numgameobj = m_mapStringToGameObjects.size(); - for (int i = 0; i < numgameobj; i++) - { - CValue** gameobjptr = m_mapStringToGameObjects.at(i); - assert(gameobjptr); - if (gameobjptr) - (*gameobjptr)->Release(); - - } - */ - /*for (int i=0;i<m_sensorcontrollermap.size();i++) - { - vector<SCA_IController*>* controllerarray = *(m_sensorcontrollermap[i]); - delete controllerarray; - } - */ - for (vector<SCA_EventManager*>::iterator it = m_eventmanagers.begin();!(it==m_eventmanagers.end());it++) + for (vector<SCA_EventManager*>::iterator it = m_eventmanagers.begin();!(it==m_eventmanagers.end());++it) { delete (*it); } m_eventmanagers.clear(); - m_sensorcontrollermapje.clear(); - m_removedActuators.clear(); - m_activeActuators.clear(); + assert(m_activeActuators.Empty()); } - /* // this kind of fixes bug 398 but breakes games, so better leave it out for now. // a removed object's gameobject (and logicbricks and stuff) didn't get released @@ -171,12 +148,7 @@ void* SCA_LogicManager::FindBlendObjByGameMeshName(const STR_String& gamemeshnam void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor) { - controllerlist contlist = m_sensorcontrollermapje[sensor]; - for (controllerlist::const_iterator c= contlist.begin();!(c==contlist.end());c++) - { - (*c)->UnlinkSensor(sensor); - } - m_sensorcontrollermapje.erase(sensor); + sensor->UnlinkAllControllers(); sensor->UnregisterToManager(); } @@ -184,35 +156,22 @@ void SCA_LogicManager::RemoveController(SCA_IController* controller) { controller->UnlinkAllSensors(); controller->UnlinkAllActuators(); - std::map<SCA_ISensor*,controllerlist>::iterator sit; - for (sit = m_sensorcontrollermapje.begin();!(sit==m_sensorcontrollermapje.end());++sit) - { - (*sit).second.remove(controller); - } + controller->Deactivate(); } -void SCA_LogicManager::RemoveDestroyedActuator(SCA_IActuator* actuator) +void SCA_LogicManager::RemoveActuator(SCA_IActuator* actuator) { - m_removedActuators.push_back(SmartActuatorPtr(actuator,0)); - // take care that no controller can use this actuator again ! - - std::map<SCA_ISensor*,controllerlist>::const_iterator sit; - for (sit = m_sensorcontrollermapje.begin();!(sit==m_sensorcontrollermapje.end());++sit) - { - controllerlist contlist = (*sit).second; - for (list<SCA_IController*>::const_iterator c= contlist.begin();!(c==contlist.end());c++) - { - (*c)->UnlinkActuator(actuator); - } - } + actuator->UnlinkAllControllers(); + actuator->Deactivate(); + actuator->SetActive(false); } void SCA_LogicManager::RegisterToSensor(SCA_IController* controller,SCA_ISensor* sensor) { - m_sensorcontrollermapje[sensor].push_back(controller); + sensor->LinkToController(controller); controller->LinkToSensor(sensor); } @@ -220,6 +179,7 @@ void SCA_LogicManager::RegisterToSensor(SCA_IController* controller,SCA_ISensor* void SCA_LogicManager::RegisterToActuator(SCA_IController* controller,SCA_IActuator* actua) { + actua->LinkToController(controller); controller->LinkToActuator(actua); } @@ -230,88 +190,62 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime) for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin(); !(ie==m_eventmanagers.end()); ie++) (*ie)->NextFrame(curtime, fixedtime); - // for this frame, look up for activated sensors, and build the collection of triggered controllers - // int numsensors = this->m_activatedsensors.size(); /*unused*/ - - for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin(); - !(is==m_activatedsensors.end());is++) + for(SG_QList* obj = (SG_QList*)m_triggeredControllerSet.Remove(); + obj != NULL; + obj = (SG_QList*)m_triggeredControllerSet.Remove()) { - SCA_ISensor* sensor = *is; - controllerlist contlist = m_sensorcontrollermapje[sensor]; - for (list<SCA_IController*>::const_iterator c= contlist.begin(); - !(c==contlist.end());c++) + for(SCA_IController* contr = (SCA_IController*)obj->QRemove(); + contr != NULL; + contr = (SCA_IController*)obj->QRemove()) { - SCA_IController* contr = *c;//controllerarray->at(c); - if (contr->IsActive()) - { - m_triggeredControllerSet.insert(SmartControllerPtr(contr,0)); - // So that the controller knows which sensor has activited it. - // Only needed for the python controller though. - if (contr->GetType() == &SCA_PythonController::Type) - { - SCA_PythonController* pythonController = (SCA_PythonController*)contr; - pythonController->AddTriggeredSensor(sensor); - } - } + contr->Trigger(this); + contr->ClrJustActivated(); } - //sensor->SetActive(false); } - - - // int numtriggered = triggeredControllerSet.size(); /*unused*/ - for (set<SmartControllerPtr>::iterator tit=m_triggeredControllerSet.begin(); - !(tit==m_triggeredControllerSet.end());tit++) - { - (*tit)->Trigger(this); - } - m_triggeredControllerSet.clear(); } void SCA_LogicManager::UpdateFrame(double curtime, bool frame) { - vector<SmartActuatorPtr>::iterator ra; - for (ra = m_removedActuators.begin(); !(ra == m_removedActuators.end()); ra++) - { - m_activeActuators.erase(*ra); - (*ra)->SetActive(false); - } - m_removedActuators.clear(); - - // About to run actuators, but before update the sensors for those which depends on actuators for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin(); !(ie==m_eventmanagers.end()); ie++) (*ie)->UpdateFrame(); - for (set<SmartActuatorPtr>::iterator ia = m_activeActuators.begin();!(ia==m_activeActuators.end());ia++) + SG_DList::iterator<SG_QList> io(m_activeActuators); + for (io.begin(); !io.end(); ) { - //SCA_IActuator* actua = *ia; - if (!(*ia)->Update(curtime, frame)) + SG_QList* ahead = *io; + // increment now so that we can remove the current element + ++io; + SG_QList::iterator<SCA_IActuator> ia(*ahead); + for (ia.begin(); !ia.end(); ) { - //*ia = m_activeactuators.back(); - m_removedActuators.push_back(*ia); - - (*ia)->SetActive(false); - //m_activeactuators.pop_back(); - } else if ((*ia)->IsNoLink()) + SCA_IActuator* actua = *ia; + // increment first to allow removal of inactive actuators. + ++ia; + if (!actua->Update(curtime, frame)) + { + // this actuator is not active anymore, remove + actua->QDelink(); + actua->SetActive(false); + } else if (actua->IsNoLink()) + { + // This actuator has no more links but it still active + // make sure it will get a negative event on next frame to stop it + // Do this check after Update() rather than before to make sure + // that all the actuators that are activated at same time than a state + // actuator have a chance to execute. + bool event = false; + actua->RemoveAllEvents(); + actua->AddEvent(event); + } + } + if (ahead->QEmpty()) { - // This actuator has no more links but it still active - // make sure it will get a negative event on next frame to stop it - // Do this check after Update() rather than before to make sure - // that all the actuators that are activated at same time than a state - // actuator have a chance to execute. - CValue* event = new CBoolValue(false); - (*ia)->RemoveAllEvents(); - (*ia)->AddEvent(event); + // no more active controller, remove from main list + ahead->Delink(); } } - - for ( ra = m_removedActuators.begin(); !(ra == m_removedActuators.end()); ra++) - { - m_activeActuators.erase(*ra); - (*ra)->SetActive(false); - } - m_removedActuators.clear(); } @@ -360,39 +294,17 @@ void SCA_LogicManager::RegisterActionName(const STR_String& actname,void* action void SCA_LogicManager::EndFrame() { - for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin(); - !(is==m_activatedsensors.end());is++) - { - SCA_ISensor* sensor = *is; - sensor->SetActive(false); - } - m_activatedsensors.clear(); - for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin(); !(ie==m_eventmanagers.end());ie++) { (*ie)->EndFrame(); } - - } - -void SCA_LogicManager::AddActivatedSensor(SCA_ISensor* sensor) -{ - // each frame, only add sensor once, and to avoid a seek, or bloated container - // hold a flag in each sensor, with the 'framenr' - if (!sensor->IsActive()) - { - sensor->SetActive(true); - m_activatedsensors.push_back(sensor); - } -} - void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor) { - m_triggeredControllerSet.insert(SmartControllerPtr(controller,0)); + controller->Activate(m_triggeredControllerSet); // so that the controller knows which sensor has activited it // only needed for python controller if (controller->GetType() == &SCA_PythonController::Type) @@ -402,19 +314,6 @@ void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_I } } - -void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,CValue* event) -{ - if (!actua->IsActive()) - { - actua->SetActive(true); - m_activeActuators.insert(SmartActuatorPtr(actua,0)); - } - actua->AddEvent(event->AddRef()); -} - - - SCA_EventManager* SCA_LogicManager::FindEventManager(int eventmgrtype) { // find an eventmanager of a certain type @@ -432,109 +331,3 @@ SCA_EventManager* SCA_LogicManager::FindEventManager(int eventmgrtype) } return eventmgr; } - - - -SmartActuatorPtr::SmartActuatorPtr(const SmartActuatorPtr& other) -{ - this->m_actuator = other.m_actuator; - this->m_actuator->AddRef(); -} - - - -SmartActuatorPtr::SmartActuatorPtr(SCA_IActuator* actua,int dummy) -: m_actuator(actua) -{ - actua->AddRef(); -} - - - -SmartActuatorPtr::~SmartActuatorPtr() -{ - m_actuator->Release(); -} - - - -bool SmartActuatorPtr::operator <(const SmartActuatorPtr& other) const -{ - - return m_actuator->LessComparedTo(*other); -} - - - -bool SmartActuatorPtr::operator ==(const SmartActuatorPtr& other) const -{ - bool result2 = other->LessComparedTo(m_actuator); - return (m_actuator->LessComparedTo(*other) && result2); -} - - - -SCA_IActuator* SmartActuatorPtr::operator->() const -{ - return m_actuator; -} - - - -SCA_IActuator* SmartActuatorPtr::operator*() const -{ - return m_actuator; -} - - - -SmartControllerPtr::SmartControllerPtr(const SmartControllerPtr& copy) -{ - this->m_controller = copy.m_controller; - this->m_controller->AddRef(); -} - - - -SmartControllerPtr::SmartControllerPtr(SCA_IController* contr,int dummy) -: m_controller(contr) -{ - m_controller->AddRef(); -} - - - -SmartControllerPtr::~SmartControllerPtr() -{ - m_controller->Release(); -} - - - -bool SmartControllerPtr::operator <(const SmartControllerPtr& other) const -{ - return m_controller->LessComparedTo(*other); -} - - - -bool SmartControllerPtr::operator ==(const SmartControllerPtr& other) const -{ - return (m_controller->LessComparedTo(*other) && other->LessComparedTo(m_controller)); -} - - - -SCA_IController* SmartControllerPtr::operator->() const -{ - return m_controller; -} - - - -SCA_IController* SmartControllerPtr::operator*() const -{ - return m_controller; -} - - diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h index 50383879d8f..53e75e1eaee 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.h +++ b/source/gameengine/GameLogic/SCA_LogicManager.h @@ -43,11 +43,13 @@ #include "GEN_Map.h" #include "STR_HashedString.h" #include "Value.h" +#include "SG_QList.h" #include "KX_HashedPtr.h" using namespace std; -typedef list<class SCA_IController*> controllerlist; +typedef std::list<class SCA_IController*> controllerlist; +typedef std::map<class SCA_ISensor*,controllerlist > sensormap_t; /** * This manager handles sensor, controllers and actuators. @@ -63,45 +65,19 @@ typedef list<class SCA_IController*> controllerlist; */ #include "SCA_ILogicBrick.h" +#include "SCA_IActuator.h" -// todo: make this into a template, but first I want to think about what exactly to put in -class SmartActuatorPtr -{ - SCA_IActuator* m_actuator; -public: - SmartActuatorPtr(SCA_IActuator* actua,int dummy); - SmartActuatorPtr(const SmartActuatorPtr& other); - virtual ~SmartActuatorPtr(); - bool operator <(const SmartActuatorPtr& other) const; - bool operator ==(const SmartActuatorPtr& other) const; - SCA_IActuator* operator->() const; - SCA_IActuator* operator*() const; - -}; - -class SmartControllerPtr -{ - SCA_IController* m_controller; -public: - SmartControllerPtr(const SmartControllerPtr& copy); - SmartControllerPtr(SCA_IController* contr,int dummy); - virtual ~SmartControllerPtr(); - bool operator <(const SmartControllerPtr& other) const; - bool operator ==(const SmartControllerPtr& other) const; - SCA_IController* operator->() const; - SCA_IController* operator*() const; - -}; class SCA_LogicManager { vector<class SCA_EventManager*> m_eventmanagers; - vector<class SCA_ISensor*> m_activatedsensors; - set<class SmartActuatorPtr> m_activeActuators; - set<class SmartControllerPtr> m_triggeredControllerSet; - - map<SCA_ISensor*,controllerlist > m_sensorcontrollermapje; + // SG_DList: Head of objects having activated actuators + // element: SCA_IObject::m_activeActuators + SG_DList m_activeActuators; + // SG_DList: Head of objects having activated controllers + // element: SCA_IObject::m_activeControllers + SG_DList m_triggeredControllerSet; // need to find better way for this // also known as FactoryManager... @@ -111,11 +87,10 @@ class SCA_LogicManager GEN_Map<STR_HashedString,void*> m_map_gamemeshname_to_blendobj; GEN_Map<CHashedPtr,void*> m_map_blendobj_to_gameobj; - - vector<SmartActuatorPtr> m_removedActuators; public: SCA_LogicManager(); virtual ~SCA_LogicManager(); + //void SetKeyboardManager(SCA_KeyboardManager* keyboardmgr) { m_keyboardmgr=keyboardmgr;} void RegisterEventManager(SCA_EventManager* eventmgr); void RegisterToSensor(SCA_IController* controller, @@ -126,8 +101,13 @@ public: void BeginFrame(double curtime, double fixedtime); void UpdateFrame(double curtime, bool frame); void EndFrame(); - void AddActivatedSensor(SCA_ISensor* sensor); - void AddActiveActuator(SCA_IActuator* sensor,class CValue* event); + void AddActiveActuator(SCA_IActuator* actua,bool event) + { + actua->SetActive(true); + actua->Activate(m_activeActuators); + actua->AddEvent(event); + } + void AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor); SCA_EventManager* FindEventManager(int eventmgrtype); @@ -138,7 +118,7 @@ public: */ void RemoveSensor(SCA_ISensor* sensor); void RemoveController(SCA_IController* controller); - void RemoveDestroyedActuator(SCA_IActuator* actuator); + void RemoveActuator(SCA_IActuator* actuator); // for the scripting... needs a FactoryManager later (if we would have time... ;) diff --git a/source/gameengine/GameLogic/SCA_MouseManager.cpp b/source/gameengine/GameLogic/SCA_MouseManager.cpp index ca875dad07c..d407647cec3 100644 --- a/source/gameengine/GameLogic/SCA_MouseManager.cpp +++ b/source/gameengine/GameLogic/SCA_MouseManager.cpp @@ -75,8 +75,8 @@ void SCA_MouseManager::NextFrame() { if (m_mousedevice) { - set<SCA_ISensor*>::iterator it; - for (it=m_sensors.begin(); it!=m_sensors.end(); it++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { SCA_MouseSensor* mousesensor = (SCA_MouseSensor*)(*it); // (0,0) is the Upper Left corner in our local window @@ -93,7 +93,7 @@ void SCA_MouseManager::NextFrame() mousesensor->setX(mx); mousesensor->setY(my); - mousesensor->Activate(m_logicmanager,NULL); + mousesensor->Activate(m_logicmanager); } } } diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 4dbeb156e63..c5e1c3c0441 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -111,7 +111,7 @@ CValue* SCA_MouseSensor::GetReplica() { SCA_MouseSensor* replica = new SCA_MouseSensor(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); return replica; @@ -144,7 +144,7 @@ SCA_IInputDevice::KX_EnumInputs SCA_MouseSensor::GetHotKey() -bool SCA_MouseSensor::Evaluate(CValue* event) +bool SCA_MouseSensor::Evaluate() { bool result = false; bool reset = m_reset && m_level; @@ -296,8 +296,13 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, /* ------------------------------------------------------------------------- */ PyTypeObject SCA_MouseSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_MouseSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -342,6 +347,10 @@ PyObject* SCA_MouseSensor::py_getattro(PyObject *attr) py_getattro_up(SCA_ISensor); } +PyObject* SCA_MouseSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_MouseSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 2d1c496029d..6d6302b514a 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -97,7 +97,7 @@ class SCA_MouseSensor : public SCA_ISensor virtual ~SCA_MouseSensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual void Init(); virtual bool IsPositiveTrigger(); short int GetModeKey(); @@ -110,6 +110,7 @@ class SCA_MouseSensor : public SCA_ISensor /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated functions -----> diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp index 703c9c1bbaf..d27aea5e6f7 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.cpp +++ b/source/gameengine/GameLogic/SCA_NANDController.cpp @@ -66,26 +66,19 @@ void SCA_NANDController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (!sensor->IsPositiveTrigger()) + if (!sensor->GetState()) { sensorresult = true; break; } } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); - } @@ -94,7 +87,7 @@ CValue* SCA_NANDController::GetReplica() { CValue* replica = new SCA_NANDController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -107,8 +100,13 @@ CValue* SCA_NANDController::GetReplica() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_NANDController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_NANDController", sizeof(PyObjectPlus_Proxy), 0, @@ -145,4 +143,8 @@ PyObject* SCA_NANDController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_NANDController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_NANDController.h b/source/gameengine/GameLogic/SCA_NANDController.h index 11600914a1a..0ae0ff19745 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.h +++ b/source/gameengine/GameLogic/SCA_NANDController.h @@ -49,6 +49,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp index 06acae5a81a..6c9141636b2 100644 --- a/source/gameengine/GameLogic/SCA_NORController.cpp +++ b/source/gameengine/GameLogic/SCA_NORController.cpp @@ -66,26 +66,19 @@ void SCA_NORController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (sensor->IsPositiveTrigger()) + if (sensor->GetState()) { sensorresult = false; break; } } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); - } @@ -94,7 +87,7 @@ CValue* SCA_NORController::GetReplica() { CValue* replica = new SCA_NORController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -107,8 +100,13 @@ CValue* SCA_NORController::GetReplica() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_NORController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_NORController", sizeof(PyObjectPlus_Proxy), 0, @@ -145,4 +143,8 @@ PyObject* SCA_NORController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_NORController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_NORController.h b/source/gameengine/GameLogic/SCA_NORController.h index fc814e28d37..06cbb70a489 100644 --- a/source/gameengine/GameLogic/SCA_NORController.h +++ b/source/gameengine/GameLogic/SCA_NORController.h @@ -49,6 +49,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp index 319ff04f776..42c0a67d657 100644 --- a/source/gameengine/GameLogic/SCA_ORController.cpp +++ b/source/gameengine/GameLogic/SCA_ORController.cpp @@ -60,7 +60,7 @@ CValue* SCA_ORController::GetReplica() { CValue* replica = new SCA_ORController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -76,21 +76,16 @@ void SCA_ORController::Trigger(SCA_LogicManager* logicmgr) while ( (!sensorresult) && (!(is==m_linkedsensors.end())) ) { sensor = *is; - if (sensor->IsPositiveTrigger()) sensorresult = true; + if (sensor->GetState()) sensorresult = true; is++; } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - - newevent->Release(); } /* ------------------------------------------------------------------------- */ @@ -99,8 +94,13 @@ void SCA_ORController::Trigger(SCA_LogicManager* logicmgr) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_ORController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_ORController", sizeof(PyObjectPlus_Proxy), 0, @@ -138,4 +138,8 @@ PyObject* SCA_ORController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_ORController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ORController.h b/source/gameengine/GameLogic/SCA_ORController.h index fdc81486e74..66f772c739e 100644 --- a/source/gameengine/GameLogic/SCA_ORController.h +++ b/source/gameengine/GameLogic/SCA_ORController.h @@ -50,6 +50,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; #endif //__KX_ORCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index c4db723ee89..4faa4b55d4a 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -186,11 +186,6 @@ GetReplica() { SCA_PropertyActuator* replica = new SCA_PropertyActuator(*this); replica->ProcessReplica(); - - // this will copy properties and so on... - - CValue::AddDataToReplica(replica); - return replica; }; @@ -233,8 +228,13 @@ void SCA_PropertyActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_PropertyActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_PropertyActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -270,8 +270,9 @@ PyMethodDef SCA_PropertyActuator::Methods[] = { }; PyAttributeDef SCA_PropertyActuator::Attributes[] = { - KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_PropertyActuator,m_propname,CheckProperty), + KX_PYATTRIBUTE_STRING_RW_CHECK("propName",0,100,false,SCA_PropertyActuator,m_propname,CheckProperty), KX_PYATTRIBUTE_STRING_RW("value",0,100,false,SCA_PropertyActuator,m_exprtxt), + KX_PYATTRIBUTE_INT_RW("mode", KX_ACT_PROP_NODEF+1, KX_ACT_PROP_MAX-1, false, SCA_PropertyActuator, m_type), /* ATTR_TODO add constents to game logic dict */ { NULL } //Sentinel }; @@ -279,6 +280,10 @@ PyObject* SCA_PropertyActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); } +PyObject* SCA_PropertyActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int SCA_PropertyActuator::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IActuator); } @@ -291,7 +296,7 @@ const char SCA_PropertyActuator::SetProperty_doc[] = "\tof this name, the call is ignored.\n"; PyObject* SCA_PropertyActuator::PySetProperty(PyObject* args, PyObject* kwds) { - ShowDeprecationWarning("setProperty()", "the 'property' property"); + ShowDeprecationWarning("setProperty()", "the 'propName' property"); /* Check whether the name exists first ! */ char *nameArg; if (!PyArg_ParseTuple(args, "s:setProperty", &nameArg)) { @@ -316,7 +321,7 @@ const char SCA_PropertyActuator::GetProperty_doc[] = "\tReturn the property on which the actuator operates.\n"; PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* args, PyObject* kwds) { - ShowDeprecationWarning("getProperty()", "the 'property' property"); + ShowDeprecationWarning("getProperty()", "the 'propName' property"); return PyString_FromString(m_propname); } diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h index bb841cf88ad..a8df08dfc6e 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.h +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h @@ -87,6 +87,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); // python wrapped methods diff --git a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp index e5e3f9cced5..764465309df 100644 --- a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp @@ -50,8 +50,9 @@ SCA_PropertyEventManager::~SCA_PropertyEventManager() void SCA_PropertyEventManager::NextFrame() { // check for changed properties - for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*it)->Activate(m_logicmgr,NULL); + (*it)->Activate(m_logicmgr); } } diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index de8a9fcf03e..3b343af3cba 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -37,6 +37,7 @@ #include "StringValue.h" #include "SCA_EventManager.h" #include "SCA_LogicManager.h" +#include "BoolValue.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -111,7 +112,7 @@ CValue* SCA_PropertySensor::GetReplica() { SCA_PropertySensor* replica = new SCA_PropertySensor(*this); // m_range_expr must be recalculated on replica! - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); replica->m_range_expr = NULL; @@ -152,7 +153,7 @@ SCA_PropertySensor::~SCA_PropertySensor() -bool SCA_PropertySensor::Evaluate(CValue* event) +bool SCA_PropertySensor::Evaluate() { bool result = CheckPropertyCondition(); bool reset = m_reset && m_level; @@ -182,17 +183,14 @@ bool SCA_PropertySensor::CheckPropertyCondition() CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { - STR_String testprop = orgprop->GetText(); + const STR_String& testprop = orgprop->GetText(); // Force strings to upper case, to avoid confusion in // bool tests. It's stupid the prop's identity is lost // on the way here... - if ((testprop == "TRUE") || (testprop == "FALSE")) { - STR_String checkprop = m_checkpropval; - checkprop.Upper(); - result = (testprop == checkprop); - } else { - result = (orgprop->GetText() == m_checkpropval); + if ((&testprop == &CBoolValue::sTrueString) || (&testprop == &CBoolValue::sFalseString)) { + m_checkpropval.Upper(); } + result = (testprop == m_checkpropval); } orgprop->Release(); @@ -232,8 +230,8 @@ bool SCA_PropertySensor::CheckPropertyCondition() CValue* vallie = m_range_expr->Calculate(); if (vallie) { - STR_String errtext = vallie->GetText(); - if (errtext == "TRUE") + const STR_String& errtext = vallie->GetText(); + if (&errtext == &CBoolValue::sTrueString) { result = true; } else @@ -295,9 +293,8 @@ CValue* SCA_PropertySensor::FindIdentifier(const STR_String& identifiername) int SCA_PropertySensor::validValueForProperty(void *self, const PyAttributeDef*) { - bool result = true; /* There is no type checking at this moment, unfortunately... */ - return result; + return 0; } /* ------------------------------------------------------------------------- */ @@ -306,8 +303,13 @@ int SCA_PropertySensor::validValueForProperty(void *self, const PyAttributeDef*) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_PropertySensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_PropertySensor", sizeof(PyObjectPlus_Proxy), 0, @@ -345,8 +347,8 @@ PyMethodDef SCA_PropertySensor::Methods[] = { }; PyAttributeDef SCA_PropertySensor::Attributes[] = { - KX_PYATTRIBUTE_INT_RW("type",KX_PROPSENSOR_NODEF,KX_PROPSENSOR_MAX-1,false,SCA_PropertySensor,m_checktype), - KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_PropertySensor,m_checkpropname,CheckProperty), + KX_PYATTRIBUTE_INT_RW("mode",KX_PROPSENSOR_NODEF,KX_PROPSENSOR_MAX-1,false,SCA_PropertySensor,m_checktype), + KX_PYATTRIBUTE_STRING_RW_CHECK("propName",0,100,false,SCA_PropertySensor,m_checkpropname,CheckProperty), KX_PYATTRIBUTE_STRING_RW_CHECK("value",0,100,false,SCA_PropertySensor,m_checkpropval,validValueForProperty), { NULL } //Sentinel }; @@ -356,6 +358,10 @@ PyObject* SCA_PropertySensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_PropertySensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_PropertySensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); } @@ -366,7 +372,7 @@ const char SCA_PropertySensor::GetType_doc[] = "\tReturns the type of check this sensor performs.\n"; PyObject* SCA_PropertySensor::PyGetType() { - ShowDeprecationWarning("getType()", "the type property"); + ShowDeprecationWarning("getType()", "the mode property"); return PyInt_FromLong(m_checktype); } @@ -379,7 +385,7 @@ const char SCA_PropertySensor::SetType_doc[] = "\tSet the type of check to perform.\n"; PyObject* SCA_PropertySensor::PySetType(PyObject* args) { - ShowDeprecationWarning("setType()", "the type property"); + ShowDeprecationWarning("setType()", "the mode property"); int typeArg; if (!PyArg_ParseTuple(args, "i:setType", &typeArg)) { @@ -400,7 +406,7 @@ const char SCA_PropertySensor::GetProperty_doc[] = "\tReturn the property with which the sensor operates.\n"; PyObject* SCA_PropertySensor::PyGetProperty() { - ShowDeprecationWarning("getProperty()", "the 'property' property"); + ShowDeprecationWarning("getProperty()", "the 'propName' property"); return PyString_FromString(m_checkpropname); } @@ -412,7 +418,7 @@ const char SCA_PropertySensor::SetProperty_doc[] = "\tof this name, the call is ignored.\n"; PyObject* SCA_PropertySensor::PySetProperty(PyObject* args) { - ShowDeprecationWarning("setProperty()", "the 'property' property"); + ShowDeprecationWarning("setProperty()", "the 'propName' property"); /* We should query whether the name exists. Or should we create a prop */ /* on the fly? */ char *propNameArg = NULL; diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h index e1e378a973c..538ecd65949 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.h +++ b/source/gameengine/GameLogic/SCA_PropertySensor.h @@ -81,7 +81,7 @@ public: void PrecalculateRangeExpression(); bool CheckPropertyCondition(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual CValue* FindIdentifier(const STR_String& identifiername); @@ -90,6 +90,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* 1. getType */ diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index b8052555528..80e4f54c9c5 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -48,12 +48,18 @@ SCA_PythonController* SCA_PythonController::m_sCurrentController = NULL; SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj, + int mode, PyTypeObject* T) : SCA_IController(gameobj, T), m_bytecode(NULL), + m_function(NULL), + m_function_argc(0), m_bModified(true), + m_debug(false), + m_mode(mode), m_pythondictionary(NULL) { + } /* @@ -74,15 +80,12 @@ int SCA_PythonController::Release() SCA_PythonController::~SCA_PythonController() { - if (m_bytecode) - { - // - //printf("released python byte script\n"); - Py_DECREF(m_bytecode); - } + //printf("released python byte script\n"); - if (m_pythondictionary) - { + Py_XDECREF(m_bytecode); + Py_XDECREF(m_function); + + if (m_pythondictionary) { // break any circular references in the dictionary PyDict_Clear(m_pythondictionary); Py_DECREF(m_pythondictionary); @@ -94,8 +97,12 @@ SCA_PythonController::~SCA_PythonController() CValue* SCA_PythonController::GetReplica() { SCA_PythonController* replica = new SCA_PythonController(*this); - // Copy the compiled bytecode if possible. + + /* why is this needed at all??? - m_bytecode is NULL'd below so this doesnt make sense + * but removing it crashes blender (with YoFrankie). so leave in for now - Campbell */ Py_XINCREF(replica->m_bytecode); + + Py_XINCREF(replica->m_function); // this is ok since its not set to NULL replica->m_bModified = replica->m_bytecode == NULL; // The replica->m_pythondictionary is stolen - replace with a copy. @@ -110,7 +117,7 @@ CValue* SCA_PythonController::GetReplica() */ // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -140,6 +147,11 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary) Py_DECREF(m_pythondictionary); } m_pythondictionary = PyDict_Copy(pythondictionary); /* new reference */ + + /* Without __file__ set the sys.argv[0] is used for the filename + * which ends up with lines from the blender binary being printed in the console */ + PyDict_SetItemString(m_pythondictionary, "__file__", PyString_FromString(m_scriptName.Ptr())); + } int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) @@ -150,13 +162,14 @@ int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) return 0; } -#if 0 -static const char* sPyGetCurrentController__doc__; -#endif - /* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */ PyObject* SCA_PythonController::sPyGetCurrentController(PyObject *self) { + if(m_sCurrentController==NULL) + { + PyErr_SetString(PyExc_SystemError, "GameLogic.getCurrentController(), this function is being run outside the python controllers context, or blenders internal state is corrupt."); + return NULL; + } return m_sCurrentController->GetProxy(); } @@ -170,15 +183,15 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) if (PyString_Check(value)) { /* get the actuator from the name */ char *name= PyString_AsString(value); - for(it = lacts.begin(); it!= lacts.end(); it++) { + for(it = lacts.begin(); it!= lacts.end(); ++it) { if( name == (*it)->GetName() ) { return *it; } } } else if (BGE_PROXY_CHECK_TYPE(value)) { - PyObjectPlus *value_plus= BGE_PROXY_REF(value); /* Expecting an actuator type */ // XXX TODO - CHECK TYPE - for(it = lacts.begin(); it!= lacts.end(); it++) { + PyObjectPlus *value_plus= BGE_PROXY_REF(value); + for(it = lacts.begin(); it!= lacts.end(); ++it) { if( static_cast<SCA_IActuator*>(value_plus) == (*it) ) { return *it; } @@ -193,13 +206,11 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) return false; } -#if 0 -static const char* sPyAddActiveActuator__doc__; -#endif - /* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */ PyObject* SCA_PythonController::sPyAddActiveActuator(PyObject* self, PyObject* args) { + ShowDeprecationWarning("GameLogic.addActiveActuator(act, bool)", "controller.activate(act) or controller.deactivate(act)"); + PyObject* ob1; int activate; if (!PyArg_ParseTuple(args, "Oi:addActiveActuator", &ob1,&activate)) @@ -209,20 +220,22 @@ PyObject* SCA_PythonController::sPyAddActiveActuator(PyObject* self, PyObject* a if(actu==NULL) return NULL; - CValue* boolval = new CBoolValue(activate!=0); + bool boolval = (activate!=0); m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu,boolval); - boolval->Release(); Py_RETURN_NONE; } - const char* SCA_PythonController::sPyGetCurrentController__doc__ = "getCurrentController()"; const char* SCA_PythonController::sPyAddActiveActuator__doc__= "addActiveActuator(actuator,bool)"; -const char SCA_PythonController::GetActuators_doc[] = "getActuator"; PyTypeObject SCA_PythonController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_PythonController", sizeof(PyObjectPlus_Proxy), 0, @@ -249,59 +262,137 @@ PyMethodDef SCA_PythonController::Methods[] = { {"activate", (PyCFunction) SCA_PythonController::sPyActivate, METH_O}, {"deactivate", (PyCFunction) SCA_PythonController::sPyDeActivate, METH_O}, - {"getActuators", (PyCFunction) SCA_PythonController::sPyGetActuators, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetActuators_doc}, - {"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator, METH_O, (PY_METHODCHAR)SCA_PythonController::GetActuator_doc}, - {"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetSensors_doc}, - {"getSensor", (PyCFunction) SCA_PythonController::sPyGetSensor, METH_O, (PY_METHODCHAR)SCA_PythonController::GetSensor_doc}, //Deprecated functions ------> {"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O}, {"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS}, - {"getState", (PyCFunction) SCA_PythonController::sPyGetState, METH_NOARGS}, //<----- Deprecated {NULL,NULL} //Sentinel }; PyAttributeDef SCA_PythonController::Attributes[] = { - KX_PYATTRIBUTE_RO_FUNCTION("state", SCA_PythonController, pyattr_get_state), KX_PYATTRIBUTE_RW_FUNCTION("script", SCA_PythonController, pyattr_get_script, pyattr_set_script), + KX_PYATTRIBUTE_INT_RO("mode", SCA_PythonController, m_mode), { NULL } //Sentinel }; -bool SCA_PythonController::Compile() +void SCA_PythonController::ErrorPrint(const char *error_msg) { + // didn't compile, so instead of compile, complain + // something is wrong, tell the user what went wrong + printf("%s - controller \"%s\":\n", error_msg, GetName().Ptr()); + //PyRun_SimpleString(m_scriptText.Ptr()); + PyErr_Print(); + + /* Added in 2.48a, the last_traceback can reference Objects for example, increasing + * their user count. Not to mention holding references to wrapped data. + * This is especially bad when the PyObject for the wrapped data is free'd, after blender + * has alredy dealocated the pointer */ + PySys_SetObject( (char *)"last_traceback", NULL); + PyErr_Clear(); /* just to be sure */ +} + +bool SCA_PythonController::Compile() +{ //printf("py script modified '%s'\n", m_scriptName.Ptr()); + m_bModified= false; // if a script already exists, decref it before replace the pointer to a new script - if (m_bytecode) - { + if (m_bytecode) { Py_DECREF(m_bytecode); m_bytecode=NULL; } + // recompile the scripttext into bytecode m_bytecode = Py_CompileString(m_scriptText.Ptr(), m_scriptName.Ptr(), Py_file_input); - m_bModified=false; - if (m_bytecode) - { - + if (m_bytecode) { return true; + } else { + ErrorPrint("Python error compiling script"); + return false; } - else { - // didn't compile, so instead of compile, complain - // something is wrong, tell the user what went wrong - printf("Python compile error from controller \"%s\": \n", GetName().Ptr()); - //PyRun_SimpleString(m_scriptText.Ptr()); - PyErr_Print(); +} + +bool SCA_PythonController::Import() +{ + //printf("py module modified '%s'\n", m_scriptName.Ptr()); + m_bModified= false; + + /* incase we re-import */ + Py_XDECREF(m_function); + m_function= NULL; + + vector<STR_String> py_function_path = m_scriptText.Explode('.'); + + if(py_function_path.size() < 2) { + printf("Python module name formatting error \"%s\":\n\texpected \"SomeModule.Func\", got \"%s\"\n", GetName().Ptr(), m_scriptText.Ptr()); + return false; + } + + PyObject *mod = PyImport_ImportModule((char *)py_function_path[0].Ptr()); + /* Dont reload yet, do this within the loop so packages reload too */ + + if(mod==NULL) { + ErrorPrint("Python module not found"); + return false; + } + /* 'mod' will be DECREF'd as 'base' + * 'm_function' will be left holding a reference that the controller owns */ + + PyObject *base= mod; + + for(unsigned int i=1; i < py_function_path.size(); i++) { + if(m_debug && PyModule_Check(base)) { /* base could be a class */ + Py_DECREF(base); /* getting a new one so dont hold a ref to the old one */ + base= PyImport_ReloadModule(base); + if (base==NULL) { + m_function= NULL; + break; + } + } - /* Added in 2.48a, the last_traceback can reference Objects for example, increasing - * their user count. Not to mention holding references to wrapped data. - * This is especially bad when the PyObject for the wrapped data is free'd, after blender - * has alredy dealocated the pointer */ - PySys_SetObject( (char *)"last_traceback", NULL); - PyErr_Clear(); /* just to be sure */ + m_function = PyObject_GetAttrString(base, py_function_path[i].Ptr()); + Py_DECREF(base); + base = m_function; /* for the next loop if there is on */ + if(m_function==NULL) { + break; + } + } + + if(m_function==NULL) { + if(PyErr_Occurred()) + ErrorPrint("Python controller found the module but could not access the function"); + else + printf("Python module error \"%s\":\n \"%s\" module found but function missing\n", GetName().Ptr(), m_scriptText.Ptr()); + return false; + } + + if(!PyCallable_Check(m_function)) { + Py_DECREF(m_function); + printf("Python module function error \"%s\":\n \"%s\" not callable\n", GetName().Ptr(), m_scriptText.Ptr()); + return false; + } + + m_function_argc = 0; /* rare cases this could be a function that isnt defined in python, assume zero args */ + if (PyFunction_Check(m_function)) { + PyObject *py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(m_function), "co_argcount"); + if(py_arg_count) { + m_function_argc = PyLong_AsLong(py_arg_count); + Py_DECREF(py_arg_count); + } + else { + PyErr_Clear(); /* unlikely to fail but just incase */ + } + } + + if(m_function_argc > 1) { + Py_DECREF(m_function); + printf("Python module function has \"%s\":\n \"%s\" takes %d args, should be zero or 1 controller arg\n", GetName().Ptr(), m_scriptText.Ptr(), m_function_argc); return false; } + + return true; } void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) @@ -309,16 +400,18 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) m_sCurrentController = this; m_sCurrentLogicManager = logicmgr; - if (m_bModified) + PyObject *excdict= NULL; + PyObject* resultobj= NULL; + + switch(m_mode) { + case SCA_PYEXEC_SCRIPT: { - if (Compile()==false) // sets m_bModified to false + if (m_bModified) + if (Compile()==false) // sets m_bModified to false + return; + if (!m_bytecode) return; - } - if (!m_bytecode) { - return; - } - /* * This part here with excdict is a temporary patch * to avoid python/gameengine crashes when python @@ -337,10 +430,36 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) * should always ensure excdict is cleared). */ - PyObject *excdict= PyDict_Copy(m_pythondictionary); - PyObject* resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode, - excdict, excdict); - + excdict= PyDict_Copy(m_pythondictionary); + resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode, excdict, excdict); + /* PyRun_SimpleString(m_scriptText.Ptr()); */ + break; + } + case SCA_PYEXEC_MODULE: + { + if (m_bModified || m_debug) + if (Import()==false) // sets m_bModified to false + return; + if (!m_function) + return; + + PyObject *args= NULL; + + if(m_function_argc==1) { + args = PyTuple_New(1); + PyTuple_SET_ITEM(args, 0, GetProxy()); + } + + resultobj = PyObject_CallObject(m_function, args); + Py_XDECREF(args); + break; + } + + } /* end switch */ + + + + /* Free the return value and print the error */ if (resultobj) { Py_DECREF(resultobj); @@ -348,7 +467,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) else { // something is wrong, tell the user what went wrong - printf("Python script error from controller \"%s\": \n", GetName().Ptr()); + printf("Python script error from controller \"%s\":\n", GetName().Ptr()); PyErr_Print(); /* Added in 2.48a, the last_traceback can reference Objects for example, increasing @@ -357,15 +476,17 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) * has alredy dealocated the pointer */ PySys_SetObject( (char *)"last_traceback", NULL); PyErr_Clear(); /* just to be sure */ - - //PyRun_SimpleString(m_scriptText.Ptr()); } - - // clear after PyErrPrint - seems it can be using - // something in this dictionary and crash? - PyDict_Clear(excdict); - Py_DECREF(excdict); - m_triggeredSensors.erase(m_triggeredSensors.begin(), m_triggeredSensors.end()); + + if(excdict) /* Only for SCA_PYEXEC_SCRIPT types */ + { + /* clear after PyErrPrint - seems it can be using + * something in this dictionary and crash? */ + PyDict_Clear(excdict); + Py_DECREF(excdict); + } + + m_triggeredSensors.clear(); m_sCurrentController = NULL; } @@ -376,6 +497,10 @@ PyObject* SCA_PythonController::py_getattro(PyObject *attr) py_getattro_up(SCA_IController); } +PyObject* SCA_PythonController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + int SCA_PythonController::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IController); @@ -383,104 +508,32 @@ int SCA_PythonController::py_setattro(PyObject *attr, PyObject *value) PyObject* SCA_PythonController::PyActivate(PyObject *value) { - SCA_IActuator* actu = LinkedActuatorFromPy(value); - if(actu==NULL) + if(m_sCurrentController != this) { + PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller"); return NULL; + } - CValue* boolval = new CBoolValue(true); - m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, boolval); - boolval->Release(); - Py_RETURN_NONE; -} - -PyObject* SCA_PythonController::PyDeActivate(PyObject *value) -{ SCA_IActuator* actu = LinkedActuatorFromPy(value); if(actu==NULL) return NULL; - CValue* boolval = new CBoolValue(false); - m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, boolval); - boolval->Release(); + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, true); Py_RETURN_NONE; } -PyObject* SCA_PythonController::PyGetActuators() -{ - PyObject* resultlist = PyList_New(m_linkedactuators.size()); - for (unsigned int index=0;index<m_linkedactuators.size();index++) - { - PyList_SET_ITEM(resultlist,index, m_linkedactuators[index]->GetProxy()); - } - - return resultlist; -} - -const char SCA_PythonController::GetSensor_doc[] = -"getSensor (char sensorname) return linked sensor that is named [sensorname]\n"; -PyObject* -SCA_PythonController::PyGetSensor(PyObject* value) +PyObject* SCA_PythonController::PyDeActivate(PyObject *value) { - - char *scriptArg = PyString_AsString(value); - if (scriptArg==NULL) { - PyErr_SetString(PyExc_TypeError, "controller.getSensor(string): Python Controller, expected a string (sensor name)"); + if(m_sCurrentController != this) { + PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller"); return NULL; } - for (unsigned int index=0;index<m_linkedsensors.size();index++) - { - SCA_ISensor* sensor = m_linkedsensors[index]; - STR_String realname = sensor->GetName(); - if (realname == scriptArg) - { - return sensor->GetProxy(); - } - } - - PyErr_Format(PyExc_AttributeError, "controller.getSensor(string): Python Controller, unable to find requested sensor \"%s\"", scriptArg); - return NULL; -} - - - -const char SCA_PythonController::GetActuator_doc[] = -"getActuator (char sensorname) return linked actuator that is named [actuatorname]\n"; -PyObject* -SCA_PythonController::PyGetActuator(PyObject* value) -{ - - char *scriptArg = PyString_AsString(value); - if (scriptArg==NULL) { - PyErr_SetString(PyExc_TypeError, "controller.getActuator(string): Python Controller, expected a string (actuator name)"); + SCA_IActuator* actu = LinkedActuatorFromPy(value); + if(actu==NULL) return NULL; - } - for (unsigned int index=0;index<m_linkedactuators.size();index++) - { - SCA_IActuator* actua = m_linkedactuators[index]; - if (actua->GetName() == scriptArg) - { - return actua->GetProxy(); - } - } - - PyErr_Format(PyExc_AttributeError, "controller.getActuator(string): Python Controller, unable to find requested actuator \"%s\"", scriptArg); - return NULL; -} - - -const char SCA_PythonController::GetSensors_doc[] = "getSensors returns a list of all attached sensors"; -PyObject* -SCA_PythonController::PyGetSensors() -{ - PyObject* resultlist = PyList_New(m_linkedsensors.size()); - for (unsigned int index=0;index<m_linkedsensors.size();index++) - { - PyList_SET_ITEM(resultlist,index, m_linkedsensors[index]->GetProxy()); - } - - return resultlist; + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, false); + Py_RETURN_NONE; } /* 1. getScript */ @@ -510,19 +563,6 @@ PyObject* SCA_PythonController::PySetScript(PyObject* value) Py_RETURN_NONE; } -/* 1. getScript */ -PyObject* SCA_PythonController::PyGetState() -{ - ShowDeprecationWarning("getState()", "the state property"); - return PyInt_FromLong(m_statemask); -} - -PyObject* SCA_PythonController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v); - return PyInt_FromLong(self->m_statemask); -} - PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v); @@ -537,14 +577,14 @@ int SCA_PythonController::pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_D if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "controller.script = string: Python Controller, expected a string script text"); - return -1; + return PY_SET_ATTR_FAIL; } /* set scripttext sets m_bModified to true, so next time the script is needed, a reparse into byte code is done */ self->SetScriptText(scriptArg); - return 0; + return PY_SET_ATTR_SUCCESS; } diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index f10c4e47ebb..0c2af79c3a3 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -42,23 +42,37 @@ class SCA_IObject; class SCA_PythonController : public SCA_IController { Py_Header; - struct _object * m_bytecode; + struct _object * m_bytecode; /* SCA_PYEXEC_SCRIPT only */ + PyObject* m_function; /* SCA_PYEXEC_MODULE only */ + int m_function_argc; bool m_bModified; + bool m_debug; /* use with SCA_PYEXEC_MODULE for reloading every logic run */ + int m_mode; + protected: STR_String m_scriptText; STR_String m_scriptName; - PyObject* m_pythondictionary; + PyObject* m_pythondictionary; /* for SCA_PYEXEC_SCRIPT only */ + PyObject* m_pythonfunction; /* for SCA_PYEXEC_MODULE only */ + std::vector<class SCA_ISensor*> m_triggeredSensors; + + public: + enum SCA_PyExecMode + { + SCA_PYEXEC_SCRIPT = 0, + SCA_PYEXEC_MODULE, + SCA_PYEXEC_MAX + }; - public: static SCA_PythonController* m_sCurrentController; // protected !!! //for debugging //virtual CValue* AddRef(); //virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) - SCA_PythonController(SCA_IObject* gameobj,PyTypeObject* T = &Type); + SCA_PythonController(SCA_IObject* gameobj, int mode, PyTypeObject* T = &Type); virtual ~SCA_PythonController(); virtual CValue* GetReplica(); @@ -67,10 +81,14 @@ class SCA_PythonController : public SCA_IController void SetScriptText(const STR_String& text); void SetScriptName(const STR_String& name); void SetDictionary(PyObject* pythondictionary); + void SetDebug(bool debug) { m_debug = debug; } void AddTriggeredSensor(class SCA_ISensor* sensor) { m_triggeredSensors.push_back(sensor); } int IsTriggered(class SCA_ISensor* sensor); bool Compile(); + bool Import(); + void ErrorPrint(const char *error_msg); + static const char* sPyGetCurrentController__doc__; static PyObject* sPyGetCurrentController(PyObject* self); @@ -78,21 +96,18 @@ class SCA_PythonController : public SCA_IController static PyObject* sPyAddActiveActuator(PyObject* self, PyObject* args); static SCA_IActuator* LinkedActuatorFromPy(PyObject *value); + virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); KX_PYMETHOD_O(SCA_PythonController,Activate); KX_PYMETHOD_O(SCA_PythonController,DeActivate); - KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetSensors); - KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetActuators); - KX_PYMETHOD_DOC_O(SCA_PythonController,GetSensor); - KX_PYMETHOD_DOC_O(SCA_PythonController,GetActuator); KX_PYMETHOD_O(SCA_PythonController,SetScript); KX_PYMETHOD_NOARGS(SCA_PythonController,GetScript); - KX_PYMETHOD_NOARGS(SCA_PythonController,GetState); + - static PyObject* pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 3a72d9b7652..a722590dd10 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -58,7 +58,6 @@ SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj, m_parameter2(para2), m_distribution(mode) { - // m_base is never deleted, probably a memory leak! m_base = new SCA_RandomNumberGenerator(seed); m_counter = 0; enforceConstraints(); @@ -68,7 +67,7 @@ SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj, SCA_RandomActuator::~SCA_RandomActuator() { - /* intentionally empty */ + m_base->Release(); } @@ -78,11 +77,16 @@ CValue* SCA_RandomActuator::GetReplica() SCA_RandomActuator* replica = new SCA_RandomActuator(*this); // replication just copy the m_base pointer => common random generator replica->ProcessReplica(); - CValue::AddDataToReplica(replica); - return replica; } +void SCA_RandomActuator::ProcessReplica() +{ + SCA_IActuator::ProcessReplica(); + // increment reference count so that we can release the generator at the end + m_base->AddRef(); +} + bool SCA_RandomActuator::Update() @@ -312,8 +316,13 @@ void SCA_RandomActuator::enforceConstraints() { /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_RandomActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_RandomActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -367,7 +376,7 @@ PyAttributeDef SCA_RandomActuator::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RO("para1",SCA_RandomActuator,m_parameter1), KX_PYATTRIBUTE_FLOAT_RO("para2",SCA_RandomActuator,m_parameter2), KX_PYATTRIBUTE_ENUM_RO("distribution",SCA_RandomActuator,m_distribution), - KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_RandomActuator,m_propname,CheckProperty), + KX_PYATTRIBUTE_STRING_RW_CHECK("propName",0,100,false,SCA_RandomActuator,m_propname,CheckProperty), KX_PYATTRIBUTE_RW_FUNCTION("seed",SCA_RandomActuator,pyattr_get_seed,pyattr_set_seed), { NULL } //Sentinel }; @@ -384,10 +393,10 @@ int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_ if (PyInt_Check(value)) { int ival = PyInt_AsLong(value); act->m_base->SetSeed(ival); - return 0; + return PY_SET_ATTR_SUCCESS; } else { PyErr_SetString(PyExc_TypeError, "actuator.seed = int: Random Actuator, expected an integer"); - return 1; + return PY_SET_ATTR_FAIL; } } @@ -395,6 +404,10 @@ PyObject* SCA_RandomActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); } +PyObject* SCA_RandomActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int SCA_RandomActuator::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IActuator); @@ -470,7 +483,7 @@ const char SCA_RandomActuator::SetProperty_doc[] = "\tSet the property to which the random value is assigned. If the \n" "\tgenerator and property types do not match, the assignment is ignored.\n"; PyObject* SCA_RandomActuator::PySetProperty(PyObject* args) { - ShowDeprecationWarning("setProperty()", "the 'property' property"); + ShowDeprecationWarning("setProperty()", "the 'propName' property"); char *nameArg; if (!PyArg_ParseTuple(args, "s:setProperty", &nameArg)) { return NULL; @@ -494,7 +507,7 @@ const char SCA_RandomActuator::GetProperty_doc[] = "\tgenerator and property types do not match, the assignment is ignored.\n"; PyObject* SCA_RandomActuator::PyGetProperty() { - ShowDeprecationWarning("getProperty()", "the 'property' property"); + ShowDeprecationWarning("getProperty()", "the 'propName' property"); return PyString_FromString(m_propname); } diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h index 8f58ed0dcec..59863589b60 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.h +++ b/source/gameengine/GameLogic/SCA_RandomActuator.h @@ -91,12 +91,14 @@ class SCA_RandomActuator : public SCA_IActuator virtual bool Update(); virtual CValue* GetReplica(); + virtual void ProcessReplica(); /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); static PyObject* pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp index 156478d866d..976597aa812 100644 --- a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp @@ -50,9 +50,10 @@ SCA_RandomEventManager::SCA_RandomEventManager(class SCA_LogicManager* logicmgr) void SCA_RandomEventManager::NextFrame() { - for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*i)->Activate(m_logicmgr, NULL); + (*it)->Activate(m_logicmgr); } } diff --git a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp index 06b5cca6ce9..0267cc8ebbf 100644 --- a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp @@ -59,6 +59,7 @@ SCA_RandomNumberGenerator::SCA_RandomNumberGenerator(long seed) { // int mti = N + 1; /*unused*/ m_seed = seed; + m_refcount = 1; SetStartVector(); } diff --git a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h index b9311d31af6..842a0331752 100644 --- a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h +++ b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h @@ -36,6 +36,9 @@ class SCA_RandomNumberGenerator { + /* reference counted for memleak */ + int m_refcount; + /** base seed */ long m_seed; @@ -56,6 +59,16 @@ class SCA_RandomNumberGenerator { float DrawFloat(); long GetSeed(); void SetSeed(long newseed); + SCA_RandomNumberGenerator* AddRef() + { + ++m_refcount; + return this; + } + void Release() + { + if (--m_refcount == 0) + delete this; + } }; #endif /* __KX_RANDOMNUMBERGENERATOR */ diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 5ead82db428..d5cbeef01ae 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -50,7 +50,6 @@ SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr, PyTypeObject* T) : SCA_ISensor(gameobj,eventmgr, T) { - // m_basegenerator is never deleted => memory leak m_basegenerator = new SCA_RandomNumberGenerator(startseed); Init(); } @@ -59,7 +58,7 @@ SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr, SCA_RandomSensor::~SCA_RandomSensor() { - /* Nothing to be done here. */ + m_basegenerator->Release(); } void SCA_RandomSensor::Init() @@ -74,13 +73,18 @@ void SCA_RandomSensor::Init() CValue* SCA_RandomSensor::GetReplica() { CValue* replica = new SCA_RandomSensor(*this); - // replication copies m_basegenerator pointer => share same generator // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } +void SCA_RandomSensor::ProcessReplica() +{ + SCA_ISensor::ProcessReplica(); + // increment reference count so that we can release the generator at this end + m_basegenerator->AddRef(); +} bool SCA_RandomSensor::IsPositiveTrigger() @@ -89,7 +93,7 @@ bool SCA_RandomSensor::IsPositiveTrigger() } -bool SCA_RandomSensor::Evaluate(CValue* event) +bool SCA_RandomSensor::Evaluate() { /* Random generator is the generator from Line 25 of Table 1 in */ /* [KNUTH 1981, The Art of Computer Programming Vol. 2 */ @@ -127,8 +131,13 @@ bool SCA_RandomSensor::Evaluate(CValue* event) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_RandomSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_RandomSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -154,9 +163,11 @@ PyParentObject SCA_RandomSensor::Parents[] = { }; PyMethodDef SCA_RandomSensor::Methods[] = { + //Deprecated functions -----> {"setSeed", (PyCFunction) SCA_RandomSensor::sPySetSeed, METH_VARARGS, (PY_METHODCHAR)SetSeed_doc}, {"getSeed", (PyCFunction) SCA_RandomSensor::sPyGetSeed, METH_NOARGS, (PY_METHODCHAR)GetSeed_doc}, {"getLastDraw", (PyCFunction) SCA_RandomSensor::sPyGetLastDraw, METH_NOARGS, (PY_METHODCHAR)GetLastDraw_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; @@ -170,6 +181,10 @@ PyObject* SCA_RandomSensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_RandomSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_RandomSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); @@ -225,10 +240,10 @@ int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *at SCA_RandomSensor* self= static_cast<SCA_RandomSensor*>(self_v); if (!PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "sensor.seed = int: Random Sensor, expected an integer"); - return -1; + return PY_SET_ATTR_FAIL; } self->m_basegenerator->SetSeed(PyInt_AsLong(value)); - return 0; + return PY_SET_ATTR_SUCCESS; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h index 764692600c3..b2bf2440966 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.h +++ b/source/gameengine/GameLogic/SCA_RandomSensor.h @@ -52,7 +52,8 @@ public: PyTypeObject* T=&Type); virtual ~SCA_RandomSensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual void ProcessReplica(); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); @@ -61,6 +62,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* 1. setSeed */ diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp index b7fadd3d62c..911ea772bef 100644 --- a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp @@ -52,7 +52,7 @@ SCA_TimeEventManager::SCA_TimeEventManager(SCA_LogicManager* logicmgr) SCA_TimeEventManager::~SCA_TimeEventManager() { for (vector<CValue*>::iterator it = m_timevalues.begin(); - !(it == m_timevalues.end()); it++) + !(it == m_timevalues.end()); ++it) { (*it)->Release(); } @@ -80,7 +80,7 @@ void SCA_TimeEventManager::NextFrame(double curtime, double fixedtime) // update sensors, but ... need deltatime ! for (vector<CValue*>::iterator it = m_timevalues.begin(); - !(it == m_timevalues.end()); it++) + !(it == m_timevalues.end()); ++it) { float newtime = (*it)->GetNumber() + fixedtime; floatval->SetFloat(newtime); @@ -104,7 +104,7 @@ void SCA_TimeEventManager::AddTimeProperty(CValue* timeval) void SCA_TimeEventManager::RemoveTimeProperty(CValue* timeval) { for (vector<CValue*>::iterator it = m_timevalues.begin(); - !(it == m_timevalues.end()); it++) + !(it == m_timevalues.end()); ++it) { if ((*it) == timeval) { diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp index e9bb37ee958..aee8e26c21a 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.cpp +++ b/source/gameengine/GameLogic/SCA_XNORController.cpp @@ -66,7 +66,7 @@ void SCA_XNORController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (sensor->IsPositiveTrigger()) + if (sensor->GetState()) { if (sensorresult == false) { @@ -77,19 +77,12 @@ void SCA_XNORController::Trigger(SCA_LogicManager* logicmgr) } } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); - } @@ -98,7 +91,7 @@ CValue* SCA_XNORController::GetReplica() { CValue* replica = new SCA_XNORController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -111,8 +104,13 @@ CValue* SCA_XNORController::GetReplica() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_XNORController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_XNORController", sizeof(PyObjectPlus_Proxy), 0, @@ -149,4 +147,8 @@ PyObject* SCA_XNORController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_XNORController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_XNORController.h b/source/gameengine/GameLogic/SCA_XNORController.h index c992d5f1834..4aad5763cb0 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.h +++ b/source/gameengine/GameLogic/SCA_XNORController.h @@ -49,6 +49,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp index 791a139975f..5afb3a750f5 100644 --- a/source/gameengine/GameLogic/SCA_XORController.cpp +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -66,7 +66,7 @@ void SCA_XORController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (sensor->IsPositiveTrigger()) + if (sensor->GetState()) { if (sensorresult == true) { @@ -77,19 +77,12 @@ void SCA_XORController::Trigger(SCA_LogicManager* logicmgr) } } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); - } @@ -98,7 +91,7 @@ CValue* SCA_XORController::GetReplica() { CValue* replica = new SCA_XORController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -111,8 +104,13 @@ CValue* SCA_XORController::GetReplica() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_XORController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_XORController", sizeof(PyObjectPlus_Proxy), 0, @@ -149,4 +147,8 @@ PyObject* SCA_XORController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_XORController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_XORController.h b/source/gameengine/GameLogic/SCA_XORController.h index 065b31fd901..feb9f2ed07c 100644 --- a/source/gameengine/GameLogic/SCA_XORController.h +++ b/source/gameengine/GameLogic/SCA_XORController.h @@ -49,6 +49,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SConscript b/source/gameengine/GameLogic/SConscript index 88e5f7e87cc..91843eef586 100644 --- a/source/gameengine/GameLogic/SConscript +++ b/source/gameengine/GameLogic/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('*.cpp') + env.Glob('Joystick/*.cpp') incs = '. #/source/kernel/gen_system #/intern/string' incs += ' #/source/gameengine/Expressions #/intern/moto/include' -incs += ' #/source/gameengine/Rasterizer' +incs += ' #/source/gameengine/Rasterizer #/source/gameengine/SceneGraph' incs += ' ' + env['BF_PYTHON_INC'] |