+
+ case '\b':
+ start_time = glutGet(GLUT_ELAPSED_TIME);
+ prev_tmsec = 0;
+ anim_stop_time = anim_stopped ? start_time : 0;
+ beam_angle = 0;
+ break;
+
+ case ' ':
+ if(anim_stopped) {
+ long msec = glutGet(GLUT_ELAPSED_TIME);
+ start_time += msec - anim_stop_time;
+ prev_tmsec = msec - start_time;
+ anim_stop_time = 0;
+ anim_stopped = false;
+ } else {
+ anim_stop_time = glutGet(GLUT_ELAPSED_TIME);
+ anim_stopped = true;
+ }
+ break;
+
+ case '=':
+ beam_speed = get_seq_value("beam-speed", anim_time);
+ set_seq_value("beam-speed", anim_time, beam_speed + 0.1);
+ break;
+
+ case '-':
+ beam_speed = get_seq_value("beam-speed", anim_time) - 0.1;
+ if(beam_speed < 0) beam_speed = 0;
+ set_seq_value("beam-speed", anim_time, beam_speed);
+ break;
+
+ case '0':
+ clear_seq_track("beam-speed");
+ break;
+
+ case '[':
+ beam_len = get_seq_value("beam-len", anim_time) - 0.5;
+ if(beam_len < 0) beam_len = 0;
+ set_seq_value("beam-len", anim_time, beam_len);
+ break;
+
+ case ']':
+ beam_len = get_seq_value("beam-len", anim_time);
+ set_seq_value("beam-len", anim_time, beam_len + 0.5);
+ break;
+
+ case '\\':
+ clear_seq_track("beam-len");
+ break;
+
+ case '\r':
+ case '\n':
+ idx = find_seq_track("beam-speed");
+ assert(idx >= 0);
+ set_seq_value(idx, anim_time, beam_speed);
+ set_seq_value(idx, anim_time + 2000, 0);
+ break;
+
+ case 'c':
+ freecam = !freecam;
+ printf("camera mode: %s\n", freecam ? "free" : "animated");
+ if(!freecam) {
+ orig_cam = cam;
+ } else {
+ cam = orig_cam;
+ }
+ break;
+
+ case 'v':
+ printf("current view\n");
+ printf(" pos: %f %f %f\n", cam.x, cam.y, cam.z);
+ printf(" theta: %f, phi: %f\n", cam.theta, cam.phi);
+ printf(" dist: %f\n", cam.dist);
+ break;
+
+ case 'L':
+ printf("clearing camera keyframes\n");
+ clear_seq_track("cam-x");
+ clear_seq_track("cam-y");
+ clear_seq_track("cam-z");
+ clear_seq_track("cam-theta");
+ clear_seq_track("cam-phi");
+ clear_seq_track("cam-dist");
+ break;
+
+ case 'k':
+ printf("setting camera keyframe for time: %ld\n", anim_time);
+ set_seq_value("cam-x", anim_time, cam.x);
+ set_seq_value("cam-y", anim_time, cam.y);
+ set_seq_value("cam-z", anim_time, cam.z);
+ set_seq_value("cam-theta", anim_time, cam.theta);
+ set_seq_value("cam-phi", anim_time, cam.phi);
+ set_seq_value("cam-dist", anim_time, cam.dist);
+ break;
+
+ case 'x':
+ set_seq_value("xlogo", anim_time, xlogo_alpha < 0.5 ? 1.0 : 0.0);
+ break;
+
+ case 'X':
+ printf("clearing logo keyframes\n");
+ clear_seq_track("xlogo");
+ break;
+
+ case 'z':
+ set_seq_value("xcircle", anim_time, xcircle < 0.5 ? 1.0 : 0.0);
+ break;
+
+ case 'Z':
+ printf("clearing circle keyframes\n");
+ clear_seq_track("xcircle");
+ break;
+
+
+ case 'p':
+ set_seq_value("paper", anim_time, paper < 0.5 ? 1.0 : 0.0);
+ break;
+
+ case 'P':
+ printf("clearing paper keyframes\n");
+ clear_seq_track("paper");
+ break;
+
+ case '`':
+ printf("dumping animation data to: seq_dump\n");
+ if(!dump_seq("seq_dump")) {
+ fprintf(stderr, "dump failed\n");
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void keyb_special(int key, int x, int y)
+{
+ switch(key) {
+ case GLUT_KEY_F1:
+ show_help = !show_help;
+ break;
+
+ case GLUT_KEY_F5:
+ show_ui = !show_ui;
+ break;
+