[Tux4kids-commits] r1157 - tuxmath/trunk/src

Bolesław Kulbabiński bolekk-guest at alioth.debian.org
Tue Jul 7 13:48:57 UTC 2009


Author: bolekk-guest
Date: 2009-07-07 13:48:56 +0000 (Tue, 07 Jul 2009)
New Revision: 1157

Modified:
   tuxmath/trunk/src/loaders.c
   tuxmath/trunk/src/loaders.h
   tuxmath/trunk/src/menu.c
Log:
added menu arrows' functionality and corrected menu re-rendering after resolution change

Modified: tuxmath/trunk/src/loaders.c
===================================================================
--- tuxmath/trunk/src/loaders.c	2009-07-07 13:25:12 UTC (rev 1156)
+++ tuxmath/trunk/src/loaders.c	2009-07-07 13:48:56 UTC (rev 1157)
@@ -33,14 +33,14 @@
 int check_file(const char* file);
 
 #ifdef HAVE_RSVG
-SDL_Surface* load_svg(char* file_name, int width, int height, char* layer_name);
-void get_svg_dimensions(char* file_name, int* width, int* height);
+SDL_Surface* load_svg(const char* file_name, int width, int height, const char* layer_name);
+void get_svg_dimensions(const char* file_name, int* width, int* height);
 #endif
 
-SDL_Surface* load_image(char* file_name, int mode, int w, int h, bool proportional);
+SDL_Surface* load_image(const char* file_name, int mode, int w, int h, bool proportional);
 void fit_in_rectangle(int* width, int* height, int max_width, int max_height);
 SDL_Surface* set_format(SDL_Surface* img, int mode);
-sprite* load_sprite(char* name, int mode, int width, int height, bool proportional);
+sprite* load_sprite(const char* name, int mode, int width, int height, bool proportional);
 
 
 
