GLUT даже позволяет изменять все меню в середине нашего приложения. Две функции: glutSetMenu и glutGetMenu. Синтаксис:
void glutSetMenu(int menu);
Параметры:
menu - индекс ранее созданного меню.
Эта функция позволяет менять меню, например, если происходит изменение в контексте приложения. Синтаксис для glutGetMenu выглядит следующим образом:
int glutGetMenu(void);
Эта функция возвращает индекс текущего меню. Затем мы приведем пример, где мы используем два меню, которые меняются местами, когда пользователь нажимает клавишу F1.
void processSpecialKeys(int c, int x, int y) { if (!flag) { if (c == GLUT_KEY_F1) { int x = glutGetMenu(); if (x == menu1) glutSetMenu(menu2); else glutSetMenu(menu1); // Не забудьте приложить меню!!! glutAttachMenu(GLUT_RIGHT_BUTTON); } } } void createGLUTMenus() { menu2 = glutCreateMenu(processMenuEvents); glutAddMenuEntry("Blue",BLUE); glutAddMenuEntry("Green",GREEN); glutAddMenuEntry("Red",RED); menu1 = glutCreateMenu(processMenuEvents); glutAddMenuEntry("Red",RED); glutAddMenuEntry("Green",GREEN); glutAddMenuEntry("Blue",BLUE); glutAttachMenu(GLUT_RIGHT_BUTTON); }
Итоговый код.
Здесь мы включим весь материала, который мы представили ранее в нашем маленьком приложении. Мы собираемся добавить меню для приложений, подменю и заменяемое меню. Просто скопируйте и вставьте следующий код в ваш проект. Правая кнопка мыши должна открыть меню. Клавиши 'S' и 'C' будет влиять на меню.
#include <stdlib.h> #include <math.h> #include <glut.h> // угол поворота камеры float angle=0.0; // координаты вектора направления движения камеры float lx=0.0f, lz=-1.0f; // XZ позиция камеры float x=0.0f, z=5.0f; //Ключи статуса камеры. Переменные инициализируются нулевыми значениями //когда клавиши не нажаты float deltaAngle = 0.0f; float deltaMove = 0; int xOrigin = -1; // Определения констант для меню #define RED 1 #define GREEN 2 #define BLUE 3 #define ORANGE 4 #define FILL 1 #define LINE 2 #define SHRINK 1 #define NORMAL 2 // идентификаторы меню int fillMenu, shrinkMenu, mainMenu, colorMenu; // цвет носа float red = 1.0f, blue=0.5f, green=0.5f; // размер снеговика float scale = 1.0f; // статус меню int menuFlag = 0; void changeSize(int w, int h) { // предотвращение деления на ноль if (h == 0) h = 1; float ratio = w * 1.0 / h; // используем матрицу проекции glMatrixMode(GL_PROJECTION); // обнуляем матрицу glLoadIdentity(); // установить параметры вьюпорта glViewport(0, 0, w, h); // установить корректную перспективу gluPerspective(45.0f, ratio, 0.1f, 100.0f); // вернуться к матрице проекции glMatrixMode(GL_MODELVIEW); } void drawSnowMan() { glColor3f(1.0f, 1.0f, 1.0f); // тело снеговика glTranslatef(0.0f ,0.75f, 0.0f); glutSolidSphere(0.75f,20,20); // голова снеговика glTranslatef(0.0f, 1.0f, 0.0f); glutSolidSphere(0.25f,20,20); // глаза снеговика glPushMatrix(); glColor3f(0.0f,0.0f,0.0f); glTranslatef(0.05f, 0.10f, 0.18f); glutSolidSphere(0.05f,10,10); glTranslatef(-0.1f, 0.0f, 0.0f); glutSolidSphere(0.05f,10,10); glPopMatrix(); // нос снеговика glColor3f(1.0f, 0.5f , 0.5f); glRotatef(0.0f,1.0f, 0.0f, 0.0f); glutSolidCone(0.08f,0.5f,10,2); } void computePos(float deltaMove) { x += deltaMove * lx * 0.1f; z += deltaMove * lz * 0.1f; } void renderScene(void) { if (deltaMove) computePos(deltaMove); //очистить буфер цвета и глубины glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // обнулить трансформацию glLoadIdentity(); // установить камеру gluLookAt( x, 1.0f, z, x+lx, 1.0f, z+lz, 0.0f, 1.0f, 0.0f ); // нарисуем "землю" glColor3f(0.9f, 0.9f, 0.9f); // полигон (plaine) glBegin(GL_QUADS); glVertex3f(-100.0f, 0.0f, -100.0f); glVertex3f(-100.0f, 0.0f, 100.0f); glVertex3f( 100.0f, 0.0f, 100.0f); glVertex3f( 100.0f, 0.0f, -100.0f); glEnd(); // Нарисуем 64 снеговика for (int i = -4; i < 4; i++) for (int j=-4; j < 4; j++) { glPushMatrix(); glTranslatef(i*5.0, 0, j * 5.0); drawSnowMan(); glPopMatrix(); } glutSwapBuffers(); } // ----------------------------------- // // клавиатура // // ----------------------------------- // void processNormalKeys(unsigned char key, int xx, int yy) { glutSetMenu(mainMenu); switch (key) { case 27: glutDestroyMenu(mainMenu); glutDestroyMenu(fillMenu); glutDestroyMenu(colorMenu); glutDestroyMenu(shrinkMenu); exit(0); break; case 's': if (!menuFlag) glutChangeToSubMenu(2,"Shrink",shrinkMenu); break; case 'c': if (!menuFlag) glutChangeToSubMenu(2,"Color",colorMenu); break; } if (key == 27) exit(0); } void pressKey(int key, int xx, int yy) { switch (key) { case GLUT_KEY_UP : deltaMove = 0.5f; break; case GLUT_KEY_DOWN : deltaMove = -0.5f; break; } } void releaseKey(int key, int x, int y) { switch (key) { case GLUT_KEY_UP : case GLUT_KEY_DOWN : deltaMove = 0;break; } } // ----------------------------------- // // функции мыши // // ----------------------------------- // void mouseMove(int x, int y) { // только когда левая кнопка не активна if (xOrigin >= 0) { // обновить deltaAngle deltaAngle = (x - xOrigin) * 0.001f; // обновить направление камеры lx = sin(angle + deltaAngle); lz = -cos(angle + deltaAngle); } } void mouseButton(int button, int state, int x, int y) { // только начало движение, если левая кнопка мыши нажата if (button == GLUT_LEFT_BUTTON) { // когда кнопка отпущена if (state == GLUT_UP) { angle += deltaAngle; xOrigin = -1; } else {// state = GLUT_DOWN xOrigin = x; } } } // ------------------------------------// // меню // // ------------------------------------// void processMenuStatus(int status, int x, int y) { if (status == GLUT_MENU_IN_USE) menuFlag = 1; else menuFlag = 0; } void processMainMenu(int option) { //ничего здесь не делаем //все действия для подменю } void processFillMenu(int option) { switch (option) { case FILL: glPolygonMode(GL_FRONT, GL_FILL); break; case LINE: glPolygonMode(GL_FRONT, GL_LINE); break; } } void processShrinkMenu(int option) { switch (option) { case SHRINK: scale = 0.5f; break; case NORMAL: scale = 1.0f; break; } } void processColorMenu(int option) { switch (option) { case RED : red = 1.0f; green = 0.0f; blue = 0.0f; break; case GREEN : red = 0.0f; green = 1.0f; blue = 0.0f; break; case BLUE : red = 0.0f; green = 0.0f; blue = 1.0f; break; case ORANGE : red = 1.0f; green = 0.5f; blue = 0.5f; break; } } void createPopupMenus() { shrinkMenu = glutCreateMenu(processShrinkMenu); glutAddMenuEntry("Shrink",SHRINK); glutAddMenuEntry("NORMAL",NORMAL); fillMenu = glutCreateMenu(processFillMenu); glutAddMenuEntry("Fill",FILL); glutAddMenuEntry("Line",LINE); colorMenu = glutCreateMenu(processColorMenu); glutAddMenuEntry("Red",RED); glutAddMenuEntry("Blue",BLUE); glutAddMenuEntry("Green",GREEN); glutAddMenuEntry("Orange",ORANGE); mainMenu = glutCreateMenu(processMainMenu); glutAddSubMenu("Polygon Mode", fillMenu); glutAddSubMenu("Color", colorMenu); // прикрепить меню к правой кнопке glutAttachMenu(GLUT_RIGHT_BUTTON); //статус активности меню glutMenuStatusFunc(processMenuStatus); } // ------------------------------------ // // main() // // ----------------------------------- // int main(int argc, char **argv) { // инициализация GLUT и создание окна glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100,100); glutInitWindowSize(400,400); glutCreateWindow("Урок 10"); //регистрация glutDisplayFunc(renderScene); glutReshapeFunc(changeSize); glutIdleFunc(renderScene); glutIgnoreKeyRepeat(1); glutKeyboardFunc(processNormalKeys); glutSpecialFunc(pressKey); glutSpecialUpFunc(releaseKey); // Новые функции для регистрации glutMouseFunc(mouseButton); glutMotionFunc(mouseMove); // OpenGL инициализация функций glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); // инициализация меню createPopupMenus(); // Главный цикл glutMainLoop(); return 1; }
Должно появляться меню и при нажатии "s" или "c" нижнее меню меняется
Комментарии
Когда изменяете цвет в функции void processColorMenu(int option), ничего не происходит, вам нужно добавить изменения в функцию, void drawSnowMan(), заменив точные значения цвета на переменные red, green, blue. Так же добавьте где-нибудь использование измененного в меню параметра scale. Я не придираюсь, просто хочется, чтобы код выполнял свои функции.
Работаю на этим
Здравствуйте,
у меня вопрос
после использования 'c' или 's' меню появляется опять, но во втором пункте уже нет подменю. Не подскажете, почему так?
Спасибо