GLUT Tutorials

메뉴 수정하기

메뉴항목을 비활성으로 바꿔야할 때가 있는데 GLUT 를 사용하면 메뉴항목을 쉽게 바꾸거나 삭제할 수 있습니다. 메뉴항목을 바꾸기 위해서 다음의 함수를 사용합니다.

void glutChangeToMenuEntry(int entry, char *name, int value); 

인자 설명:
entry - 메뉴항목의 인덱스입니다. 반드시 1 부터 전메뉴항목의 개수사이여야합니다.
name - 메뉴항목의 새로운 이름입니다.
value - 메뉴항목이 선택되었을 때 콜백함수로 반환되는 값입니다.
void glutChangeToSubMenu(int entry, char *name, int menu); 

인자 설명:
entry - 메뉴항목의 인덱스입니다. 반드시 1 부터 전메뉴항목의 개수사이여야합니다.
name - 메뉴항목의 새로운 이름입니다.
menu - 메뉴의 인덱스입니다.

주의: 이 함수는 마이크로소프트 윈도우즈에서 사용하기에 약간 문제가 있습니다. 필자 생각에는 이식성 때문인 것 같습니다. 서브메뉴를 연달아 두번바꾸면 첫번째변환만 실행되고 나머지는 실행되지 않습니다.

메뉴항목을 지우기 위해서는 다음 함수를 사용하면 됩니다.

void glutRemoveMenuItem(int entry); 

인자 설명:
entry - 메뉴항목의 인덱스입니다. 반드시 1 부터 전메뉴항목의 개수사이여야합니다.

마지막으로 메뉴항목의 개수는 아무때나 알 수 있습니다. glutGet 함수를 사용해서 현재 메뉴에 질의하면 됩니다. 다음 예제는 메뉴를 수정하는 것입니다.:

void processMenuEvents(int option) 
{
    red = 0.0;
    green = 0.0;
    blue = 0.0;
    switch (option) 
    {
        case RED :
            red = 1.0;
            break;
        case GREEN :
            green = 1.0;
            break;
        case BLUE :
            blue = 1.0;
            break;
        case WHITE :
            red = 1.0; 
            green = 1.0; 
            blue = 1.0;
            break;
    }
}

void processKeys(unsigned char c, int x, int y)
{
    int num = glutGet(GLUT_MENU_NUM_ITEMS);
    switch (c)
    {
        case 'a': 
            glutChangeToMenuEntry(1,"Blue",BLUE);
            glutChangeToMenuEntry(3,"Red",RED);
            break;
        case 'b': 
            glutChangeToMenuEntry(3,"Blue",BLUE);
            glutChangeToMenuEntry(1,"Red",RED);
            break;
        case 'c': 
            if (num > 3)
                glutRemoveMenuItem(num);
            break;
        case 'd': if (num == 3)
            glutAddMenuEntry("White",WHITE);
            break;
    }
    glutSetMenu(menu);
}

void createGLUTMenus()
{
     menu = glutCreateMenu(processMenuEvents);
    glutAddMenuEntry("Red",RED);
    glutAddMenuEntry("Green",GREEN);
    glutAddMenuEntry("Blue",BLUE);
    glutAddMenuEntry("White",WHITE);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
}

메뉴의 콜백함수에서 메뉴를 수정한 것이 아니라 키보드의 콜백함수에서 메뉴를 수정했습니다. 이 이유는 메뉴를 사용중일 때는 메뉴를 수정할 수 없기 때문입니다. 콜백함수가 끝나기 전까지는 메뉴가 사용되고 있는 것이기 때문에 메뉴의 구조를 메뉴의 콜백함수내에서 바꿀 수 없는 것입니다. 시험해보고 싶다면 Visual C 프로젝트 파일( glut81.zip ) 을 받아서 실행해보세요.

위에서도 말했지만, 메뉴가 사용중일 때에는 메뉴항목을 수정할 수 없습니다. 메뉴가 사용중이 아닐 때에만 메뉴를 수정할 수 있습니다. GLUT 에는 메뉴가 나타날 때와 사라질 때 호출되는 함수를 등록해주는 콜백함수가 있습니다. 이 함수는 glutMenuStatusFunc 로 다음은 이 함수의 설명입니다.

void glutMenuStatusFunc(void (*func)(int status, int x, int y); 

인자 설명:
func - 콜백함수의 이름입니다.

이 함수는 main 함수에서 호출할 수 있습니다. 나중에 추가해봅시다. glutMenuStatusFunc 함수의 원형을 보면 콜백함수는 세개의 인자를 받습니다.

  • status - GLUT_MENU_IN_USE 또는 GLUT_MENU_NOT_IN_USE 값 중 하나입니다.
  • x - 윈도우 클라이언트 영역을 기준으로 메뉴의 왼쪽(left) 좌표입니다.
  • y - 윈도우 클라이언트 영역을 기준으로 메뉴의 위쪽(top) 좌표입니다.

다음 예제 함수는 메뉴가 사용중일 때와 아닐때를 가려 알맞게 flag 변수를 설정합니다.

void processMenuStatus(int status, int x, int y)
{
    if (status == GLUT_MENU_IN_USE)
        flag = 1;
    else
        flag = 0;
}

이제 이 flag 변수를 사용해서 키보드 이벤트 처리함수를 수정해봅시다.

void processKeys(unsigned char c, int x, int y) 
{
     if (!flag)
    {
        int num = glutGet(GLUT_MENU_NUM_ITEMS);
        switch (c) 
        {
            case 'a': 
                glutChangeToMenuEntry(1,"Blue",BLUE);
                glutChangeToMenuEntry(3,"Red",RED);
                break;
            case 'b': 
                glutChangeToMenuEntry(3,"Blue",BLUE);
                glutChangeToMenuEntry(1,"Red",RED);
                break;
            case 'c': 
                if (num > 3)
                    glutRemoveMenuItem(num);
                break;
            case 'd':
                if (num == 3)
                    glutAddMenuEntry("White",WHITE);
                break;
        }
    }
}

다음은 새로운 코드가 추가된 main 함수입니다.

void main(int argc, char **argv) 
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(320,320);
    glutCreateWindow("SnowMen");
    glutDisplayFunc(renderScene);
    glutIdleFunc(renderScene);
    glutReshapeFunc(changeSize);

    createGLUTMenus();

    glutMenuStatusFunc(processMenuStatus);

    glutKeyboardFunc(processKeys);

    glutMainLoop();
}

소스코드를 받아서 자세하게 살펴보세요.