1 #ifndef _MSC_VER // MSVC really needs a definition for wchar_t
2 #define _WCHAR_T_DEFINED 1 // Glut needs this, or else it tries to
10 #include <osgViewer/Viewer>
11 #include <osgViewer/ViewerEventHandlers>
13 #include <simgear/compiler.h>
19 #include <Scenery/scenery.hxx>
21 #include "globals.hxx"
22 #include "renderer.hxx"
23 #include "fg_props.hxx"
25 // We need to flush all pending mouse move events past a mouse warp to avoid
26 // a race condition ending in warping twice and having huge increments for the
28 // I am not aware of such a flush function in glut. So we emulate that by
29 // ignoring mouse move events between a warp mouse and the next frame.
30 static bool mouseWarped = false;
33 // Native glut callbacks.
34 // These translate the glut event model into osgGA events
37 static osg::ref_ptr<osgViewer::Viewer> viewer;
38 static osg::ref_ptr<osg::Camera> mainCamera;
39 static osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw;
41 static int GlutModifiers = 0;
42 static unsigned int getOSGModifiers(int modifiers);
44 static void callKeyHandler(int k, int mods, int x, int y)
49 case 0x1b: key = osgGA::GUIEventAdapter::KEY_Escape; break;
50 case '\n': key = osgGA::GUIEventAdapter::KEY_Return; break;
51 case '\b': key = osgGA::GUIEventAdapter::KEY_BackSpace; break;
52 case 0x7f: key = osgGA::GUIEventAdapter::KEY_Delete; break;
53 case '\t': key = osgGA::GUIEventAdapter::KEY_Tab; break;
54 case PU_KEY_LEFT: key = osgGA::GUIEventAdapter::KEY_Left; break;
55 case PU_KEY_UP: key = osgGA::GUIEventAdapter::KEY_Up; break;
56 case PU_KEY_RIGHT: key = osgGA::GUIEventAdapter::KEY_Right; break;
57 case PU_KEY_DOWN: key = osgGA::GUIEventAdapter::KEY_Down; break;
58 case PU_KEY_PAGE_UP: key = osgGA::GUIEventAdapter::KEY_Page_Up; break;
59 case PU_KEY_PAGE_DOWN: key = osgGA::GUIEventAdapter::KEY_Page_Down; break;
60 case PU_KEY_HOME: key = osgGA::GUIEventAdapter::KEY_Home; break;
61 case PU_KEY_END: key = osgGA::GUIEventAdapter::KEY_End; break;
62 case PU_KEY_INSERT: key = osgGA::GUIEventAdapter::KEY_Insert; break;
63 case PU_KEY_F1: key = osgGA::GUIEventAdapter::KEY_F1; break;
64 case PU_KEY_F2: key = osgGA::GUIEventAdapter::KEY_F2; break;
65 case PU_KEY_F3: key = osgGA::GUIEventAdapter::KEY_F3; break;
66 case PU_KEY_F4: key = osgGA::GUIEventAdapter::KEY_F4; break;
67 case PU_KEY_F5: key = osgGA::GUIEventAdapter::KEY_F5; break;
68 case PU_KEY_F6: key = osgGA::GUIEventAdapter::KEY_F6; break;
69 case PU_KEY_F7: key = osgGA::GUIEventAdapter::KEY_F7; break;
70 case PU_KEY_F8: key = osgGA::GUIEventAdapter::KEY_F8; break;
71 case PU_KEY_F9: key = osgGA::GUIEventAdapter::KEY_F9; break;
72 case PU_KEY_F10: key = osgGA::GUIEventAdapter::KEY_F10; break;
73 case PU_KEY_F11: key = osgGA::GUIEventAdapter::KEY_F11; break;
74 case PU_KEY_F12: key = osgGA::GUIEventAdapter::KEY_F12; break;
75 default: key = k; break;
77 unsigned int osgModifiers = getOSGModifiers(mods);
78 osgGA::EventQueue& queue = *gw->getEventQueue();
79 queue.getCurrentEventState()->setModKeyMask(osgModifiers);
80 if (mods & KEYMOD_RELEASED)
81 queue.keyRelease((osgGA::GUIEventAdapter::KeySymbol)key);
83 queue.keyPress((osgGA::GUIEventAdapter::KeySymbol)key);
86 static void GLUTmotion (int x, int y)
88 if (mouseWarped || !gw.valid())
90 gw->getEventQueue()->mouseMotion(x, y);
93 static void GLUTmouse (int button, int updown, int x, int y)
95 GlutModifiers = glutGetModifiers();
98 gw->getEventQueue()->mouseButtonPress(x, y, button+1);
100 gw->getEventQueue()->mouseButtonRelease(x, y, button+1);
104 static void GLUTspecialkeyup(int k, int x, int y)
106 GlutModifiers = glutGetModifiers();
107 callKeyHandler(256 + k, fgGetKeyModifiers() | KEYMOD_RELEASED, x, y);
110 static void GLUTspecialkey(int k, int x, int y)
112 GlutModifiers = glutGetModifiers();
113 callKeyHandler(256 + k, fgGetKeyModifiers(), x, y);
116 static unsigned char release_keys[256];
118 static void GLUTkeyup(unsigned char k, int x, int y)
120 GlutModifiers = glutGetModifiers();
121 callKeyHandler(release_keys[k], fgGetKeyModifiers() | KEYMOD_RELEASED, x, y);
124 static void GLUTkey(unsigned char k, int x, int y)
126 GlutModifiers = glutGetModifiers();
128 if (k >= 1 && k <= 26) {
129 release_keys[k + '@'] = k;
130 release_keys[k + '`'] = k;
131 } else if (k >= 'A' && k <= 'Z') {
132 release_keys[k - '@'] = k;
133 release_keys[tolower(k)] = k;
134 } else if (k >= 'a' && k <= 'z') {
135 release_keys[k - '`'] = k;
136 release_keys[toupper(k)] = k;
138 callKeyHandler(k, fgGetKeyModifiers(), x, y);
141 static void GLUTdraw()
149 static void GLUTreshape(int w, int h)
151 // update the window dimensions, in case the window has been resized.
152 gw->resized(gw->getTraits()->x, gw->getTraits()->y, w, h);
153 gw->getEventQueue()->windowResize(gw->getTraits()->x, gw->getTraits()->y,
158 // fg_os API definition
161 void fgOSInit(int* argc, char** argv)
163 glutInit(argc, argv);
166 void fgOSFullScreen()
176 void fgOSExit(int code)
181 static int CurrentCursor = MOUSE_CURSOR_POINTER;
183 int fgGetMouseCursor()
185 return CurrentCursor;
188 void fgSetMouseCursor(int cursor)
190 CurrentCursor = cursor;
191 if (cursor == MOUSE_CURSOR_NONE) cursor = GLUT_CURSOR_NONE;
192 else if(cursor == MOUSE_CURSOR_POINTER) cursor = GLUT_CURSOR_INHERIT;
193 else if(cursor == MOUSE_CURSOR_WAIT) cursor = GLUT_CURSOR_WAIT;
194 else if(cursor == MOUSE_CURSOR_CROSSHAIR) cursor = GLUT_CURSOR_CROSSHAIR;
195 else if(cursor == MOUSE_CURSOR_LEFTRIGHT) cursor = GLUT_CURSOR_LEFT_RIGHT;
196 // Otherwise, pass it through unchanged...
197 glutSetCursor(cursor);
200 void fgWarpMouse(int x, int y)
203 glutWarpPointer(x, y);
206 int fgGetKeyModifiers()
209 if(GlutModifiers & GLUT_ACTIVE_SHIFT) result |= KEYMOD_SHIFT;
210 if(GlutModifiers & GLUT_ACTIVE_CTRL) result |= KEYMOD_CTRL;
211 if(GlutModifiers & GLUT_ACTIVE_ALT) result |= KEYMOD_ALT;
215 static unsigned int getOSGModifiers(int glutModifiers)
217 unsigned int result = 0;
218 if (glutModifiers & GLUT_ACTIVE_SHIFT)
219 result |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
220 if (glutModifiers & GLUT_ACTIVE_CTRL)
221 result |= osgGA::GUIEventAdapter::MODKEY_CTRL;
222 if(glutModifiers & GLUT_ACTIVE_ALT)
223 result |= osgGA::GUIEventAdapter::MODKEY_ALT;
227 void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
228 bool stencil, bool fullscreen)
230 int mode = GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE;
231 if(alpha) mode |= GLUT_ALPHA;
232 if(stencil && bpp > 16) mode |= GLUT_STENCIL;
234 glutInitDisplayMode(mode);
235 glutInitWindowSize(w, h);
236 if(!fgGetBool("/sim/startup/game-mode")) {
237 glutCreateWindow("FlightGear");
239 char game_mode_str[20];
240 SGPropertyNode *p = fgGetNode("/sim/frame-rate-throttle-hz", false);
242 int hz = p->getIntValue();
243 snprintf(game_mode_str, 20, "%dx%d:%d@%d", w, h, bpp, hz);
245 snprintf(game_mode_str, 20, "%dx%d:%d", w, h, bpp);
247 glutGameModeString( game_mode_str );
251 // Register these here. Calling them before the window is open
253 glutMotionFunc(GLUTmotion);
254 glutPassiveMotionFunc(GLUTmotion);
255 glutMouseFunc(GLUTmouse);
256 glutSpecialUpFunc(GLUTspecialkeyup);
257 glutSpecialFunc(GLUTspecialkey);
258 glutKeyboardUpFunc(GLUTkeyup);
259 glutKeyboardFunc(GLUTkey);
260 glutDisplayFunc(GLUTdraw);
261 glutReshapeFunc(GLUTreshape);
265 viewer = new osgViewer::Viewer;
266 gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, realw, realh);
267 // now the main camera ...
268 //osg::ref_ptr<osg::Camera> camera = new osg::Camera;
269 osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
271 osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
272 // If a viewport isn't set on the camera, then it's hard to dig it
273 // out of the SceneView objects in the viewer, and the coordinates
274 // of mouse events are somewhat bizzare.
275 camera->setViewport(new osg::Viewport(0, 0, realw, realh));
276 camera->setProjectionResizePolicy(rsp);
277 //viewer->addSlave(camera.get());
278 globals->get_renderer()->getManipulator()->setUseEventModifiers(true);
279 viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
280 // Let FG handle the escape key with a confirmation
281 viewer->setKeyEventSetsDone(0);
282 osgViewer::StatsHandler* statsHandler = new osgViewer::StatsHandler;
283 statsHandler->setKeyEventTogglesOnScreenStats('*');
284 statsHandler->setKeyEventPrintsOutStats(0);
285 viewer->addEventHandler(statsHandler);
286 // The viewer won't start without some root.
287 viewer->setSceneData(new osg::Group);
288 globals->get_renderer()->setViewer(viewer.get());
291 // Noop; the graphics context is always current
296 bool fgOSIsMainCamera(const osg::Camera*)
301 bool fgOSIsMainContext(const osg::GraphicsContext*)