/*==============================================*/
/*  Interaction.c - How to work with the mouse  */
/*                  and the keyboard            */
/*                                              */
/*  Author:  Bary W Pollack                     */
/*  Updated: Apr. 3, 2004                       */
/*==============================================*/

#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>

GLsizei ww = 500, wh = 500;         /* world width and height */
GLfloat fVSize = 60;
GLsizei mx = -1, my = -1;           /* clicked mouse x,y in screen coordinates  */
GLsizei lx = -1, ly = -1;           /* line to this point in screen coordinates */
int     bFlag = 1;

/*==============================================*/

void myReshape (int w, int h)       /* screen resized; update internal world accordingly */
{
    ww = w;  wh = h;
    glutPostRedisplay ();
}

void keyboard (unsigned char key, int x, int y)     /* get key, x, y; echo to screen */
{
    printf ("key=%3u (%c) x=%4d y=%4d\n", key, key, x, y);
}

int screen2world (int x)
{
    return (20.0 * x) / 167.0 + 30.0 / 167.0 + 0.5;
}

void mouseEcho (int btn, int state)
{
    if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        puts ("LEFT-DOWN");
    else if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        puts ("RIGHT-DOWN");
    else if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        puts ("MIDDLE-DOWN");
    else if (btn == GLUT_LEFT_BUTTON && state == GLUT_UP)
        puts ("LEFT-UP");
    else if (btn == GLUT_RIGHT_BUTTON && state == GLUT_UP)
        puts ("RIGHT-UP");
    else if (btn == GLUT_RIGHT_BUTTON && state == GLUT_UP)
        puts ("MIDDLE-UP");
}


void mouse (int btn, int state, int x, int y)       /* get button, x, y; react accordingly */
{
    mouseEcho (btn, state);

    if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)  /* force display update */
    {
        mx = screen2world (x);
        my = screen2world (wh - y);
        glutPostRedisplay ();
        bFlag = 1 - bFlag;              /* invert the line flag */
        if (! bFlag)
            lx = ly = -1;
    }

    if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) /* terminate the program */
        exit (0);
}

void mouseMotion (int x, int y)         /* mouse moved */
{
    lx = screen2world (x);
    ly = screen2world (wh - y);
    if (bFlag)
        glutPostRedisplay ();
}

/*==============================================*/

void display (void)         /* the display callback */
{
    int  d = 0;
    int  size = 1;

    glClear (GL_COLOR_BUFFER_BIT);

    /* draw a rectangle */
    glLineWidth (2.0);
    glBegin (GL_LINE_LOOP);
        glColor3f (0.0, 0.0, 0.0);
        glVertex2i (10+d, 10+d);  glVertex2i (50-d, 10+d);
        glVertex2i (50-d, 50-d);  glVertex2i (10+d, 50-d);
    glEnd ();

    /* put points at the 4 vertices */
    glPointSize (4.0);
    glBegin (GL_POINTS);
        glColor3f (0.0, 0.0, 1.0);
        glVertex2i (30+d, 30+d);
        glVertex2i (10+d, 10+d);  glVertex2i (50-d, 10+d);
        glVertex2i (50-d, 50-d);  glVertex2i (10+d, 50-d);

        glPointSize (1.0);  glColor3f (0.0, 0.0, 0.0);
        glVertex2i (1, 1);  glVertex2i (2, 2);  glVertex2i (3, 3);
        glVertex2i (4, 4);  glVertex2i (5, 5);  glVertex2i (6, 6);
        glVertex2i (8, 8);
    glEnd ( );

    /* mouse has been pressed; draw "echo square" using a random color */
    if (mx >= 0 && my >= 0)
    {
        glColor3ub ((GLubyte) (rand () % 256), (GLubyte) (rand () % 256), (GLubyte) (rand () % 256));
        glLineWidth (1.0);
        printf ("--> %d %d\n", mx, my);         /* echo coordinates to screen for reference */
        glBegin (GL_LINE_LOOP);
            glVertex2i (mx-size, my-size);  glVertex2i (mx+size, my-size);
            glVertex2i (mx+size, my+size);  glVertex2i (mx-size, my+size);
        glEnd ();
    }

    if (bFlag && mx >= 0 && my >= 0 && lx >= 0 && ly >= 0)
    {
        glColor3f (0.0, 0.0, 0.0);
        glLineWidth (2.0);
        glBegin (GL_LINES);
            glVertex2i (mx, my);  glVertex2i (lx, ly);
        glEnd ();
    }

    glFlush ();
}

/*==============================================*/

void myinit ()      /* standard initialization for OpenGL and GLUT */
{
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluOrtho2D (-0.00, fVSize + 0.00, -0.00, fVSize + 0.00);
    glMatrixMode (GL_MODELVIEW);
    glClearColor  (0.6, 7.0, 0.9, 1.0);
}

/*==============================================*/

int main (int argc, char **argv)
{
    printf ("\nClick the mouse, move the mouse, repeat...\n");
    printf ("You also can type any key(s)\n");
    printf ("Right-click to terminate the program\n\n");

    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB );
    glutInitWindowSize (wh, ww);
    glutInitWindowPosition (25, 50);
    glutCreateWindow ("Interaction");

    glutReshapeFunc (myReshape);
    glutMouseFunc (mouse);
    // glutMotionFunc (mouseMotion);        /* use for drag, not move */
    glutPassiveMotionFunc (mouseMotion); 
    glutKeyboardFunc (keyboard);
    glutDisplayFunc (display);

    myinit ();

    glutMainLoop ();

    return 0;
}

/*==============================================*/

