Creating mouse-driven menus
CS-116A: Introduction to Computer Graphics
Instructor: Rob Bruce
Fall 2016

SLIDE 1: Example glut menu

  • Mouse-driven menus are a quick and useful way to gather input from users through the OpenGL Utility Toolkit (GLUT).
  • In the example below we will dissect the sample program, example_glut_menu.c.

SLIDE 2: Example glut menu: main()

  • Step 1 of 9: glutCreateMenu(): This function associates a user-defined subroutine (menu) with a glut menu. For future referencing, this menu will be assigned to the variable glut_sub_sub_menu.

int main (int argc, char *argv[])
{
  int window;
  int glut_sub_menu, glut_sub_sub_menu;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (640, 480);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Creating GLUT menus");
  glut_sub_sub_menu = glutCreateMenu (menu);
  glutAddMenuEntry ("selection 1", 1);
  glutAddMenuEntry ("selection 2", 2);
  glutAddMenuEntry ("selection 3", 3);
  glut_sub_menu = glutCreateMenu (menu);
  glutAddSubMenu ("sub menu", glut_sub_sub_menu);
  glutCreateMenu (menu);
  glutAddSubMenu ("menu", glut_sub_menu);
  glutAttachMenu (GLUT_LEFT_BUTTON);
  glutDisplayFunc (&DrawGLScene);
  glutReshapeFunc (&ReSizeGLScene);
  InitGL (640, 480);
  glutMainLoop ();
}

SLIDE 3: Example glut menu: main()

  • Step 2 of 9: glutAddMenuEntry(): Now we will add the first of three menu items to this menu. If the user selects "selection 1" GLUT will return the value "1" to our program. That's how we will know the user selected item, "selection 1".

int main (int argc, char *argv[])
{
  int window;
  int glut_sub_menu, glut_sub_sub_menu;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (640, 480);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Creating GLUT menus");
  glut_sub_sub_menu = glutCreateMenu (menu);
  glutAddMenuEntry ("selection 1", 1);
  glutAddMenuEntry ("selection 2", 2);
  glutAddMenuEntry ("selection 3", 3);
  glut_sub_menu = glutCreateMenu (menu);
  glutAddSubMenu ("sub menu", glut_sub_sub_menu);
  glutCreateMenu (menu);
  glutAddSubMenu ("menu", glut_sub_menu);
  glutAttachMenu (GLUT_LEFT_BUTTON);
  glutDisplayFunc (&DrawGLScene);
  glutReshapeFunc (&ReSizeGLScene);
  InitGL (640, 480);
  glutMainLoop ();
}

SLIDE 4: Example glut menu: main()

  • Step 3 of 9: glutAddMenuEntry(): Now we will add the second of three menu items to this menu. If the user selects "selection 2" GLUT will return the value "2" to our program. That's how we will know the user selected item, "selection 2".

int main (int argc, char *argv[])
{
  int window;
  int glut_sub_menu, glut_sub_sub_menu;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (640, 480);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Creating GLUT menus");
  glut_sub_sub_menu = glutCreateMenu (menu);
  glutAddMenuEntry ("selection 1", 1);
  glutAddMenuEntry ("selection 2", 2);
  glutAddMenuEntry ("selection 3", 3);
  glut_sub_menu = glutCreateMenu (menu);
  glutAddSubMenu ("sub menu", glut_sub_sub_menu);
  glutCreateMenu (menu);
  glutAddSubMenu ("menu", glut_sub_menu);
  glutAttachMenu (GLUT_LEFT_BUTTON);
  glutDisplayFunc (&DrawGLScene);
  glutReshapeFunc (&ReSizeGLScene);
  InitGL (640, 480);
  glutMainLoop ();
}

SLIDE 5: Example glut menu: main()

  • Step 4 of 9: glutAddMenuEntry(): Now we will add the third of three menu items to this menu. If the user selects "selection 3" GLUT will return the value "3" to our program. That's how we will know the user selected item, "selection 3".