@@ -98,7 +98,7 @@
    If layer = NULL then the whole image is loaded.
    Return NULL on failure.
    (partly based on TuxPaint's SVG loading function) */
-SDL_Surface* load_svg(char* file_name, int width, int height, char* layer_name)
+SDL_Surface* load_svg(const char* file_name, int width, int height, const char* layer_name)
 {
   cairo_surface_t* temp_surf;
   cairo_t* context;
@@ -195,7 +195,7 @@
   return dest;
 }
 
-void get_svg_dimensions(char* file_name, int* width, int* height)
+void get_svg_dimensions(const char* file_name, int* width, int* height)
 {
   RsvgHandle* file_handle;
   RsvgDimensionData dimensions;
@@ -227,7 +227,7 @@
    The loader (load_svg() or IMG_Load()) is chosen depending on file extension,
    If an SVG file is not found try to load its PNG equivalent
    (unless IMG_NO_PNG_FALLBACK is set) */
-SDL_Surface* LoadScaledImage(char* file_name, int mode, int width, int height)
+SDL_Surface* LoadScaledImage(const char* file_name, int mode, int width, int height)
 {
   return load_image(file_name, mode, width, height, false);
 }
@@ -235,14 +235,14 @@
 /* LoadImageOfBoundingBox : Same as LoadScaledImage but preserve image proportions
    and fit it into max_width x max_height rectangle.
    Returned surface is not necessarily max_width x max_height ! */
-SDL_Surface* LoadImageOfBoundingBox(char* file_name, int mode, int max_width, int max_height)
+SDL_Surface* LoadImageOfBoundingBox(const char* file_name, int mode, int max_width, int max_height)
 {
   return load_image(file_name, mode, max_width, max_height, true);
 }
 
 
 /* load_image : helper function used by LoadScaledImage and LoadImageOfBoundingBox */
-SDL_Surface* load_image(char* file_name, int mode, int w, int h, bool proportional)
+SDL_Surface* load_image(const char* file_name, int mode, int w, int h, bool proportional)
 {
   SDL_Surface* loaded_pic = NULL;
   SDL_Surface* final_pic = NULL;
@@ -392,7 +392,7 @@
 }
 
 /* Load an image without scaling it */
-SDL_Surface* LoadImage(char* file_name, int mode)
+SDL_Surface* LoadImage(const char* file_name, int mode)
 {
   return LoadScaledImage(file_name, mode, -1, -1);
 }
@@ -400,7 +400,7 @@
 
 /* LoadBkgd() : a wrapper for LoadImage() that optimizes
    the format of background image */
-SDL_Surface* LoadBkgd(char* file_name, int width, int height)
+SDL_Surface* LoadBkgd(const char* file_name, int width, int height)
 {
   SDL_Surface* orig = NULL;
   SDL_Surface* final_pic = NULL;
@@ -425,7 +425,7 @@
 /* LoadBothBkgds() : loads two scaled images: one for the fullscreen mode
    (fs_res_x,fs_rex_y) and one for the windowed mode (win_res_x,win_rex_y)
    Now we also optimize the format for best performance */
-void LoadBothBkgds(char* file_name, SDL_Surface** fs_bkgd, SDL_Surface** win_bkgd)
+void LoadBothBkgds(const char* file_name, SDL_Surface** fs_bkgd, SDL_Surface** win_bkgd)
 {
   DEBUGMSG(debug_loaders, "Entering LoadBothBkgds()\n");
   *fs_bkgd = LoadBkgd(file_name, fs_res_x, fs_res_y);
@@ -433,22 +433,22 @@
 }
 
 
-sprite* LoadSprite(char* name, int mode)
+sprite* LoadSprite(const char* name, int mode)
 {
   return LoadScaledSprite(name, mode, -1, -1);
 }
 
-sprite* LoadScaledSprite(char* name, int mode, int width, int height)
+sprite* LoadScaledSprite(const char* name, int mode, int width, int height)
 {
   return load_sprite(name, mode, width, height, false);
 }
 
-sprite* LoadSpriteOfBoundingBox(char* name, int mode, int max_width, int max_height)
+sprite* LoadSpriteOfBoundingBox(const char* name, int mode, int max_width, int max_height)
 {
   return load_sprite(name, mode, max_width, max_height, true);
 }
 
-sprite* load_sprite(char* name, int mode, int width, int height, bool proportional)
+sprite* load_sprite(const char* name, int mode, int width, int height, bool proportional)
 {
   sprite *new_sprite;
   char fn[PATH_MAX];

Modified: tuxmath/trunk/src/loaders.h
===================================================================
--- tuxmath/trunk/src/loaders.h	2009-07-07 13:25:12 UTC (rev 1156)
+++ tuxmath/trunk/src/loaders.h	2009-07-07 13:48:56 UTC (rev 1157)
@@ -44,16 +44,16 @@
 } sprite;
 
 
-SDL_Surface* LoadImage(char* file_name, int mode);
-SDL_Surface* LoadScaledImage(char* file_name, int mode, int width, int height);
-SDL_Surface* LoadImageOfBoundingBox(char* file_name, int mode, int max_width, int max_height);
+SDL_Surface* LoadImage(const char* file_name, int mode);
+SDL_Surface* LoadScaledImage(const char* file_name, int mode, int width, int height);
+SDL_Surface* LoadImageOfBoundingBox(const char* file_name, int mode, int max_width, int max_height);
 
-SDL_Surface* LoadBkgd(char* file_name, int width, int height);
-void         LoadBothBkgds(char* file_name, SDL_Surface** fs_bkgd, SDL_Surface** win_bkgd);
+SDL_Surface* LoadBkgd(const char* file_name, int width, int height);
+void         LoadBothBkgds(const char* file_name, SDL_Surface** fs_bkgd, SDL_Surface** win_bkgd);
 
-sprite*      LoadSprite(char* name, int mode);
-sprite*      LoadScaledSprite(char* name, int mode, int width, int height);
-sprite*      LoadSpriteOfBoundingBox(char* name, int mode, int max_width, int max_height);
+sprite*      LoadSprite(const char* name, int mode);
+sprite*      LoadScaledSprite(const char* name, int mode, int width, int height);
+sprite*      LoadSpriteOfBoundingBox(const char* name, int mode, int max_width, int max_height);
 sprite*      FlipSprite(sprite* in, int X, int Y);
 void         FreeSprite(sprite* gfx);
 void         NextFrame(sprite* s);

Modified: tuxmath/trunk/src/menu.c
===================================================================
--- tuxmath/trunk/src/menu.c	2009-07-07 13:25:12 UTC (rev 1156)
+++ tuxmath/trunk/src/menu.c	2009-07-07 13:48:56 UTC (rev 1157)
@@ -37,14 +37,36 @@
   MENU_MAIN,
   MENU_DIFFICULTY,
   MENU_LESSONS,
+  MENU_LOGIN,
   N_OF_MENUS
 } MenuType;
 
+MenuNode* menus[N_OF_MENUS];
+
 /* actions available while viewing the menu */
 enum { NONE, CLICK, PAGEUP, PAGEDOWN, STOP, RESIZED };
 
-MenuNode* menus[N_OF_MENUS];
+/* stop button, left and right arrow positions do not
+   depend on currently displayed menu */
+SDL_Rect menu_rect, stop_rect, prev_rect, next_rect;
+SDL_Surface *stop_button, *prev_arrow, *next_arrow;
 
+/*TODO: move these constants into a config file (maybe together with
+  titlescreen paths and rects ? ) */
+const float menu_pos[4] = {0.4, 0.25, 0.55, 0.7};
+const float stop_pos[4] = {0.95, 0.0, 0.05, 0.05};
+const float prev_pos[4] = {0.9, 0.95, 0.05, 0.05};
+const float next_pos[4] = {0.95, 0.95, 0.05, 0.05};
+const char* stop_path = "status/stop.png";
+const char* prev_path = "status/left.png";
+const char* next_path = "status/right.png";
+const float button_gap = 0.2, text_h_gap = 0.25, text_w_gap = 0.5;
+
+/* menu title rect */
+SDL_Rect title_rect;
+
+
+
 /* buffer size used when reading attributes or names */
 const int buf_size = 128;
 
@@ -63,6 +85,7 @@
 
 int run_menu(MenuNode* menu, bool return_choice);
 void prerender_menu(MenuNode* menu);
+void prerender_all();
 SDL_Surface** render_buttons(MenuNode* menu, bool selected);
 MenuNode* create_one_level_menu(int items, char** item_names, char* title, char* trailer);
 
@@ -288,7 +311,7 @@
   MenuNode* menu = root;
   MenuNode* tmp_node;
 
-  SDL_Rect left_arrow_rect, right_arrow_rect, stopRect, tmp_rect;
+  SDL_Rect tmp_rect;
   sprite* tmp_sprite;
   int i;
   int stop = 0;
@@ -313,33 +336,6 @@
     menu_item_selected = render_buttons(menu, true);
     items = min(menu->entries_per_screen, menu->submenu_size - menu->first_entry);
 
-    /* Arrow buttons in right lower corner, inset by 20 pixels     */
-    /* with a 10 pixel space between:                              */
-    if (images[IMG_RIGHT])
-    {
-      right_arrow_rect.w = images[IMG_RIGHT]->w;
-      right_arrow_rect.h = images[IMG_RIGHT]->h;
-      right_arrow_rect.x = screen->w - images[IMG_RIGHT]->w - 20;
-      right_arrow_rect.y = screen->h - images[IMG_RIGHT]->h - 20;
-    }
-
-    if (images[IMG_LEFT])
-    {
-      left_arrow_rect.w = images[IMG_LEFT]->w;
-      left_arrow_rect.h = images[IMG_LEFT]->h;
-      left_arrow_rect.x = right_arrow_rect.x - 10 - images[IMG_LEFT]->w;
-      left_arrow_rect.y = screen->h - images[IMG_LEFT]->h - 20;
-    }
-    /* Red "Stop" circle in upper right corner to go back to main menu: */
-    if (images[IMG_STOP])
-    {
-      stopRect.w = images[IMG_STOP]->w;
-      stopRect.h = images[IMG_STOP]->h;
-      stopRect.x = screen->w - images[IMG_STOP]->w;
-      stopRect.y = 0;
-    }
-
-
     DEBUGMSG(debug_menu, "run_menu(): drawing %d buttons\n", items);
     for(i = 0; i < items; i++)
     {
@@ -350,11 +346,13 @@
       if(menu->submenu[menu->first_entry + i]->icon)
         SDL_BlitSurface(menu->submenu[menu->first_entry + i]->icon->default_img, NULL, screen, &menu->submenu[menu->first_entry + i]->icon_rect);
     }
+    SDL_BlitSurface(stop_button, NULL, screen, &stop_rect);
+    if(menu->first_entry > 0)
+      SDL_BlitSurface(prev_arrow, NULL, screen, &prev_rect);
+    if(menu->first_entry + items < menu->submenu_size)
+      SDL_BlitSurface(next_arrow, NULL, screen, &next_rect);
     SDL_UpdateRect(screen, 0, 0, 0, 0);
 
-    /* Move mouse to current button: */
-    //cursor.x = menu_button_rect[imod].x + menu_button_rect[imod].w/2;
-    //cursor.y = menu_button_rect[imod].y + menu_button_rect[imod].h/2;
     SDL_WM_GrabInput(SDL_GRAB_OFF);
 
     /******** Main loop:                                *********/
@@ -396,7 +394,7 @@
             }
 
             /* "Left" button - make click if button active: */
-            if (inRect(left_arrow_rect, event.motion.x, event.motion.y))
+            if (inRect(prev_rect, event.motion.x, event.motion.y))
             {
               if (menu->first_entry > 0)
               {
@@ -410,7 +408,7 @@
             }
 
             /* "Right" button - go to next page: */
-            else if (inRect(right_arrow_rect, event.motion.x, event.motion.y ))
+            else if (inRect(next_rect, event.motion.x, event.motion.y ))
             {
               if (menu->first_entry + items < menu->submenu_size)
               {
@@ -447,31 +445,31 @@
             }
 
             /* "Left" button */
-            if (inRect(left_arrow_rect, event.motion.x, event.motion.y))
+            if (inRect(prev_rect, event.motion.x, event.motion.y))
             {
               if (menu->first_entry > 0)
               {
                 if (Opts_GetGlobalOpt(MENU_SOUND))
                   playsound(SND_POP);
-                action = PAGEDOWN;
+                action = PAGEUP;
               }
               break;  /* from case switch */
             }
 
             /* "Right" button - go to next page: */
-            else if (inRect(right_arrow_rect, event.motion.x, event.motion.y ))
+            else if (inRect(next_rect, event.motion.x, event.motion.y ))
             {
               if (menu->first_entry + items < menu->submenu_size)
               {
-                if (Opts_GetGlobalOpt(MENU_SOUND) && click_flag)
+                if (Opts_GetGlobalOpt(MENU_SOUND))
                   playsound(SND_POP);
-                action = PAGEUP;
+                action = PAGEDOWN;
               }
               break;  /* from case switch */
             }
 
-          /* "Stop" button - go to main menu: */
-            else if (inRect(stopRect, event.button.x, event.button.y ))
+            /* "Stop" button - go to main menu: */
+            else if (inRect(stop_rect, event.button.x, event.button.y ))
             {
               playsound(SND_TOCK);
               action = STOP;
@@ -508,7 +506,7 @@
                 if (Opts_GetGlobalOpt(MENU_SOUND))
                   playsound(SND_TOCK);
                 if (menu->first_entry > 0)
-                  action = PAGEDOWN;
+                  action = PAGEUP;
                 break;
               }
 
@@ -519,7 +517,7 @@
                 if (Opts_GetGlobalOpt(MENU_SOUND))
                   playsound(SND_TOCK);
                 if (menu->first_entry + items < menu->submenu_size)
-                  action = PAGEUP;
+                  action = PAGEDOWN;
                 break;
               }
 
@@ -597,7 +595,7 @@
                     default:
                       break;
                   }
-                  prerender_menu(menu);
+                  prerender_all();
                   action = RESIZED;
                 }
                 break;
