diegotoral

Gtkglext Gtk+3 Example

Nov 15th, 2012
79
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * button.c:
  3.  * Simple toggle button example.
  4.  *
  5.  * written by Naofumi Yasufuku  <naofumi@users.sourceforge.net>
  6.  */
  7.  
  8. #include <stdlib.h>
  9. #include <math.h>
  10.  
  11. #include <gtk/gtk.h>
  12.  
  13. #include <gtk/gtkgl.h>
  14.  
  15. #ifdef G_OS_WIN32
  16. #define WIN32_LEAN_AND_MEAN 1
  17. #include <windows.h>
  18. #endif
  19.  
  20. #ifdef GDK_WINDOWING_QUARTZ
  21. #include <OpenGL/gl.h>
  22. #else
  23. #include <GL/gl.h>
  24. #endif
  25.  
  26. #include "drawshapes.h"
  27.  
  28. #define TIMEOUT_INTERVAL 10
  29.  
  30. static gboolean animate = TRUE;
  31.  
  32. static GLfloat angle = 0.0;
  33. static GLfloat pos_y = 0.0;
  34.  
  35. static void
  36. realize (GtkWidget *widget,
  37.          gpointer   data)
  38. {
  39.   static GLfloat ambient[]  = { 0.0, 0.0, 0.0, 1.0 };
  40.   static GLfloat diffuse[]  = { 1.0, 1.0, 1.0, 1.0 };
  41.   static GLfloat position[] = { 1.0, 1.0, 1.0, 0.0 };
  42.   static GLfloat lmodel_ambient[] = {0.2, 0.2, 0.2, 1.0};
  43.   static GLfloat local_view[] = {0.0};
  44.  
  45.   /*** OpenGL BEGIN ***/
  46.   if (!gtk_widget_begin_gl (widget))
  47.     return;
  48.  
  49.   glLightfv (GL_LIGHT0, GL_AMBIENT, ambient);
  50.   glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse);
  51.   glLightfv (GL_LIGHT0, GL_POSITION, position);
  52.   glLightModelfv (GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
  53.   glLightModelfv (GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
  54.   glEnable (GL_LIGHTING);
  55.   glEnable (GL_LIGHT0);
  56.   glEnable (GL_DEPTH_TEST);
  57.  
  58.   glClearColor (1.0, 1.0, 1.0, 1.0);
  59.   glClearDepth (1.0);
  60.  
  61.   gtk_widget_end_gl (widget, FALSE);
  62.   /*** OpenGL END ***/
  63. }
  64.  
  65. static gboolean
  66. configure_event (GtkWidget         *widget,
  67.                  GdkEventConfigure *event,
  68.                  gpointer           data)
  69. {
  70.   GtkAllocation allocation;
  71.  
  72.   GLfloat w;
  73.   GLfloat h;
  74.   GLfloat aspect;
  75.  
  76.   gtk_widget_get_allocation (widget, &allocation);
  77.   w = allocation.width;
  78.   h = allocation.height;
  79.  
  80.   /*** OpenGL BEGIN ***/
  81.   if (!gtk_widget_begin_gl (widget))
  82.     return FALSE;
  83.  
  84.   glViewport (0, 0, w, h);
  85.  
  86.   glMatrixMode (GL_PROJECTION);
  87.   glLoadIdentity ();
  88.   if (w > h)
  89.     {
  90.       aspect = w / h;
  91.       glFrustum (-aspect, aspect, -1.0, 1.0, 5.0, 60.0);
  92.     }
  93.   else
  94.     {
  95.       aspect = h / w;
  96.       glFrustum (-1.0, 1.0, -aspect, aspect, 5.0, 60.0);
  97.     }
  98.  
  99.   glMatrixMode (GL_MODELVIEW);
  100.  
  101.   gtk_widget_end_gl (widget, FALSE);
  102.   /*** OpenGL END ***/
  103.  
  104.   return TRUE;
  105. }
  106.  
  107. static gboolean
  108. draw (GtkWidget *widget,
  109.       cairo_t   *cr,
  110.       gpointer   data)
  111. {
  112.   /* brass */
  113.   static GLfloat ambient[4]  = { 0.329412, 0.223529, 0.027451, 1.0 };
  114.   static GLfloat diffuse[4]  = { 0.780392, 0.568627, 0.113725, 1.0 };
  115.   static GLfloat specular[4] = { 0.992157, 0.941176, 0.807843, 1.0 };
  116.   static GLfloat shininess   = 0.21794872 * 128.0;
  117.  
  118.   /*** OpenGL BEGIN ***/
  119.   if (!gtk_widget_begin_gl (widget))
  120.     return FALSE;
  121.  
  122.   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  123.  
  124.   glLoadIdentity ();
  125.   glTranslatef (0.0, 0.0, -10.0);
  126.  
  127.   glPushMatrix ();
  128.     glTranslatef (0.0, pos_y, 0.0);
  129.     glRotatef (angle, 0.0, 1.0, 0.0);
  130.     glMaterialfv (GL_FRONT, GL_AMBIENT, ambient);
  131.     glMaterialfv (GL_FRONT, GL_DIFFUSE, diffuse);
  132.     glMaterialfv (GL_FRONT, GL_SPECULAR, specular);
  133.     glMaterialf (GL_FRONT, GL_SHININESS, shininess);
  134.     draw_torus (TRUE, 0.3, 0.6, 30, 30);
  135.   glPopMatrix ();
  136.  
  137.   gtk_widget_end_gl (widget, TRUE);
  138.   /*** OpenGL END ***/
  139.  
  140.   return TRUE;
  141. }
  142.  
  143. static gboolean
  144. timeout (GtkWidget *widget)
  145. {
  146.   GtkAllocation allocation;
  147.   GdkWindow *window;
  148.   GLfloat t;
  149.  
  150.   window = gtk_widget_get_window (widget);
  151.   gtk_widget_get_allocation (widget, &allocation);
  152.  
  153.   angle += 3.0;
  154.   if (angle >= 360.0)
  155.     angle -= 360.0;
  156.  
  157.   t = angle * G_PI / 180.0;
  158.   if (t > G_PI)
  159.     t = 2.0 * G_PI - t;
  160.  
  161.   pos_y = 2.0 * (sin (t) + 0.4 * sin (3.0*t)) - 1.0;
  162.  
  163.   /* Invalidate the whole window. */
  164.   gdk_window_invalidate_rect (window, &allocation, FALSE);
  165.  
  166.   /* Update synchronously (fast). */
  167.   gdk_window_process_updates (window, FALSE);
  168.  
  169.   return TRUE;
  170. }
  171.  
  172. static guint timeout_id = 0;
  173.  
  174. static void
  175. timeout_add (GtkWidget *widget)
  176. {
  177.   if (timeout_id == 0)
  178.     {
  179.       timeout_id = g_timeout_add (TIMEOUT_INTERVAL,
  180.                                   (GSourceFunc) timeout,
  181.                                   widget);
  182.     }
  183. }
  184.  
  185. static void
  186. timeout_remove (GtkWidget *widget)
  187. {
  188.   if (timeout_id != 0)
  189.     {
  190.       g_source_remove (timeout_id);
  191.       timeout_id = 0;
  192.     }
  193. }
  194.  
  195. static void
  196. unrealize (GtkWidget *widget,
  197.        gpointer   data)
  198. {
  199.   timeout_remove (widget);
  200. }
  201.  
  202. static gboolean
  203. map_event (GtkWidget *widget,
  204.        GdkEvent  *event,
  205.        gpointer   data)
  206. {
  207.   if (animate)
  208.     timeout_add (widget);
  209.  
  210.   return TRUE;
  211. }
  212.  
  213. static gboolean
  214. unmap_event (GtkWidget *widget,
  215.          GdkEvent  *event,
  216.          gpointer   data)
  217. {
  218.   timeout_remove (widget);
  219.  
  220.   return TRUE;
  221. }
  222.  
  223. static gboolean
  224. visibility_notify_event (GtkWidget          *widget,
  225.              GdkEventVisibility *event,
  226.              gpointer            data)
  227. {
  228.   if (animate)
  229.     {
  230.       if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
  231.     timeout_remove (widget);
  232.       else
  233.     timeout_add (widget);
  234.     }
  235.  
  236.   return TRUE;
  237. }
  238.  
  239. static void
  240. toggle_animation (GtkWidget *widget)
  241. {
  242.   GtkAllocation allocation;
  243.   animate = !animate;
  244.  
  245.   if (animate)
  246.     {
  247.       timeout_add (widget);
  248.     }
  249.   else
  250.     {
  251.       timeout_remove (widget);
  252.       gtk_widget_get_allocation (widget, &allocation);
  253.       gdk_window_invalidate_rect (gtk_widget_get_window (widget), &allocation, FALSE);
  254.     }
  255. }
  256.  
  257. static GtkWidget *
  258. create_gl_toggle_button (GdkGLConfig *glconfig)
  259. {
  260.   GtkWidget *vbox;
  261.   GtkWidget *drawing_area;
  262.   GtkWidget *label;
  263.   GtkWidget *button;
  264.  
  265.   /*
  266.    * VBox.
  267.    */
  268.  
  269.   vbox = gtk_vbox_new (FALSE, 0);
  270.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
  271.  
  272.   /*
  273.    * Drawing area for drawing OpenGL scene.
  274.    */
  275.  
  276.   drawing_area = gtk_drawing_area_new ();
  277.   gtk_widget_set_size_request (drawing_area, 200, 200);
  278.  
  279.   /* Set OpenGL-capability to the widget. */
  280.   gtk_widget_set_gl_capability (drawing_area,
  281.                                 glconfig,
  282.                                 NULL,
  283.                                 TRUE,
  284.                                 GDK_GL_RGBA_TYPE);
  285.  
  286.   g_signal_connect_after (G_OBJECT (drawing_area), "realize",
  287.                           G_CALLBACK (realize), NULL);
  288.   g_signal_connect (G_OBJECT (drawing_area), "configure_event",
  289.             G_CALLBACK (configure_event), NULL);
  290.   g_signal_connect (G_OBJECT (drawing_area), "draw",
  291.             G_CALLBACK (draw), NULL);
  292.   g_signal_connect (G_OBJECT (drawing_area), "unrealize",
  293.             G_CALLBACK (unrealize), NULL);
  294.  
  295.   g_signal_connect (G_OBJECT (drawing_area), "map_event",
  296.             G_CALLBACK (map_event), NULL);
  297.   g_signal_connect (G_OBJECT (drawing_area), "unmap_event",
  298.             G_CALLBACK (unmap_event), NULL);
  299.   g_signal_connect (G_OBJECT (drawing_area), "visibility_notify_event",
  300.             G_CALLBACK (visibility_notify_event), NULL);
  301.  
  302.   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
  303.   gtk_widget_show (drawing_area);
  304.  
  305.   /*
  306.    * Label.
  307.    */
  308.  
  309.   label = gtk_label_new ("Toggle Animation");
  310.   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 10);
  311.   gtk_widget_show (label);
  312.  
  313.   /*
  314.    * Toggle button.
  315.    */
  316.  
  317.   button = gtk_toggle_button_new ();
  318.  
  319.   g_signal_connect_swapped (G_OBJECT (button), "toggled",
  320.                             G_CALLBACK (toggle_animation), drawing_area);
  321.  
  322.   /* Add VBox. */
  323.   gtk_widget_show (vbox);
  324.   gtk_container_add (GTK_CONTAINER (button), vbox);
  325.  
  326.   return button;
  327. }
  328.  
  329. int
  330. main (int   argc,
  331.       char *argv[])
  332. {
  333.   GdkGLConfig *glconfig;
  334.   GtkWidget *window;
  335.   GtkWidget *button;
  336.  
  337.   /*
  338.    * Init GTK.
  339.    */
  340.  
  341.   gtk_init (&argc, &argv);
  342.  
  343.   /*
  344.    * Init GtkGLExt.
  345.    */
  346.  
  347.   gtk_gl_init (&argc, &argv);
  348.  
  349.   /*
  350.    * Configure OpenGL-capable visual.
  351.    */
  352.  
  353.   /* Try double-buffered visual */
  354.   glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB    |
  355.                                         GDK_GL_MODE_DEPTH  |
  356.                                         GDK_GL_MODE_DOUBLE);
  357.   if (glconfig == NULL)
  358.     {
  359.       g_print ("*** Cannot find the double-buffered visual.\n");
  360.       g_print ("*** Trying single-buffered visual.\n");
  361.  
  362.       /* Try single-buffered visual */
  363.       glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB   |
  364.                                             GDK_GL_MODE_DEPTH);
  365.       if (glconfig == NULL)
  366.         {
  367.           g_print ("*** No appropriate OpenGL-capable visual found.\n");
  368.           exit (1);
  369.         }
  370.     }
  371.  
  372.   /*
  373.    * Top-level window.
  374.    */
  375.  
  376.   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  377.   gtk_window_set_title (GTK_WINDOW (window), "button");
  378.  
  379.   /* Get automatically redrawn if any of their children changed allocation. */
  380.   gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);
  381.   /* Set border width. */
  382.   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
  383.  
  384.   g_signal_connect (G_OBJECT (window), "delete_event",
  385.                     G_CALLBACK (gtk_main_quit), NULL);
  386.  
  387.   /*
  388.    * Toggle button which contains an OpenGL scene.
  389.    */
  390.  
  391.   button = create_gl_toggle_button (glconfig);
  392.   gtk_widget_show (button);
  393.   gtk_container_add (GTK_CONTAINER (window), button);
  394.  
  395.   /*
  396.    * Show window.
  397.    */
  398.  
  399.   gtk_widget_show (window);
  400.  
  401.   /*
  402.    * Main loop.
  403.    */
  404.  
  405.   gtk_main ();
  406.  
  407.   return 0;
  408. }
RAW Paste Data