glwidget.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:10k
源码类别:

OpenGL

开发平台:

Visual C++

  1. /*
  2.  *  Celestia GTK+ Front-End
  3.  *  Copyright (C) 2005 Pat Suwalski <pat@suwalski.net>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  $Id: glwidget.cpp,v 1.2 2006-07-24 17:31:24 christey Exp $
  11.  */
  12. #include <gdk/gdkkeysyms.h>
  13. #include <gtk/gtk.h>
  14. #include <gtk/gtkgl.h>
  15. #include <celestia/celestiacore.h>
  16. #include "glwidget.h"
  17. #include "actions.h"
  18. #include "common.h"
  19. /* Declarations: Callbacks */
  20. static gint glarea_idle(AppData* app);
  21. static gint glarea_configure(GtkWidget* widget, GdkEventConfigure*, AppData* app);
  22. static gint glarea_expose(GtkWidget* widget, GdkEventExpose* event, AppData* app);
  23. static gint glarea_motion_notify(GtkWidget*, GdkEventMotion* event, AppData* app);
  24. static gint glarea_mouse_scroll(GtkWidget*, GdkEventScroll* event, AppData* app);
  25. static gint glarea_button_press(GtkWidget*, GdkEventButton* event, AppData* app);
  26. static gint glarea_button_release(GtkWidget*, GdkEventButton* event, AppData* app);
  27. static gint glarea_key_press(GtkWidget* widget, GdkEventKey* event, AppData* app);
  28. static gint glarea_key_release(GtkWidget* widget, GdkEventKey* event, AppData* app);
  29. /* Declarations: Helpers */
  30. static gint glDrawFrame(AppData* app);
  31. static bool handleSpecialKey(int key, int state, bool down, AppData* app);
  32. /* ENTRY: Initialize/Bind all glArea Callbacks */
  33. void initGLCallbacks(AppData* app)
  34. {
  35. g_signal_connect(GTK_OBJECT(app->glArea), "expose_event",
  36.                  G_CALLBACK(glarea_expose), app);
  37. g_signal_connect(GTK_OBJECT(app->glArea), "configure_event",
  38.                  G_CALLBACK(glarea_configure), app);
  39. g_signal_connect(GTK_OBJECT(app->glArea), "button_press_event",
  40.                  G_CALLBACK(glarea_button_press), app);
  41. g_signal_connect(GTK_OBJECT(app->glArea), "button_release_event",
  42.                  G_CALLBACK(glarea_button_release), app);
  43. g_signal_connect(GTK_OBJECT(app->glArea), "scroll_event",
  44.                  G_CALLBACK(glarea_mouse_scroll), app);
  45. g_signal_connect(GTK_OBJECT(app->glArea), "motion_notify_event",
  46.                  G_CALLBACK(glarea_motion_notify), app);
  47. g_signal_connect(GTK_OBJECT(app->glArea), "key_press_event",
  48.                  G_CALLBACK(glarea_key_press), app);
  49. g_signal_connect(GTK_OBJECT(app->glArea), "key_release_event",
  50.                  G_CALLBACK(glarea_key_release), app);
  51. /* Main call to execute redraw during GTK main loop */
  52. g_idle_add((GSourceFunc)glarea_idle, app);
  53. }
  54. /* CALLBACK: GL Function for main update (in GTK idle loop) */
  55. static gint glarea_idle(AppData* app)
  56. {
  57. app->core->tick();
  58. return glDrawFrame(app);
  59. }
  60. /* CALLBACK: GL Function for event "configure_event" */
  61. static gint glarea_configure(GtkWidget* widget, GdkEventConfigure*, AppData* app)
  62. {
  63. GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
  64. GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
  65. if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
  66. return FALSE;
  67. app->core->resize(widget->allocation.width, widget->allocation.height);
  68. /* GConf changes only saved upon exit, since caused a lot of CPU activity
  69.  * while saving intermediate steps. */
  70. gdk_gl_drawable_gl_end (gldrawable);
  71. return TRUE;
  72. }
  73. /* CALLBACK: GL Function for event "expose_event" */
  74. static gint glarea_expose(GtkWidget*, GdkEventExpose* event, AppData* app)
  75. {
  76. /* Draw only the last expose */
  77. if (event->count > 0)
  78. return TRUE;
  79. /* Redraw -- draw checks are made in function */
  80. return glDrawFrame(app);
  81. }
  82. /* CALLBACK: GL Function for event "motion_notify_event" */
  83. static gint glarea_motion_notify(GtkWidget*, GdkEventMotion* event, AppData* app)
  84. {
  85. int x = (int) event->x;
  86. int y = (int) event->y;
  87. int buttons = 0;
  88. if ((event->state & GDK_BUTTON1_MASK) != 0)
  89. buttons |= CelestiaCore::LeftButton;
  90. if ((event->state & GDK_BUTTON2_MASK) != 0)
  91. buttons |= CelestiaCore::MiddleButton;
  92. if ((event->state & GDK_BUTTON3_MASK) != 0)
  93. buttons |= CelestiaCore::RightButton;
  94. if ((event->state & GDK_SHIFT_MASK) != 0)
  95. buttons |= CelestiaCore::ShiftKey;
  96. if ((event->state & GDK_CONTROL_MASK) != 0)
  97. buttons |= CelestiaCore::ControlKey;
  98. app->core->mouseMove(x - app->lastX, y - app->lastY, buttons);
  99. app->lastX = x;
  100. app->lastY = y;
  101. return TRUE;
  102. }
  103. /* CALLBACK: GL Function for event "scroll_event" */
  104. static gint glarea_mouse_scroll(GtkWidget*, GdkEventScroll* event, AppData* app)
  105. {
  106. if (event->direction == GDK_SCROLL_UP)
  107. app->core->mouseWheel(-1.0f, 0);
  108. else 
  109. app->core->mouseWheel(1.0f, 0);
  110. return TRUE;
  111. }
  112. /* CALLBACK: GL Function for event "button_press_event" */
  113. static gint glarea_button_press(GtkWidget*, GdkEventButton* event, AppData* app)
  114. {
  115. app->lastX = (int) event->x;
  116. app->lastY = (int) event->y;
  117. if (event->button == 1)
  118. app->core->mouseButtonDown(event->x, event->y, CelestiaCore::LeftButton);
  119. else if (event->button == 2)
  120. app->core->mouseButtonDown(event->x, event->y, CelestiaCore::MiddleButton);
  121. else if (event->button == 3)
  122. app->core->mouseButtonDown(event->x, event->y, CelestiaCore::RightButton);
  123. return TRUE;
  124. }
  125. /* CALLBACK: GL Function for event "button_release_event" */
  126. static gint glarea_button_release(GtkWidget*, GdkEventButton* event, AppData* app)
  127. {
  128. app->lastX = (int) event->x;
  129. app->lastY = (int) event->y;
  130. if (event->button == 1)
  131. app->core->mouseButtonUp(event->x, event->y, CelestiaCore::LeftButton);
  132. else if (event->button == 2)
  133. app->core->mouseButtonUp(event->x, event->y, CelestiaCore::MiddleButton);
  134. else if (event->button == 3)
  135. app->core->mouseButtonUp(event->x, event->y, CelestiaCore::RightButton);
  136. return TRUE;
  137. }
  138. /* CALLBACK: GL Function for event "key_press_event" */
  139. static gint glarea_key_press(GtkWidget* widget, GdkEventKey* event, AppData* app)
  140. {
  141. gtk_signal_emit_stop_by_name(GTK_OBJECT(widget),"key_press_event");
  142. switch (event->keyval)
  143. {
  144. case GDK_Escape:
  145. app->core->charEntered('33');
  146. break;
  147. case GDK_BackSpace:
  148. app->core->charEntered('b');
  149. break;
  150. case GDK_Tab:
  151. /* Tab has to be handled specially because keyDown and keyUp
  152.  * do not trigger auto-completion. */
  153. app->core->charEntered(event->keyval);
  154. break;
  155. case GDK_ISO_Left_Tab:
  156. /* This is what Celestia calls BackTab */
  157. app->core->charEntered(CelestiaCore::Key_BackTab);
  158. break;
  159. /* Temporary until galaxy brightness added as GtkAction */
  160. case GDK_bracketleft:
  161. app->core->charEntered('(');
  162. break;
  163. case GDK_bracketright:
  164. app->core->charEntered(')');
  165. break;
  166. default:
  167. if (!handleSpecialKey(event->keyval, event->state, true, app))
  168. {
  169. if ((event->string != NULL) && (*(event->string)))
  170. {
  171. /* See if our key accelerators will handle this event. */
  172. if((!app->core->getTextEnterMode()) && gtk_accel_groups_activate (G_OBJECT (app->mainWindow), event->keyval, GDK_SHIFT_MASK))
  173. return TRUE;
  174. char* s = event->string;
  175. while (*s != '')
  176. {
  177. char c = *s++;
  178. app->core->charEntered(c);
  179. }
  180. }
  181. }
  182. if (event->state & GDK_MOD1_MASK)
  183. return FALSE;
  184. }
  185. return TRUE;
  186. }
  187. /* CALLBACK: GL Function for event "key_release_event" */
  188. static gint glarea_key_release(GtkWidget* widget, GdkEventKey* event, AppData* app)
  189. {
  190. gtk_signal_emit_stop_by_name(GTK_OBJECT(widget),"key_release_event");
  191. return handleSpecialKey(event->keyval, event->state, false, app);
  192. }
  193. /* HELPER: GL Common Draw function.
  194.  *         If everything checks out, call appCore->draw() */
  195. static gint glDrawFrame(AppData* app)
  196. {
  197. GdkGLContext *glcontext = gtk_widget_get_gl_context(app->glArea);
  198. GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(app->glArea);
  199. if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
  200. return FALSE;
  201. if (app->bReady)
  202. {
  203. app->core->draw();
  204. gdk_gl_drawable_swap_buffers(GDK_GL_DRAWABLE(gldrawable));
  205. }
  206. gdk_gl_drawable_gl_end(gldrawable);
  207. return TRUE;
  208. }
  209. /* HELPER: Lookup function for keypress-action. Any key that is not part of
  210.  *         the menu system must be listed here. */
  211. static bool handleSpecialKey(int key, int state, bool down, AppData* app)
  212. {
  213. int k = -1;
  214. switch (key)
  215. {
  216. case GDK_Up:
  217. k = CelestiaCore::Key_Up;
  218. break;
  219. case GDK_Down:
  220. k = CelestiaCore::Key_Down;
  221. break;
  222. case GDK_Left:
  223. k = CelestiaCore::Key_Left;
  224. break;
  225. case GDK_Right:
  226. k = CelestiaCore::Key_Right;
  227. break;
  228. case GDK_Home:
  229. k = CelestiaCore::Key_Home;
  230. break;
  231. case GDK_End:
  232. k = CelestiaCore::Key_End;
  233. break;
  234. case GDK_F1:
  235. k = CelestiaCore::Key_F1;
  236. break;
  237. case GDK_F2:
  238. k = CelestiaCore::Key_F2;
  239. break;
  240. case GDK_F3:
  241. k = CelestiaCore::Key_F3;
  242. break;
  243. case GDK_F4:
  244. k = CelestiaCore::Key_F4;
  245. break;
  246. case GDK_F5:
  247. k = CelestiaCore::Key_F5;
  248. break;
  249. case GDK_F6:
  250. k = CelestiaCore::Key_F6;
  251. break;
  252. case GDK_F7:
  253. k = CelestiaCore::Key_F7;
  254. break;
  255. case GDK_F10:
  256. if (down) actionCaptureImage(NULL, app);
  257. break;
  258. case GDK_F11:
  259. k = CelestiaCore::Key_F11;
  260. break;
  261. case GDK_F12:
  262. k = CelestiaCore::Key_F12;
  263. break;
  264. case GDK_KP_Insert:
  265. case GDK_KP_0:
  266. k = CelestiaCore::Key_NumPad0;
  267. break;
  268. case GDK_KP_End:
  269. case GDK_KP_1:
  270. k = CelestiaCore::Key_NumPad1;
  271. break;
  272. case  GDK_KP_Down:
  273. case GDK_KP_2:
  274. k = CelestiaCore::Key_NumPad2;
  275. break;
  276. case GDK_KP_Next:
  277. case GDK_KP_3:
  278. k = CelestiaCore::Key_NumPad3;
  279. break;
  280. case GDK_KP_Left:
  281. case GDK_KP_4:
  282. k = CelestiaCore::Key_NumPad4;
  283. break;
  284. case GDK_KP_Begin:
  285. case GDK_KP_5:
  286. k = CelestiaCore::Key_NumPad5;
  287. break;
  288. case GDK_KP_Right:
  289. case GDK_KP_6:
  290. k = CelestiaCore::Key_NumPad6;
  291. break;
  292. case GDK_KP_Home:
  293. case GDK_KP_7:
  294. k = CelestiaCore::Key_NumPad7;
  295. break;
  296. case GDK_KP_Up:
  297. case GDK_KP_8:
  298. k = CelestiaCore::Key_NumPad8;
  299. break;
  300. case GDK_KP_Prior:
  301. case GDK_KP_9:
  302. k = CelestiaCore::Key_NumPad9;
  303. break;
  304. case GDK_A:
  305. case GDK_a:
  306. k = 'A';
  307. break;
  308. case GDK_Z:
  309. case GDK_z:
  310. k = 'Z';
  311. break;
  312. }
  313. if (k >= 0)
  314. {
  315. if (down)
  316. app->core->keyDown(k, (state & GDK_SHIFT_MASK) 
  317.                    ? CelestiaCore::ShiftKey 
  318.                    : 0);
  319. else
  320. app->core->keyUp(k);
  321. return (k < 'A' || k > 'Z');
  322. }
  323. else
  324. {
  325. return false;
  326. }
  327. }