1
0
Fork 0

Rewrite SDL code to use an embedded osgViewer.

This uses the osgViewer infrastructure instead of setting up and osg::SceneView.
When the same change is made for glut, much of render.cxx can be deleted.
This commit is contained in:
timoore 2007-11-30 00:01:01 +00:00
parent 49f7330150
commit ae8509c827
4 changed files with 145 additions and 156 deletions

View file

@ -121,7 +121,7 @@ eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us,
const osg::Camera* camera; const osg::Camera* camera;
camera = viewer->getCameraContainingPosition(ea.getX(), ea.getY(), lx, ly); camera = viewer->getCameraContainingPosition(ea.getX(), ea.getY(), lx, ly);
if (!fgOSIsMainCamera(camera)) if (!(camera && fgOSIsMainCamera(camera)))
return false; return false;
x = int(lx); x = int(lx);
@ -133,7 +133,8 @@ eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us,
bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea, bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& us) osgGA::GUIActionAdapter& us)
{ {
int x, y; int x = 0;
int y = 0;
switch (ea.getEventType()) { switch (ea.getEventType()) {
case osgGA::GUIEventAdapter::FRAME: case osgGA::GUIEventAdapter::FRAME:
if (idleHandler) if (idleHandler)
@ -201,8 +202,7 @@ bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
// that with osgViewer. // that with osgViewer.
if (mouseWarped) if (mouseWarped)
return true; return true;
eventToViewport(ea, us, x, y); if (eventToViewport(ea, us, x, y) && mouseMotionHandler)
if (mouseMotionHandler)
(*mouseMotionHandler)(x, y); (*mouseMotionHandler)(x, y);
return true; return true;
case osgGA::GUIEventAdapter::RESIZE: case osgGA::GUIEventAdapter::RESIZE:

View file

@ -16,7 +16,7 @@ THREAD_LIBS =
endif endif
if USE_SDL 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 else
if USE_OSGVIEWER if USE_OSGVIEWER
GFX_CODE = fg_os_osgviewer.cxx fg_os_common.cxx fg_os.hxx GFX_CODE = fg_os_osgviewer.cxx fg_os_common.cxx fg_os.hxx

View file

@ -1,5 +1,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/Viewer>
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
@ -7,62 +10,30 @@
#include <SDL/SDL.h> #include <SDL/SDL.h>
#include <plib/pu.h> #include <plib/pu.h>
#include <Scenery/scenery.hxx>
#include "fg_os.hxx" #include "fg_os.hxx"
#include "globals.hxx"
#include "renderer.hxx"
// //
// fg_os callback registration APIs // 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 CurrentModifiers = 0;
static int CurrentMouseX = 0; static int CurrentMouseX = 0;
static int CurrentMouseY = 0; static int CurrentMouseY = 0;
static int CurrentMouseCursor = MOUSE_CURSOR_POINTER; static int CurrentMouseCursor = MOUSE_CURSOR_POINTER;
static bool NeedRedraw = false;
static int VidMask = SDL_OPENGL|SDL_RESIZABLE; 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 // fg_os implementation
// //
static void initCursors(); static void initCursors();
static osg::ref_ptr<osgViewer::Viewer> viewer;
static osg::ref_ptr<osg::Camera> mainCamera;
static osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw;
void fgOSOpenWindow(int w, int h, int bpp, void fgOSOpenWindow(int w, int h, int bpp,
bool alpha, bool stencil, bool fullscreen) bool alpha, bool stencil, bool fullscreen)
{ {
@ -89,7 +60,8 @@ void fgOSOpenWindow(int w, int h, int bpp,
if(fullscreen) { if(fullscreen) {
VidMask |= SDL_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: ") throw sg_throwable(string("Failed to set SDL video mode: ")
+ SDL_GetError()); + 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 // screen modes), so these need to be propagated back to the
// property tree for the rest of the code to inspect... // property tree for the rest of the code to inspect...
// //
// SDL_Surface* screen = SDL_GetVideoSurface(); int realw = screen->w;
// int realw = screen->w; int realh = screen->h;
// int realh = screen->h; viewer = new osgViewer::Viewer;
gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, realw, realh);
// now the main camera ...
//osg::ref_ptr<osg::Camera> camera = new osg::Camera;
osg::ref_ptr<osg::Camera> 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());
} }
// Cheap trick to avoid typing GUIEventAdapter over and over...
struct keydata { class SDLKeyTranslator : osgGA::GUIEventAdapter
keydata() : unicode(0), mod(0) {};
Uint16 unicode;
unsigned int mod;
} keys[SDLK_LAST];
static void handleKey(int key, int raw, int keyup)
{ {
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 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) { switch(key) {
case SDLK_RSHIFT: modmask = KEYMOD_SHIFT; break; case SDLK_RSHIFT: modmask = KEYMOD_SHIFT; osgKey = KEY_Shift_R; break;
case SDLK_LSHIFT: modmask = KEYMOD_SHIFT; break; case SDLK_LSHIFT: modmask = KEYMOD_SHIFT; osgKey = KEY_Shift_L; break;
case SDLK_RCTRL: modmask = KEYMOD_CTRL; break; case SDLK_RCTRL: modmask = KEYMOD_CTRL; osgKey = KEY_Control_R; break;
case SDLK_LCTRL: modmask = KEYMOD_CTRL; break; case SDLK_LCTRL: modmask = KEYMOD_CTRL; osgKey = KEY_Control_L; break;
case SDLK_RALT: modmask = KEYMOD_ALT; break; case SDLK_RALT: modmask = KEYMOD_ALT; osgKey = KEY_Alt_R; break;
case SDLK_LALT: modmask = KEYMOD_ALT; break; case SDLK_LALT: modmask = KEYMOD_ALT; osgKey = KEY_Alt_L; break;
case SDLK_LEFT: key = PU_KEY_LEFT; break; case SDLK_LEFT: osgKey = KEY_Left; break;
case SDLK_UP: key = PU_KEY_UP; break; case SDLK_UP: osgKey = KEY_Up; break;
case SDLK_RIGHT: key = PU_KEY_RIGHT; break; case SDLK_RIGHT: osgKey = KEY_Right; break;
case SDLK_DOWN: key = PU_KEY_DOWN; break; case SDLK_DOWN: osgKey = KEY_Down; break;
case SDLK_PAGEUP: key = PU_KEY_PAGE_UP; break; case SDLK_PAGEUP: osgKey = KEY_Page_Up; break;
case SDLK_PAGEDOWN: key = PU_KEY_PAGE_DOWN; break; case SDLK_PAGEDOWN: osgKey = KEY_Page_Down; break;
case SDLK_HOME: key = PU_KEY_HOME; break; case SDLK_HOME: osgKey = KEY_Home; break;
case SDLK_END: key = PU_KEY_END; break; case SDLK_END: osgKey = KEY_End; break;
case SDLK_INSERT: key = PU_KEY_INSERT; break; case SDLK_INSERT: osgKey = KEY_Insert; break;
case SDLK_F1: key = PU_KEY_F1; break; case SDLK_F1: osgKey = KEY_F1; break;
case SDLK_F2: key = PU_KEY_F2; break; case SDLK_F2: osgKey = KEY_F2; break;
case SDLK_F3: key = PU_KEY_F3; break; case SDLK_F3: osgKey = KEY_F3; break;
case SDLK_F4: key = PU_KEY_F4; break; case SDLK_F4: osgKey = KEY_F4; break;
case SDLK_F5: key = PU_KEY_F5; break; case SDLK_F5: osgKey = KEY_F5; break;
case SDLK_F6: key = PU_KEY_F6; break; case SDLK_F6: osgKey = KEY_F6; break;
case SDLK_F7: key = PU_KEY_F7; break; case SDLK_F7: osgKey = KEY_F7; break;
case SDLK_F8: key = PU_KEY_F8; break; case SDLK_F8: osgKey = KEY_F8; break;
case SDLK_F9: key = PU_KEY_F9; break; case SDLK_F9: osgKey = KEY_F9; break;
case SDLK_F10: key = PU_KEY_F10; break; case SDLK_F10: osgKey = KEY_F10; break;
case SDLK_F11: key = PU_KEY_F11; break; case SDLK_F11: osgKey = KEY_F11; break;
case SDLK_F12: key = PU_KEY_F12; 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; int keymod = 0;
if(keyup) { if(keyup) {
CurrentModifiers &= ~modmask; CurrentModifiers &= ~modmask;
@ -181,73 +166,84 @@ static void handleKey(int key, int raw, int keyup)
CurrentModifiers |= modmask; CurrentModifiers |= modmask;
keymod = CurrentModifiers & ~KEYMOD_RELEASED; keymod = CurrentModifiers & ~KEYMOD_RELEASED;
} }
return osgKey;
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);
}
} }
// FIXME: Integrate with existing fgExit() in util.cxx. // FIXME: Integrate with existing fgExit() in util.cxx.
void fgOSExit(int code) void fgOSExit(int code)
{ {
viewer->setDone(true);
exit(code); 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() void fgOSMainLoop()
{ {
while(1) { while(1) {
SDL_Event e; SDL_Event e;
int key; int key;
while(SDL_PollEvent(&e)) { while(SDL_PollEvent(&e)) {
// pass the SDL event into the viewers event queue
convertEvent(e, *(gw->getEventQueue()));
switch(e.type) { switch(e.type) {
case SDL_QUIT: case SDL_QUIT:
fgOSExit(0); fgOSExit(0);
break; 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: case SDL_VIDEORESIZE:
if (SDL_SetVideoMode(e.resize.w, e.resize.h, 16, VidMask) == 0) gw->resized(0, 0, e.resize.w, e.resize.h );
throw sg_throwable(string("Failed to set SDL video mode: ")
+ SDL_GetError());
if (WindowResizeHandler)
(*WindowResizeHandler)(e.resize.w, e.resize.h);
break; break;
} }
} }
if(IdleHandler) (*IdleHandler)(); // draw the new frame
if(NeedRedraw && DrawHandler) { viewer->frame();
(*DrawHandler)();
// Swap Buffers
SDL_GL_SwapBuffers(); SDL_GL_SwapBuffers();
NeedRedraw = false;
}
} }
} }
@ -264,11 +260,6 @@ void fgWarpMouse(int x, int y)
SDL_WarpMouse(x, y); SDL_WarpMouse(x, y);
} }
void fgRequestRedraw()
{
NeedRedraw = true;
}
void fgOSInit(int* argc, char** argv) void fgOSInit(int* argc, char** argv)
{ {
// Nothing to do here. SDL has no command line options. // Nothing to do here. SDL has no command line options.

View file

@ -373,9 +373,7 @@ FGRenderer::FGRenderer()
#ifdef FG_JPEG_SERVER #ifdef FG_JPEG_SERVER
jpgRenderFrame = FGRenderer::update; jpgRenderFrame = FGRenderer::update;
#endif #endif
#ifdef ENABLE_OSGVIEWER
manipulator = new FGManipulator; manipulator = new FGManipulator;
#endif
} }
FGRenderer::~FGRenderer() FGRenderer::~FGRenderer()