From 4dcd4cda79a8238065d1522e50120a75a741e53b Mon Sep 17 00:00:00 2001 From: curt Date: Fri, 14 Jul 2000 15:46:27 +0000 Subject: [PATCH] Joystick updates from David Megginson to add the beginnings of button support. --- src/Joystick/joystick.cxx | 271 ++++++++++++++++++++++++++++++++++---- src/Main/bfi.cxx | 52 +++++++- src/Main/bfi.hxx | 4 + 3 files changed, 300 insertions(+), 27 deletions(-) diff --git a/src/Joystick/joystick.cxx b/src/Joystick/joystick.cxx index 49a1655d3..d72c5cad4 100644 --- a/src/Joystick/joystick.cxx +++ b/src/Joystick/joystick.cxx @@ -41,6 +41,7 @@ using std::string; static const int MAX_JOYSTICKS = 10; static const int MAX_AXES = 10; +static const int MAX_BUTTONS = 10; /** @@ -54,6 +55,10 @@ static const char * axisNames[] = { "axis0", "axis1", "axis2", "axis3", "axis4", "axis5", "axis6", "axis7", "axis8", "axis9" }; +static const char * buttonNames[] = { + "button0", "button1", "button2", "button3", "button4", + "button5", "button6", "button7", "button8", "button9" +}; /** @@ -70,6 +75,25 @@ struct axis { }; +/** + * Settings for a single button. + */ +struct button { + enum Action { + TOGGLE, + SWITCH, + ADJUST + }; + button () : value(0), step(0.0), action(ADJUST), isRepeatable(true), + lastState(-1) {} + FGValue * value; + float step; + Action action; + bool isRepeatable; + int lastState; +}; + + /** * Settings for a single joystick. */ @@ -77,6 +101,7 @@ struct joystick { virtual ~joystick () { delete js; delete axes; } jsJoystick * js; axis * axes; + button * buttons; }; @@ -121,6 +146,61 @@ setupDefaults () if (!props.getValue("/input/js0/axis3/control")) { props.setStringValue("/input/js0/axis3/control", "/controls/rudder"); props.setFloatValue("/input/js0/axis3/dead-band", 0.3); + } + + // Default button 0 to all brakes + if (!props.getValue("/input/js0/button0/control")) { + props.setStringValue("/input/js0/button0/action", "switch"); + props.setStringValue("/input/js0/button0/control", "/controls/brake"); + props.setFloatValue("/input/js0/button0/step", 1.0); + props.setFloatValue("/input/js0/button0/repeatable", false); + } + + // Default button 1 to left brake. + if (!props.getValue("/input/js0/button1/control")) { + props.setStringValue("/input/js0/button1/action", "switch"); + props.setStringValue("/input/js0/button1/control", "/controls/left-brake"); + props.setFloatValue("/input/js0/button1/step", 1.0); + props.setFloatValue("/input/js0/button1/repeatable", false); + } + + // Default button 2 to right brake. + if (!props.getValue("/input/js0/button2/control")) { + props.setStringValue("/input/js0/button2/action", "switch"); + props.setStringValue("/input/js0/button2/control", + "/controls/right-brake"); + props.setFloatValue("/input/js0/button2/step", 1.0); + props.setFloatValue("/input/js0/button2/repeatable", false); + } + + // Default buttons 3 and 4 to elevator trim + if (!props.getValue("/input/js0/button3/control")) { + props.setStringValue("/input/js0/button3/action", "adjust"); + props.setStringValue("/input/js0/button3/control", + "/controls/elevator-trim"); + props.setFloatValue("/input/js0/button3/step", 0.001); + props.setBoolValue("/input/js0/button3/repeatable", true); + } + if (!props.getValue("/input/js0/button4/control")) { + props.setStringValue("/input/js0/button4/action", "adjust"); + props.setStringValue("/input/js0/button4/control", + "/controls/elevator-trim"); + props.setFloatValue("/input/js0/button4/step", -0.001); + props.setBoolValue("/input/js0/button4/repeatable", true); + } + + // Default buttons 5 and 6 to flaps + if (!props.getValue("/input/js0/button5/control")) { + props.setStringValue("/input/js0/button5/action", "adjust"); + props.setStringValue("/input/js0/button5/control", "/controls/flaps"); + props.setFloatValue("/input/js0/button5/step", -0.34); + props.setBoolValue("/input/js0/button5/repeatable", false); + } + if (!props.getValue("/input/js0/button6/control")) { + props.setStringValue("/input/js0/button6/action", "adjust"); + props.setStringValue("/input/js0/button6/control", "/controls/flaps"); + props.setFloatValue("/input/js0/button6/step", 0.34); + props.setBoolValue("/input/js0/button6/repeatable", false); } } @@ -158,10 +238,17 @@ fgJoystickInit() js->getMaxRange(maxRange); js->getCenter(center); - // Allocate axes + // Allocate axes and buttons joysticks[i].axes = new axis[js->getNumAxes()]; + joysticks[i].buttons = new button[MAX_BUTTONS]; + + // + // Initialize the axes. + // for (int j = 0; j < min(js->getNumAxes(), MAX_AXES); j++) { + axis &a = joysticks[i].axes[j]; + string base = "/input/"; base += jsNames[i]; base += '/'; @@ -177,7 +264,7 @@ fgJoystickInit() continue; } const string &control = value->getStringValue(); - joysticks[i].axes[j].value = current_properties.getValue(control, true); + a.value = current_properties.getValue(control, true); FG_LOG(FG_INPUT, FG_INFO, " using control " << control); // Dead band @@ -193,9 +280,8 @@ fgJoystickInit() name += "/offset"; value = current_properties.getValue(name); if (value != 0) - joysticks[i].axes[j].offset = value->getFloatValue(); - FG_LOG(FG_INPUT, FG_INFO, " offset is " - << joysticks[i].axes[j].offset); + a.offset = value->getFloatValue(); + FG_LOG(FG_INPUT, FG_INFO, " offset is " << a.offset); // Factor @@ -203,9 +289,8 @@ fgJoystickInit() name += "/factor"; value = current_properties.getValue(name); if (value != 0) - joysticks[i].axes[j].factor = value->getFloatValue(); - FG_LOG(FG_INPUT, FG_INFO, " factor is " - << joysticks[i].axes[j].factor); + a.factor = value->getFloatValue(); + FG_LOG(FG_INPUT, FG_INFO, " factor is " << a.factor); // Tolerance @@ -213,9 +298,8 @@ fgJoystickInit() name += "/tolerance"; value = current_properties.getValue(name); if (value != 0) - joysticks[i].axes[j].tolerance = value->getFloatValue(); - FG_LOG(FG_INPUT, FG_INFO, " tolerance is " - << joysticks[i].axes[j].tolerance); + a.tolerance = value->getFloatValue(); + FG_LOG(FG_INPUT, FG_INFO, " tolerance is " << a.tolerance); // Saturation @@ -251,6 +335,74 @@ fgJoystickInit() FG_LOG(FG_INPUT, FG_INFO, " center is " << center[j]); } + + // + // Initialize the buttons. + // + for (int j = 0; j < MAX_BUTTONS; j++) { + button &b = joysticks[i].buttons[j]; + + string base = "/input/"; + base += jsNames[i]; + base += '/'; + base += buttonNames[j]; + FG_LOG(FG_INPUT, FG_INFO, " Button " << j << ':'); + + // Control property + string name = base; + name += "/control"; + cout << "Trying name " << name << endl; + FGValue * value = current_properties.getValue(name); + if (value == 0) { + FG_LOG(FG_INPUT, FG_INFO, " no control defined"); + continue; + } + const string &control = value->getStringValue(); + b.value = current_properties.getValue(control, true); + FG_LOG(FG_INPUT, FG_INFO, " using control " << control); + + // Step + name = base; + name += "/step"; + value = current_properties.getValue(name); + if (value != 0) + b.step = value->getFloatValue(); + FG_LOG(FG_INPUT, FG_INFO, " step is " << b.step); + + // Type + name = base; + name += "/action"; + value = current_properties.getValue(name); + string action = "adjust"; + if (value != 0) + action = value->getStringValue(); + if (action == "toggle") { + b.action = button::TOGGLE; + b.isRepeatable = false; + } else if (action == "switch") { + b.action = button::SWITCH; + b.isRepeatable = false; + } else if (action == "adjust") { + b.action = button::ADJUST; + b.isRepeatable = true; + } else { + FG_LOG(FG_INPUT, FG_ALERT, " unknown action " << action); + action = "adjust"; + b.action = button::ADJUST; + b.isRepeatable = true; + } + FG_LOG(FG_INPUT, FG_INFO, " action is " << action); + + // Repeatability. + name = base; + name += "/repeatable"; + value = current_properties.getValue(name); + if (value != 0) + b.isRepeatable = value->getBoolValue(); + FG_LOG(FG_INPUT, FG_INFO, (b.isRepeatable ? + " repeatable" : " not repeatable")); + } + js->setMinRange(minRange); js->setMaxRange(maxRange); js->setCenter(center); @@ -282,28 +434,101 @@ fgJoystickRead() js->read(&buttons, axis_values); + // + // Axes + // for (int j = 0; j < min(MAX_AXES, js->getNumAxes()); j++) { + bool flag = true; + axis &a = joysticks[i].axes[j]; // If the axis hasn't changed, don't // force the value. - if (fabs(axis_values[j] - joysticks[i].axes[j].last_value) <= - joysticks[i].axes[j].tolerance) + if (fabs(axis_values[j] - a.last_value) <= a.tolerance) continue; else - joysticks[i].axes[j].last_value = axis_values[j]; - - FGValue * value = joysticks[i].axes[j].value; - if (value) { - if (!value->setDoubleValue((axis_values[j] + - joysticks[i].axes[j].offset) * - joysticks[i].axes[j].factor)) - FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick " - << i << ", axis " << j); + a.last_value = axis_values[j]; + + if (a.value) + flag = a.value->setDoubleValue((axis_values[j] + a.offset) * + a.factor); + if (!flag) + FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick " + << i << ", axis " << j); + } + + // + // Buttons + // + for (int j = 0; j < MAX_BUTTONS; j++) { + bool flag; + button &b = joysticks[i].buttons[j]; + if (b.value == 0) + continue; + + // Button is on. + if ((buttons & (1 << j)) > 0) { + // Repeating? + if (b.lastState == 1 && !b.isRepeatable) + continue; + + switch (b.action) { + case button::TOGGLE: + if (b.step != 0.0) { + if (b.value->getDoubleValue() == 0.0) + flag = b.value->setDoubleValue(b.step); + else + flag = b.value->setDoubleValue(0.0); + } else { + if (b.value->getBoolValue()) + flag = b.value->setBoolValue(false); + else + flag = b.value->setBoolValue(true); + } + break; + case button::SWITCH: + flag = b.value->setDoubleValue(b.step); + break; + case button::ADJUST: + if (!b.value->setDoubleValue(b.value->getDoubleValue() + b.step)) + FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for joystick " + << i << ", axis " << j); + break; + default: + flag = false; + break; + } + b.lastState = 1; + + // Button is off + } else { + // Repeating? + if (b.lastState == 0 && !b.isRepeatable) + continue; + + switch (b.action) { + case button::TOGGLE: + // no op + break; + case button::SWITCH: + flag = b.value->setDoubleValue(0.0); + break; + case button::ADJUST: + // no op + break; + default: + flag = false; + break; + } + + b.lastState = 0; } + if (!flag) + FG_LOG(FG_INPUT, FG_ALERT, "Failed to set value for " + << jsNames[i] << ' ' << buttonNames[j]); } } - return true; // FIXME + return true; } // end of joystick.cxx diff --git a/src/Main/bfi.cxx b/src/Main/bfi.cxx index 5d1f23a95..aafa5cd16 100644 --- a/src/Main/bfi.cxx +++ b/src/Main/bfi.cxx @@ -149,6 +149,10 @@ FGBFI::init () getElevatorTrim, setElevatorTrim); current_properties.tieDouble("/controls/brake", getBrake, setBrake); + current_properties.tieDouble("/controls/left-brake", + getLeftBrake, setLeftBrake); + current_properties.tieDouble("/controls/right-brake", + getRightBrake, setRightBrake); // Autopilot current_properties.tieBool("/autopilot/locks/altitude", @@ -509,7 +513,7 @@ double FGBFI::getAGL () { return current_aircraft.fdm_state->get_Altitude() - - scenery.cur_elev * METER_TO_FEET; + - (scenery.cur_elev * METER_TO_FEET); } @@ -866,7 +870,7 @@ double FGBFI::getBrake () { // FIXME: add brake selector - return controls.get_brake(0); + return controls.get_brake(2); } @@ -876,12 +880,52 @@ FGBFI::getBrake () void FGBFI::setBrake (double brake) { - // FIXME: clamp? - // FIXME: allow brake selection + controls.set_brake(FGControls::ALL_WHEELS, brake); +} + + +/** + * Get the left brake, from 0.0 (none) to 1.0 (full). + */ +double +FGBFI::getLeftBrake () +{ + return controls.get_brake(0); +} + + +/** + * Set the left brake, from 0.0 (none) to 1.0 (full). + */ +void +FGBFI::setLeftBrake (double brake) +{ controls.set_brake(0, brake); } +/** + * Get the right brake, from 0.0 (none) to 1.0 (full). + */ +double +FGBFI::getRightBrake () +{ + return controls.get_brake(1); +} + + +/** + * Set the right brake, from 0.0 (none) to 1.0 (full). + */ +void +FGBFI::setRightBrake (double brake) +{ + controls.set_brake(1, brake); +} + + + + //////////////////////////////////////////////////////////////////////// // Autopilot diff --git a/src/Main/bfi.hxx b/src/Main/bfi.hxx index cac3bb812..d13a99567 100644 --- a/src/Main/bfi.hxx +++ b/src/Main/bfi.hxx @@ -111,6 +111,8 @@ public: static double getElevator (); static double getElevatorTrim (); static double getBrake (); + static double getLeftBrake (); + static double getRightBrake (); static void setThrottle (double throttle); static void setFlaps (double flaps); @@ -119,6 +121,8 @@ public: static void setElevator (double elevator); static void setElevatorTrim (double trim); static void setBrake (double brake); + static void setLeftBrake (double brake); + static void setRightBrake (double brake); // Autopilot -- 2.39.5