Rube Goldberg Machine 1.0
This is the base code for Rube Goldberg designed for the CS296 Software Systems Lab
|
00001 /* 00002 * Base code for CS 296 Software Systems Lab 00003 * Department of Computer Science and Engineering, IIT Bombay 00004 * Instructor: Parag Chaudhuri 00005 */ 00006 00009 #include "callbacks.hpp" 00010 00011 #ifndef __APPLE__ 00012 #include "GL/glui.h" 00013 #else 00014 #include "GL/glui.h" 00015 #endif 00016 00021 namespace cs296 00022 { 00023 int32 test_index = 0; 00024 int32 test_selection = 0; 00025 int32 test_count = 0; 00026 cs296::sim_t* entry; 00027 cs296::base_sim_t* test; 00028 cs296::settings_t settings; 00029 int32 width = 640; 00030 int32 height = 480; 00031 int32 frame_period = 16; 00032 int32 main_window; 00033 float settings_hz = 60.0; 00034 float32 view_zoom = 1.0f; 00035 int tx, ty, tw, th; 00036 bool r_mouse_down; 00037 b2Vec2 lastp; 00038 00039 b2Vec2 callbacks_t::convert_screen_to_world(int32 x, int32 y) 00040 { 00041 float32 u = x / static_cast<float32>(tw); 00042 float32 v = (th - y) / float32(th); 00043 00044 float32 ratio = static_cast<float32>(tw) / static_cast<float32>(th); 00045 b2Vec2 extents(ratio * 25.0f, 25.0f); 00046 extents *= view_zoom; 00047 00048 b2Vec2 lower = settings.view_center - extents; 00049 b2Vec2 upper = settings.view_center + extents; 00050 00051 b2Vec2 p; 00052 p.x = (1.0f - u) * lower.x + u * upper.x; 00053 p.y = (1.0f - v) * lower.y + v * upper.y; 00054 return p; 00055 } 00056 00057 00058 void callbacks_t::resize_cb(int32 w, int32 h) 00059 { 00060 width = w; 00061 height = h; 00062 00063 GLUI_Master.get_viewport_area(&tx, &ty, &tw, &th); 00064 glViewport(tx, ty, tw, th); 00065 00066 glMatrixMode(GL_PROJECTION); 00067 glLoadIdentity(); 00068 00071 float32 ratio = static_cast<float32>(tw) / static_cast<float32>(th); 00072 00073 b2Vec2 extents(ratio * 25.0f, 25.0f); 00074 extents *= view_zoom; 00075 00076 b2Vec2 lower = settings.view_center - extents; 00077 b2Vec2 upper = settings.view_center + extents; 00078 00081 gluOrtho2D(lower.x, upper.x, lower.y, upper.y); 00082 } 00083 00084 00085 void callbacks_t::keyboard_cb(unsigned char key, int x, int y) 00086 { 00088 B2_NOT_USED(x); 00089 B2_NOT_USED(y); 00090 00091 switch (key) 00092 { 00093 case 27: 00094 exit(0); 00095 break; 00096 00098 case 'z': 00099 view_zoom = b2Min(1.1f * view_zoom, 20.0f); 00100 resize_cb(width, height); 00101 break; 00102 00104 case 'x': 00105 view_zoom = b2Max(0.9f * view_zoom, 0.02f); 00106 resize_cb(width, height); 00107 break; 00108 00110 case 'r': 00111 delete test; 00112 test = entry->create_fcn(); 00113 break; 00114 00116 case 'p': 00117 settings.pause = !settings.pause; 00118 break; 00119 00121 default: 00122 if (test) 00123 { 00124 test->keyboard(key); 00125 } 00126 } 00127 } 00128 00129 00130 void callbacks_t::keyboard_special_cb(int key, int x, int y) 00131 { 00132 B2_NOT_USED(x); 00133 B2_NOT_USED(y); 00134 00135 switch (key) 00136 { 00137 case GLUT_ACTIVE_SHIFT: 00138 00140 case GLUT_KEY_LEFT: 00141 settings.view_center.x -= 0.5f; 00142 resize_cb(width, height); 00143 break; 00144 00146 case GLUT_KEY_RIGHT: 00147 settings.view_center.x += 0.5f; 00148 resize_cb(width, height); 00149 break; 00150 00152 case GLUT_KEY_DOWN: 00153 settings.view_center.y -= 0.5f; 00154 resize_cb(width, height); 00155 break; 00156 00158 case GLUT_KEY_UP: 00159 settings.view_center.y += 0.5f; 00160 resize_cb(width, height); 00161 break; 00162 00164 case GLUT_KEY_HOME: 00165 view_zoom = 1.0f; 00166 settings.view_center.Set(0.0f, 20.0f); 00167 callbacks_t::resize_cb(width, height); 00168 break; 00169 } 00170 } 00171 00172 void callbacks_t::keyboard_up_cb(unsigned char key, int x, int y) 00173 { 00174 B2_NOT_USED(x); 00175 B2_NOT_USED(y); 00176 00177 if (test) 00178 { 00179 test->keyboard_up(key); 00180 } 00181 } 00182 00183 void callbacks_t::mouse_cb(int32 button, int32 state, int32 x, int32 y) 00184 { 00186 if (button == GLUT_LEFT_BUTTON) 00187 { 00188 int mod = glutGetModifiers(); 00189 b2Vec2 p = convert_screen_to_world(x, y); 00190 if (state == GLUT_DOWN) 00191 { 00192 b2Vec2 p = convert_screen_to_world(x, y); 00193 if (mod == GLUT_ACTIVE_SHIFT) 00194 { 00195 test->shift_mouse_down(p); 00196 } 00197 else 00198 { 00199 test->mouse_down(p); 00200 } 00201 } 00202 00203 if (state == GLUT_UP) 00204 { 00205 test->mouse_up(p); 00206 } 00207 } 00208 else if (button == GLUT_RIGHT_BUTTON) 00209 { 00210 if (state == GLUT_DOWN) 00211 { 00212 lastp = convert_screen_to_world(x, y); 00213 r_mouse_down = true; 00214 } 00215 00216 if (state == GLUT_UP) 00217 { 00218 r_mouse_down = false; 00219 } 00220 } 00221 } 00222 00223 00224 void callbacks_t::mouse_motion_cb(int32 x, int32 y) 00225 { 00226 b2Vec2 p = convert_screen_to_world(x, y); 00227 test->mouse_move(p); 00228 00229 if (r_mouse_down) 00230 { 00231 b2Vec2 diff = p - lastp; 00232 settings.view_center.x -= diff.x; 00233 settings.view_center.y -= diff.y; 00234 resize_cb(width, height); 00235 lastp = convert_screen_to_world(x, y); 00236 } 00237 } 00238 00239 void callbacks_t::timer_cb(int) 00240 { 00241 glutSetWindow(main_window); 00242 glutPostRedisplay(); 00243 glutTimerFunc(frame_period, timer_cb, 0); 00244 } 00245 00246 void callbacks_t::display_cb(void) 00247 { 00248 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 00249 00250 glMatrixMode(GL_MODELVIEW); 00251 glLoadIdentity(); 00252 00253 test->set_text_line(30); 00254 b2Vec2 old_center = settings.view_center; 00255 settings.hz = settings_hz; 00256 00257 test->step(&settings); 00258 00259 if (old_center.x != settings.view_center.x || old_center.y != settings.view_center.y) 00260 { 00261 resize_cb(width, height); 00262 } 00263 00264 test->draw_title(5, 15, entry->name); 00265 00266 glutSwapBuffers(); 00267 00268 if (test_selection != test_index) 00269 { 00270 test_index = test_selection; 00271 delete test; 00272 entry = cs296::sim; 00273 test = entry->create_fcn(); 00274 view_zoom = 1.0f; 00275 settings.view_center.Set(0.0f, 20.0f); 00276 resize_cb(width, height); 00277 } 00278 } 00279 00280 00281 00282 void callbacks_t::restart_cb(int) 00283 { 00284 delete test; 00285 entry = cs296::sim; 00286 test = entry->create_fcn(); 00287 resize_cb(width, height); 00288 } 00289 00290 void callbacks_t::pause_cb(int) 00291 { 00292 settings.pause = !settings.pause; 00293 } 00294 00295 void callbacks_t::exit_cb(int code) 00296 { 00297 exit(code); 00298 } 00299 00300 void callbacks_t::single_step_cb(int) 00301 { 00302 settings.pause = 1; 00303 settings.single_step = 1; 00304 } 00305 00306 };