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;
136 case SDLK_RMETA: modmask = KEYMOD_META; osgKey = KEY_Meta_R; break;
137 case SDLK_LMETA: modmask = KEYMOD_META; osgKey = KEY_Meta_L; break;
138 case SDLK_RSUPER: modmask = KEYMOD_SUPER; osgKey = KEY_Super_R; break;
139 case SDLK_LSUPER: modmask = KEYMOD_SUPER; osgKey = KEY_Super_L; break;
141 case SDLK_LEFT: osgKey = KEY_Left; break;
142 case SDLK_UP: osgKey = KEY_Up; break;
143 case SDLK_RIGHT: osgKey = KEY_Right; break;
144 case SDLK_DOWN: osgKey = KEY_Down; break;
145 case SDLK_PAGEUP: osgKey = KEY_Page_Up; break;
146 case SDLK_PAGEDOWN: osgKey = KEY_Page_Down; break;
147 case SDLK_HOME: osgKey = KEY_Home; break;
148 case SDLK_END: osgKey = KEY_End; break;
149 case SDLK_INSERT: osgKey = KEY_Insert; break;
150 case SDLK_F1: osgKey = KEY_F1; break;
151 case SDLK_F2: osgKey = KEY_F2; break;
152 case SDLK_F3: osgKey = KEY_F3; break;
153 case SDLK_F4: osgKey = KEY_F4; break;
154 case SDLK_F5: osgKey = KEY_F5; break;
155 case SDLK_F6: osgKey = KEY_F6; break;
156 case SDLK_F7: osgKey = KEY_F7; break;
157 case SDLK_F8: osgKey = KEY_F8; break;
158 case SDLK_F9: osgKey = KEY_F9; break;
159 case SDLK_F10: osgKey = KEY_F10; break;
160 case SDLK_F11: osgKey = KEY_F11; break;
161 case SDLK_F12: osgKey = KEY_F12; break;
167 CurrentModifiers &= ~modmask;
168 keymod = CurrentModifiers | KEYMOD_RELEASED;
170 CurrentModifiers |= modmask;
171 keymod = CurrentModifiers & ~KEYMOD_RELEASED;
176 // FIXME: Integrate with existing fgExit() in util.cxx.
177 void fgOSExit(int code)
179 viewer->setDone(true);
183 // originally from osgexamples/osgviewerSDL.cpp
184 bool convertEvent(SDL_Event& event, osgGA::EventQueue& eventQueue)
186 using namespace osgGA;
187 switch (event.type) {
189 case SDL_MOUSEMOTION:
190 eventQueue.mouseMotion(event.motion.x, event.motion.y);
193 case SDL_MOUSEBUTTONDOWN:
194 eventQueue.mouseButtonPress(event.button.x, event.button.y, event.button.button);
197 case SDL_MOUSEBUTTONUP:
198 eventQueue.mouseButtonRelease(event.button.x, event.button.y, event.button.button);
204 int realKey = SDLKeyTranslator::handleKey(event.key.keysym.unicode,
205 event.key.keysym.sym,
206 event.type == SDL_KEYUP);
209 if (event.type == SDL_KEYUP)
210 eventQueue.keyRelease((osgGA::GUIEventAdapter::KeySymbol)realKey);
212 eventQueue.keyPress((osgGA::GUIEventAdapter::KeySymbol)realKey);
215 case SDL_VIDEORESIZE:
216 if (SDL_SetVideoMode(event.resize.w, event.resize.h, 16, VidMask) == 0)
217 throw sg_throwable(string("Failed to set SDL video mode: ")
219 eventQueue.windowResize(0, 0, event.resize.w, event.resize.h );
233 while(SDL_PollEvent(&e)) {
234 // pass the SDL event into the viewers event queue
235 convertEvent(e, *(gw->getEventQueue()));
241 case SDL_VIDEORESIZE:
242 gw->resized(0, 0, e.resize.w, e.resize.h );
246 // draw the new frame
250 SDL_GL_SwapBuffers();
254 int fgGetKeyModifiers()
256 return CurrentModifiers;
259 void fgWarpMouse(int x, int y)
263 SDL_PeepEvents(e, 10, SDL_GETEVENT, SDL_MOUSEMOTIONMASK);
267 void fgOSInit(int* argc, char** argv)
269 // Nothing to do here. SDL has no command line options.
272 void fgOSFullScreen()
274 // Noop. SDL must set fullscreen at window open time and cannot
278 static struct cursor_rec {
280 SDL_Cursor* sdlCursor;
285 char *img[32]; // '.' == white, '#' == black, ' ' == transparent
287 { MOUSE_CURSOR_POINTER, 0, // must be first!
305 { MOUSE_CURSOR_CROSSHAIR, 0,
324 { MOUSE_CURSOR_WAIT, 0,
342 { MOUSE_CURSOR_LEFTRIGHT, 0,
353 { MOUSE_CURSOR_NONE, 0, // must come last!
354 1, 1, 0, 0, { " " } },
357 #define NCURSORS (sizeof(cursors)/sizeof(struct cursor_rec))
359 void fgSetMouseCursor(int cursor)
361 if(cursor == MOUSE_CURSOR_NONE) {
362 SDL_ShowCursor(SDL_DISABLE);
365 SDL_ShowCursor(SDL_ENABLE);
366 for(unsigned int i=0; i<NCURSORS; i++) {
367 if(cursor == cursors[i].name) {
368 CurrentMouseCursor = cursor;
369 SDL_SetCursor(cursors[i].sdlCursor);
373 // Default to pointer
374 CurrentMouseCursor = MOUSE_CURSOR_POINTER;
375 SDL_SetCursor(cursors[0].sdlCursor);
378 int fgGetMouseCursor()
380 return CurrentMouseCursor;
383 static void initCursors()
385 unsigned char mask[128], img[128];
386 for(unsigned int i=0; i<NCURSORS; i++) {
387 if(cursors[i].name == MOUSE_CURSOR_NONE) break;
388 for(int j=0; j<128; j++) mask[j] = img[j] = 0;
389 for(int y=0; y<cursors[i].h; y++) {
390 for(int x=0; x<cursors[i].w; x++) {
391 int byte = (4 * y) + (x >> 3);
392 int bit = 1 << (7 - (x & 7));
393 int pix = cursors[i].img[y][x];
394 if(pix != ' ') { mask[byte] |= bit; }
395 if(pix == '#') { img[byte] |= bit; }
398 cursors[i].sdlCursor = SDL_CreateCursor(img, mask, 32, 32,
404 // Noop; the graphics context is always current
409 bool fgOSIsMainCamera(const osg::Camera*)
414 bool fgOSIsMainContext(const osg::GraphicsContext*)