#ifdef G_OS_WIN32 #define WIN32_LEAN_AND_MEAN 1 #include #else #define FALSE 0 #define TRUE !FALSE #endif #include #include #include "message_queue.h" #include "menu_msg.h" #include "message_input.h" #include "menu.h" #include "button.h" #include "font.h" #define MENU_MAX_BUTTONS 16 enum MenuState { MENU_OFF, 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_sMenuOff; // definition of the menu when it's disabled (empty menu) 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 struct BitmapStruct g_sCursorImage; // bitmap struct of the cursor int g_iWinWidth; int g_iWinHeight; int g_iXPos; // last cursor pos int g_iYPos; 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, void (*f_fpFunc)(void)) { int i = g_pCurMenu->m_iButtonCount; if (i > MENU_MAX_BUTTONS - 1) { // return } else { // 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, f_fpFunc); g_pCurMenu->m_iButtonCount = i + 1; } } // MenuAddButton void MenuAddLabel(int f_dXPos, int f_dYPos, char *f_pcTitle) { MenuAddButton(f_dXPos, f_dYPos, 0, 0, f_pcTitle, BUTTON_LABEL, BUTTON_NO_GROUP, NULL); } //MenuAddLabel 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_OFF: // no buttons break; case MENU_MAIN: MenuAddLabel(200, 150, "Press A+B to begin"); break; case MENU_START: MenuAddLabel(50, 50, "Headtracking"); MenuAddButton(150, 100, 64, 64, "On", BUTTON_RADIO, BUTTON_GROUP1, NULL); MenuAddButton(350, 100, 64, 64, "Off", BUTTON_RADIO, BUTTON_GROUP1, NULL); MenuEnableGroup(BUTTON_GROUP1); MenuAddLabel(50, 250, "Stereo vision"); MenuAddButton(150, 300, 64, 64, "On", BUTTON_RADIO, BUTTON_GROUP2, NULL); MenuAddButton(350, 300, 64, 64, "Off", BUTTON_RADIO, BUTTON_GROUP2, NULL); MenuAddButton(350, 400, 256, 64, "Next", BUTTON_CLICK, BUTTON_NO_GROUP, MenuPostMessageStart); MenuEnableGroup(BUTTON_GROUP2); break; case MENU_OPTIONS: MenuAddButton(200, 150, 250, 64, "Abort", BUTTON_CLICK, BUTTON_NO_GROUP, MenuPostMessageAbort); MenuAddButton(200, 250, 250, 64, "Recalibrate", BUTTON_CLICK, BUTTON_NO_GROUP, MenuPostMessageAbort); MenuEnableGroup(BUTTON_GROUP1); break; } } // MenuBuild void MenuNext(void) { int l_iMenuId = g_pCurMenu->m_iMenuId; l_iMenuId = (l_iMenuId + 1) % 4; switch (l_iMenuId) { default: case MENU_OFF: g_pCurMenu = &g_sMenuOff; break; case MENU_MAIN: g_pCurMenu = &g_sMenuMain; break; case MENU_START: g_pCurMenu = &g_sMenuStart; break; case MENU_OPTIONS: g_pCurMenu = &g_sMenuOptions; break; } } // MenuNext void MenuInit(int f_iWinWidth, int f_iWinHeight) { // init menu props g_iWinWidth = f_iWinWidth; g_iWinHeight = f_iWinHeight; g_iXPos = -100; g_iYPos = -100; // init main off g_sMenuOff.m_iMenuId = MENU_OFF; g_pCurMenu = &g_sMenuOff; MenuBuild(); // init main menu g_sMenuMain.m_iMenuId = MENU_MAIN; g_pCurMenu = &g_sMenuMain; MenuBuild(); // init start menu g_sMenuStart.m_iMenuId = MENU_START; g_pCurMenu = &g_sMenuStart; MenuBuild(); // init options menu g_sMenuOptions.m_iMenuId = MENU_OPTIONS; g_pCurMenu = &g_sMenuOptions; MenuBuild(); // init font FontInit(f_iWinWidth, f_iWinHeight); //g_pCurMenu = &g_sMenuOff; g_pCurMenu = &g_sMenuMain; // load cursor image g_sCursorImage = BitmapLoad("img/cursor.bmp"); } // MenuInit void MenuRender(void) { int i = 0; glClearColor(0.9, 0.9, 0.9, 1); glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, g_iWinWidth, g_iWinHeight, 0, 0, 1); glMatrixMode(GL_MODELVIEW); glEnable(GL_BLEND); if (g_pCurMenu->m_iMenuId != MENU_OFF) { glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR); glColor3f(0.6, 0.6, 0.7); glBegin(GL_QUADS); glVertex2i(0, 0); glVertex2i(0, g_iWinHeight); glVertex2i(g_iWinWidth, g_iWinHeight); glVertex2i(g_iWinWidth, 0); glEnd(); } glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // render the buttons of the current menu for (i; i < g_pCurMenu->m_iButtonCount; i++) { glColor4d(1, 1, 1, 1); ButtonRender(&g_pCurMenu->m_sButtons[i]); } if (g_pCurMenu->m_iMenuId != MENU_OFF) { // render cursor glColor4d(1, 1, 1, 1); BitmapRender(g_iXPos, g_iYPos, 64, //g_sCursorImage.m_iWidth, 64, //g_sCursorImage.m_iHeight, g_sCursorImage.m_iImageId); } glDisable(GL_BLEND); //restore the previous projection matrix glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); } // MenuRender void MenuProcessMessage(void) { struct messageq_s *message; struct input_payload_wiimote *l_pMsg; int l_iXPos, l_iYPos; int l_iWidth, l_iHeight; int i = 0; message = messageq_get(MESSAGE_MENU); if (message) { switch(message->sender) { case MESSAGE_INPUT_KEYBOARD: break; case MESSAGE_INPUT_MOUSE: break; case MESSAGE_INPUT_WIIMOTE: l_pMsg = (struct input_payload_wiimote*)message->payload; switch (g_pCurMenu->m_iMenuId) { case MENU_MAIN: if (l_pMsg->btns & WIIMOTE_BUTTON_A && l_pMsg->btns & WIIMOTE_BUTTON_B) { MenuNext(); } break; default: if (l_pMsg->posDataValid) { l_iWidth = glutGet(GLUT_WINDOW_WIDTH); l_iHeight = glutGet(GLUT_WINDOW_HEIGHT); l_iXPos = l_pMsg->relX * l_iWidth; l_iYPos = l_iHeight - (l_pMsg->relY * l_iHeight); if (l_pMsg->btns & WIIMOTE_BUTTON_A) { MenuMouseClick(GLUT_LEFT_BUTTON, GLUT_DOWN, l_iXPos, l_iYPos); } else if (l_pMsg->btnsUp & WIIMOTE_BUTTON_A) { MenuMouseClick(GLUT_LEFT_BUTTON, GLUT_UP, l_iXPos, l_iYPos); } else { MenuMouseMove(l_iXPos, l_iYPos); } } break; break; } break; } } } int MenuCollision(struct ButtonStruct *f_sButton, int f_iXPos, int f_iYPos) { int l_bCollision; int l_iButtonX, l_iButtonY; int l_iButtonWidth, l_iButtonHeight; l_iButtonX = f_sButton->m_iXPos; l_iButtonY = f_sButton->m_iYPos; l_iButtonWidth = f_sButton->m_iWidth; l_iButtonHeight = f_sButton->m_iHeight; l_bCollision = f_iXPos >= l_iButtonX; l_bCollision &= f_iYPos >= l_iButtonY; l_bCollision &= f_iXPos <= l_iButtonX + l_iButtonWidth; l_bCollision &= f_iYPos <= l_iButtonY + l_iButtonHeight; if (l_bCollision) return TRUE; return FALSE; } // MenuCollision void MenuMouseClick(int f_iGlutButton, int f_iGlutState, int f_iXPos, int f_iYPos) { int i = 0; 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]); if (MenuCollision(&g_pCurMenu->m_sButtons[i], f_iXPos, f_iYPos)) { ButtonExecute(&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_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; g_iXPos = f_iXPos; g_iYPos = f_iYPos; // 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 void MenuOff(void) { g_pCurMenu = &g_sMenuOff; } // MenuOff