}
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();
}
}
FGInput::FGInput ()
- : _current_mouse_mode(-1),
- _last_mouse_mode(-1)
{
// no op
}
_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
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
int j;
for (int i = 0; i < MAX_MICE; i++) {
- SGPropertyNode * mouse_node = mouse_nodes->getChild("mouse", 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;
+ SGPropertyNode * mouse_node = mouse_nodes->getChild("mouse", i, true);
+ mouse &m = _mouse_bindings[i];
+
+ // 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);
}
}
}
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);
}
}
}
+\f
+////////////////////////////////////////////////////////////////////////
+// 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;
+}
+
+
\f
////////////////////////////////////////////////////////////////////////
// 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;
}
void
GLUTmotion (int x, int y)
{
- puMouse(x, y);
+// puMouse(x, y);
// glutPostRedisplay();
current_input.doMouseMotion(x, y);
}
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; }
*
* 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;
{
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();
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();
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();
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();