1 /* Timer (callback) demo
3 * Written by John Tsiombikas <nuclear@member.fsf.org>
4 * Modified by Vincent Simonetti
6 * A modification of the timer sample, but with this
7 * offering a use of the user-data callback.
10 #include <GL/freeglut.h>
12 struct display_index_s
14 /* color index will be advanced every time the timer expires */
15 int surround_color_index;
16 int center_color_index;
18 typedef struct display_index_s display_index_t;
25 typedef struct timer_state_s timer_state_t;
32 typedef struct menu_state_s menu_state_t;
34 void disp(void* uptr);
35 void timer_func(int which, void* uptr);
37 const float color[][3] = {
45 const int timerInts[] = {
51 void createMenuEntries(menu_state_t* menuState)
54 for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++)
56 char temp[10] = {'\0'};
57 /* flag current value */
58 if ((*menuState->timer_time_ptr) == timerInts[i])
63 sprintf(temp + 1, " %4d ms", timerInts[i]);
65 glutAddMenuEntry(temp, timerInts[i]);
69 void updateMenuEntries(menu_state_t* menuState)
72 for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++)
74 char temp[10] = { '\0' };
75 /* flag current value */
76 if ((*menuState->timer_time_ptr) == timerInts[i])
81 sprintf(temp + 1, " %4d ms", timerInts[i]);
83 glutChangeToMenuEntry(i+1, temp, timerInts[i]);
87 void MenuHandler(int timerInt, void* user_ptr)
89 menu_state_t* menuState;
93 /* In case main menu is selected somehow */
97 menuState = (menu_state_t*)user_ptr;
99 *menuState->timer_time_ptr = timerInt;
100 glutSetMenu(menuState->menu_id);
101 updateMenuEntries(menuState);
104 int main(int argc, char **argv)
106 int timerSurroundInt = 1000, timerCenterInt = 500;
107 display_index_t displayIndex = { 0, 2 };
108 timer_state_t surroundTimerState = { &displayIndex.surround_color_index, &timerSurroundInt };
109 timer_state_t centerTimerState = { &displayIndex.center_color_index, &timerCenterInt };
110 menu_state_t surroundMenuState = { &timerSurroundInt, 0 };
111 menu_state_t centerMenuState = { &timerCenterInt, 0 };
113 glutInit(&argc, argv);
114 glutInitWindowSize(128, 128);
115 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
116 glutCreateWindow("timer test");
118 glutDisplayFuncUcall(disp, &displayIndex);
120 /* get timer started, its reset in the timer function itself */
121 glutTimerFuncUcall(timerSurroundInt, timer_func, 1, &surroundTimerState);
122 glutTimerFuncUcall(timerCenterInt, timer_func, 2, ¢erTimerState);
124 /* menus for setting timing */
125 surroundMenuState.menu_id = glutCreateMenuUcall(MenuHandler, &surroundMenuState);
126 createMenuEntries(&surroundMenuState);
128 centerMenuState.menu_id = glutCreateMenuUcall(MenuHandler, ¢erMenuState);
129 createMenuEntries(¢erMenuState);
131 glutCreateMenuUcall(MenuHandler, NULL); /* doesn't matter, no clickable entries in this menu */
132 glutAddSubMenu("Center", centerMenuState.menu_id);
133 glutAddSubMenu("Surround", surroundMenuState.menu_id);
134 glutAttachMenu(GLUT_RIGHT_BUTTON);
140 void disp(void* user_ptr)
142 const display_index_t* displayIndex;
145 displayIndex = (display_index_t*)user_ptr;
147 cidx = displayIndex->surround_color_index;
148 glClearColor(color[cidx][0], color[cidx][1], color[cidx][2], 1);
149 glClear(GL_COLOR_BUFFER_BIT);
151 pcidx = displayIndex->center_color_index;
153 glColor3f(color[pcidx][0], color[pcidx][1], color[pcidx][2]);
161 void timer_func(int which, void* user_ptr)
163 const timer_state_t* timerState;
165 timerState = (timer_state_t*)user_ptr;
167 /* advance the color index and trigger a redisplay */
168 *timerState->color_index_ptr = (*timerState->color_index_ptr + 1) % (sizeof color / sizeof *color);
172 /* (re)set the timer callback and ask glut to call it in x ms */
173 glutTimerFuncUcall(*timerState->timer_time_ptr, timer_func, which, user_ptr);