#ifdef G_OS_WIN32 #define WIN32_LEAN_AND_MEAN 1 #include #else #define FALSE 0 #define TRUE !FALSE #endif #include #include #include #include #include "menu.h" #include "button.h" #include "font.h" #define MENU_MAX_BUTTONS 16 enum MenuState { MENU_MAIN, MENU_START, MENU_OPTIONS }; struct MenuStruct { enum MenuState m_iMenuId; int m_iButtonCount; struct ButtonStruct m_sButtons[MENU_MAX_BUTTONS]; }; struct MenuStruct g_sMenuMain; // definition of the main menu struct MenuStruct g_sMenuStart; // definition of the start menu struct MenuStruct g_sMenuOptions; // definition of the options menu struct MenuStruct *g_pCurMenu; // current menu int g_iWinWidth; int g_iWinHeight; void MenuEnableGroup(int f_iGroup) { struct ButtonStruct l_sButton; int l_iType, l_iGroup; int i = 0; // enable first radio button in this group while (i < g_pCurMenu->m_iButtonCount) { l_sButton = g_pCurMenu->m_sButtons[i]; l_iType = l_sButton.m_iType; l_iGroup = l_sButton.m_iGroup; if (l_iType == BUTTON_RADIO && l_iGroup == f_iGroup) { ButtonEnable(&g_pCurMenu->m_sButtons[i]); return; } i++; } } // MenuEnableGroup void MenuAddButton(int f_dXPos, int f_dYPos, int f_dWidth, int f_dHeight, char *f_pcTitle, int f_iType, int f_iGroup) { int i = g_pCurMenu->m_iButtonCount;; // create the button with the right parameters g_pCurMenu->m_sButtons[i] = ButtonCreate(f_dXPos, f_dYPos, f_dWidth, f_dHeight, f_pcTitle, f_iType, f_iGroup, i); g_pCurMenu->m_iButtonCount = i + 1; } // MenuAddButton void MenuClear(void) { g_pCurMenu->m_iButtonCount = 0; memset(&g_pCurMenu->m_sButtons, 0, sizeof(g_pCurMenu->m_sButtons)); } // MenuClear void MenuBuild (void) { int l_iMenuId = g_pCurMenu->m_iMenuId; switch (l_iMenuId) { default: case MENU_MAIN: MenuAddButton(50, 50, 250, 64, "Button 1", BUTTON_CLICK, BUTTON_NO_GROUP); MenuAddButton(50, 150, 250, 64, "Button 2", BUTTON_CLICK, BUTTON_NO_GROUP); MenuAddButton(350, 50, 64, 64, "Radio 1", BUTTON_RADIO, BUTTON_GROUP1); MenuAddButton(350, 150, 64, 64, "Radio 2", BUTTON_RADIO, BUTTON_GROUP1); MenuEnableGroup(BUTTON_GROUP1); MenuAddButton(50, 250, 256, 64, "Button 3", BUTTON_CLICK, BUTTON_NO_GROUP); MenuAddButton(50, 350, 256, 64, "Button 4", BUTTON_CLICK, BUTTON_NO_GROUP); MenuAddButton(350, 250, 64, 64, "Radio A", BUTTON_RADIO, BUTTON_GROUP2); MenuAddButton(350, 350, 64, 64, "Radio B", BUTTON_RADIO, BUTTON_GROUP2); MenuEnableGroup(BUTTON_GROUP2); break; case MENU_START: MenuAddButton(50, 150, 250, 64, "Start", BUTTON_CLICK, BUTTON_NO_GROUP); MenuAddButton(50, 250, 250, 64, "Back", BUTTON_CLICK, BUTTON_NO_GROUP); MenuAddButton(350, 150, 64, 64, "Try first!", BUTTON_RADIO, BUTTON_GROUP1); MenuAddButton(350, 250, 64, 64, "10 games", BUTTON_RADIO, BUTTON_GROUP1); MenuEnableGroup(BUTTON_GROUP1); break; case MENU_OPTIONS: MenuAddButton(50, 50, 64, 64, "Headtracking", BUTTON_RADIO, BUTTON_GROUP1); MenuAddButton(50, 150, 64, 64, "Stereo vision", BUTTON_RADIO, BUTTON_GROUP1); MenuEnableGroup(BUTTON_GROUP1); break; } } // MenuBuild void MenuRebuild(void) { MenuClear(); MenuBuild(); } // MenuRebuild void MenuNext(void) { int l_iMenuId = g_pCurMenu->m_iMenuId; l_iMenuId = (l_iMenuId + 1) % 3; g_pCurMenu->m_iMenuId = l_iMenuId; MenuRebuild(); } // MenuNext void MenuInit(int f_iWinWidth, int f_iWinHeight) { // init menu props g_iWinWidth = f_iWinWidth; g_iWinHeight = f_iWinHeight; // set pointer to the current menu g_pCurMenu = &g_sMenuStart; // init main menu g_sMenuMain.m_iMenuId = MENU_MAIN; // init start menu g_sMenuStart.m_iMenuId = MENU_START; // init options menu g_sMenuOptions.m_iMenuId = MENU_OPTIONS; // init font FontInit(f_iWinWidth, f_iWinHeight); // build the current menu (main) MenuBuild(); } // MenuInit void MenuRender(void) { int i = 0; glClearColor(0.9, 0.9, 0.9, 1); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glColor4d(1, 1, 1, 1); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, g_iWinWidth, g_iWinHeight, 0, 0, 1); glMatrixMode(GL_MODELVIEW); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // render the buttons of the current menu for (i; i < g_pCurMenu->m_iButtonCount; i++) { ButtonRender(&g_pCurMenu->m_sButtons[i]); } glDisable(GL_BLEND); //restore the previous projection matrix glMatrixMode(GL_PROJECTION); glPopMatrix(); } // MenuRender int MenuCollision(struct ButtonStruct *f_sButton, int f_iXPos, int f_iYPos) { int l_iCollision; int l_iButtonX, l_iButtonY; int l_iButtonWidth, l_iButtonHeight; l_iButtonX = f_sButton->m_dXPos; l_iButtonY = f_sButton->m_dYPos; l_iButtonWidth = f_sButton->m_dWidth; l_iButtonHeight = f_sButton->m_dHeight; l_iCollision = f_iXPos >= l_iButtonX; l_iCollision &= f_iYPos >= l_iButtonY; l_iCollision &= f_iXPos <= l_iButtonX + l_iButtonWidth; l_iCollision &= f_iYPos <= l_iButtonY + l_iButtonHeight; if (l_iCollision) return TRUE; return FALSE; } // MenuCollision void MenuMouseClick(int f_iGlutButton, int f_iGlutState, int f_iXPos, int f_iYPos) { int i = 0; int l_iXPos, l_iYPos; int l_iWidth, l_iHeight; int l_iType, l_iId, l_iGroup; struct ButtonStruct l_sButton; // button released if (f_iGlutButton == GLUT_LEFT_BUTTON && f_iGlutState == GLUT_UP) { // post a button released event to all buttons for (i; i < g_pCurMenu->m_iButtonCount; i++) { l_iType = g_pCurMenu->m_sButtons[i].m_iType; ButtonRelease(&g_pCurMenu->m_sButtons[i]); } } // check if any button needs attention from the mouse i = g_pCurMenu->m_iButtonCount; for (i; i >= 0; i--) { l_sButton = g_pCurMenu->m_sButtons[i]; l_iXPos = l_sButton.m_dXPos; l_iYPos = l_sButton.m_dYPos; l_iWidth = l_sButton.m_dWidth; l_iHeight = l_sButton.m_dHeight; l_iType = l_sButton.m_iType; l_iId = l_sButton.m_iId; l_iGroup = l_sButton.m_iGroup; if (MenuCollision(&l_sButton, f_iXPos, f_iYPos)) { // button pressed? if (f_iGlutButton == GLUT_LEFT_BUTTON && f_iGlutState == GLUT_DOWN) { ButtonPress(&g_pCurMenu->m_sButtons[i]); if (l_iType == BUTTON_RADIO) { i = 0; while (i < g_pCurMenu->m_iButtonCount) { if (l_iId != g_pCurMenu->m_sButtons[i].m_iId && l_iType == g_pCurMenu->m_sButtons[i].m_iType && l_iGroup == g_pCurMenu->m_sButtons[i].m_iGroup) { ButtonDisable(&g_pCurMenu->m_sButtons[i]); } i++; } } return; } } } } // MenuMouseClick void MenuMouseMove(int f_iXPos, int f_iYPos) { int i = 0; struct ButtonStruct l_sButton; // check if any button needs attention from the mouse for (i; i < g_pCurMenu->m_iButtonCount; i++) { l_sButton = g_pCurMenu->m_sButtons[i]; if (MenuCollision(&l_sButton, f_iXPos, f_iYPos)) { ButtonEnter(&g_pCurMenu->m_sButtons[i]); } else // mouse leaves button { ButtonExit(&g_pCurMenu->m_sButtons[i]); } } } // MenuMouseMove