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