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