int main (int argc, char *argv[])
{
  int window;
  int glut_sub_menu, glut_sub_sub_menu;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (640, 480);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Creating GLUT menus");
  glut_sub_sub_menu = glutCreateMenu (menu);
  glutAddMenuEntry ("selection 1", 1);
  glutAddMenuEntry ("selection 2", 2);
  glutAddMenuEntry ("selection 3", 3);
  glut_sub_menu = glutCreateMenu (menu);
  glutAddSubMenu ("sub menu", glut_sub_sub_menu);
  glutCreateMenu (menu);
  glutAddSubMenu ("menu", glut_sub_menu);
  glutAttachMenu (GLUT_LEFT_BUTTON);
  glutDisplayFunc (&DrawGLScene);
  glutReshapeFunc (&ReSizeGLScene);
  InitGL (640, 480);
  glutMainLoop ();
}

SLIDE 6: Example glut menu: main()

  • A screenshot of the menu defined by variable glut_sub_sub_menu looks like this:
    Screenshot of three menu options: selection 1, selection 2, and selection 3.

SLIDE 7: Example glut menu: main()

  • Step 5 of 9: glutCreateMenu(): This function associates the user-defined subroutine (menu) with a glut menu. For future referencing, this menu will be assigned to the variable glut_sub_menu

int main (int argc, char *argv[])
{
  int window;
  int glut_sub_menu, glut_sub_sub_menu;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (640, 480);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Creating GLUT menus");
  glut_sub_sub_menu = glutCreateMenu (menu);
  glutAddMenuEntry ("selection 1", 1);
  glutAddMenuEntry ("selection 2", 2);
  glutAddMenuEntry ("selection 3", 3);
  glut_sub_menu = glutCreateMenu (menu);
  glutAddSubMenu ("sub menu", glut_sub_sub_menu);
  glutCreateMenu (menu);
  glutAddSubMenu ("menu", glut_sub_menu);
  glutAttachMenu (GLUT_LEFT_BUTTON);
  glutDisplayFunc (&DrawGLScene);
  glutReshapeFunc (&ReSizeGLScene);
  InitGL (640, 480);
  glutMainLoop ();
}

SLIDE 8: Example glut menu: main()

  • Step 6 of 9: glutAddSubMenu(): Now we will add a menu option labeled as "sub menu". This menu option will then point to the menu defined by variable glut_sub_sub_menu.

int main (int argc, char *argv[])
{
  int window;
  int glut_sub_menu, glut_sub_sub_menu;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (640, 480);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Creating GLUT menus");
  glut_sub_sub_menu = glutCreateMenu (menu);
  glutAddMenuEntry ("selection 1", 1);
  glutAddMenuEntry ("selection 2", 2);
  glutAddMenuEntry ("selection 3", 3);
  glut_sub_menu = glutCreateMenu (menu);
  glutAddSubMenu ("sub menu", glut_sub_sub_menu);
  glutCreateMenu (menu);
  glutAddSubMenu ("menu", glut_sub_menu);
  glutAttachMenu (GLUT_LEFT_BUTTON);
  glutDisplayFunc (&DrawGLScene);
  glutReshapeFunc (&ReSizeGLScene);
  InitGL (640, 480);
  glutMainLoop ();
}

SLIDE 9: Example glut menu: main()

  • A screenshot of the menu defined by variable glut_sub_menu looks like this:
    Screenshot of a submenu in glut with three menu options: selection 1, selection 2, and selection 3.

SLIDE 10: Example glut menu: main()

  • Step 7 of 9: glutCreateMenu(): This function associates the user-defined subroutine (menu) with a glut menu. Notice that no variable is assigned to this menu?! That is because it will be a top menu.

int main (int argc, char *argv[])
{
  int window;
  int glut_sub_menu, glut_sub_sub_menu;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (640, 480);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Creating GLUT menus");
  glut_sub_sub_menu = glutCreateMenu (menu);
  glutAddMenuEntry ("selection 1", 1);
  glutAddMenuEntry ("selection 2", 2);
  glutAddMenuEntry ("selection 3", 3);
  glut_sub_menu = glutCreateMenu (menu);
  glutAddSubMenu ("sub menu", glut_sub_sub_menu);
  glutCreateMenu (menu);
  glutAddSubMenu ("menu", glut_sub_menu);
  glutAttachMenu (GLUT_LEFT_BUTTON);
  glutDisplayFunc (&DrawGLScene);
  glutReshapeFunc (&ReSizeGLScene);
  InitGL (640, 480);
  glutMainLoop ();
}

