Bug #923 : repeatable flag set on input reload.
Clean-up how axes and button bindings are destroyed are re-built on reinit of the FGJoystickInput subsystem, so we get new, cleanly initialised items each time.
This commit is contained in:
parent
12076bce0e
commit
e9ecf4eb52
3 changed files with 98 additions and 86 deletions
|
@ -26,7 +26,7 @@
|
||||||
#define FGBUTTON_H
|
#define FGBUTTON_H
|
||||||
|
|
||||||
#include "FGCommonInput.hxx"
|
#include "FGCommonInput.hxx"
|
||||||
#include <Main/fg_os.hxx>
|
#include <Main/fg_os.hxx> // for KEYMOD_MAX
|
||||||
|
|
||||||
class FGButton : public FGCommonInput {
|
class FGButton : public FGCommonInput {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -52,7 +52,6 @@ FGJoystickInput::axis::~axis ()
|
||||||
|
|
||||||
FGJoystickInput::joystick::joystick ()
|
FGJoystickInput::joystick::joystick ()
|
||||||
: jsnum(0),
|
: jsnum(0),
|
||||||
js(0),
|
|
||||||
naxes(0),
|
naxes(0),
|
||||||
nbuttons(0),
|
nbuttons(0),
|
||||||
axes(0),
|
axes(0),
|
||||||
|
@ -61,17 +60,20 @@ FGJoystickInput::joystick::joystick ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGJoystickInput::joystick::clearAxesAndButtons()
|
||||||
|
{
|
||||||
|
delete[] axes;
|
||||||
|
delete[] buttons;
|
||||||
|
axes = NULL;
|
||||||
|
buttons = NULL;
|
||||||
|
naxes = 0;
|
||||||
|
nbuttons = 0;
|
||||||
|
}
|
||||||
|
|
||||||
FGJoystickInput::joystick::~joystick ()
|
FGJoystickInput::joystick::~joystick ()
|
||||||
{
|
{
|
||||||
// delete js? no, since js == this - and we're in the destructor already.
|
|
||||||
delete[] axes;
|
|
||||||
delete[] buttons;
|
|
||||||
jsnum = 0;
|
jsnum = 0;
|
||||||
js = NULL;
|
clearAxesAndButtons();
|
||||||
naxes = 0;
|
|
||||||
nbuttons = 0;
|
|
||||||
axes = NULL;
|
|
||||||
buttons = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,12 +92,13 @@ void FGJoystickInput::_remove(bool all)
|
||||||
|
|
||||||
for (int i = 0; i < MAX_JOYSTICKS; i++)
|
for (int i = 0; i < MAX_JOYSTICKS; i++)
|
||||||
{
|
{
|
||||||
|
joystick* joy = &joysticks[i];
|
||||||
// do not remove predefined joysticks info on reinit
|
// do not remove predefined joysticks info on reinit
|
||||||
if (all || (!bindings[i].predefined))
|
if (all || (!joy->predefined))
|
||||||
js_nodes->removeChild("js", i, false);
|
js_nodes->removeChild("js", i, false);
|
||||||
if (bindings[i].js)
|
|
||||||
delete bindings[i].js;
|
joy->plibJS.reset();
|
||||||
bindings[i].js = NULL;
|
joy->clearAxesAndButtons();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,8 +113,8 @@ void FGJoystickInput::init()
|
||||||
|
|
||||||
for (int i = 0; i < MAX_JOYSTICKS; i++) {
|
for (int i = 0; i < MAX_JOYSTICKS; i++) {
|
||||||
jsJoystick * js = new jsJoystick(i);
|
jsJoystick * js = new jsJoystick(i);
|
||||||
bindings[i].js = js;
|
joysticks[i].plibJS.reset(js);
|
||||||
|
|
||||||
if (js->notWorking()) {
|
if (js->notWorking()) {
|
||||||
SG_LOG(SG_INPUT, SG_DEBUG, "Joystick " << i << " not found");
|
SG_LOG(SG_INPUT, SG_DEBUG, "Joystick " << i << " not found");
|
||||||
continue;
|
continue;
|
||||||
|
@ -124,7 +127,7 @@ void FGJoystickInput::init()
|
||||||
SG_LOG(SG_INPUT, SG_INFO, "Using existing bindings for joystick " << i);
|
SG_LOG(SG_INPUT, SG_INFO, "Using existing bindings for joystick " << i);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
bindings[i].predefined = false;
|
joysticks[i].predefined = false;
|
||||||
SG_LOG(SG_INPUT, SG_INFO, "Looking for bindings for joystick \"" << name << '"');
|
SG_LOG(SG_INPUT, SG_INFO, "Looking for bindings for joystick \"" << name << '"');
|
||||||
SGPropertyNode_ptr named;
|
SGPropertyNode_ptr named;
|
||||||
|
|
||||||
|
@ -163,7 +166,7 @@ void FGJoystickInput::postinit()
|
||||||
|
|
||||||
for (int i = 0; i < MAX_JOYSTICKS; i++) {
|
for (int i = 0; i < MAX_JOYSTICKS; i++) {
|
||||||
SGPropertyNode_ptr js_node = js_nodes->getChild("js", i);
|
SGPropertyNode_ptr js_node = js_nodes->getChild("js", i);
|
||||||
jsJoystick *js = bindings[i].js;
|
jsJoystick *js = joysticks[i].plibJS.get();
|
||||||
if (!js_node || js->notWorking())
|
if (!js_node || js->notWorking())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -178,8 +181,8 @@ void FGJoystickInput::postinit()
|
||||||
|
|
||||||
int naxes = js->getNumAxes();
|
int naxes = js->getNumAxes();
|
||||||
if (naxes > MAX_JOYSTICK_AXES) naxes = MAX_JOYSTICK_AXES;
|
if (naxes > MAX_JOYSTICK_AXES) naxes = MAX_JOYSTICK_AXES;
|
||||||
bindings[i].naxes = naxes;
|
joysticks[i].naxes = naxes;
|
||||||
bindings[i].nbuttons = nbuttons;
|
joysticks[i].nbuttons = nbuttons;
|
||||||
|
|
||||||
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing joystick " << i);
|
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing joystick " << i);
|
||||||
|
|
||||||
|
@ -194,8 +197,8 @@ void FGJoystickInput::postinit()
|
||||||
js->getCenter(center);
|
js->getCenter(center);
|
||||||
|
|
||||||
// Allocate axes and buttons
|
// Allocate axes and buttons
|
||||||
bindings[i].axes = new axis[naxes];
|
joysticks[i].axes = new axis[naxes];
|
||||||
bindings[i].buttons = new FGButton[nbuttons];
|
joysticks[i].buttons = new FGButton[nbuttons];
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize nasal groups.
|
// Initialize nasal groups.
|
||||||
|
@ -243,7 +246,7 @@ void FGJoystickInput::postinit()
|
||||||
SG_LOG(SG_INPUT, SG_DEBUG, "Dropping bindings for axis " << n_axis);
|
SG_LOG(SG_INPUT, SG_DEBUG, "Dropping bindings for axis " << n_axis);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
axis &a = bindings[i].axes[n_axis];
|
axis &a = joysticks[i].axes[n_axis];
|
||||||
|
|
||||||
js->setDeadBand(n_axis, axis_node->getDoubleValue("dead-band", 0.0));
|
js->setDeadBand(n_axis, axis_node->getDoubleValue("dead-band", 0.0));
|
||||||
|
|
||||||
|
@ -284,7 +287,7 @@ void FGJoystickInput::postinit()
|
||||||
buf << (unsigned)n_but;
|
buf << (unsigned)n_but;
|
||||||
|
|
||||||
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing button " << buf.str());
|
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing button " << buf.str());
|
||||||
FGButton &b = bindings[i].buttons[n_but];
|
FGButton &b = joysticks[i].buttons[n_but];
|
||||||
b.init(button_node, buf.str(), module );
|
b.init(button_node, buf.str(), module );
|
||||||
// get interval-sec property
|
// get interval-sec property
|
||||||
b.interval_sec = button_node->getDoubleValue("interval-sec",0.0);
|
b.interval_sec = button_node->getDoubleValue("interval-sec",0.0);
|
||||||
|
@ -297,69 +300,74 @@ void FGJoystickInput::postinit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGJoystickInput::update( double dt )
|
void FGJoystickInput::updateJoystick(int index, FGJoystickInput::joystick* joy, double dt)
|
||||||
{
|
{
|
||||||
float axis_values[MAX_JOYSTICK_AXES];
|
float axis_values[MAX_JOYSTICK_AXES];
|
||||||
int modifiers = fgGetKeyModifiers();
|
int modifiers = fgGetKeyModifiers();
|
||||||
int buttons;
|
int buttons;
|
||||||
|
|
||||||
for (int i = 0; i < MAX_JOYSTICKS; i++) {
|
jsJoystick * js = joy->plibJS.get();
|
||||||
|
if (js == 0 || js->notWorking())
|
||||||
jsJoystick * js = bindings[i].js;
|
return;
|
||||||
if (js == 0 || js->notWorking())
|
|
||||||
continue;
|
js->read(&buttons, axis_values);
|
||||||
|
if (js->notWorking()) // If js is disconnected
|
||||||
js->read(&buttons, axis_values);
|
return;
|
||||||
if (js->notWorking()) // If js is disconnected
|
|
||||||
continue;
|
// Update device status
|
||||||
|
SGPropertyNode_ptr status = status_node->getChild("joystick", index, true);
|
||||||
// Update device status
|
for (int j = 0; j < MAX_JOYSTICK_AXES; j++) {
|
||||||
SGPropertyNode_ptr status = status_node->getChild("joystick", i, true);
|
status->getChild("axis", j, true)->setFloatValue(axis_values[j]);
|
||||||
for (int j = 0; j < MAX_JOYSTICK_AXES; j++) {
|
}
|
||||||
status->getChild("axis", j, true)->setFloatValue(axis_values[j]);
|
|
||||||
|
for (int j = 0; j < MAX_JOYSTICK_BUTTONS; j++) {
|
||||||
|
status->getChild("button", j, true)->setBoolValue((buttons & (1u << j)) > 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire bindings for the axes.
|
||||||
|
for (int j = 0; j < joy->naxes; j++) {
|
||||||
|
axis &a = joy->axes[j];
|
||||||
|
|
||||||
|
// Do nothing if the axis position
|
||||||
|
// is unchanged; only a change in
|
||||||
|
// position fires the bindings.
|
||||||
|
// But only if there are bindings
|
||||||
|
if (fabs(axis_values[j] - a.last_value) > a.tolerance
|
||||||
|
&& a.bindings[KEYMOD_NONE].size() > 0 ) {
|
||||||
|
a.last_value = axis_values[j];
|
||||||
|
for (unsigned int k = 0; k < a.bindings[KEYMOD_NONE].size(); k++)
|
||||||
|
a.bindings[KEYMOD_NONE][k]->fire(axis_values[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < MAX_JOYSTICK_BUTTONS; j++) {
|
// do we have to emulate axis buttons?
|
||||||
status->getChild("button", j, true)->setBoolValue((buttons & (1u << j)) > 0 );
|
a.last_dt += dt;
|
||||||
|
if(a.last_dt >= a.interval_sec) {
|
||||||
|
if (a.low.bindings[modifiers].size())
|
||||||
|
joy->axes[j].low.update( modifiers, axis_values[j] < a.low_threshold );
|
||||||
|
|
||||||
|
if (a.high.bindings[modifiers].size())
|
||||||
|
joy->axes[j].high.update( modifiers, axis_values[j] > a.high_threshold );
|
||||||
|
|
||||||
|
a.last_dt -= a.interval_sec;
|
||||||
}
|
}
|
||||||
|
} // of axes iteration
|
||||||
// Fire bindings for the axes.
|
|
||||||
for (int j = 0; j < bindings[i].naxes; j++) {
|
// Fire bindings for the buttons.
|
||||||
axis &a = bindings[i].axes[j];
|
for (int j = 0; j < joy->nbuttons; j++) {
|
||||||
|
FGButton &b = joy->buttons[j];
|
||||||
// Do nothing if the axis position
|
b.last_dt += dt;
|
||||||
// is unchanged; only a change in
|
if(b.last_dt >= b.interval_sec) {
|
||||||
// position fires the bindings.
|
joy->buttons[j].update( modifiers, (buttons & (1u << j)) > 0 );
|
||||||
// But only if there are bindings
|
b.last_dt -= b.interval_sec;
|
||||||
if (fabs(axis_values[j] - a.last_value) > a.tolerance
|
|
||||||
&& a.bindings[KEYMOD_NONE].size() > 0 ) {
|
|
||||||
a.last_value = axis_values[j];
|
|
||||||
for (unsigned int k = 0; k < a.bindings[KEYMOD_NONE].size(); k++)
|
|
||||||
a.bindings[KEYMOD_NONE][k]->fire(axis_values[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do we have to emulate axis buttons?
|
|
||||||
a.last_dt += dt;
|
|
||||||
if(a.last_dt >= a.interval_sec) {
|
|
||||||
if (a.low.bindings[modifiers].size())
|
|
||||||
bindings[i].axes[j].low.update( modifiers, axis_values[j] < a.low_threshold );
|
|
||||||
|
|
||||||
if (a.high.bindings[modifiers].size())
|
|
||||||
bindings[i].axes[j].high.update( modifiers, axis_values[j] > a.high_threshold );
|
|
||||||
|
|
||||||
a.last_dt -= a.interval_sec;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} // of butotns iterations
|
||||||
|
|
||||||
// Fire bindings for the buttons.
|
}
|
||||||
for (int j = 0; j < bindings[i].nbuttons; j++) {
|
|
||||||
FGButton &b = bindings[i].buttons[j];
|
void FGJoystickInput::update( double dt )
|
||||||
b.last_dt += dt;
|
{
|
||||||
if(b.last_dt >= b.interval_sec) {
|
for (int i = 0; i < MAX_JOYSTICKS; i++) {
|
||||||
bindings[i].buttons[j].update( modifiers, (buttons & (1u << j)) > 0 );
|
updateJoystick(i, &joysticks[i], dt);
|
||||||
b.last_dt -= b.interval_sec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,10 @@
|
||||||
#ifndef _FGJOYSTICKINPUT_HXX
|
#ifndef _FGJOYSTICKINPUT_HXX
|
||||||
#define _FGJOYSTICKINPUT_HXX
|
#define _FGJOYSTICKINPUT_HXX
|
||||||
|
|
||||||
#ifndef __cplusplus
|
|
||||||
# error This library requires C++
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "FGCommonInput.hxx"
|
#include "FGCommonInput.hxx"
|
||||||
#include "FGButton.hxx"
|
#include "FGButton.hxx"
|
||||||
|
|
||||||
|
#include <memory> // for std::auto_ptr
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
#include <plib/js.h>
|
#include <plib/js.h>
|
||||||
|
|
||||||
|
@ -52,6 +50,8 @@ public:
|
||||||
static const int MAX_JOYSTICK_BUTTONS = 32;
|
static const int MAX_JOYSTICK_BUTTONS = 32;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
void _remove(bool all);
|
void _remove(bool all);
|
||||||
SGPropertyNode_ptr status_node;
|
SGPropertyNode_ptr status_node;
|
||||||
|
|
||||||
|
@ -79,15 +79,19 @@ private:
|
||||||
joystick ();
|
joystick ();
|
||||||
virtual ~joystick ();
|
virtual ~joystick ();
|
||||||
int jsnum;
|
int jsnum;
|
||||||
jsJoystick * js;
|
std::auto_ptr<jsJoystick> plibJS;
|
||||||
int naxes;
|
int naxes;
|
||||||
int nbuttons;
|
int nbuttons;
|
||||||
axis * axes;
|
axis * axes;
|
||||||
FGButton * buttons;
|
FGButton * buttons;
|
||||||
bool predefined;
|
bool predefined;
|
||||||
|
|
||||||
|
void clearAxesAndButtons();
|
||||||
};
|
};
|
||||||
joystick bindings[MAX_JOYSTICKS];
|
|
||||||
|
joystick joysticks[MAX_JOYSTICKS];
|
||||||
|
void updateJoystick(int index, joystick* joy, double dt);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue