diff --git a/src/Main/FGManipulator.cxx b/src/Main/FGManipulator.cxx index 492f17966..646e6b386 100644 --- a/src/Main/FGManipulator.cxx +++ b/src/Main/FGManipulator.cxx @@ -121,7 +121,7 @@ eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us, const osg::Camera* camera; camera = viewer->getCameraContainingPosition(ea.getX(), ea.getY(), lx, ly); - if (!fgOSIsMainCamera(camera)) + if (!(camera && fgOSIsMainCamera(camera))) return false; x = int(lx); @@ -133,7 +133,8 @@ eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us, bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us) { - int x, y; + int x = 0; + int y = 0; switch (ea.getEventType()) { case osgGA::GUIEventAdapter::FRAME: if (idleHandler) @@ -201,8 +202,7 @@ bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea, // that with osgViewer. if (mouseWarped) return true; - eventToViewport(ea, us, x, y); - if (mouseMotionHandler) + if (eventToViewport(ea, us, x, y) && mouseMotionHandler) (*mouseMotionHandler)(x, y); return true; case osgGA::GUIEventAdapter::RESIZE: diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index bdafefb54..ca2a2e696 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -16,7 +16,7 @@ THREAD_LIBS = endif if USE_SDL -GFX_CODE = fg_os_sdl.cxx fg_os.hxx +GFX_CODE = fg_os_sdl.cxx fg_os_common.cxx fg_os.hxx else if USE_OSGVIEWER GFX_CODE = fg_os_osgviewer.cxx fg_os_common.cxx fg_os.hxx diff --git a/src/Main/fg_os_sdl.cxx b/src/Main/fg_os_sdl.cxx index 81f2e4c5a..0b43ef93b 100644 --- a/src/Main/fg_os_sdl.cxx +++ b/src/Main/fg_os_sdl.cxx @@ -1,5 +1,8 @@ #include +#include +#include + #include #include #include @@ -7,62 +10,30 @@ #include #include +#include #include "fg_os.hxx" +#include "globals.hxx" +#include "renderer.hxx" // // fg_os callback registration APIs // -static fgIdleHandler IdleHandler = 0; -static fgDrawHandler DrawHandler = 0; -static fgWindowResizeHandler WindowResizeHandler = 0; -static fgKeyHandler KeyHandler = 0; -static fgMouseClickHandler MouseClickHandler = 0; -static fgMouseMotionHandler MouseMotionHandler = 0; - static int CurrentModifiers = 0; static int CurrentMouseX = 0; static int CurrentMouseY = 0; static int CurrentMouseCursor = MOUSE_CURSOR_POINTER; -static bool NeedRedraw = false; static int VidMask = SDL_OPENGL|SDL_RESIZABLE; -void fgRegisterIdleHandler(fgIdleHandler func) -{ - IdleHandler = func; -} - -void fgRegisterDrawHandler(fgDrawHandler func) -{ - DrawHandler = func; - NeedRedraw = true; -} - -void fgRegisterWindowResizeHandler(fgWindowResizeHandler func) -{ - WindowResizeHandler = func; -} - -void fgRegisterKeyHandler(fgKeyHandler func) -{ - KeyHandler = func; -} - -void fgRegisterMouseClickHandler(fgMouseClickHandler func) -{ - MouseClickHandler = func; -} - -void fgRegisterMouseMotionHandler(fgMouseMotionHandler func) -{ - MouseMotionHandler = func; -} - // // fg_os implementation // static void initCursors(); +static osg::ref_ptr viewer; +static osg::ref_ptr mainCamera; +static osg::ref_ptr gw; + void fgOSOpenWindow(int w, int h, int bpp, bool alpha, bool stencil, bool fullscreen) { @@ -89,7 +60,8 @@ void fgOSOpenWindow(int w, int h, int bpp, if(fullscreen) { VidMask |= SDL_FULLSCREEN; } - if (SDL_SetVideoMode(w, h, 16, VidMask) == 0) + SDL_Surface* screen = SDL_SetVideoMode(w, h, 16, VidMask); + if ( screen == 0) throw sg_throwable(string("Failed to set SDL video mode: ") + SDL_GetError()); @@ -107,72 +79,85 @@ void fgOSOpenWindow(int w, int h, int bpp, // screen modes), so these need to be propagated back to the // property tree for the rest of the code to inspect... // - // SDL_Surface* screen = SDL_GetVideoSurface(); - // int realw = screen->w; - // int realh = screen->h; + int realw = screen->w; + int realh = screen->h; + viewer = new osgViewer::Viewer; + gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, realw, realh); + // now the main camera ... + //osg::ref_ptr camera = new osg::Camera; + osg::ref_ptr camera = viewer->getCamera(); + mainCamera = camera; + osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL; + // If a viewport isn't set on the camera, then it's hard to dig it + // out of the SceneView objects in the viewer, and the coordinates + // of mouse events are somewhat bizzare. + camera->setViewport(new osg::Viewport(0, 0, realw, realh)); + camera->setProjectionResizePolicy(rsp); + //viewer->addSlave(camera.get()); + viewer->setCameraManipulator(globals->get_renderer()->getManipulator()); + // Let FG handle the escape key with a confirmation + viewer->setKeyEventSetsDone(0); + osgViewer::StatsHandler* statsHandler = new osgViewer::StatsHandler; + statsHandler->setKeyEventTogglesOnScreenStats('*'); + statsHandler->setKeyEventPrintsOutStats(0); + viewer->addEventHandler(statsHandler); + // The viewer won't start without some root. + viewer->setSceneData(new osg::Group); + globals->get_renderer()->setViewer(viewer.get()); } - -struct keydata { - keydata() : unicode(0), mod(0) {}; - Uint16 unicode; - unsigned int mod; -} keys[SDLK_LAST]; - - -static void handleKey(int key, int raw, int keyup) +// Cheap trick to avoid typing GUIEventAdapter over and over... +class SDLKeyTranslator : osgGA::GUIEventAdapter { +public: + static int handleKey(int key, int raw, int keyup); +}; + +int SDLKeyTranslator::handleKey(int key, int raw, int keyup) +{ + using namespace osgGA; + int modmask = 0; + int osgKey = 0; + if (key == 0) + key = raw; + // Don't pass capslock or numlock to the FGManipulator; SDL + // already transforms the key properly, so FGManipulator will get + // confused. + if (key == SDLK_CAPSLOCK || key == SDLK_NUMLOCK) + return -1; switch(key) { - case SDLK_RSHIFT: modmask = KEYMOD_SHIFT; break; - case SDLK_LSHIFT: modmask = KEYMOD_SHIFT; break; - case SDLK_RCTRL: modmask = KEYMOD_CTRL; break; - case SDLK_LCTRL: modmask = KEYMOD_CTRL; break; - case SDLK_RALT: modmask = KEYMOD_ALT; break; - case SDLK_LALT: modmask = KEYMOD_ALT; break; + case SDLK_RSHIFT: modmask = KEYMOD_SHIFT; osgKey = KEY_Shift_R; break; + case SDLK_LSHIFT: modmask = KEYMOD_SHIFT; osgKey = KEY_Shift_L; break; + case SDLK_RCTRL: modmask = KEYMOD_CTRL; osgKey = KEY_Control_R; break; + case SDLK_LCTRL: modmask = KEYMOD_CTRL; osgKey = KEY_Control_L; break; + case SDLK_RALT: modmask = KEYMOD_ALT; osgKey = KEY_Alt_R; break; + case SDLK_LALT: modmask = KEYMOD_ALT; osgKey = KEY_Alt_L; break; - case SDLK_LEFT: key = PU_KEY_LEFT; break; - case SDLK_UP: key = PU_KEY_UP; break; - case SDLK_RIGHT: key = PU_KEY_RIGHT; break; - case SDLK_DOWN: key = PU_KEY_DOWN; break; - case SDLK_PAGEUP: key = PU_KEY_PAGE_UP; break; - case SDLK_PAGEDOWN: key = PU_KEY_PAGE_DOWN; break; - case SDLK_HOME: key = PU_KEY_HOME; break; - case SDLK_END: key = PU_KEY_END; break; - case SDLK_INSERT: key = PU_KEY_INSERT; break; - case SDLK_F1: key = PU_KEY_F1; break; - case SDLK_F2: key = PU_KEY_F2; break; - case SDLK_F3: key = PU_KEY_F3; break; - case SDLK_F4: key = PU_KEY_F4; break; - case SDLK_F5: key = PU_KEY_F5; break; - case SDLK_F6: key = PU_KEY_F6; break; - case SDLK_F7: key = PU_KEY_F7; break; - case SDLK_F8: key = PU_KEY_F8; break; - case SDLK_F9: key = PU_KEY_F9; break; - case SDLK_F10: key = PU_KEY_F10; break; - case SDLK_F11: key = PU_KEY_F11; break; - case SDLK_F12: key = PU_KEY_F12; break; + case SDLK_LEFT: osgKey = KEY_Left; break; + case SDLK_UP: osgKey = KEY_Up; break; + case SDLK_RIGHT: osgKey = KEY_Right; break; + case SDLK_DOWN: osgKey = KEY_Down; break; + case SDLK_PAGEUP: osgKey = KEY_Page_Up; break; + case SDLK_PAGEDOWN: osgKey = KEY_Page_Down; break; + case SDLK_HOME: osgKey = KEY_Home; break; + case SDLK_END: osgKey = KEY_End; break; + case SDLK_INSERT: osgKey = KEY_Insert; break; + case SDLK_F1: osgKey = KEY_F1; break; + case SDLK_F2: osgKey = KEY_F2; break; + case SDLK_F3: osgKey = KEY_F3; break; + case SDLK_F4: osgKey = KEY_F4; break; + case SDLK_F5: osgKey = KEY_F5; break; + case SDLK_F6: osgKey = KEY_F6; break; + case SDLK_F7: osgKey = KEY_F7; break; + case SDLK_F8: osgKey = KEY_F8; break; + case SDLK_F9: osgKey = KEY_F9; break; + case SDLK_F10: osgKey = KEY_F10; break; + case SDLK_F11: osgKey = KEY_F11; break; + case SDLK_F12: osgKey = KEY_F12; break; + default: + osgKey = key; } - - // Keypad codes. This is a situation where we *don't* want the - // Unicode cooking for our input. Oddly, neither PUI nor Glut - // define these anywhere, so I lifted the numbers out of - // FlightGear's keyboard.xml. Some unused code are therefore - // missing. - switch(raw) { - case SDLK_KP0: key = 364; break; - case SDLK_KP1: key = 363; break; - case SDLK_KP2: key = 359; break; - case SDLK_KP3: key = 361; break; - case SDLK_KP4: key = 356; break; - case SDLK_KP5: key = 309; break; - case SDLK_KP6: key = 358; break; - case SDLK_KP7: key = 362; break; - case SDLK_KP8: key = 357; break; - case SDLK_KP9: key = 360; break; - case SDLK_KP_ENTER: key = 269; break; - } - int keymod = 0; if(keyup) { CurrentModifiers &= ~modmask; @@ -181,73 +166,84 @@ static void handleKey(int key, int raw, int keyup) CurrentModifiers |= modmask; keymod = CurrentModifiers & ~KEYMOD_RELEASED; } - - if(modmask == 0 && KeyHandler) { - if (keymod & KEYMOD_RELEASED) { - key = keys[raw].unicode; - - } else { - keys[raw].mod = keymod; - keys[raw].unicode = key; - } - (*KeyHandler)(key, keymod, CurrentMouseX, CurrentMouseY); - } + return osgKey; } // FIXME: Integrate with existing fgExit() in util.cxx. void fgOSExit(int code) { + viewer->setDone(true); exit(code); } +// originally from osgexamples/osgviewerSDL.cpp +bool convertEvent(SDL_Event& event, osgGA::EventQueue& eventQueue) +{ + using namespace osgGA; + switch (event.type) { + + case SDL_MOUSEMOTION: + eventQueue.mouseMotion(event.motion.x, event.motion.y); + return true; + + case SDL_MOUSEBUTTONDOWN: + eventQueue.mouseButtonPress(event.button.x, event.button.y, event.button.button); + return true; + + case SDL_MOUSEBUTTONUP: + eventQueue.mouseButtonRelease(event.button.x, event.button.y, event.button.button); + return true; + + case SDL_KEYUP: + case SDL_KEYDOWN: + { + int realKey = SDLKeyTranslator::handleKey(event.key.keysym.unicode, + event.key.keysym.sym, + event.type == SDL_KEYUP); + if (realKey < -1) + return true; + if (event.type == SDL_KEYUP) + eventQueue.keyRelease((osgGA::GUIEventAdapter::KeySymbol)realKey); + else + eventQueue.keyPress((osgGA::GUIEventAdapter::KeySymbol)realKey); + return true; + } + case SDL_VIDEORESIZE: + if (SDL_SetVideoMode(event.resize.w, event.resize.h, 16, VidMask) == 0) + throw sg_throwable(string("Failed to set SDL video mode: ") + + SDL_GetError()); + eventQueue.windowResize(0, 0, event.resize.w, event.resize.h ); + return true; + + default: + break; + } + return false; +} + void fgOSMainLoop() { while(1) { SDL_Event e; int key; while(SDL_PollEvent(&e)) { + // pass the SDL event into the viewers event queue + convertEvent(e, *(gw->getEventQueue())); + switch(e.type) { case SDL_QUIT: fgOSExit(0); break; - case SDL_KEYDOWN: - case SDL_KEYUP: - key = e.key.keysym.unicode; - if(key == 0) key = e.key.keysym.sym; - handleKey(key, e.key.keysym.sym, e.key.state == SDL_RELEASED); - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - // Note offset: SDL uses buttons 1,2,3 not 0,1,2 - CurrentMouseX = e.button.x; - CurrentMouseY = e.button.y; - if(MouseClickHandler) - (*MouseClickHandler)(e.button.button - 1, - e.button.state == SDL_RELEASED, - e.button.x, e.button.y, true, 0); - break; - case SDL_MOUSEMOTION: - CurrentMouseX = e.motion.x; - CurrentMouseY = e.motion.y; - if(MouseMotionHandler) - (*MouseMotionHandler)(e.motion.x, e.motion.y); - break; case SDL_VIDEORESIZE: - if (SDL_SetVideoMode(e.resize.w, e.resize.h, 16, VidMask) == 0) - throw sg_throwable(string("Failed to set SDL video mode: ") - + SDL_GetError()); - - if (WindowResizeHandler) - (*WindowResizeHandler)(e.resize.w, e.resize.h); + gw->resized(0, 0, e.resize.w, e.resize.h ); break; } } - if(IdleHandler) (*IdleHandler)(); - if(NeedRedraw && DrawHandler) { - (*DrawHandler)(); - SDL_GL_SwapBuffers(); - NeedRedraw = false; - } + // draw the new frame + viewer->frame(); + + // Swap Buffers + SDL_GL_SwapBuffers(); } } @@ -264,11 +260,6 @@ void fgWarpMouse(int x, int y) SDL_WarpMouse(x, y); } -void fgRequestRedraw() -{ - NeedRedraw = true; -} - void fgOSInit(int* argc, char** argv) { // Nothing to do here. SDL has no command line options. diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index 7b26b30b8..c2c36d6cd 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -373,9 +373,7 @@ FGRenderer::FGRenderer() #ifdef FG_JPEG_SERVER jpgRenderFrame = FGRenderer::update; #endif -#ifdef ENABLE_OSGVIEWER manipulator = new FGManipulator; -#endif } FGRenderer::~FGRenderer()