SLIDE 11: Example glut menu: main()

  • Step 8 of 9: glutAddSubMenu(): Now we will add a menu option labeled as "menu". This menu option will then point to the menu defined by variable glut_sub_menu.

int main (int argc, char *argv[])
{
  int window;
  int glut_sub_menu, glut_sub_sub_menu;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (640, 480);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Creating GLUT menus");
  glut_sub_sub_menu = glutCreateMenu (menu);
  glutAddMenuEntry ("selection 1", 1);
  glutAddMenuEntry ("selection 2", 2);
  glutAddMenuEntry ("selection 3", 3);
  glut_sub_menu = glutCreateMenu (menu);
  glutAddSubMenu ("sub menu", glut_sub_sub_menu);
  glutCreateMenu (menu);
  glutAddSubMenu ("menu", glut_sub_menu);
  glutAttachMenu (GLUT_LEFT_BUTTON);
  glutDisplayFunc (&DrawGLScene);
  glutReshapeFunc (&ReSizeGLScene);
  InitGL (640, 480);
  glutMainLoop ();
}

SLIDE 12: Example glut menu: main()

  • A screenshot of the menu defined by variable glut_sub_menu now looks like this:
    Screenshot of a menu in glut labeled as "menu" with submenu option labeled as "sub menu"followed by three sub-submenu options: "selection 1", "selection 2", and "selection 3".

SLIDE 13: Example glut menu: main()

  • Step 9 of 9: glutAttachMenu(): This function tells GLUT to draw the menu (shown in SLIDE 12) when the user presses the left mouse button.

int main (int argc, char *argv[])
{
  int window;
  int glut_sub_menu, glut_sub_sub_menu;

  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
  glutInitWindowSize (640, 480);
  glutInitWindowPosition (0, 0);
  window = glutCreateWindow ("Creating GLUT menus");
  glut_sub_sub_menu = glutCreateMenu (menu);
  glutAddMenuEntry ("selection 1", 1);
  glutAddMenuEntry ("selection 2", 2);
  glutAddMenuEntry ("selection 3", 3);
  glut_sub_menu = glutCreateMenu (menu);
  glutAddSubMenu ("sub menu", glut_sub_sub_menu);
  glutCreateMenu (menu);
  glutAddSubMenu ("menu", glut_sub_menu);
  glutAttachMenu (GLUT_LEFT_BUTTON);
  glutDisplayFunc (&DrawGLScene);
  glutReshapeFunc (&ReSizeGLScene);
  InitGL (640, 480);
  glutMainLoop ();
}

SLIDE 14: IMPORTANT NOTE!

  • In the menu showin above (SLIDE 12), there are ultimately three options to select:
    selection 1
    selection 2
    selection 3
  • It is very important to assign unique integer values to each of these menu items. Why? Because GLUT returns the value associated with the menu item selected.
    For example, if the user selected "selection 1" GLUT would return a value of "1" to our program.
    If the user selected "selection 2" GLUT would return a value of "2" to our program.
    If the user selected "selection 3" GLUT would return a value of "3" to our program.
  • In a very long menu with LOTS of sub-menu options, be sure to assign unique integer values for each button. No button should ever share an integer value with any other button. They must be distinct otherwise your program will not be able to determine what button was really selected due to ambiguity.
  • Now that we have dissected main(), it is time to dissect the menu() subroutine...

SLIDE 15: Example glut menu: menu()

  • The variable value holds the unique value returned from GLUT for the menu item the user selected. In this program, there are three possible values: 1, 2, and 3. Therefore, we need to develop case statements for each of these values. For simplicity, I simply output to Standard output (the terminal window) that the user pressed the appropriate button.
  • This is a very simple subroutine. Therefore, I will stop dissecting the code at this point.

void menu (int value)
{
  switch (value)
  {
    case 1:
      printf ("menu -> sub_menu -> selection 1\n");
    break;
    case 2:
      printf ("menu -> sub_menu -> selection 2\n");
    break;
    case 3:
      printf ("menu -> sub_menu -> selection 3\n");
    break;
    default:
    break;
  }
  glutPostRedisplay();
}