/************************************************** * File: Interaction.cpp * Author: Dr. Dalton R. Hunkins * Date: September 2008 * * * Modes of User Interaction * Mouse: * Left-Click - select an object * Left Drag - move the selected object * Right-Click - triggers popup menu * Keyboard: * r, R - change color of object to Red * g, G - change color of object to Green * b, B - change color of object to Blue * c, C - change color of object to Cyan * m, M - change color of object to Magenta * y, Y - change color of object to Yellow * Up Arrow - scale up slected object * Down Arrow - scale down selecte object * **************************************************/ #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #include "Object.h" // Set Constants used in Menu #define MENU_CLOSE 900 #define MENU_RESET 901 #define MENU_RED 913 #define MENU_GREEN 914 #define MENU_BLUE 915 #define MENU_YELLOW 916 #define MENU_CYAN 917 #define MENU_MAGENTA 918 #define NUMBER_OF_OBJECTS 7 class ProgramExit{ }; int mainMenuId; int setColorMenuId; float red[] = {1.0, 0.0, 0.0}; float green[] = {0.0, 1.0, 0.0}; float blue[] = {0.0, 0.0, 1.0}; float yellow[] = {1.0, 1.0, 0.0}; float cyan[] = {0.0, 1.0, 1.0}; float magenta[] = {1.0, 0.0, 1.0}; int originalCursor; bool translating = false; double currentScale = 0.0; // Declare Objects Object *objects[NUMBER_OF_OBJECTS]; Object *selectedObject = NULL; int deviceWindowWidth = 500; int deviceWindowHeight = 500; struct { int width; int height; } deviceWindow; struct { double left; double right; double bottom; double top; double width; double height; } projectionWindow; void init() { glClearColor(0.0, 0.0, 0.0, 1.0); // Set Projection Window Values projectionWindow.left = projectionWindow.bottom = -1.0; projectionWindow.right = projectionWindow.top = 1.0; projectionWindow.width = 2.0; projectionWindow.height = 2.0; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(projectionWindow.left, projectionWindow.right, projectionWindow.bottom, projectionWindow.top); // Construct the Objects objects[0] = new Square(red, 0.05, 0.75, 0.75); objects[1] = new Disk(cyan, 0.1, 0.0, 0.0); objects[2] = new Triangle(yellow, 0.15, -0.75,-0.75); objects[3] = new Square(yellow, 0.08, -0.50, 0.50); objects[4] = new Disk(magenta, 0.15, -0.50, 0.50); objects[5] = new Disk(green, 0.1, 0.60, -0.25); objects[6] = new Triangle(red, 0.25, 0.60, -0.25); currentScale = 0.0; } void reshape(int width, int height) { deviceWindow.width = width; deviceWindow.height = height; glViewport(0, 0, width, height); } double getProjectionX(int x) { return ( projectionWindow.width / (double) deviceWindow.width) * x + projectionWindow.left; } double getProjectionY(int y) { return (-projectionWindow.height / (double) deviceWindow.height) * y + projectionWindow.top; } void display() { glClear(GL_COLOR_BUFFER_BIT); for (int i=NUMBER_OF_OBJECTS-1; i>=0; i--) objects[i]->draw(); glutSwapBuffers(); } void reset() { currentScale = 0.0; for (int i=0; i<NUMBER_OF_OBJECTS; i++) objects[i]->reset(); } void menuHandler(int choice) { switch (choice) { case MENU_RED : if (selectedObject != NULL) { selectedObject->setColor(red); glutPostRedisplay(); } break; case MENU_GREEN : if (selectedObject != NULL) { selectedObject->setColor(green); glutPostRedisplay(); } break; case MENU_BLUE : if (selectedObject != NULL) { selectedObject->setColor(blue); glutPostRedisplay(); } break; case MENU_YELLOW : if (selectedObject != NULL) { selectedObject->setColor(yellow); glutPostRedisplay(); } break; case MENU_CYAN : if (selectedObject != NULL) { selectedObject->setColor(cyan); glutPostRedisplay(); } break; case MENU_MAGENTA : if (selectedObject != NULL) { selectedObject->setColor(magenta); glutPostRedisplay(); } break; case MENU_RESET : reset(); break; case MENU_CLOSE : throw ProgramExit(); break; } } void createMenu() { mainMenuId = glutCreateMenu(menuHandler); setColorMenuId = glutCreateMenu(menuHandler); // Create Main Menu Entries glutSetMenu(mainMenuId); glutAddSubMenu("Set Color", setColorMenuId); glutAddMenuEntry("Reset", MENU_RESET); glutAddMenuEntry("Close", MENU_CLOSE); glutAttachMenu(GLUT_RIGHT_BUTTON); // Create SubMenu Entries glutSetMenu(setColorMenuId); glutAddMenuEntry("Red ", MENU_RED); glutAddMenuEntry("Green ", MENU_GREEN); glutAddMenuEntry("Blue ", MENU_BLUE); glutAddMenuEntry("Yellow ", MENU_YELLOW); glutAddMenuEntry("Cyan ", MENU_CYAN); glutAddMenuEntry("Magenta ", MENU_MAGENTA); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 'r' : case 'R' : if (selectedObject != NULL) { selectedObject->setColor(red); glutPostRedisplay(); } break; case 'g' : case 'G' : if (selectedObject != NULL) { selectedObject->setColor(green); glutPostRedisplay(); } break; case 'b' : case 'B' : if (selectedObject != NULL) { selectedObject->setColor(blue); glutPostRedisplay(); } break; case 'y' : case 'Y' : if (selectedObject != NULL) { selectedObject->setColor(yellow); glutPostRedisplay(); } break; case 'c' : case 'C' : if (selectedObject != NULL) { selectedObject->setColor(cyan); glutPostRedisplay(); } break; case 'm' : case 'M' : if (selectedObject != NULL) { selectedObject->setColor(magenta); glutPostRedisplay(); } break; } } void specialKeyboard(int key, int x, int y) { if (selectedObject != NULL) switch (key) { case GLUT_KEY_UP : selectedObject->incrementScale(0.01); glutPostRedisplay(); break; case GLUT_KEY_DOWN : selectedObject->incrementScale(-0.01); glutPostRedisplay(); break; } } Object* findObject(double x, double y) { Object *object = NULL; for (int i=0; i<NUMBER_OF_OBJECTS; i++) if (objects[i]->isOver(x, y)) { object = objects[i]; break; } for (int i=0; i<NUMBER_OF_OBJECTS; i++) objects[i]->setAsCurrentObject(false); if (object != NULL) object->setAsCurrentObject(true); return object; } void mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON) if (state == GLUT_DOWN) { selectedObject = findObject(getProjectionX(x), getProjectionY(y)); if (selectedObject != NULL) { originalCursor = glutGet(GLUT_WINDOW_CURSOR); glutSetCursor(GLUT_CURSOR_INFO); translating = true; } } else if (translating) { translating = false; glutSetCursor(originalCursor); glutPostRedisplay(); } } void motion(int x, int y) { if (translating) { selectedObject->setTranslation( getProjectionX(x), getProjectionY(y)); glutPostRedisplay(); } } int main (int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition(10, 10); glutInitWindowSize(500, 500); glutCreateWindow("Interaction"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); createMenu(); // Register Callback Functions glutMouseFunc(mouse); glutMotionFunc(motion); glutKeyboardFunc(keyboard); glutSpecialFunc(specialKeyboard); try { glutMainLoop(); } catch (ProgramExit) { } return 0; }