📄 button.c
字号:
/* * button.c: * Simple toggle button example. * * written by Naofumi Yasufuku <naofumi@users.sourceforge.net> */#include <stdlib.h>#include <math.h>#include <gtk/gtk.h>#include <gtk/gtkgl.h>#ifdef G_OS_WIN32#define WIN32_LEAN_AND_MEAN 1#include <windows.h>#endif#include <GL/gl.h>#include <GL/glu.h>#define TIMEOUT_INTERVAL 10static gboolean animate = TRUE;static GLfloat angle = 0.0;static GLfloat pos_y = 0.0;static voidrealize (GtkWidget *widget, gpointer data){ GdkGLContext *glcontext = gtk_widget_get_gl_context (widget); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget); static GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 }; static GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; static GLfloat position[] = { 1.0, 1.0, 1.0, 0.0 }; static GLfloat lmodel_ambient[] = {0.2, 0.2, 0.2, 1.0}; static GLfloat local_view[] = {0.0}; /*** OpenGL BEGIN ***/ if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) return; glLightfv (GL_LIGHT0, GL_AMBIENT, ambient); glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv (GL_LIGHT0, GL_POSITION, position); glLightModelfv (GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glLightModelfv (GL_LIGHT_MODEL_LOCAL_VIEWER, local_view); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); glEnable (GL_DEPTH_TEST); glClearColor (1.0, 1.0, 1.0, 1.0); glClearDepth (1.0); gdk_gl_drawable_gl_end (gldrawable); /*** OpenGL END ***/}static gbooleanconfigure_event (GtkWidget *widget, GdkEventConfigure *event, gpointer data){ GdkGLContext *glcontext = gtk_widget_get_gl_context (widget); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget); GLfloat w = widget->allocation.width; GLfloat h = widget->allocation.height; GLfloat aspect; /*** OpenGL BEGIN ***/ if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) return FALSE; glViewport (0, 0, w, h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); if (w > h) { aspect = w / h; glFrustum (-aspect, aspect, -1.0, 1.0, 5.0, 60.0); } else { aspect = h / w; glFrustum (-1.0, 1.0, -aspect, aspect, 5.0, 60.0); } glMatrixMode (GL_MODELVIEW); gdk_gl_drawable_gl_end (gldrawable); /*** OpenGL END ***/ return TRUE;}static gbooleanexpose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data){ GdkGLContext *glcontext = gtk_widget_get_gl_context (widget); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget); /* brass */ static GLfloat ambient[4] = { 0.329412, 0.223529, 0.027451, 1.0 }; static GLfloat diffuse[4] = { 0.780392, 0.568627, 0.113725, 1.0 }; static GLfloat specular[4] = { 0.992157, 0.941176, 0.807843, 1.0 }; static GLfloat shininess = 0.21794872 * 128.0; /*** OpenGL BEGIN ***/ if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) return FALSE; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity (); glTranslatef (0.0, 0.0, -10.0); glPushMatrix (); glTranslatef (0.0, pos_y, 0.0); glRotatef (angle, 0.0, 1.0, 0.0); glMaterialfv (GL_FRONT, GL_AMBIENT, ambient); glMaterialfv (GL_FRONT, GL_DIFFUSE, diffuse); glMaterialfv (GL_FRONT, GL_SPECULAR, specular); glMaterialf (GL_FRONT, GL_SHININESS, shininess); gdk_gl_draw_torus (TRUE, 0.3, 0.6, 30, 30); glPopMatrix (); if (gdk_gl_drawable_is_double_buffered (gldrawable)) gdk_gl_drawable_swap_buffers (gldrawable); else glFlush (); gdk_gl_drawable_gl_end (gldrawable); /*** OpenGL END ***/ return TRUE;}static gbooleantimeout (GtkWidget *widget){ GLfloat t; angle += 3.0; if (angle >= 360.0) angle -= 360.0; t = angle * G_PI / 180.0; if (t > G_PI) t = 2.0 * G_PI - t; pos_y = 2.0 * (sin (t) + 0.4 * sin (3.0*t)) - 1.0; /* Invalidate the whole window. */ gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE); /* Update synchronously (fast). */ gdk_window_process_updates (widget->window, FALSE); return TRUE;}static guint timeout_id = 0;static voidtimeout_add (GtkWidget *widget){ if (timeout_id == 0) { timeout_id = gtk_timeout_add (TIMEOUT_INTERVAL, (GtkFunction) timeout, widget); }}static voidtimeout_remove (GtkWidget *widget){ if (timeout_id != 0) { gtk_timeout_remove (timeout_id); timeout_id = 0; }}static voidunrealize (GtkWidget *widget, gpointer data){ timeout_remove (widget);}static gbooleanmap_event (GtkWidget *widget, GdkEvent *event, gpointer data){ if (animate) timeout_add (widget); return TRUE;}static gbooleanunmap_event (GtkWidget *widget, GdkEvent *event, gpointer data){ timeout_remove (widget); return TRUE;}static gbooleanvisibility_notify_event (GtkWidget *widget, GdkEventVisibility *event, gpointer data){ if (animate) { if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) timeout_remove (widget); else timeout_add (widget); } return TRUE;}static voidtoggle_animation (GtkWidget *widget){ animate = !animate; if (animate) { timeout_add (widget); } else { timeout_remove (widget); gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE); }}static GtkWidget *create_gl_toggle_button (GdkGLConfig *glconfig){ GtkWidget *vbox; GtkWidget *drawing_area; GtkWidget *label; GtkWidget *button; /* * VBox. */ vbox = gtk_vbox_new (FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (vbox), 10); /* * Drawing area for drawing OpenGL scene. */ drawing_area = gtk_drawing_area_new (); gtk_widget_set_size_request (drawing_area, 200, 200); /* Set OpenGL-capability to the widget. */ gtk_widget_set_gl_capability (drawing_area, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE); g_signal_connect_after (G_OBJECT (drawing_area), "realize", G_CALLBACK (realize), NULL); g_signal_connect (G_OBJECT (drawing_area), "configure_event", G_CALLBACK (configure_event), NULL); g_signal_connect (G_OBJECT (drawing_area), "expose_event", G_CALLBACK (expose_event), NULL); g_signal_connect (G_OBJECT (drawing_area), "unrealize", G_CALLBACK (unrealize), NULL); g_signal_connect (G_OBJECT (drawing_area), "map_event", G_CALLBACK (map_event), NULL); g_signal_connect (G_OBJECT (drawing_area), "unmap_event", G_CALLBACK (unmap_event), NULL); g_signal_connect (G_OBJECT (drawing_area), "visibility_notify_event", G_CALLBACK (visibility_notify_event), NULL); gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0); gtk_widget_show (drawing_area); /* * Label. */ label = gtk_label_new ("Toggle Animation"); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 10); gtk_widget_show (label); /* * Toggle button. */ button = gtk_toggle_button_new (); g_signal_connect_swapped (G_OBJECT (button), "toggled", G_CALLBACK (toggle_animation), drawing_area); /* Add VBox. */ gtk_widget_show (vbox); gtk_container_add (GTK_CONTAINER (button), vbox); return button;}intmain (int argc, char *argv[]){ GdkGLConfig *glconfig; GtkWidget *window; GtkWidget *button; /* * Init GTK. */ gtk_init (&argc, &argv); /* * Init GtkGLExt. */ gtk_gl_init (&argc, &argv); /* * Configure OpenGL-capable visual. */ /* Try double-buffered visual */ glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE); if (glconfig == NULL) { g_print ("*** Cannot find the double-buffered visual.\n"); g_print ("*** Trying single-buffered visual.\n"); /* Try single-buffered visual */ glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH); if (glconfig == NULL) { g_print ("*** No appropriate OpenGL-capable visual found.\n"); exit (1); } } /* * Top-level window. */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "button"); /* Get automatically redrawn if any of their children changed allocation. */ gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE); /* Set border width. */ gtk_container_set_border_width (GTK_CONTAINER (window), 10); g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (gtk_main_quit), NULL); /* * Toggle button which contains an OpenGL scene. */ button = create_gl_toggle_button (glconfig); gtk_widget_show (button); gtk_container_add (GTK_CONTAINER (window), button); /* * Show window. */ gtk_widget_show (window); /* * Main loop. */ gtk_main (); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -