BGE Joystick Hat Bugfix

bug reported by blenderage on blenderartist (found other bugs too).

- "All Hat Events" didnt work.
- Multiple hats didnt work
- use a menu with direction names rather then have the user guess. disallow zero as a direction.
- Allow up to 4 hats (was 2).
- Python api was clamping the axis to 2, maximum is currently JOYAXIS_MAX - 16
- New python attributes hatValues and hatSingle, match axis functions.
- Use SDL Axis events to fill in the axis and hat array rather then filling in every axis with SDL_JoystickGetAxis for each axis event.
This commit is contained in:
Campbell Barton 2009-05-25 06:24:23 +00:00
parent 2a9d9605d0
commit 2fa8504dd1
8 changed files with 99 additions and 100 deletions

@ -1534,13 +1534,14 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short
else if (joy->type == SENS_JOY_HAT)
{
uiDefButI(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19,
&joy->hat, 1, 2.0, 100, 0,
&joy->hat, 1, 4.0, 100, 0,
"Specify which hat to use");
if ((joy->flag & SENS_JOY_ANY_EVENT)==0) {
uiDefButI(block, NUM, 1, "Direction:", xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19,
&joy->hatf, 0, 12, 100, 0,
"Specify hat direction");
str = "Direction%t|Up%x1|Down%x4|Left%x8|Right%x2|%l|Up/Right%x3|Down/Left%x12|Up/Left%x9|Down/Right%x6";
uiDefButI(block, MENU, B_NOP, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19,
&joy->hatf, 2.0, 31, 0, 0,
"The direction of the hat, use 'All Events' to recieve events on any direction");
}
}
else { /* (joy->type == SENS_JOY_AXIS_SINGLE)*/
@ -2752,12 +2753,12 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+40, yco-44, (width-80), 19, &(parAct->ob), "Set this object as parent");
uiBlockBeginAlign(block);
uiDefButBitI(block, TOGN, ACT_PARENT_COMPOUND, B_REDR,
uiDefButBitS(block, TOGN, ACT_PARENT_COMPOUND, B_REDR,
"Compound",
xco + 40, yco - 64, (width - 80)/2, 19, &parAct->flag,
0.0, 0.0, 0, 0,
"Add this object shape to the parent shape (only if the parent shape is already compound)");
uiDefButBitI(block, TOGN, ACT_PARENT_GHOST, B_REDR,
uiDefButBitS(block, TOGN, ACT_PARENT_GHOST, B_REDR,
"Ghost",
xco + 40 + ((width - 80)/2), yco - 64, (width - 80)/2, 19, &parAct->flag,
0.0, 0.0, 0, 0,

@ -42,7 +42,6 @@ SCA_Joystick::SCA_Joystick(short int index)
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 +49,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
@ -184,20 +187,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()
@ -248,8 +240,11 @@ bool SCA_Joystick::CreateJoystickDevice(void)
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;
if(m_hatmax<0) m_hatmax= 0;
}
return true;
#endif
@ -278,15 +273,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

@ -53,28 +53,20 @@ 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
*/
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
*/
@ -88,18 +80,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 +116,6 @@ class SCA_Joystick
/*
* fills the axis mnember values
*/
void pFillAxes(void);
void pFillButtons(void);
/*
@ -149,11 +128,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();
@ -175,7 +149,7 @@ public:
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
@ -191,8 +165,8 @@ public:
return m_buttonnum;
}
int GetHat(void){
return m_hatdir;
int GetHat(int index){
return m_hat_array[index];
}
int GetThreshold(void){

@ -40,6 +40,7 @@
#define JOYINDEX_MAX 8
#define JOYAXIS_MAX 16
#define JOYHAT_MAX 4
#define JOYAXIS_RIGHT 0
#define JOYAXIS_UP 1

@ -35,17 +35,20 @@
#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;
}
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 >= JOYAXIS_MAX)
return;
m_hat_array[sdl_event->jhat.hat]= sdl_event->jhat.value;
m_istrig_hat = 1;
}

@ -198,33 +198,20 @@ bool SCA_JoystickSensor::Evaluate()
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;
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;
}
}
}
if(m_hat == 2){
if(js->aHatIsPositive(m_hatf)){
m_istrig = 1;
result = true;
}else{
if(m_istrig){
m_istrig = 0;
result = true;
}
}
}
break;
@ -331,6 +318,8 @@ 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),
@ -617,6 +606,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);

@ -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;
/**
@ -152,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);
@ -164,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*)
@ -173,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;
}

@ -47,6 +47,7 @@ class CValue(PyObjectPlus):
This class is a basis for other classes.
@ivar name: The name of this CValue derived object (read-only).
@type name: string
@group Deprecated: getName
"""
def getName():
"""
@ -259,7 +260,7 @@ class SCA_IController(SCA_ILogicBrick):
@type actuators: sequence supporting index/string lookups and iteration.
@ivar bookmark: the bookmark option.
If set, the controller executes always before all other non-bookmarked controllers.
- note: Order of execution between bookmarked controllers is not guaranteed.
note: Order of execution between bookmarked controllers is not guaranteed.
@type bookmark: bool
"""
#{ Deprecated
@ -4741,6 +4742,24 @@ class SCA_JoystickSensor(SCA_ISensor):
Only use this for "Single Axis" type sensors otherwise it will raise an error.
@type axisSingle: int
@ivar hatValues: (read-only) The state of the joysticks hats as a list of values L{numHats} long.
each spesifying the direction of the hat from 1 to 12, 0 when inactive.
Hat directions are as follows...
- 0:None
- 1:Up
- 2:Right
- 4:Down
- 8:Left
- 3:Up - Right
- 6:Down - Right
- 12:Down - Left
- 9:Up - Left
@type hatValues: list of ints
@ivar hatSingle: (read-only) like L{hatValues} but returns a single hat direction value that is set by the sensor.
@type hatSingle: int
@ivar numAxis: (read-only) The number of axes for the joystick at this index.
@type numAxis: integer
@ivar numButtons: (read-only) The number of buttons for the joystick at this index.
@ -4760,8 +4779,8 @@ class SCA_JoystickSensor(SCA_ISensor):
axisDirection: 0=right, 1=up, 2=left, 3=down
@type axis: [integer, integer]
@ivar hat: The hat the sensor reacts to, as a list of two values: [hatIndex, hatDirection]
hatIndex: the hat index to use when detecting hat movement, 1=primary hat, 2=secondary hat.
hatDirection: 0-11
hatIndex: the hat index to use when detecting hat movement, 1=primary hat, 2=secondary hat (4 max).
hatDirection: 1-12
@type hat: [integer, integer]
"""