1 /***************************************************************************
2                           kdeglwidget.cpp  -  description
3                              -------------------
4     begin                : Tue Jul 16 2002
5     copyright            : (C) 2002 by Christophe Teyssier
6     email                : chris@teyssier.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "kdeglwidget.h"
19 #include <kaccel.h>
20 
21 #include <unistd.h>
22 #include <celengine/gl.h>
23 //#include <celengine/glext.h>
24 #include <celengine/celestia.h>
25 #include <celengine/starbrowser.h>
26 #include <kmainwindow.h>
27 #include <kconfig.h>
28 #include <qcursor.h>
29 #include <qpaintdevicemetrics.h>
30 
31 #ifndef DEBUG
32 #  define G_DISABLE_ASSERT
33 #endif
34 
35 #include "celmath/vecmath.h"
36 #include "celmath/quaternion.h"
37 #include "celmath/mathlib.h"
38 #include "celengine/astro.h"
39 #include "celutil/util.h"
40 #include "celutil/filetype.h"
41 #include "celutil/debug.h"
42 #include "imagecapture.h"
43 #include "celestiacore.h"
44 #include "celengine/simulation.h"
45 #include "celengine/glcontext.h"
46 
47 #include "kdeapp.h"
48 
49 #include <math.h>
50 #include <vector>
51 
KdeGlWidget(QWidget * parent,const char * name,CelestiaCore * core)52 KdeGlWidget::KdeGlWidget(  QWidget* parent, const char* name, CelestiaCore* core)
53     : QGLWidget( parent, name )
54 {
55 
56 
57     actionColl = ((KdeApp*)parent)->actionCollection();
58 
59     setFocusPolicy(QWidget::ClickFocus);
60 
61     appCore = core;
62     appRenderer=appCore->getRenderer();
63     appSim = appCore->getSimulation();
64 
65     setCursor(QCursor(Qt::CrossCursor));
66     currentCursor = CelestiaCore::CrossCursor;
67     setMouseTracking(true);
68 
69     appCore->setCursorHandler(this);
70 
71     lastX = lastY = 0;
72 }
73 
74 
75 /*!
76   Release allocated resources
77 */
78 
~KdeGlWidget()79 KdeGlWidget::~KdeGlWidget()
80 {
81 }
82 
83 
84 /*!
85   Paint the box. The actual openGL commands for drawing the box are
86   performed here.
87 */
88 
paintGL()89 void KdeGlWidget::paintGL()
90 {
91     appCore->draw();
92 }
93 
94 
95 /*!
96   Set up the OpenGL rendering state, and define display list
97 */
98 
initializeGL()99 void KdeGlWidget::initializeGL()
100 {
101     if (!appCore->initRenderer())
102     {
103 //        cerr << "Failed to initialize renderer.\n";
104         exit(1);
105     }
106 
107     time_t curtime=time(NULL);
108     appCore->start(astro::UTCtoTDB((double) curtime / 86400.0 + (double) astro::Date(1970, 1, 1)));
109 #if defined(__FreeBSD__)
110     /* FreeBSD does not export raw `timezone' and `daylight' values */
111     struct tm *temptime = localtime(&curtime);
112     appCore->setTimeZoneBias(temptime->tm_gmtoff);
113     appCore->setTimeZoneName(temptime->tm_zone);
114 #else
115     localtime(&curtime); /* Only doing this to set timezone as a side effect*/
116     appCore->setTimeZoneBias(-timezone+3600*daylight);
117     appCore->setTimeZoneName(tzname[daylight?0:1]);
118 #endif
119     appCore->tick();
120 
121     KGlobal::config()->setGroup("Preferences");
122     if (KGlobal::config()->hasKey("RendererFlags"))
123         appRenderer->setRenderFlags(KGlobal::config()->readNumEntry("RendererFlags"));
124     if (KGlobal::config()->hasKey("OrbitMask"))
125         appRenderer->setOrbitMask(KGlobal::config()->readNumEntry("OrbitMask"));
126     if (KGlobal::config()->hasKey("LabelMode"))
127         appRenderer->setLabelMode(KGlobal::config()->readNumEntry("LabelMode"));
128     if (KGlobal::config()->hasKey("AmbientLightLevel"))
129         appRenderer->setAmbientLightLevel(KGlobal::config()->readDoubleNumEntry("AmbientLightLevel"));
130     if (KGlobal::config()->hasKey("FaintestVisible"))
131         appCore->setFaintest(KGlobal::config()->readDoubleNumEntry("FaintestVisible"));
132     if (KGlobal::config()->hasKey("HudDetail"))
133         appCore->setHudDetail(KGlobal::config()->readNumEntry("HudDetail"));
134     if (KGlobal::config()->hasKey("TimeZoneBias"))
135         appCore->setTimeZoneBias(KGlobal::config()->readNumEntry("TimeZoneBias"));
136     if (KGlobal::config()->hasKey("MinFeatureSize"))
137         appRenderer->setMinimumFeatureSize(KGlobal::config()->readNumEntry("MinFeatureSize"));
138 
139 
140     if (!appCore->getRenderer()->getGLContext()->renderPathSupported(GLContext::GLPath_Basic))
141         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathBasic")))->setEnabled(false);
142     if (!appCore->getRenderer()->getGLContext()->renderPathSupported(GLContext::GLPath_Multitexture))
143         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathMultitexture")))->setEnabled(false);
144     if (!appCore->getRenderer()->getGLContext()->renderPathSupported(GLContext::GLPath_NvCombiner))
145         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathNvCombiner")))->setEnabled(false);
146     if (!appCore->getRenderer()->getGLContext()->renderPathSupported(GLContext::GLPath_DOT3_ARBVP))
147         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathDOT3ARBVP")))->setEnabled(false);
148     if (!appCore->getRenderer()->getGLContext()->renderPathSupported(GLContext::GLPath_NvCombiner_NvVP))
149         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathNvCombinerNvVP")))->setEnabled(false);
150     if (!appCore->getRenderer()->getGLContext()->renderPathSupported(GLContext::GLPath_NvCombiner_ARBVP))
151         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathNvCombinerARBVP")))->setEnabled(false);
152     if (!appCore->getRenderer()->getGLContext()->renderPathSupported(GLContext::GLPath_ARBFP_ARBVP))
153         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathARBFPARBVP")))->setEnabled(false);
154     if (!appCore->getRenderer()->getGLContext()->renderPathSupported(GLContext::GLPath_NV30))
155         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathNV30")))->setEnabled(false);
156     if (!appCore->getRenderer()->getGLContext()->renderPathSupported(GLContext::GLPath_GLSL))
157         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathGLSL")))->setEnabled(false);
158 
159     if (KGlobal::config()->hasKey("RenderPath")) {
160        GLContext::GLRenderPath path = (GLContext::GLRenderPath)KGlobal::config()->readNumEntry("RenderPath");
161        if (appCore->getRenderer()->getGLContext()->renderPathSupported(path)) {
162             appCore->getRenderer()->getGLContext()->setRenderPath(path);
163        }
164     }
165 
166     switch (appCore->getRenderer()->getGLContext()->getRenderPath()) {
167     case GLContext::GLPath_Basic:
168         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathBasic")))->setChecked(true);
169         break;
170     case GLContext::GLPath_Multitexture:
171         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathMultitexture")))->setChecked(true);
172         break;
173     case GLContext::GLPath_NvCombiner:
174         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathNvCombiner")))->setChecked(true);
175         break;
176     case GLContext::GLPath_DOT3_ARBVP:
177         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathDOT3ARBVP")))->setChecked(true);
178         break;
179     case GLContext::GLPath_NvCombiner_NvVP:
180         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathNvCombinerNvVP")))->setChecked(true);
181         break;
182     case GLContext::GLPath_NvCombiner_ARBVP:
183         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathNvCombinerARBVP")))->setChecked(true);
184         break;
185     case GLContext::GLPath_ARBFP_ARBVP:
186         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathARBFPARBVP")))->setChecked(true);
187         break;
188     case GLContext::GLPath_NV30:
189         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathNV30")))->setChecked(true);
190         break;
191     case GLContext::GLPath_GLSL:
192         ((KToggleAction*)(((KdeApp*)parentWidget())->action("renderPathGLSL")))->setChecked(true);
193         break;
194     }
195 
196     KGlobal::config()->setGroup(0);
197 
198     QPaintDeviceMetrics pdm(this);
199     appCore->setScreenDpi(pdm.logicalDpiY());
200 }
201 
resizeGL(int w,int h)202 void KdeGlWidget::resizeGL( int w, int h )
203 {
204     appCore->resize(w, h);
205 }
206 
mouseMoveEvent(QMouseEvent * m)207 void KdeGlWidget::mouseMoveEvent( QMouseEvent* m )
208 {
209     int x = (int) m->x();
210     int y = (int) m->y();
211 
212     int buttons = 0;
213     if (m->state() & LeftButton)
214         buttons |= CelestiaCore::LeftButton;
215     if (m->state() & MidButton)
216         buttons |= CelestiaCore::MiddleButton;
217     if (m->state() & RightButton)
218         buttons |= CelestiaCore::RightButton;
219     if (m->state() & ShiftButton)
220         buttons |= CelestiaCore::ShiftKey;
221     if (m->state() & ControlButton)
222         buttons |= CelestiaCore::ControlKey;
223 
224     if (buttons != 0)
225         appCore->mouseMove(x - lastX, y - lastY, buttons);
226     else
227         appCore->mouseMove(x, y);
228 
229     lastX = x;
230     lastY = y;
231 }
232 
mousePressEvent(QMouseEvent * m)233 void KdeGlWidget::mousePressEvent( QMouseEvent* m )
234 {
235     lastX = (int) m->x();
236     lastY = (int) m->y();
237 
238     if (m->button() == LeftButton)
239         appCore->mouseButtonDown(m->x(), m->y(), CelestiaCore::LeftButton);
240     else if (m->button() == MidButton)
241         appCore->mouseButtonDown(m->x(), m->y(), CelestiaCore::MiddleButton);
242     else if (m->button() == RightButton)
243         appCore->mouseButtonDown(m->x(), m->y(), CelestiaCore::RightButton);
244 
245 }
246 
mouseReleaseEvent(QMouseEvent * m)247 void KdeGlWidget::mouseReleaseEvent( QMouseEvent* m )
248 {
249     lastX = (int) m->x();
250     lastY = (int) m->y();
251     if (m->button() == LeftButton)
252         appCore->mouseButtonUp(m->x(), m->y(), CelestiaCore::LeftButton);
253     else if (m->button() == MidButton)
254         appCore->mouseButtonUp(m->x(), m->y(), CelestiaCore::MiddleButton);
255     else if (m->button() == RightButton)
256         appCore->mouseButtonUp(m->x(), m->y(), CelestiaCore::RightButton);
257 }
258 
wheelEvent(QWheelEvent * w)259 void KdeGlWidget::wheelEvent( QWheelEvent* w )
260 {
261     if (w->delta() > 0 )
262     {
263         appCore->mouseWheel(-1.0f, 0);
264     }
265     else if (w->delta() < 0)
266     {
267         appCore->mouseWheel(1.0f, 0);
268     }
269 }
270 
271 
handleSpecialKey(QKeyEvent * e,bool down)272 bool KdeGlWidget::handleSpecialKey(QKeyEvent* e, bool down)
273 {
274     int k = -1;
275     switch (e->key())
276     {
277     case Key_Up:
278         k = CelestiaCore::Key_Up;
279         break;
280     case Key_Down:
281         k = CelestiaCore::Key_Down;
282         break;
283     case Key_Left:
284         k = CelestiaCore::Key_Left;
285         break;
286     case Key_Right:
287         k = CelestiaCore::Key_Right;
288         break;
289     case Key_Home:
290         k = CelestiaCore::Key_Home;
291         break;
292     case Key_End:
293         k = CelestiaCore::Key_End;
294         break;
295     case Key_F1:
296         k = CelestiaCore::Key_F1;
297         break;
298     case Key_F2:
299         k = CelestiaCore::Key_F2;
300         break;
301     case Key_F3:
302         k = CelestiaCore::Key_F3;
303         break;
304     case Key_F4:
305         k = CelestiaCore::Key_F4;
306         break;
307     case Key_F5:
308         k = CelestiaCore::Key_F5;
309         break;
310     case Key_F6:
311         k = CelestiaCore::Key_F6;
312         break;
313     case Key_F7:
314         k = CelestiaCore::Key_F7;
315         break;
316     case Key_F11:
317         k = CelestiaCore::Key_F11;
318         break;
319     case Key_F12:
320         k = CelestiaCore::Key_F12;
321         break;
322     case Key_PageDown:
323         k = CelestiaCore::Key_PageDown;
324         break;
325     case Key_PageUp:
326         k = CelestiaCore::Key_PageUp;
327         break;
328 /*    case Key_F10:
329         if (down)
330             menuCaptureImage();
331         break;     */
332     case Key_0:
333         if (e->state() & Qt::Keypad)
334             k = CelestiaCore::Key_NumPad0;
335         break;
336     case Key_1:
337         if (e->state() & Qt::Keypad)
338             k = CelestiaCore::Key_NumPad1;
339         break;
340     case Key_2:
341         if (e->state() & Qt::Keypad)
342             k = CelestiaCore::Key_NumPad2;
343         break;
344     case Key_3:
345         if (e->state() & Qt::Keypad)
346             k = CelestiaCore::Key_NumPad3;
347         break;
348     case Key_4:
349         if (e->state() & Qt::Keypad)
350             k = CelestiaCore::Key_NumPad4;
351         break;
352     case Key_5:
353         if (e->state() & Qt::Keypad)
354             k = CelestiaCore::Key_NumPad5;
355         break;
356     case Key_6:
357         if (e->state() & Qt::Keypad)
358             k = CelestiaCore::Key_NumPad6;
359         break;
360     case Key_7:
361         if (e->state() & Qt::Keypad)
362             k = CelestiaCore::Key_NumPad7;
363         break;
364     case Key_8:
365         if (e->state() & Qt::Keypad)
366             k = CelestiaCore::Key_NumPad8;
367         break;
368     case Key_9:
369         if (e->state() & Qt::Keypad)
370             k = CelestiaCore::Key_NumPad9;
371         break;
372     case Key_A:
373         k = 'A';
374         break;
375     case Key_Z:
376         k = 'Z';
377         break;
378     }
379 
380     if (k >= 0)
381     {
382         int buttons = 0;
383         if (e->state() & ShiftButton)
384             buttons |= CelestiaCore::ShiftKey;
385 
386         if (down)
387             appCore->keyDown(k, buttons);
388         else
389             appCore->keyUp(k);
390         return (k < 'A' || k > 'Z');
391     }
392     else
393     {
394         return false;
395     }
396 }
397 
398 
keyPressEvent(QKeyEvent * e)399 void KdeGlWidget::keyPressEvent( QKeyEvent* e )
400 {
401     switch (e->key())
402     {
403     case Key_Escape:
404         appCore->charEntered('\033');
405         break;
406     case Key_BackTab:
407         appCore->charEntered(CelestiaCore::Key_BackTab);
408         break;
409     default:
410         if (!handleSpecialKey(e, true))
411         {
412             if ((e->text() != 0) && (e->text() != ""))
413             {
414                 appCore->charEntered(e->text().utf8().data());
415             }
416         }
417     }
418 }
419 
420 
keyReleaseEvent(QKeyEvent * e)421 void KdeGlWidget::keyReleaseEvent( QKeyEvent* e )
422 {
423     handleSpecialKey(e, false);
424 }
425 
setCursorShape(CelestiaCore::CursorShape shape)426 void KdeGlWidget::setCursorShape(CelestiaCore::CursorShape shape)
427 {
428     int cursor;
429     if (currentCursor != shape)
430     {
431         switch(shape)
432         {
433         case CelestiaCore::ArrowCursor:
434             cursor = Qt::ArrowCursor;
435             break;
436         case CelestiaCore::UpArrowCursor:
437             cursor = Qt::UpArrowCursor;
438             break;
439         case CelestiaCore::CrossCursor:
440             cursor = Qt::CrossCursor;
441             break;
442         case CelestiaCore::InvertedCrossCursor:
443             cursor = Qt::CrossCursor;
444             break;
445         case CelestiaCore::WaitCursor:
446             cursor = Qt::WaitCursor;
447             break;
448         case CelestiaCore::BusyCursor:
449             cursor = Qt::WaitCursor;
450             break;
451         case CelestiaCore::IbeamCursor:
452             cursor = Qt::IbeamCursor;
453             break;
454         case CelestiaCore::SizeVerCursor:
455             cursor = Qt::SizeVerCursor;
456             break;
457         case CelestiaCore::SizeHorCursor:
458             cursor = Qt::SizeHorCursor;
459             break;
460         case CelestiaCore::SizeBDiagCursor:
461             cursor = Qt::SizeBDiagCursor;
462             break;
463         case CelestiaCore::SizeFDiagCursor:
464             cursor = Qt::SizeFDiagCursor;
465             break;
466         case CelestiaCore::SizeAllCursor:
467             cursor = Qt::SizeAllCursor;
468             break;
469         case CelestiaCore::SplitVCursor:
470             cursor = Qt::SplitVCursor;
471             break;
472         case CelestiaCore::SplitHCursor:
473             cursor = Qt::SplitHCursor;
474             break;
475         case CelestiaCore::PointingHandCursor:
476             cursor = Qt::PointingHandCursor;
477             break;
478         case CelestiaCore::ForbiddenCursor:
479             cursor = Qt::ForbiddenCursor;
480             break;
481         case CelestiaCore::WhatsThisCursor:
482             cursor = Qt::WhatsThisCursor;
483             break;
484         default:
485             cursor = Qt::CrossCursor;
486             break;
487         }
488         setCursor(QCursor(cursor));
489         currentCursor = shape;
490     }
491 }
492 
getCursorShape() const493 CelestiaCore::CursorShape KdeGlWidget::getCursorShape() const
494 {
495     return currentCursor;
496 }
497