3 #include <osgViewer/ViewerEventHandlers>
4 #include <osgViewer/Viewer>
6 #include <simgear/compiler.h>
7 #include <simgear/structure/exception.hxx>
8 #include <simgear/debug/logstream.hxx>
13 #include <Scenery/scenery.hxx>
15 #include "globals.hxx"
16 #include "renderer.hxx"
19 // fg_os callback registration APIs
22 static int CurrentModifiers = 0;
23 static int CurrentMouseX = 0;
24 static int CurrentMouseY = 0;
25 static int CurrentMouseCursor = MOUSE_CURSOR_POINTER;
26 static int VidMask = SDL_OPENGL|SDL_RESIZABLE;
29 // fg_os implementation
31 static void initCursors();
33 static osg::ref_ptr<osgViewer::Viewer> viewer;
34 static osg::ref_ptr<osg::Camera> mainCamera;
35 static osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw;
37 void fgOSOpenWindow(int w, int h, int bpp,
38 bool alpha, bool stencil, bool fullscreen)
40 int cbits = (bpp <= 16) ? 5 : 8;
41 int zbits = (bpp <= 16) ? 16 : 24;
43 if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) == -1)
44 throw sg_throwable(string("Failed to initialize SDL: ")
48 SDL_WM_SetCaption("FlightGear", "FlightGear");
50 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, cbits);
51 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, cbits);
52 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, cbits);
54 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
55 if(bpp > 16 && stencil)
56 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
57 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, zbits);
58 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
61 VidMask |= SDL_FULLSCREEN;
63 SDL_Surface* screen = SDL_SetVideoMode(w, h, 16, VidMask);
65 throw sg_throwable(string("Failed to set SDL video mode: ")
68 // This enables keycode translation (e.g. capital letters when
69 // shift is pressed, as well as i18n input methods). Eventually,
70 // we may want to port the input maps to specify <mod-shift>
71 // explicitly, and will turn this off.
73 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
76 fgSetMouseCursor(MOUSE_CURSOR_POINTER);
78 // FIXME: we may not get what we asked for (especially in full
79 // screen modes), so these need to be propagated back to the
80 // property tree for the rest of the code to inspect...
82 int realw = screen->w;
83 int realh = screen->h;
84 viewer = new osgViewer::Viewer;
85 gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, realw, realh);
86 // now the main camera ...
87 //osg::ref_ptr<osg::Camera> camera = new osg::Camera;
88 osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
90 osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
91 // If a viewport isn't set on the camera, then it's hard to dig it
92 // out of the SceneView objects in the viewer, and the coordinates
93 // of mouse events are somewhat bizzare.
94 camera->setViewport(new osg::Viewport(0, 0, realw, realh));
95 camera->setProjectionResizePolicy(rsp);
96 //viewer->addSlave(camera.get());
97 viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
98 // Let FG handle the escape key with a confirmation
99 viewer->setKeyEventSetsDone(0);
100 osgViewer::StatsHandler* statsHandler = new osgViewer::StatsHandler;
101 statsHandler->setKeyEventTogglesOnScreenStats('*');
102 statsHandler->setKeyEventPrintsOutStats(0);
103 viewer->addEventHandler(statsHandler);
104 // The viewer won't start without some root.
105 viewer->setSceneData(new osg::Group);
106 globals->get_renderer()->setViewer(viewer.get());
109 // Cheap trick to avoid typing GUIEventAdapter over and over...
110 class SDLKeyTranslator : osgGA::GUIEventAdapter
113 static int handleKey(int key, int raw, int keyup);
116 int SDLKeyTranslator::handleKey(int key, int raw, int keyup)
118 using namespace osgGA;
124 // Don't pass capslock or numlock to the FGManipulator; SDL
125 // already transforms the key properly, so FGManipulator will get
127 if (key == SDLK_CAPSLOCK || key == SDLK_NUMLOCK)
130 case SDLK_RSHIFT: modmask = KEYMOD_SHIFT; osgKey = KEY_Shift_R; break;
131 case SDLK_LSHIFT: modmask = KEYMOD_SHIFT; osgKey = KEY_Shift_L; break;
132 case SDLK_RCTRL: modmask = KEYMOD_CTRL; osgKey = KEY_Control_R; break;
133 case SDLK_LCTRL: modmask = KEYMOD_CTRL; osgKey = KEY_Control_L; break;
134 case SDLK_RALT: modmask = KEYMOD_ALT; osgKey = KEY_Alt_R; break;
135 case SDLK_LALT: modmask = KEYMOD_ALT; osgKey = KEY_Alt_L; break;
137 case SDLK_LEFT: osgKey = KEY_Left; break;
138 case SDLK_UP: osgKey = KEY_Up; break;
139 case SDLK_RIGHT: osgKey = KEY_Right; break;
140 case SDLK_DOWN: osgKey = KEY_Down; break;
141 case SDLK_PAGEUP: osgKey = KEY_Page_Up; break;
142 case SDLK_PAGEDOWN: osgKey = KEY_Page_Down; break;
143 case SDLK_HOME: osgKey = KEY_Home; break;
144 case SDLK_END: osgKey = KEY_End; break;
145 case SDLK_INSERT: osgKey = KEY_Insert; break;
146 case SDLK_F1: osgKey = KEY_F1; break;
147 case SDLK_F2: osgKey = KEY_F2; break;
148 case SDLK_F3: osgKey = KEY_F3; break;
149 case SDLK_F4: osgKey = KEY_F4; break;
150 case SDLK_F5: osgKey = KEY_F5; break;
151 case SDLK_F6: osgKey = KEY_F6; break;
152 case SDLK_F7: osgKey = KEY_F7; break;
153 case SDLK_F8: osgKey = KEY_F8; break;
154 case SDLK_F9: osgKey = KEY_F9; break;
155 case SDLK_F10: osgKey = KEY_F10; break;
156 case SDLK_F11: osgKey = KEY_F11; break;
157 case SDLK_F12: osgKey = KEY_F12; break;
163 CurrentModifiers &= ~modmask;
164 keymod = CurrentModifiers | KEYMOD_RELEASED;
166 CurrentModifiers |= modmask;
167 keymod = CurrentModifiers & ~KEYMOD_RELEASED;
172 // FIXME: Integrate with existing fgExit() in util.cxx.
173 void fgOSExit(int code)
175 viewer->setDone(true);
179 // originally from osgexamples/osgviewerSDL.cpp
180 bool convertEvent(SDL_Event& event, osgGA::EventQueue& eventQueue)
182 using namespace osgGA;
183 switch (event.type) {
185 case SDL_MOUSEMOTION:
186 eventQueue.mouseMotion(event.motion.x, event.motion.y);
189 case SDL_MOUSEBUTTONDOWN:
190 eventQueue.mouseButtonPress(event.button.x, event.button.y, event.button.button);
193 case SDL_MOUSEBUTTONUP:
194 eventQueue.mouseButtonRelease(event.button.x, event.button.y, event.button.button);
200 int realKey = SDLKeyTranslator::handleKey(event.key.keysym.unicode,
201 event.key.keysym.sym,
202 event.type == SDL_KEYUP);
205 if (event.type == SDL_KEYUP)
206 eventQueue.keyRelease((osgGA::GUIEventAdapter::KeySymbol)realKey);
208 eventQueue.keyPress((osgGA::GUIEventAdapter::KeySymbol)realKey);
211 case SDL_VIDEORESIZE:
212 if (SDL_SetVideoMode(event.resize.w, event.resize.h, 16, VidMask) == 0)
213 throw sg_throwable(string("Failed to set SDL video mode: ")
215 eventQueue.windowResize(0, 0, event.resize.w, event.resize.h );
229 while(SDL_PollEvent(&e)) {
230 // pass the SDL event into the viewers event queue
231 convertEvent(e, *(gw->getEventQueue()));
237 case SDL_VIDEORESIZE:
238 gw->resized(0, 0, e.resize.w, e.resize.h );
242 // draw the new frame
246 SDL_GL_SwapBuffers();
250 int fgGetKeyModifiers()
252 return CurrentModifiers;
255 void fgWarpMouse(int x, int y)
259 SDL_PeepEvents(e, 10, SDL_GETEVENT, SDL_MOUSEMOTIONMASK);
263 void fgOSInit(int* argc, char** argv)
265 // Nothing to do here. SDL has no command line options.
268 void fgOSFullScreen()
270 // Noop. SDL must set fullscreen at window open time and cannot
274 static struct cursor_rec {
276 SDL_Cursor* sdlCursor;
281 char *img[32]; // '.' == white, '#' == black, ' ' == transparent
283 { MOUSE_CURSOR_POINTER, 0, // must be first!
301 { MOUSE_CURSOR_CROSSHAIR, 0,
320 { MOUSE_CURSOR_WAIT, 0,
338 { MOUSE_CURSOR_LEFTRIGHT, 0,
349 { MOUSE_CURSOR_NONE, 0, // must come last!
350 1, 1, 0, 0, { " " } },
353 #define NCURSORS (sizeof(cursors)/sizeof(struct cursor_rec))
355 void fgSetMouseCursor(int cursor)
357 if(cursor == MOUSE_CURSOR_NONE) {
358 SDL_ShowCursor(SDL_DISABLE);
361 SDL_ShowCursor(SDL_ENABLE);
362 for(unsigned int i=0; i<NCURSORS; i++) {
363 if(cursor == cursors[i].name) {
364 CurrentMouseCursor = cursor;
365 SDL_SetCursor(cursors[i].sdlCursor);
369 // Default to pointer
370 CurrentMouseCursor = MOUSE_CURSOR_POINTER;
371 SDL_SetCursor(cursors[0].sdlCursor);
374 int fgGetMouseCursor()
376 return CurrentMouseCursor;
379 static void initCursors()
381 unsigned char mask[128], img[128];
382 for(unsigned int i=0; i<NCURSORS; i++) {
383 if(cursors[i].name == MOUSE_CURSOR_NONE) break;
384 for(int j=0; j<128; j++) mask[j] = img[j] = 0;
385 for(int y=0; y<cursors[i].h; y++) {
386 for(int x=0; x<cursors[i].w; x++) {
387 int byte = (4 * y) + (x >> 3);
388 int bit = 1 << (7 - (x & 7));
389 int pix = cursors[i].img[y][x];
390 if(pix != ' ') { mask[byte] |= bit; }
391 if(pix == '#') { img[byte] |= bit; }
394 cursors[i].sdlCursor = SDL_CreateCursor(img, mask, 32, 32,
400 // Noop; the graphics context is always current
405 bool fgOSIsMainCamera(const osg::Camera*)
410 bool fgOSIsMainContext(const osg::GraphicsContext*)