// event handling method is also a convenient place to run the the FG
// idle and draw handlers.
+FGManipulator::FGManipulator() :
+ idleHandler(0), drawHandler(0), windowResizeHandler(0), keyHandler(0),
+ mouseClickHandler(0), mouseMotionHandler(0), currentModifiers(0),
+ osgModifiers(0), resizable(true)
+{
+ using namespace osgGA;
+
+ keyMaskMap[GUIEventAdapter::KEY_Shift_L]
+ = GUIEventAdapter::MODKEY_LEFT_SHIFT;
+ keyMaskMap[GUIEventAdapter::KEY_Shift_R]
+ = GUIEventAdapter::MODKEY_RIGHT_SHIFT;
+ keyMaskMap[GUIEventAdapter::KEY_Control_L]
+ = GUIEventAdapter::MODKEY_LEFT_CTRL;
+ keyMaskMap[GUIEventAdapter::KEY_Control_R]
+ = GUIEventAdapter::MODKEY_RIGHT_CTRL;
+ keyMaskMap[GUIEventAdapter::KEY_Alt_L] = GUIEventAdapter::MODKEY_LEFT_ALT;
+ keyMaskMap[GUIEventAdapter::KEY_Alt_R] = GUIEventAdapter::MODKEY_RIGHT_ALT;
+ // We have to implement numlock too.
+ numlockKeyMap[GUIEventAdapter::KEY_KP_Insert] = '0';
+ numlockKeyMap[GUIEventAdapter::KEY_KP_End] = '1';
+ numlockKeyMap[GUIEventAdapter::KEY_KP_Down] = '2';
+ numlockKeyMap[GUIEventAdapter::KEY_KP_Page_Down] = '3';
+ numlockKeyMap[GUIEventAdapter::KEY_KP_Left] = '4';
+ numlockKeyMap[GUIEventAdapter::KEY_KP_Begin] = '5';
+ numlockKeyMap[GUIEventAdapter::KEY_KP_Right] = '6';
+ numlockKeyMap[GUIEventAdapter::KEY_KP_Home] = '7';
+ numlockKeyMap[GUIEventAdapter::KEY_KP_Up] = '8';
+ numlockKeyMap[GUIEventAdapter::KEY_KP_Page_Up] = '9';
+}
+
void FGManipulator::setByMatrix(const osg::Matrixd& matrix)
{
// Yuck
return _node.get();
}
-namespace {
// All the usual translation from window system to FG / plib
-int osgToFGModifiers(int modifiers)
+static int osgToFGModifiers(int modifiers)
{
int result = 0;
if (modifiers & (osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT |
result |= KEYMOD_ALT;
return result;
}
-} // namespace
void FGManipulator::init(const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& us)
(void)handle(ea, us);
}
-namespace {
-void eventToViewport(const osgGA::GUIEventAdapter& ea,
- osgGA::GUIActionAdapter& us,
- int& x, int& y)
+static bool
+eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us,
+ int& x, int& y)
{
- osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&us);
- osg::Viewport* viewport = viewer->getCamera()->getViewport();
- const osg::GraphicsContext::Traits* traits
- = viewer->getCamera()->getGraphicsContext()->getTraits();
- x = (int)ea.getX();
- y = (int)ea.getY();
- if (ea.getMouseYOrientation()
- == osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
- y = (int)traits->height - y;
-}
+ x = -1;
+ y = -1;
+
+ const osgViewer::Viewer* viewer;
+ viewer = dynamic_cast<const osgViewer::Viewer*>(&us);
+ if (!viewer)
+ return false;
+
+ float lx, ly;
+ const osg::Camera* camera;
+ camera = viewer->getCameraContainingPosition(ea.getX(), ea.getY(), lx, ly);
+
+ if (!fgOSIsMainCamera(camera))
+ return false;
+
+ x = int(lx);
+ y = int(camera->getViewport()->height() - ly);
+
+ return true;
}
bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
eventToViewport(ea, us, x, y);
if (keyHandler)
(*keyHandler)(key, modmask, x, y);
+ return true;
}
- return true;
case osgGA::GUIEventAdapter::PUSH:
case osgGA::GUIEventAdapter::RELEASE:
{
- eventToViewport(ea, us, x, y);
+ bool mainWindow = eventToViewport(ea, us, x, y);
int button = 0;
switch (ea.getButton()) {
case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
if (mouseClickHandler)
(*mouseClickHandler)(button,
(ea.getEventType()
- == osgGA::GUIEventAdapter::RELEASE), x, y);
+ == osgGA::GUIEventAdapter::RELEASE), x, y, mainWindow, &ea);
return true;
}
case osgGA::GUIEventAdapter::MOVE:
(*mouseMotionHandler)(x, y);
return true;
case osgGA::GUIEventAdapter::RESIZE:
- if (windowResizeHandler)
+ if (resizable && windowResizeHandler)
(*windowResizeHandler)(ea.getWindowWidth(), ea.getWindowHeight());
return true;
+ case osgGA::GUIEventAdapter::CLOSE_WINDOW:
+ case osgGA::GUIEventAdapter::QUIT_APPLICATION:
+ fgOSExit(0);
+ return true;
default:
return false;
}
}
-
+
void FGManipulator::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
int& modifiers)
{
switch (key) {
case osgGA::GUIEventAdapter::KEY_Escape: key = 0x1b; break;
case osgGA::GUIEventAdapter::KEY_Return: key = '\n'; break;
+ case osgGA::GUIEventAdapter::KEY_BackSpace: key = '\b'; break;
+ case osgGA::GUIEventAdapter::KEY_Delete: key = 0x7f; break;
+ case osgGA::GUIEventAdapter::KEY_Tab: key = '\t'; break;
case osgGA::GUIEventAdapter::KEY_Left: key = PU_KEY_LEFT; break;
case osgGA::GUIEventAdapter::KEY_Up: key = PU_KEY_UP; break;
case osgGA::GUIEventAdapter::KEY_Right: key = PU_KEY_RIGHT; break;
case osgGA::GUIEventAdapter::KEY_F10: key = PU_KEY_F10; break;
case osgGA::GUIEventAdapter::KEY_F11: key = PU_KEY_F11; break;
case osgGA::GUIEventAdapter::KEY_F12: key = PU_KEY_F12; break;
+ case osgGA::GUIEventAdapter::KEY_KP_Delete: key = '.'; break;
+ case osgGA::GUIEventAdapter::KEY_KP_Enter: key = '\r'; break;
+ case osgGA::GUIEventAdapter::KEY_KP_Add: key = '+'; break;
+ case osgGA::GUIEventAdapter::KEY_KP_Divide: key = '/'; break;
+ case osgGA::GUIEventAdapter::KEY_KP_Multiply: key = '*'; break;
+ case osgGA::GUIEventAdapter::KEY_KP_Subtract: key = '-'; break;
+ }
+ osgGA::GUIEventAdapter::EventType eventType = ea.getEventType();
+ std::map<int, int>::iterator numPadIter = numlockKeyMap.find(key);
+
+ if (numPadIter != numlockKeyMap.end()) {
+ if (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_NUM_LOCK) {
+ key = numPadIter->second;
+ }
+ } else {
+ // Track the modifiers because OSG is currently (2.0) broken
+ KeyMaskMap::iterator iter = keyMaskMap.find(key);
+ if (iter != keyMaskMap.end()) {
+ int mask = iter->second;
+ if (eventType == osgGA::GUIEventAdapter::KEYUP)
+ osgModifiers &= ~mask;
+ else
+ osgModifiers |= mask;
+ }
}
- modifiers = osgToFGModifiers(ea.getModKeyMask());
+ modifiers = osgToFGModifiers(osgModifiers);
currentModifiers = modifiers;
- if (ea.getEventType() == osgGA::GUIEventAdapter::KEYUP)
+ if (eventType == osgGA::GUIEventAdapter::KEYUP)
modifiers |= KEYMOD_RELEASED;
}