X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInput%2FFGJoystickInput.cxx;h=b15649cda3b334589e90c4b84495d68ea80e9fbd;hb=5151f7f5e0ba7c7e6688bdfbc4cea365196e1ed3;hp=349782d5b5e3c890abfb46e89a7c45c3e79cd59a;hpb=11a371b31377905933b2d89f752a32d1b988e5cb;p=flightgear.git diff --git a/src/Input/FGJoystickInput.cxx b/src/Input/FGJoystickInput.cxx index 349782d5b..b15649cda 100644 --- a/src/Input/FGJoystickInput.cxx +++ b/src/Input/FGJoystickInput.cxx @@ -22,10 +22,17 @@ // // $Id$ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include "FGJoystickInput.hxx" + +#include #include "FGDeviceConfigurationMap.hxx" #include
#include +#include using simgear::PropertyList; @@ -45,20 +52,28 @@ FGJoystickInput::axis::~axis () FGJoystickInput::joystick::joystick () : jsnum(0), - js(0), naxes(0), nbuttons(0), axes(0), - buttons(0) + buttons(0), + predefined(true) +{ +} + +void FGJoystickInput::joystick::clearAxesAndButtons() { + delete[] axes; + delete[] buttons; + axes = NULL; + buttons = NULL; + naxes = 0; + nbuttons = 0; } FGJoystickInput::joystick::~joystick () { -// delete js? why not? -// delete js; - delete[] axes; - delete[] buttons; + jsnum = 0; + clearAxesAndButtons(); } @@ -68,22 +83,38 @@ FGJoystickInput::FGJoystickInput() FGJoystickInput::~FGJoystickInput() { + _remove(true); } +void FGJoystickInput::_remove(bool all) +{ + SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true); + + for (int i = 0; i < MAX_JOYSTICKS; i++) + { + joystick* joy = &joysticks[i]; + // do not remove predefined joysticks info on reinit + if (all || (!joy->predefined)) + js_nodes->removeChild("js", i, false); + + joy->plibJS.reset(); + joy->clearAxesAndButtons(); + } +} void FGJoystickInput::init() { jsInit(); - // TODO: zero the old bindings first. SG_LOG(SG_INPUT, SG_DEBUG, "Initializing joystick bindings"); - SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true); + SGPropertyNode_ptr js_nodes = fgGetNode("/input/joysticks", true); + status_node = fgGetNode("/devices/status/joysticks", true); - FGDeviceConfigurationMap configMap("Input/Joysticks", js_nodes, "js-named"); + FGDeviceConfigurationMap configMap("Input/Joysticks",js_nodes, "js-named"); for (int i = 0; i < MAX_JOYSTICKS; i++) { jsJoystick * js = new jsJoystick(i); - bindings[i].js = js; - + joysticks[i].plibJS.reset(js); + if (js->notWorking()) { SG_LOG(SG_INPUT, SG_DEBUG, "Joystick " << i << " not found"); continue; @@ -96,15 +127,17 @@ void FGJoystickInput::init() SG_LOG(SG_INPUT, SG_INFO, "Using existing bindings for joystick " << i); } else { + joysticks[i].predefined = false; SG_LOG(SG_INPUT, SG_INFO, "Looking for bindings for joystick \"" << name << '"'); SGPropertyNode_ptr named; - if ((named = configMap[name])) { - string source = named->getStringValue("source", "user defined"); + if (configMap.hasConfiguration(name)) { + named = configMap.configurationForDeviceName(name); + std::string source = named->getStringValue("source", "user defined"); SG_LOG(SG_INPUT, SG_INFO, "... found joystick: " << source); - } else if ((named = configMap["default"])) { - string source = named->getStringValue("source", "user defined"); + } else if ((named = configMap.configurationForDeviceName("default"))) { + std::string source = named->getStringValue("source", "user defined"); SG_LOG(SG_INPUT, SG_INFO, "No config found for joystick \"" << name << "\"\nUsing default: \"" << source << '"'); @@ -119,6 +152,13 @@ void FGJoystickInput::init() } } +void FGJoystickInput::reinit() { + SG_LOG(SG_INPUT, SG_DEBUG, "Re-Initializing joystick bindings"); + _remove(false); + FGJoystickInput::init(); + FGJoystickInput::postinit(); +} + void FGJoystickInput::postinit() { FGNasalSys *nasalsys = (FGNasalSys *)globals->get_subsystem("nasal"); @@ -126,7 +166,7 @@ void FGJoystickInput::postinit() for (int i = 0; i < MAX_JOYSTICKS; 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()) continue; @@ -141,8 +181,8 @@ void FGJoystickInput::postinit() int naxes = js->getNumAxes(); if (naxes > MAX_JOYSTICK_AXES) naxes = MAX_JOYSTICK_AXES; - bindings[i].naxes = naxes; - bindings[i].nbuttons = nbuttons; + joysticks[i].naxes = naxes; + joysticks[i].nbuttons = nbuttons; SG_LOG(SG_INPUT, SG_DEBUG, "Initializing joystick " << i); @@ -157,15 +197,15 @@ void FGJoystickInput::postinit() js->getCenter(center); // Allocate axes and buttons - bindings[i].axes = new axis[naxes]; - bindings[i].buttons = new FGButton[nbuttons]; + joysticks[i].axes = new axis[naxes]; + joysticks[i].buttons = new FGButton[nbuttons]; // // Initialize nasal groups. // - ostringstream str; + std::ostringstream str; str << "__js" << i; - string module = str.str(); + std::string module = str.str(); nasalsys->createModule(module.c_str(), module.c_str(), "", 0); PropertyList nasal = js_node->getChildren("nasal"); @@ -187,17 +227,26 @@ void FGJoystickInput::postinit() if (num_node != 0) { n_axis = num_node->getIntValue(TGT_PLATFORM, -1); + #ifdef SG_MAC + // Mac falls back to Unix by default - avoids specifying many + // duplicate entries in joystick config files + if (n_axis < 0) { + n_axis = num_node->getIntValue("unix", -1); + } + #endif + // Silently ignore platforms that are not specified within the // section - if (n_axis < 0) - continue; + if (n_axis < 0) { + continue; + } } if (n_axis >= naxes) { SG_LOG(SG_INPUT, SG_DEBUG, "Dropping bindings for axis " << n_axis); 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)); @@ -222,30 +271,27 @@ void FGJoystickInput::postinit() // Initialize the buttons. // PropertyList buttons = js_node->getChildren("button"); - char buf[32]; - for (j = 0; j < buttons.size() && j < nbuttons; j++) { - const SGPropertyNode * button_node = buttons[j]; - const SGPropertyNode * num_node = button_node->getChild("number"); + BOOST_FOREACH( SGPropertyNode * button_node, buttons ) { size_t n_but = button_node->getIndex(); - if (num_node != 0) { + + const SGPropertyNode * num_node = button_node->getChild("number"); + if (NULL != num_node) n_but = num_node->getIntValue(TGT_PLATFORM,n_but); - } if (n_but >= nbuttons) { SG_LOG(SG_INPUT, SG_DEBUG, "Dropping bindings for button " << n_but); continue; } - sprintf(buf, "%u", (unsigned)n_but); - SG_LOG(SG_INPUT, SG_DEBUG, "Initializing button " << n_but); - bindings[i].buttons[n_but].init(button_node, buf, module ); + std::ostringstream buf; + buf << (unsigned)n_but; + SG_LOG(SG_INPUT, SG_DEBUG, "Initializing button " << buf.str()); + FGButton &b = joysticks[i].buttons[n_but]; + b.init(button_node, buf.str(), module ); // get interval-sec property - FGButton &b = bindings[i].buttons[n_but]; - if (button_node != 0) { - b.interval_sec = button_node->getDoubleValue("interval-sec",0.0); - b.last_dt = 0.0; - } + b.interval_sec = button_node->getDoubleValue("interval-sec",0.0); + b.last_dt = 0.0; } js->setMinRange(minRange); @@ -254,55 +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]; int modifiers = fgGetKeyModifiers(); int buttons; - - for (int i = 0; i < MAX_JOYSTICKS; i++) { - - jsJoystick * js = bindings[i].js; - if (js == 0 || js->notWorking()) - continue; - - js->read(&buttons, axis_values); - - // Fire bindings for the axes. - for (int j = 0; j < bindings[i].naxes; j++) { - axis &a = bindings[i].axes[j]; - - // Do nothing if the axis position - // is unchanged; only a change in - // position fires the bindings. - if (fabs(axis_values[j] - a.last_value) > a.tolerance) { - 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; - } + + jsJoystick * js = joy->plibJS.get(); + if (js == 0 || js->notWorking()) + return; + + js->read(&buttons, axis_values); + if (js->notWorking()) // If js is disconnected + return; + + // Update device status + SGPropertyNode_ptr status = status_node->getChild("joystick", index, true); + 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]); } - - // Fire bindings for the buttons. - for (int j = 0; j < bindings[i].nbuttons; j++) { - FGButton &b = bindings[i].buttons[j]; - b.last_dt += dt; - if(b.last_dt >= b.interval_sec) { - bindings[i].buttons[j].update( modifiers, (buttons & (1 << j)) > 0 ); - b.last_dt -= b.interval_sec; - } + + // do we have to emulate axis buttons? + 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 buttons. + for (int j = 0; j < joy->nbuttons; j++) { + FGButton &b = joy->buttons[j]; + b.last_dt += dt; + if(b.last_dt >= b.interval_sec) { + joy->buttons[j].update( modifiers, (buttons & (1u << j)) > 0 ); + b.last_dt -= b.interval_sec; + } + } // of butotns iterations + +} + +void FGJoystickInput::update( double dt ) +{ + for (int i = 0; i < MAX_JOYSTICKS; i++) { + updateJoystick(i, &joysticks[i], dt); } }