]> git.mxchange.org Git - flightgear.git/blob - src/Main/fg_os.cxx
Add the alpha test back in so the instruments won't disappear after changing the...
[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 <osg/Matrix>
11 #include <osgViewer/Viewer>
12 #include <osgViewer/ViewerEventHandlers>
13
14 #include <simgear/compiler.h>
15
16 #if defined( __APPLE__)
17 # include <GLUT/glut.h>
18 #else
19 # include <GL/glut.h>
20 #endif
21 #include <plib/pu.h>
22
23 #include <Scenery/scenery.hxx>
24 #include "fg_os.hxx"
25 #include "globals.hxx"
26 #include "renderer.hxx"
27 #include "fg_props.hxx"
28 #include "WindowSystemAdapter.hxx"
29 #include "CameraGroup.hxx"
30
31 using namespace flightgear;
32
33 //
34 // Native glut callbacks.
35 // These translate the glut event model into osgGA events
36 //
37
38 static osg::ref_ptr<osgViewer::Viewer> viewer;
39 static osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw;
40
41 static int GlutModifiers = 0;
42 static unsigned int getOSGModifiers(int modifiers);
43
44 static void callKeyHandler(int k, int mods, int x, int y)
45 {
46
47     int key = 0;
48     switch (k) {
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;
76     }
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);
82     else
83         queue.keyPress((osgGA::GUIEventAdapter::KeySymbol)key);
84 }
85
86 static void GLUTmotion (int x, int y)
87 {
88     if (!gw.valid())
89         return;
90     gw->getEventQueue()->mouseMotion(x, y);
91 }
92
93 static void GLUTmouse (int button, int updown, int x, int y)
94 {
95     GlutModifiers = glutGetModifiers();
96     if (gw.valid()) {
97         if (updown == 0)
98             gw->getEventQueue()->mouseButtonPress(x, y, button+1);
99         else
100             gw->getEventQueue()->mouseButtonRelease(x, y, button+1);
101     }
102 }
103
104 static void GLUTspecialkeyup(int k, int x, int y)
105 {
106     GlutModifiers = glutGetModifiers();
107     callKeyHandler(256 + k, fgGetKeyModifiers() | KEYMOD_RELEASED, x, y);
108 }
109
110 static void GLUTspecialkey(int k, int x, int y)
111 {
112     GlutModifiers = glutGetModifiers();
113     callKeyHandler(256 + k, fgGetKeyModifiers(), x, y);
114 }
115
116 static unsigned char release_keys[256];
117
118 static void GLUTkeyup(unsigned char k, int x, int y)
119 {
120     GlutModifiers = glutGetModifiers();
121     callKeyHandler(release_keys[k], fgGetKeyModifiers() | KEYMOD_RELEASED, x, y);
122 }
123
124 static void GLUTkey(unsigned char k, int x, int y)
125 {
126     GlutModifiers = glutGetModifiers();
127     release_keys[k] = k;
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;
137     }
138     callKeyHandler(k, fgGetKeyModifiers(), x, y);
139 }
140
141 static void GLUTdraw()
142 {
143     viewer->frame();
144     glutSwapBuffers();
145     glutPostRedisplay();
146 }
147
148 static void GLUTreshape(int w, int h)
149 {
150     // update the window dimensions, in case the window has been resized.
151     gw->resized(gw->getTraits()->x, gw->getTraits()->y, w, h);
152     gw->getEventQueue()->windowResize(gw->getTraits()->x, gw->getTraits()->y,
153                                       w, h);
154 }
155
156 //
157 // fg_os API definition
158 //
159
160 void fgOSInit(int* argc, char** argv)
161 {
162     glutInit(argc, argv);
163     WindowSystemAdapter::setWSA(new WindowSystemAdapter);
164 }
165
166 void fgOSFullScreen()
167 {
168     glutFullScreen();
169 }
170
171 void fgOSMainLoop()
172 {
173     glutMainLoop();
174 }
175
176 void fgOSExit(int code)
177 {
178     exit(code);
179 }
180
181 static int CurrentCursor = MOUSE_CURSOR_POINTER;
182
183 int fgGetMouseCursor()
184 {
185     return CurrentCursor;
186 }
187
188 void fgSetMouseCursor(int cursor)
189 {
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);
198 }
199
200 void fgWarpMouse(int x, int y)
201 {
202     globals->get_renderer()->getManipulator()->setMouseWarped();
203     glutWarpPointer(x, y);
204 }
205
206 int fgGetKeyModifiers()
207 {
208     int result = 0;
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;
212     return result;
213 }
214
215 static unsigned int getOSGModifiers(int glutModifiers)
216 {
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;
224     return result;
225 }
226
227 void fgOSOpenWindow(bool stencil)
228 {
229     int w = fgGetInt("/sim/startup/xsize");
230     int h = fgGetInt("/sim/startup/ysize");
231     int bpp = fgGetInt("/sim/rendering/bits-per-pixel");
232     bool alpha = fgGetBool("/sim/rendering/clouds3d-enable");
233     bool fullscreen = fgGetBool("/sim/startup/fullscreen");
234     WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
235     int mode = GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE;
236
237     if(alpha) mode |= GLUT_ALPHA;
238     if(stencil && bpp > 16) mode |= GLUT_STENCIL;
239
240     glutInitDisplayMode(mode);
241     glutInitWindowSize(w, h);
242     if(!fgGetBool("/sim/startup/game-mode")) {
243         glutCreateWindow("FlightGear");
244     } else {
245         char game_mode_str[20];
246         SGPropertyNode *p = fgGetNode("/sim/frame-rate-throttle-hz", false);
247         if (p) {
248             int hz = p->getIntValue();
249             snprintf(game_mode_str, 20, "%dx%d:%d@%d", w, h, bpp, hz);
250         } else {
251             snprintf(game_mode_str, 20, "%dx%d:%d", w, h, bpp);
252         }
253         glutGameModeString( game_mode_str );
254         glutEnterGameMode();
255     }
256
257     // Register these here.  Calling them before the window is open
258     // crashes.
259     glutMotionFunc(GLUTmotion);
260     glutPassiveMotionFunc(GLUTmotion);
261     glutMouseFunc(GLUTmouse);
262     glutSpecialUpFunc(GLUTspecialkeyup);
263     glutSpecialFunc(GLUTspecialkey);
264     glutKeyboardUpFunc(GLUTkeyup);
265     glutKeyboardFunc(GLUTkey);
266     glutDisplayFunc(GLUTdraw);
267     glutReshapeFunc(GLUTreshape);
268     // XXX
269     int realw = w;
270     int realh = h;
271     viewer = new osgViewer::Viewer;
272     gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, realw, realh);
273     GraphicsWindow* window = wsa->registerWindow(gw.get(), string("main"));
274     window->flags |= GraphicsWindow::GUI;
275     viewer->setDatabasePager(FGScenery::getPagerSingleton());
276     // now the main camera ...
277     osg::Camera* camera = new osg::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     CameraGroup* cgroup = new CameraGroup(viewer.get());
284     cgroup->addCamera(CameraGroup::DO_INTERSECTION_TEST, camera,
285                       osg::Matrixd::identity(), osg::Matrixd::identity(),
286                       true);
287     cgroup->buildGUICamera(0, window);
288     CameraGroup::setDefault(cgroup);
289     viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
290     // Let FG handle the escape key with a confirmation
291     viewer->setKeyEventSetsDone(0);
292     osgViewer::StatsHandler* statsHandler = new osgViewer::StatsHandler;
293     statsHandler->setKeyEventTogglesOnScreenStats('*');
294     statsHandler->setKeyEventPrintsOutStats(0);
295     viewer->addEventHandler(statsHandler);
296     // The viewer won't start without some root.
297     viewer->setSceneData(new osg::Group);
298     globals->get_renderer()->setViewer(viewer.get());
299 }