/*************************************************************************** * Copyright (C) 2005 by Michal Turek - Woq * * WOQ (zavinac) seznam.cz * * * * Program demonstruje vytvoreni jednoducheho menu, ktere je zapouzdrene * * do specialni tridy. Vyber polozek je aplikaci elegantne oznamovan * * prostrednictvim uzivatelskych udalosti. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include <stdio.h> #include <SDL.h> #include <SDL_image.h> #include <SDL_ttf.h> #include "qsdlmenu.h" // Trida menu using namespace std; using namespace libQuark; /* * Symbolicke konstanty */ #define SDL_SUBSYSTEMS SDL_INIT_VIDEO #define WIN_WIDTH 320 #define WIN_HEIGHT 240 #define WIN_BPP 0 #define WIN_TITLE "Menu" // Pocet obrazku pozadi #define NUM_BG 5 // Kody zivatelskych udalosti #define USR_EVT_CHANGE_BG 0 #define USR_EVT_HIDE_MENU 1 #define USR_EVT_EXIT_PROG 2 /* * Funkcni prototypy */ bool Init(); // Inicializace void Destroy(); // Deinicializace void Draw(); // Vykresleni bool ProcessEvent(); // Osetruje udalosti int main(int argc, char *argv[]); // Vstup do programu bool ToggleFullscreen(); // Zmena okno/fullscreen SDL_Surface *LoadImage(const char *filename, bool alpha = false); /* * Globalni promenne */ Uint8 g_win_flags = SDL_HWSURFACE|SDL_DOUBLEBUF; SDL_Surface *g_screen = NULL; // Okno SDL_Surface *g_bg[NUM_BG]; // Pozadi int g_act_bg = 0; // Index aktualniho pozadi TTF_Font *g_font; // Font QSDLMenu g_menu; // Objekt menu bool g_menu_active = true; // Menu aktivni? /* * Inicializacni funkce */ bool Init() { // Inicializace SDL if(SDL_Init(SDL_SUBSYSTEMS) == -1) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return false; } // Inicializace SDL_ttf if(TTF_Init() == -1) { printf("Unable to initialize SDL_ttf: %s\n", TTF_GetError()); return false; } // Nastaveni ikony SDL_Surface *icon = SDL_LoadBMP("./icon.bmp"); if(icon != NULL) { SDL_WM_SetIcon(icon, NULL); SDL_FreeSurface(icon); } // Vytvori okno s definovanymi vlastnostmi g_screen = SDL_SetVideoMode(WIN_WIDTH, WIN_HEIGHT, WIN_BPP, g_win_flags); if(g_screen == NULL) { fprintf(stderr, "Unable to set %dx%d video: %s\n", WIN_WIDTH, WIN_HEIGHT, SDL_GetError()); return false; } // Titulek okna SDL_WM_SetCaption(WIN_TITLE, NULL); // Nahrani fontu g_font = TTF_OpenFont("DejaVuSansCondensed.ttf", 16); if(!g_font) { printf("Unable to open font: %s\n", TTF_GetError()); return false; } TTF_SetFontStyle(g_font, TTF_STYLE_BOLD);// Tucne // Inicializace menu g_menu.Init(g_font, 10); // Nahrani obrazku char tmp[10]; for(int i = 0; i < NUM_BG; i++) { sprintf(tmp, "bg%d.jpg", i); if((g_bg[i] = LoadImage(tmp, false)) == NULL) return false; // Pridani polozky do menu g_menu.AddItem(USR_EVT_CHANGE_BG, tmp); } g_menu.AddItem(USR_EVT_HIDE_MENU, "Skryt"); g_menu.AddItem(USR_EVT_EXIT_PROG, "Konec"); return true; } /* * Deinicializacni funkce */ void Destroy() { g_menu.Destroy(); // Smaze obrazky for(int i = 0; i < NUM_BG; i++) { if(g_bg[i] != NULL) { SDL_FreeSurface(g_bg[i]); g_bg[i] = NULL; } } // Smaze font a uklidi po SDL_ttf if(g_font != NULL) { TTF_CloseFont(g_font); g_font = NULL; } TTF_Quit(); SDL_Quit(); } /* * Vykresleni sceny */ void Draw() { SDL_Rect rect; int x, y; // Pozadi dlazdicove pres cele okno for(x = 0; x < g_screen->w; x += g_bg[g_act_bg]->w) { for(y = 0; y < g_screen->h; y += g_bg[g_act_bg]->h) { rect.x = x; rect.y = y; SDL_BlitSurface(g_bg[g_act_bg], NULL, g_screen, &rect); } } // Menu if(g_menu_active) g_menu.Draw(125, 70); SDL_Flip(g_screen); } /* * Osetreni udalosti */ bool ProcessEvent() { SDL_Event event; while(SDL_WaitEvent(&event)) { switch(event.type) { // Stisk klavesy case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_ESCAPE: if(!g_menu_active) { g_menu_active = true; } else { // Esc, menu aktivni, posl. polozka if(g_menu.GetSel() == (int)g_menu.GetNumItems()-1) { // Konec aplikace return false; } else { // Zvoli posledni polozku g_menu.SelectLast(); } } break; case SDLK_UP: if(g_menu_active) g_menu.SelectPrevious(); break; case SDLK_DOWN: if(g_menu_active) g_menu.SelectNext(); break; case SDLK_RETURN: case SDLK_KP_ENTER: if(g_menu_active) g_menu.Choose(); break; case SDLK_F1: if(!ToggleFullscreen()) return false; break; default: break; } break; // Uzivatelska udalost case SDL_USEREVENT: switch(event.user.code) { // Zmena pozadi case USR_EVT_CHANGE_BG: // Poradi je ve tride stejne jako v poli g_act_bg = g_menu.GetSel(); break; // Skryti menu case USR_EVT_HIDE_MENU: g_menu_active = false; g_menu.SelectFirst();// Vyber pro priste break; // Konec programu case USR_EVT_EXIT_PROG: return false; break; default: break; } break; // Zmena velikosti okna case SDL_VIDEORESIZE: g_screen = SDL_SetVideoMode(event.resize.w, event.resize.h, WIN_BPP, g_win_flags); if(g_screen == NULL) { fprintf(stderr, "Unable to resize window: %s\n", SDL_GetError()); return false; } break; // Pozadavek na ukonceni case SDL_QUIT: return false; break; default: break; } // Prekresleni Draw(); } return true; } /* * Vstup do programu */ int main(int argc, char *argv[]) { printf(WIN_TITLE); printf("\nPress ESC key to quit.\n"); // Inicializace if(!Init()) { Destroy(); return 1; } // Hlavni smycka programu bool done = false; while(!done) { done = !ProcessEvent(); } // Deinicializace a konec Destroy(); return 0; } //////////////////////////////////////////////////////////////// // "Standardni funkce" // //////////////////////////////////////////////////////////////// /* * Funkce se pokusi nahrat obrazek ze souboru a zkonvertovat ho * na stejny pixel format, jako ma okno (framebuffer) */ SDL_Surface *LoadImage(const char *filename, bool alpha) { SDL_Surface *tmp;// Pomocny SDL_Surface *ret;// Bude vracen if((tmp = IMG_Load(filename)) == NULL)// Prilinkovat SDL_image { fprintf(stderr, "%s\n", SDL_GetError()); return NULL; } if((ret = (alpha) ? SDL_DisplayFormatAlpha(tmp) : SDL_DisplayFormat(tmp)) == NULL) { fprintf(stderr, "%s\n", SDL_GetError()); SDL_FreeSurface(tmp); return NULL; } SDL_FreeSurface(tmp);// Uz neni potreba return ret; } /* * Zmena modu okno/fullscreen (melo by fungovat vsude, nejen pod X11) */ bool ToggleFullscreen() { // Negace priznakoveho bitu ve flagach if(g_win_flags & SDL_FULLSCREEN)// Z fullscreenu do okna g_win_flags &= ~SDL_FULLSCREEN; else// Z okna do fullscreenu g_win_flags |= SDL_FULLSCREEN; // Pokus o prepnuti if(SDL_WM_ToggleFullScreen(g_screen) == 0) { fprintf(stderr, "Unable to toggle fullscreen," "trying to recreate window\n"); SDL_FreeSurface(g_screen); g_screen = SDL_SetVideoMode(WIN_WIDTH, WIN_HEIGHT, WIN_BPP, g_win_flags); if(g_screen == NULL) { fprintf(stderr, "Unable to recreate window: %s\n", SDL_GetError()); return false;// Ukonci program } Draw();// Prekresli scenu } return true;// OK }