]> git.mxchange.org Git - flightgear.git/blob - src/Main/fg_os.cxx
remove redundant --airport-id option (OK'ed by Curt, no longer used by fgrun)
[flightgear.git] / src / Main / fg_os.cxx
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
3                            // redefine it
4 #endif
5
6 #ifdef HAVE_CONFIG_H
7 #  include <config.h>
8 #endif
9
10 #include <osgViewer/Viewer>
11 #include <osgViewer/ViewerEventHandlers>
12
13 #include <simgear/compiler.h>
14
15 #include SG_GLUT_H
16
17 #include <plib/pu.h>
18
19 #include <Scenery/scenery.hxx>
20 #include "fg_os.hxx"
21 #include "globals.hxx"
22 #include "renderer.hxx"
23 #include "fg_props.hxx"
24
25 //
26 // Native glut callbacks.
27 // These translate the glut event model into osgGA events
28 //
29
30 static osg::ref_ptr<osgViewer::Viewer> viewer;
31 static osg::ref_ptr<osg::Camera> mainCamera;
32 static osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw;
33
34 static int GlutModifiers = 0;
35 static unsigned int getOSGModifiers(int modifiers);
36
37 static void callKeyHandler(int k, int mods, int x, int y)
38 {
39
40     int key = 0;
41     switch (k) {
42     case 0x1b:            key = osgGA::GUIEventAdapter::KEY_Escape;  break;
43     case '\n':            key = osgGA::GUIEventAdapter::KEY_Return; break;
44     case '\b':            key = osgGA::GUIEventAdapter::KEY_BackSpace; break;
45     case 0x7f:            key = osgGA::GUIEventAdapter::KEY_Delete; break;
46     case '\t':            key = osgGA::GUIEventAdapter::KEY_Tab; break;
47     case PU_KEY_LEFT:     key = osgGA::GUIEventAdapter::KEY_Left;      break;
48     case PU_KEY_UP:       key = osgGA::GUIEventAdapter::KEY_Up;        break;
49     case PU_KEY_RIGHT:    key = osgGA::GUIEventAdapter::KEY_Right;     break;
50     case PU_KEY_DOWN:     key = osgGA::GUIEventAdapter::KEY_Down;      break;
51     case PU_KEY_PAGE_UP:   key = osgGA::GUIEventAdapter::KEY_Page_Up;   break;
52     case PU_KEY_PAGE_DOWN: key = osgGA::GUIEventAdapter::KEY_Page_Down; break;
53     case PU_KEY_HOME:     key = osgGA::GUIEventAdapter::KEY_Home;      break;
54     case PU_KEY_END:      key = osgGA::GUIEventAdapter::KEY_End;       break;
55     case PU_KEY_INSERT:   key = osgGA::GUIEventAdapter::KEY_Insert;    break;
56     case PU_KEY_F1:       key = osgGA::GUIEventAdapter::KEY_F1;        break;
57     case PU_KEY_F2:       key = osgGA::GUIEventAdapter::KEY_F2;        break;
58     case PU_KEY_F3:       key = osgGA::GUIEventAdapter::KEY_F3;        break;
59     case PU_KEY_F4:       key = osgGA::GUIEventAdapter::KEY_F4;        break;
60     case PU_KEY_F5:       key = osgGA::GUIEventAdapter::KEY_F5;        break;
61     case PU_KEY_F6:       key = osgGA::GUIEventAdapter::KEY_F6;        break;
62     case PU_KEY_F7:       key = osgGA::GUIEventAdapter::KEY_F7;        break;
63     case PU_KEY_F8:       key = osgGA::GUIEventAdapter::KEY_F8;        break;
64     case PU_KEY_F9:       key = osgGA::GUIEventAdapter::KEY_F9;        break;
65     case PU_KEY_F10:      key = osgGA::GUIEventAdapter::KEY_F10;       break;
66     case PU_KEY_F11:      key = osgGA::GUIEventAdapter::KEY_F11;       break;
67     case PU_KEY_F12:      key = osgGA::GUIEventAdapter::KEY_F12;       break;
68     default: key = k; break;
69     }
70     unsigned int osgModifiers = getOSGModifiers(mods);
71     osgGA::EventQueue& queue = *gw->getEventQueue();
72     queue.getCurrentEventState()->setModKeyMask(osgModifiers);
73     if (mods & KEYMOD_RELEASED)
74         queue.keyRelease((osgGA::GUIEventAdapter::KeySymbol)key);
75     else
76         queue.keyPress((osgGA::GUIEventAdapter::KeySymbol)key);
77 }
78
79 static void GLUTmotion (int x, int y)
80 {
81     if (!gw.valid())
82         return;
83     gw->getEventQueue()->mouseMotion(x, y);
84 }
85
86 static void GLUTmouse (int button, int updown, int x, int y)
87 {
88     GlutModifiers = glutGetModifiers();
89     if (gw.valid()) {
90         if (updown == 0)
91             gw->getEventQueue()->mouseButtonPress(x, y, button+1);
92         else
93             gw->getEventQueue()->mouseButtonRelease(x, y, button+1);
94     }
95 }
96
97 static void GLUTspecialkeyup(int k, int x, int y)
98 {
99     GlutModifiers = glutGetModifiers();
100     callKeyHandler(256 + k, fgGetKeyModifiers() | KEYMOD_RELEASED, x, y);
101 }
102
103 static void GLUTspecialkey(int k, int x, int y)
104 {
105     GlutModifiers = glutGetModifiers();
106     callKeyHandler(256 + k, fgGetKeyModifiers(), x, y);
107 }
108
109 static unsigned char release_keys[256];
110
111 static void GLUTkeyup(unsigned char k, int x, int y)
112 {
113     GlutModifiers = glutGetModifiers();
114     callKeyHandler(release_keys[k], fgGetKeyModifiers() | KEYMOD_RELEASED, x, y);
115 }
116
117 static void GLUTkey(unsigned char k, int x, int y)
118 {
119     GlutModifiers = glutGetModifiers();
120     release_keys[k] = k;
121     if (k >= 1 && k <= 26) {
122         release_keys[k + '@'] = k;
123         release_keys[k + '`'] = k;
124     } else if (k >= 'A' && k <= 'Z') {
125         release_keys[k - '@'] = k;
126         release_keys[tolower(k)] = k;
127     } else if (k >= 'a' && k <= 'z') {
128         release_keys[k - '`'] = k;
129         release_keys[toupper(k)] = k;
130     }
131     callKeyHandler(k, fgGetKeyModifiers(), x, y);
132 }
133
134 static void GLUTdraw()
135 {
136     viewer->frame();
137     glutSwapBuffers();
138     glutPostRedisplay();
139 }
140
141 static void GLUTreshape(int w, int h)
142 {
143     // update the window dimensions, in case the window has been resized.
144     gw->resized(gw->getTraits()->x, gw->getTraits()->y, w, h);
145     gw->getEventQueue()->windowResize(gw->getTraits()->x, gw->getTraits()->y,
146                                       w, h);
147 }
148
149 //
150 // fg_os API definition
151 //
152
153 void fgOSInit(int* argc, char** argv)
154 {
155     glutInit(argc, argv);
156 }
157
158 void fgOSFullScreen()
159 {
160     glutFullScreen();
161 }
162
163 void fgOSMainLoop()
164 {
165     glutMainLoop();
166 }
167
168 void fgOSExit(int code)
169 {
170     exit(code);
171 }
172
173 static int CurrentCursor = MOUSE_CURSOR_POINTER;
174
175 int fgGetMouseCursor()
176 {
177     return CurrentCursor;
178 }
179
180 void fgSetMouseCursor(int cursor)
181 {
182     CurrentCursor = cursor;
183     if     (cursor == MOUSE_CURSOR_NONE)      cursor = GLUT_CURSOR_NONE;
184     else if(cursor == MOUSE_CURSOR_POINTER)   cursor = GLUT_CURSOR_INHERIT;
185     else if(cursor == MOUSE_CURSOR_WAIT)      cursor = GLUT_CURSOR_WAIT;
186     else if(cursor == MOUSE_CURSOR_CROSSHAIR) cursor = GLUT_CURSOR_CROSSHAIR;
187     else if(cursor == MOUSE_CURSOR_LEFTRIGHT) cursor = GLUT_CURSOR_LEFT_RIGHT;
188     // Otherwise, pass it through unchanged...
189     glutSetCursor(cursor);
190 }
191
192 void fgWarpMouse(int x, int y)
193 {
194     globals->get_renderer()->getManipulator()->setMouseWarped();
195     glutWarpPointer(x, y);
196 }
197
198 int fgGetKeyModifiers()
199 {
200     int result = 0;
201     if(GlutModifiers & GLUT_ACTIVE_SHIFT) result |= KEYMOD_SHIFT;
202     if(GlutModifiers & GLUT_ACTIVE_CTRL)  result |= KEYMOD_CTRL;
203     if(GlutModifiers & GLUT_ACTIVE_ALT)   result |= KEYMOD_ALT;
204     return result;
205 }
206
207 static unsigned int getOSGModifiers(int glutModifiers)
208 {
209     unsigned int result = 0;
210     if (glutModifiers & GLUT_ACTIVE_SHIFT)
211         result |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
212     if (glutModifiers & GLUT_ACTIVE_CTRL)
213         result |= osgGA::GUIEventAdapter::MODKEY_CTRL;
214     if(glutModifiers & GLUT_ACTIVE_ALT)
215         result |= osgGA::GUIEventAdapter::MODKEY_ALT;
216     return result;
217 }
218
219 void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
220                     bool stencil, bool fullscreen)
221 {
222     int mode = GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE;
223     if(alpha) mode |= GLUT_ALPHA;
224     if(stencil && bpp > 16) mode |= GLUT_STENCIL;
225
226     glutInitDisplayMode(mode);
227     glutInitWindowSize(w, h);
228     if(!fgGetBool("/sim/startup/game-mode")) {
229         glutCreateWindow("FlightGear");
230     } else {
231         char game_mode_str[20];
232         SGPropertyNode *p = fgGetNode("/sim/frame-rate-throttle-hz", false);
233         if (p) {
234             int hz = p->getIntValue();
235             snprintf(game_mode_str, 20, "%dx%d:%d@%d", w, h, bpp, hz);
236         } else {
237             snprintf(game_mode_str, 20, "%dx%d:%d", w, h, bpp);
238         }
239         glutGameModeString( game_mode_str );
240         glutEnterGameMode();
241     }
242
243     // Register these here.  Calling them before the window is open
244     // crashes.
245     glutMotionFunc(GLUTmotion);
246     glutPassiveMotionFunc(GLUTmotion);
247     glutMouseFunc(GLUTmouse);
248     glutSpecialUpFunc(GLUTspecialkeyup);
249     glutSpecialFunc(GLUTspecialkey);
250     glutKeyboardUpFunc(GLUTkeyup);
251     glutKeyboardFunc(GLUTkey);
252     glutDisplayFunc(GLUTdraw);
253     glutReshapeFunc(GLUTreshape);
254     // XXX
255     int realw = w;
256     int realh = h;
257     viewer = new osgViewer::Viewer;
258     gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, realw, realh);
259     viewer->setDatabasePager(FGScenery::getPagerSingleton());
260     // now the main camera ...
261     //osg::ref_ptr<osg::Camera> camera = new osg::Camera;
262     osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
263     mainCamera = camera;
264     osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
265     // If a viewport isn't set on the camera, then it's hard to dig it
266     // out of the SceneView objects in the viewer, and the coordinates
267     // of mouse events are somewhat bizzare.
268     camera->setViewport(new osg::Viewport(0, 0, realw, realh));
269     camera->setProjectionResizePolicy(rsp);
270     //viewer->addSlave(camera.get());
271     globals->get_renderer()->getManipulator()->setUseEventModifiers(true);
272     viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
273     // Let FG handle the escape key with a confirmation
274     viewer->setKeyEventSetsDone(0);
275     osgViewer::StatsHandler* statsHandler = new osgViewer::StatsHandler;
276     statsHandler->setKeyEventTogglesOnScreenStats('*');
277     statsHandler->setKeyEventPrintsOutStats(0);
278     viewer->addEventHandler(statsHandler);
279     // The viewer won't start without some root.
280     viewer->setSceneData(new osg::Group);
281     globals->get_renderer()->setViewer(viewer.get());
282 }
283
284 // Noop; the graphics context is always current
285 void fgMakeCurrent()
286 {
287 }
288
289 bool fgOSIsMainCamera(const osg::Camera*)
290 {
291   return true;
292 }
293
294 bool fgOSIsMainContext(const osg::GraphicsContext*)
295 {
296   return true;
297 }