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