@@ -608,7 +606,7 @@
               {
                 SwitchScreenMode();
                 RenderTitleScreen();
-                prerender_menu(menu);
+                prerender_all();
                 action = RESIZED;
                 break;
               }
@@ -701,6 +699,16 @@
               stop = true;
             }
             break;
+
+          case PAGEUP:
+            menu->first_entry -= menu->entries_per_screen;
+            stop = true;
+            break;
+
+          case PAGEDOWN:
+            menu->first_entry += menu->entries_per_screen;
+            stop = true;
+            break;
         }
 
       }  // End of SDL_PollEvent while loop
@@ -775,7 +783,7 @@
 
     /* text */
     tmp_surf = BlackOutline(_(menu->submenu[menu->first_entry + i]->title),
-                            DEFAULT_MENU_FONT_SIZE, selected ? &yellow : &white);
+                            menu->submenu[menu->first_entry + i]->font_size, selected ? &yellow : &white);
     SDL_BlitSurface(tmp_surf, NULL, menu_items[i], &menu->submenu[menu->first_entry + i]->text_rect);
     SDL_FreeSurface(tmp_surf);
   }
@@ -787,12 +795,10 @@
    to fit into current screen */
 void prerender_menu(MenuNode* menu)
 {
-  SDL_Rect menu_rect;
   SDL_Surface* temp_surf;
   MenuNode* curr_node;
   int i, imod, max_text_h = 0, max_text_w = 0;
   int button_h, button_w;
-  float gap;
   char filename[buf_size];
 
   if(NULL == menu)
@@ -807,11 +813,6 @@
     return;
   }
 
