From db7013c83a40e7cf0fc387b814c01bc3e3b2fc93 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 26 Mar 2002 13:45:44 +0000 Subject: [PATCH] More work on the configurable mouse. Mouse motion is now configurable as well as mouse clicks. You must configure with --with-new-mouse to get this. --- src/Input/input.cxx | 189 ++++++++++++++++++++++++++++----------- src/Input/input.hxx | 29 ++++-- src/Main/fg_commands.cxx | 45 ++++++++-- src/Main/main.cxx | 12 +-- 4 files changed, 199 insertions(+), 76 deletions(-) diff --git a/src/Input/input.cxx b/src/Input/input.cxx index 349226a03..20024c4d2 100644 --- a/src/Input/input.cxx +++ b/src/Input/input.cxx @@ -143,13 +143,10 @@ FGBinding::fire () const } void -FGBinding::fire (int x, int y) const +FGBinding::fire (double offset, double max) const { if (test()) { - if (x >= 0) - _arg->setIntValue("x-pos", x); - if (y >= 0) - _arg->setIntValue("y-pos", y); + _arg->setDoubleValue("offset", offset/max); fire(); } } @@ -180,8 +177,6 @@ FGInput current_input; FGInput::FGInput () - : _current_mouse_mode(-1), - _last_mouse_mode(-1) { // no op } @@ -197,6 +192,16 @@ FGInput::init () _init_keyboard(); _init_joystick(); _init_mouse(); + + glutKeyboardFunc(GLUTkey); + glutKeyboardUpFunc(GLUTkeyup); + glutSpecialFunc(GLUTspecialkey); + glutSpecialUpFunc(GLUTspecialkeyup); +#ifdef FG_NEW_MOUSE + glutMouseFunc (GLUTmouse); + glutMotionFunc (GLUTmotion); + glutPassiveMotionFunc (GLUTmotion); +#endif } void @@ -349,22 +354,65 @@ FGInput::doKey (int k, int modifiers, int x, int y) void FGInput::doMouseClick (int b, int updown, int x, int y) { - std::cout << "Mouse click " << b << ',' << updown << std::endl; int modifiers = FG_MOD_NONE; // FIXME: any way to get the real ones? + mouse &m = _mouse_bindings[0]; + if (b >= MAX_MOUSE_BUTTONS) { SG_LOG(SG_INPUT, SG_ALERT, "Mouse button " << b << " where only " << MAX_MOUSE_BUTTONS << " expected"); return; } - _update_button(_mouse_bindings[0].buttons[b], modifiers, updown, x, y); + _update_button(m.modes[m.current_mode].buttons[b], modifiers, updown, x, y); } void FGInput::doMouseMotion (int x, int y) { - // TODO + int modifiers = FG_MOD_NONE; // FIXME: any way to get the real ones? + + int xsize = fgGetInt("/sim/startup/xsize", 800); + int ysize = fgGetInt("/sim/startup/ysize", 600); + mouse &m = _mouse_bindings[0]; + if (m.current_mode < 0 || m.current_mode >= m.nModes) + return; + mouse_mode &mode = m.modes[m.current_mode]; + if (x != m.x) { + int delta = x - m.x; + for (int i = 0; i < mode.x_bindings[modifiers].size(); i++) + mode.x_bindings[modifiers][i]->fire(double(delta), double(xsize)); + } + if (y != m.y) { + int delta = y - m.y; + for (int i = 0; i < mode.y_bindings[modifiers].size(); i++) + mode.y_bindings[modifiers][i]->fire(double(delta), double(ysize)); + } + + // Constrain the mouse if requested + if (mode.constrained) { + bool need_warp = false; + if (x < 0) { + x = xsize - 1; + need_warp = true; + } else if (x >= xsize) { + x = 0; + need_warp = true; + } + + if (y < 0) { + y = ysize - 1; + need_warp = true; + } else if (y >= ysize) { + y = 0; + need_warp = true; + } + + if (need_warp) + glutWarpPointer(x, y); + } + m.x = x; + m.y = y; } void @@ -539,40 +587,49 @@ FGInput::_init_mouse () int j; for (int i = 0; i < MAX_MICE; i++) { - SGPropertyNode * mouse_node = mouse_nodes->getChild("mouse", i); + SGPropertyNode * mouse_node = mouse_nodes->getChild("mouse", i, true); + mouse &m = _mouse_bindings[i]; - // Read the cursor type for each mode. - _mouse_bindings[i].nModes = mouse_node->getIntValue("mode-count", 1); - _mouse_bindings[i].cursors = new int[_mouse_bindings[i].nModes]; - SGPropertyNode * cursor_nodes = - mouse_node->getChild("mode-cursors", 0, true); - for (j = 0; j < _mouse_bindings[i].nModes; j++) { - const char * name = cursor_nodes->getChild("cursor", j, true) - ->getStringValue(); - if (name[0] == '\0') - name = "inherit"; - _mouse_bindings[i].cursors[j] = GLUT_CURSOR_INHERIT; - for (int k = 0; mouse_cursor_map[k].name != 0; k++) { - if (!strcmp(mouse_cursor_map[k].name, name)) { - _mouse_bindings[i].cursors[j] = mouse_cursor_map[k].cursor; + // Read all the modes + m.nModes = mouse_node->getIntValue("mode-count", 1); + m.modes = new mouse_mode[m.nModes]; + + for (int j = 0; j < m.nModes; j++) { + int k; + + // Read the mouse cursor for this mode + SGPropertyNode * mode_node = mouse_node->getChild("mode", j, true); + const char * cursor_name = + mode_node->getStringValue("cursor", "inherit"); + m.modes[j].cursor = GLUT_CURSOR_INHERIT; + for (k = 0; mouse_cursor_map[k].name != 0; k++) { + if (!strcmp(mouse_cursor_map[k].name, cursor_name)) { + m.modes[j].cursor = mouse_cursor_map[k].cursor; break; } } - } - // Read the binding for each button - _mouse_bindings[i].buttons = new button[MAX_MOUSE_BUTTONS]; - if (mouse_node == 0) { - SG_LOG(SG_INPUT, SG_DEBUG, "No bindings for mouse " << i); - mouse_node = mouse_nodes->getChild("mouse", i, true); - } - char buf[8]; - for (j = 0; j < MAX_MOUSE_BUTTONS; j++) { - sprintf(buf, "%d", j); - SG_LOG(SG_INPUT, SG_DEBUG, "Initializing mouse button " << j); - _init_button(mouse_node->getChild("button", j), - _mouse_bindings[i].buttons[j], - buf); + // Read other properties for this mode + m.modes[j].constrained = mode_node->getBoolValue("constrained", false); + + // Read the button bindings for this mode + m.modes[j].buttons = new button[MAX_MOUSE_BUTTONS]; + char buf[8]; + for (k = 0; k < MAX_MOUSE_BUTTONS; k++) { + sprintf(buf, "mouse button %d", k); + SG_LOG(SG_INPUT, SG_DEBUG, "Initializing mouse button " << k); + _init_button(mode_node->getChild("button", k), + m.modes[j].buttons[k], + buf); + } + + // Read the axis bindings for this mode + _read_bindings(mode_node->getChild("x-axis", 0, true), + m.modes[j].x_bindings, + FG_MOD_NONE); + _read_bindings(mode_node->getChild("y-axis", 0, true), + m.modes[j].y_bindings, + FG_MOD_NONE); } } } @@ -665,15 +722,14 @@ FGInput::_update_joystick () void FGInput::_update_mouse () { - _current_mouse_mode = fgGetInt("/input/mice/mouse[0]/mode"); - if (_current_mouse_mode != _last_mouse_mode) { - _last_mouse_mode = _current_mouse_mode; - if (_current_mouse_mode >= 0 - && _current_mouse_mode < _mouse_bindings[0].nModes) { - glutSetCursor(_mouse_bindings[0].cursors[_current_mouse_mode]); + mouse &m = _mouse_bindings[0]; + int mode = fgGetInt("/input/mice/mouse[0]/mode"); + if (mode != m.current_mode) { + m.current_mode = mode; + if (mode >= 0 && mode < m.nModes) { + glutSetCursor(m.modes[mode].cursor); } else { - SG_LOG(SG_INPUT, SG_DEBUG, "Mouse mode " - << _current_mouse_mode << " out of range"); + SG_LOG(SG_INPUT, SG_DEBUG, "Mouse mode " << mode << " out of range"); glutSetCursor(GLUT_CURSOR_INHERIT); } } @@ -825,22 +881,49 @@ FGInput::joystick::~joystick () } + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGInput::mouse_mode +//////////////////////////////////////////////////////////////////////// + +FGInput::mouse_mode::mouse_mode () + : cursor(GLUT_CURSOR_INHERIT), + constrained(false), + buttons(0) +{ +} + +FGInput::mouse_mode::~mouse_mode () +{ + // FIXME: memory leak +// for (int i = 0; i < FG_MOD_MAX; i++) { +// int j; +// for (j = 0; i < x_bindings[i].size(); j++) +// delete bindings[i][j]; +// for (j = 0; j < y_bindings[i].size(); j++) +// delete bindings[i][j]; +// } + delete [] buttons; +} + + //////////////////////////////////////////////////////////////////////// // Implementation of FGInput::mouse //////////////////////////////////////////////////////////////////////// FGInput::mouse::mouse () - : nModes(0), - cursors(0), - buttons(0) + : nModes(1), + current_mode(0), + x(-1), + y(-1), + modes(0) { } FGInput::mouse::~mouse () { - delete [] cursors; - delete [] buttons; + delete [] modes; } @@ -911,7 +994,7 @@ GLUTmouse (int button, int updown, int x, int y) void GLUTmotion (int x, int y) { - puMouse(x, y); +// puMouse(x, y); // glutPostRedisplay(); current_input.doMouseMotion(x, y); } diff --git a/src/Input/input.hxx b/src/Input/input.hxx index 95731f8f0..f0c99491d 100644 --- a/src/Input/input.hxx +++ b/src/Input/input.hxx @@ -123,9 +123,9 @@ public: /** - * Fire a binding with x and y positions. + * Fire a binding with a scaled movement (rather than absolute position). */ - virtual void fire (int x, int y) const; + virtual void fire (double offset, double max) const; /** @@ -246,7 +246,7 @@ private: MAX_JOYSTICK_BUTTONS = 32, MAX_MICE = 1, - MAX_MOUSE_BUTTONS = 3 + MAX_MOUSE_BUTTONS = 8 }; typedef vector binding_list_t; @@ -294,15 +294,31 @@ private: }; + /** + * Settings for a mouse mode. + */ + struct mouse_mode { + mouse_mode (); + virtual ~mouse_mode (); + int cursor; + bool constrained; + button * buttons; + binding_list_t x_bindings[FG_MOD_MAX]; + binding_list_t y_bindings[FG_MOD_MAX]; + }; + + /** * Settings for a mouse. */ struct mouse { mouse (); virtual ~mouse (); + int x; + int y; int nModes; - int * cursors; - button * buttons; + int current_mode; + mouse_mode * modes; }; @@ -374,9 +390,6 @@ private: joystick _joystick_bindings[MAX_JOYSTICKS]; mouse _mouse_bindings[MAX_MICE]; - int _current_mouse_mode; - int _last_mouse_mode; - }; diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index 4ce64780d..b9060df06 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -52,6 +52,7 @@ public: virtual SGPropertyNode * getProp2 () const { return _prop2; } virtual const SGPropertyNode * getValue () const { return _value ? _value : &_dummy_0; } + virtual const bool hasStep () const { return _step != 0; } virtual const SGPropertyNode * getStep () const { return _step ? _step : &_dummy_0; } virtual const SGPropertyNode * getMin () const { return _min; } @@ -427,6 +428,8 @@ do_property_assign (const SGPropertyNode * arg, SGCommandState ** state) * * property: the name of the property to increment or decrement. * step: the amount of the increment or decrement (default: 0). + * offset: a normalized amount to offset by (if step is not present). + * factor: the amount by which to multiply the offset (if step is not present). * min: the minimum allowed value (default: no minimum). * max: the maximum allowed value (default: no maximum). * wrap: true if the value should be wrapped when it passes min or max; @@ -438,20 +441,40 @@ do_property_adjust (const SGPropertyNode * arg, SGCommandState ** state) { if (*state == 0) *state = new PropertyCommandState(arg); + bool hasStep = ((PropertyCommandState *)(*state))->hasStep(); SGPropertyNode * prop = ((PropertyCommandState *)(*state))->getProp(); const SGPropertyNode * step = ((PropertyCommandState *)(*state))->getStep(); + const SGPropertyNode * offset = + ((PropertyCommandState *)(*state))->getOffset(); + const SGPropertyNode * factor = + ((PropertyCommandState *)(*state))->getFactor(); const SGPropertyNode * min = ((PropertyCommandState *)(*state))->getMin(); const SGPropertyNode * max = ((PropertyCommandState *)(*state))->getMax(); bool wrap = ((PropertyCommandState *)(*state))->getWrap()->getBoolValue(); + double amount = 0; + if (!hasStep) { + amount = offset->getDoubleValue() * factor->getDoubleValue(); + } + + switch (prop->getType()) { case SGPropertyNode::BOOL: - if (step->getBoolValue()) + bool value; + if (hasStep) + value = step->getBoolValue(); + else + value = amount; + if (value) return prop->setBoolValue(!prop->getBoolValue()); else return true; case SGPropertyNode::INT: { - int value = prop->getIntValue() + step->getIntValue(); + int value; + if (hasStep) + value = prop->getIntValue() + step->getIntValue(); + else + value = prop->getIntValue() + int(amount); if (min && (value < min->getIntValue())) { if (wrap && max) value = max->getIntValue(); @@ -467,7 +490,11 @@ do_property_adjust (const SGPropertyNode * arg, SGCommandState ** state) return prop->setIntValue(value); } case SGPropertyNode::LONG: { - long value = prop->getLongValue() + step->getLongValue(); + long value; + if (hasStep) + value = prop->getLongValue() + step->getLongValue(); + else + value = prop->getLongValue() + long(amount); if (min && (value < min->getLongValue())) { if (wrap && max) value = max->getLongValue(); @@ -483,7 +510,11 @@ do_property_adjust (const SGPropertyNode * arg, SGCommandState ** state) return prop->setLongValue(value); } case SGPropertyNode::FLOAT: { - float value = prop->getFloatValue() + step->getFloatValue(); + float value; + if (hasStep) + value = prop->getFloatValue() + step->getFloatValue(); + else + value = prop->getFloatValue() + float(amount); if (min && (value < min->getFloatValue())) { if (wrap && max) value = max->getFloatValue(); @@ -501,7 +532,11 @@ do_property_adjust (const SGPropertyNode * arg, SGCommandState ** state) case SGPropertyNode::DOUBLE: case SGPropertyNode::UNSPECIFIED: case SGPropertyNode::NONE: { - double value = prop->getDoubleValue() + step->getDoubleValue(); + double value; + if (hasStep) + value = prop->getDoubleValue() + step->getDoubleValue(); + else + value = prop->getDoubleValue() + amount; if (min && (value < min->getDoubleValue())) { if (wrap && max) value = max->getDoubleValue(); diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 7ddd9f41f..cdd158a13 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -1259,17 +1259,9 @@ int fgGlutInitEvents( void ) { // call fgReshape() on window resizes glutReshapeFunc( fgReshape ); - // call GLUTkey() on keyboard event - glutKeyboardFunc(GLUTkey); - glutKeyboardUpFunc(GLUTkeyup); - glutSpecialFunc(GLUTspecialkey); - glutSpecialUpFunc(GLUTspecialkeyup); + // keyboard and mouse callbacks are set in FGInput::init -#if FG_NEW_MOUSE - glutMouseFunc (GLUTmouse); - glutMotionFunc (GLUTmotion); - glutPassiveMotionFunc (GLUTmotion); -#else +#ifndef FG_NEW_MOUSE // call guiMouseFunc() whenever our little rodent is used glutMouseFunc ( guiMouseFunc ); glutMotionFunc (guiMotionFunc );