-  menu_rect.x = 0.4 * screen->w;
-  menu_rect.y = 0.25 * screen->h;
-  menu_rect.w = 0.55 * screen->w;
-  menu_rect.h = 0.7 * screen->h;
-
   for(i = 0; i < menu->submenu_size; i++)
   {
     temp_surf = NULL;
@@ -824,29 +825,28 @@
     }
   }
 
-  button_h = 2 * max_text_h;
-  button_w = max_text_w + 3 * max_text_h;
+  button_h = (1.0 + 2.0 * text_h_gap) * max_text_h;
+  button_w = max_text_w + (1.0 + 2.0 * text_w_gap) * button_h;
 
-  gap = 0.2;
-  menu->entries_per_screen = (int) ( (menu_rect.h - gap * button_h) / ( (1.0 + gap) * button_h ));
+  menu->entries_per_screen = (int) ( (menu_rect.h - button_gap * button_h) /
+                                   ( (1.0 + button_gap) * button_h ) );
 
   for(i = 0; i < menu->submenu_size; i++)
   {
     curr_node = menu->submenu[i];
     curr_node->button_rect.x = menu_rect.x;
     imod = i % menu->entries_per_screen;
-    curr_node->button_rect.y = menu_rect.y + imod * button_h + (imod + 1) * gap * button_h;
+    curr_node->button_rect.y = menu_rect.y + imod * button_h + (imod + 1) * button_gap * button_h;
     curr_node->button_rect.w = button_w;
     curr_node->button_rect.h = button_h;
 
     curr_node->icon_rect = curr_node->button_rect;
     curr_node->icon_rect.w = curr_node->icon_rect.h;
 
-    curr_node->text_rect = curr_node->button_rect;
-    curr_node->text_rect.y = 0.25 * button_h;
-    curr_node->text_rect.x = (1.0 + gap) * button_h;
-    curr_node->text_rect.h -= 0.25 * button_h;
-    curr_node->text_rect.w -= (1.0 + gap) * button_h;
+    curr_node->text_rect.x = (1.0 + text_w_gap) * curr_node->icon_rect.w;
+    curr_node->text_rect.y = text_h_gap * max_text_h;
+    curr_node->text_rect.h = max_text_h;
+    curr_node->text_rect.w = max_text_w;
 
     curr_node->font_size = DEFAULT_MENU_FONT_SIZE;
 
@@ -864,14 +864,56 @@
 
     prerender_menu(menu->submenu[i]);
   }
+}
 
+void set_rect(SDL_Rect* rect, const float* pos)
+{
+  rect->x = pos[0] * screen->w;
+  rect->y = pos[1] * screen->h;
+  rect->w = pos[2] * screen->w;
+  rect->h = pos[3] * screen->h;
 }
 
+/* prerender arrows, stop button and all non-NULL menus from menus[] array
+   this function should be invoked after every resolution change */
+void prerender_all()
+{
+  int i;
+
+  set_rect(&menu_rect, menu_pos);
+
+  set_rect(&stop_rect, stop_pos);
+  if(stop_button)
+    SDL_FreeSurface(stop_button);
+  stop_button = LoadImageOfBoundingBox(stop_path, IMG_ALPHA, stop_rect.w, stop_rect.h);
+  stop_rect.x = screen->w - stop_button->w;
+
+  set_rect(&prev_rect, prev_pos);
+  if(prev_arrow)
+    SDL_FreeSurface(prev_arrow);
+  prev_arrow = LoadImageOfBoundingBox(prev_path, IMG_ALPHA, prev_rect.w, prev_rect.h);
+
+  set_rect(&next_rect, next_pos);
+  if(next_arrow)
+    SDL_FreeSurface(next_arrow);
+  next_arrow = LoadImageOfBoundingBox(next_path, IMG_ALPHA, next_rect.w, next_rect.h);
+
+  for(i = 0; i < N_OF_MENUS; i++)
+    if(menus[i])
+      prerender_menu(menus[i]);
+}
+
 /* load menu trees from disk and prerender them */
 void LoadMenus(void)
 {
+  FILE* menu_file = NULL;
+  int i;
+
+  for(i = 0; i < N_OF_MENUS; i++)
+    menus[i] = NULL;
+
   /* main menu */
-  FILE* menu_file = fopen(DATA_PREFIX "/menus/main_menu.xml", "r");
+  menu_file = fopen(DATA_PREFIX "/menus/main_menu.xml", "r");
   if(menu_file == NULL)
   {
     DEBUGMSG(debug_menu, "LoadMenus(): Could not load main menu file !\n");
@@ -879,7 +921,6 @@
   else
   {
     menus[MENU_MAIN] = load_menu_from_file(menu_file, NULL);
-    prerender_menu(menus[MENU_MAIN]);
     fclose(menu_file);
   }
 
@@ -892,9 +933,10 @@
   else
   {
     menus[MENU_DIFFICULTY] = load_menu_from_file(menu_file, NULL);
-    prerender_menu(menus[MENU_DIFFICULTY]);
     fclose(menu_file);
   }
+
+  prerender_all();
 }
 
 /* create a simple one-level menu without sprites.
@@ -941,7 +983,6 @@
   char *trailer_quit = "Quit";
   char *trailer_back = "Back";
   char *trailer = NULL;
-  MenuNode* menu;
   SDLMod mod;
 
   DEBUGMSG(debug_menu, "Entering RunLoginMenu()");
@@ -964,12 +1005,12 @@
   if (n_login_questions > 0)
     title = user_login_questions[0];
 
-  menu = create_one_level_menu(n_users, user_names, title, trailer_quit);
+  menus[MENU_LOGIN] = create_one_level_menu(n_users, user_names, title, trailer_quit);
 
   while (n_users) {
     // Get the user choice
-    prerender_menu(menu);
-    chosen_login = run_menu(menu, true);
+    prerender_menu(menus[MENU_LOGIN]);
+    chosen_login = run_menu(menus[MENU_LOGIN], true);
     // Determine whether there were any modifier (CTRL) keys pressed
     mod = SDL_GetModState();
     if (chosen_login == -1 || chosen_login == n_users) {
@@ -984,7 +1025,8 @@
         for (i = 0; i < n_users; i++)
           free(user_names[i]);
         free(user_names);
-        free_menu(menu);
+        free_menu(menus[MENU_LOGIN]);
+        menus[MENU_LOGIN] = NULL;
         return -1;
       }
       else {
@@ -1021,16 +1063,16 @@
       trailer = trailer_back;
     // Check to see if there are more choices to be made
     n_users = read_user_menu_entries(&user_names);
-    DEBUGMSG(debug_menu, "aa");
-    free_menu(menu);
-    menu = create_one_level_menu(n_users, user_names, title, trailer);
+    free_menu(menus[MENU_LOGIN]);
+    menus[MENU_LOGIN] = create_one_level_menu(n_users, user_names, title, trailer);
   }
 
   // The user home directory is set, clean up remaining memory
   for (i = 0; i < n_login_questions; i++)
     free(user_login_questions[i]);
   free(user_login_questions);
-  free_menu(menu);
+  free_menu(menus[MENU_LOGIN]);
+  menus[MENU_LOGIN] = NULL;
 
   // Signal success
   return 0;




More information about the Tux4kids-commits mailing list