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

Bolesław Kulbabiński bolekk-guest at alioth.debian.org
Fri Jul 3 00:42:41 UTC 2009


Author: bolekk-guest
Date: 2009-07-03 00:42:41 +0000 (Fri, 03 Jul 2009)
New Revision: 1136

Modified:
   tuxmath/trunk/src/SDL_extras.c
   tuxmath/trunk/src/SDL_extras.h
   tuxmath/trunk/src/menu.c
   tuxmath/trunk/src/menu.h
   tuxmath/trunk/src/titlescreen.c
Log:
added primitive menu rendering functions to test xml menus

Modified: tuxmath/trunk/src/SDL_extras.c
===================================================================
--- tuxmath/trunk/src/SDL_extras.c	2009-07-02 22:26:35 UTC (rev 1135)
+++ tuxmath/trunk/src/SDL_extras.c	2009-07-03 00:42:41 UTC (rev 1136)
@@ -25,23 +25,30 @@
                 int radius,
                 Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 {
+  SDL_Surface* tmp_surf = CreateButton(target_rect->w, target_rect->h,
+                                       radius, r, g, b, a);
+  SDL_BlitSurface(tmp_surf, NULL, screen, target_rect);
+  SDL_FreeSurface(tmp_surf);
+}
+
+SDL_Surface* CreateButton(int w, int h, int radius,
+                          Uint8 r, Uint8 g, Uint8 b, Uint8 a)
+{
   /* NOTE - we use a 32-bit temp surface even if we have a 16-bit */
   /* screen - it gets converted during blitting.                  */
   SDL_Surface* tmp_surf = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCALPHA,
-                                          target_rect->w,
-                                          target_rect->h,
+                                          w,
+                                          h,
                                           32,
                                           rmask, gmask, bmask, amask);
+
   Uint32 color = SDL_MapRGBA(tmp_surf->format, r, g, b, a);
   SDL_FillRect(tmp_surf, NULL, color);
   RoundCorners(tmp_surf, radius);
-
-  SDL_BlitSurface(tmp_surf, NULL, screen, target_rect);
-  SDL_FreeSurface(tmp_surf);
+  return tmp_surf;
 }
 
 
-
 void RoundCorners(SDL_Surface* s, Uint16 radius)
 {
   int y = 0;

Modified: tuxmath/trunk/src/SDL_extras.h
===================================================================
--- tuxmath/trunk/src/SDL_extras.h	2009-07-02 22:26:35 UTC (rev 1135)
+++ tuxmath/trunk/src/SDL_extras.h	2009-07-03 00:42:41 UTC (rev 1136)
@@ -30,6 +30,8 @@
 
 /* Non-text graphics functions: */
 void DrawButton(SDL_Rect* target_rect, int radius, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
+SDL_Surface* CreateButton(int w, int h, int radius,
+                          Uint8 r, Uint8 g, Uint8 b, Uint8 a);
 void RoundCorners(SDL_Surface* s, Uint16 radius);
 SDL_Surface* Flip(SDL_Surface *in, int x, int y);
 int  inRect(SDL_Rect r, int x, int y);

Modified: tuxmath/trunk/src/menu.c
===================================================================
--- tuxmath/trunk/src/menu.c	2009-07-02 22:26:35 UTC (rev 1135)
+++ tuxmath/trunk/src/menu.c	2009-07-03 00:42:41 UTC (rev 1136)
@@ -11,8 +11,11 @@
   Copyright: See COPYING file that comes with this distribution.
 */
 
-#include "globals.h"
 #include "menu.h"
+#include "SDL_extras.h"
+#include "titlescreen.h"
+#include "options.h"
+#include "fileops.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,16 +46,21 @@
 MenuNode* load_menu_from_file(FILE* xml_file);
 void free_menu(MenuNode* menu);
 
+SDL_Surface** render_buttons(MenuNode* menu, bool selected);
 
-/* creates new MenuNode struct with all field set to NULL (or 0) */
+
+
+/* creates new MenuNode struct with all fields set to NULL (or 0) */
 MenuNode* create_empty_node()
 {
   MenuNode* new_node = malloc(sizeof(MenuNode));
   new_node->title = NULL;
-  new_node->sprite = NULL;
-  new_node->choice = 0;
+  new_node->icon_name = NULL;
+  new_node->icon = NULL;
   new_node->submenu_size = 0;
   new_node->submenu = NULL;
+  new_node->activity = 0;
+  new_node->begin = 0;
 
   return new_node;
 }
@@ -81,12 +89,12 @@
     else if(strcmp(attr_name, "entries") == 0)
       node->submenu_size = atoi(attr_val);
     else if(strcmp(attr_name, "sprite") == 0)
-      node->sprite = strdup(attr_val);
+      node->icon_name = strdup(attr_val);
     else if(strcmp(attr_name, "run") == 0)
     {
       for(i = 0; i < N_OF_ACTIVITIES; i++)
         if(strcmp(attr_val, activities[i]) == 0)
-          node->choice = i;
+          node->activity = i;
     }
     else
       DEBUGMSG(debug_menu_parser, "read_attributes(): unknown attribute %s , omitting\n", attr_name);
@@ -154,8 +162,10 @@
   {
     if(menu->title != NULL)
       free(menu->title);
-    if(menu->sprite != NULL)
-      free(menu->sprite);
+    if(menu->icon_name != NULL)
+      free(menu->icon_name);
+    if(menu->icon != NULL)
+      FreeSprite(menu->icon);
 
     if(menu->submenu != NULL)
     {
@@ -172,14 +182,206 @@
   }
 }
 
-/* display the menu
+
+
+/* Display the menu and run the event loop.
    if return_choice = true then return chosen value instead of
    running handle_choice() */
 int run_menu(MenuNode* menu, bool return_choice)
 {
-  
+  SDL_Surface **menu_item_unselected = NULL;
+  SDL_Surface **menu_item_selected = NULL;
+  SDL_Event event;
+  int redraw, i;
+  int stop = 0;
+  int items;
+
+  for(;;) /* one execution for one menu level */
+  {
+    /* render buttons for current menu page */
+    menu_item_unselected = render_buttons(menu, false);
+    menu_item_selected = render_buttons(menu, true);
+    items = min(menu->entries_per_page, menu->submenu_size - menu->begin);
+
+
+    redraw = 1;  // force a full redraw on first pass
+    while (SDL_PollEvent(&event));  // clear pending events
+    while (!stop)
+    {
+      while (SDL_PollEvent(&event))
+      {
+        switch (event.type)
+        {
+          case SDL_MOUSEMOTION:
+          {
+            for (i = menu->begin; i < menu->begin + items; i++)
+            {
+              if (inRect(menu->submenu[i]->button_rect, event.motion.x, event.motion.y))
+              {
+                // Play sound if loc is being changed:
+                if (Opts_GetGlobalOpt(MENU_SOUND))
+                {
+                  playsound(SND_TOCK);
+                }
+                break;   /* from for loop */
+              }
+            }
+
+            break;
+          }
+        }
+      }
+
+      if(redraw)
+      {
+        for(i = 0; i < menu->submenu_size; i++)
+          SDL_BlitSurface(menu_item_unselected[i], NULL, screen, &menu->submenu[i]->button_rect);
+        SDL_UpdateRect(screen, 0, 0, 0, 0);
+        redraw = 0;
+      }
+    }
+    break;
+
+    /* free button surfaces */
+    for(i = 0; i < items; i++)
+    {
+      SDL_FreeSurface(menu_item_unselected[i]);
+      SDL_FreeSurface(menu_item_selected[i]);
+    }
+    free(menu_item_unselected);
+    free(menu_item_selected);
+  }
+
+  return -1;
 }
 
+SDL_Surface** render_buttons(MenuNode* menu, bool selected)
+{
+  SDL_Surface** menu_items = NULL;
+  SDL_Rect curr_rect, tmp_rect;
+  SDL_Surface* tmp_surf = NULL;
+  int i;
+  int items = min(menu->entries_per_page, menu->submenu_size - menu->begin);
+
+  menu_items = (SDL_Surface**) malloc(items * sizeof(SDL_Surface*));
+  if(NULL == menu_items)
+  {
+    DEBUGMSG(debug_menu, "render_buttons(): failed to allocate memory for buttons!");
+    return NULL;  // error
+  }
+
+  for (i = 0; i < items; i++)
+  {
+    curr_rect = menu->submenu[menu->begin + i]->button_rect;
+    menu_items[i] = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCALPHA,
+                                          curr_rect.w,
+                                          curr_rect.h,
+                                          32,
+                                          rmask, gmask, bmask, amask);
+
+    SDL_BlitSurface(screen, &curr_rect, menu_items[i], NULL);
+    /* button */
+    if(selected)
+      tmp_surf = CreateButton(curr_rect.w, curr_rect.h, 10, SEL_RGBA);
+    else
+      tmp_surf = CreateButton(curr_rect.w, curr_rect.h, 10, REG_RGBA);
+
+    SDL_BlitSurface(tmp_surf, NULL, menu_items[i], NULL);
+    SDL_FreeSurface(tmp_surf);
+
+    /* text */
+    tmp_surf = BlackOutline(_(menu->submenu[menu->begin + i]->title),
+                            DEFAULT_MENU_FONT_SIZE, selected ? &yellow : &white);
+    tmp_rect = tmp_surf->clip_rect;
+    tmp_rect.x = curr_rect.h * 2;
+    tmp_rect.y = (curr_rect.h - tmp_surf->h) / 2;
+    SDL_BlitSurface(tmp_surf, NULL, menu_items[i], &tmp_rect);
+    SDL_FreeSurface(tmp_surf);
+
+    /* icon */
+    if(menu->submenu[menu->begin + i]->icon)
+    {
+      tmp_rect = menu->submenu[menu->begin + i]->icon->default_img->clip_rect;
+      tmp_rect.x = 0;
+      tmp_rect.y = 0;
+      SDL_BlitSurface(menu->submenu[menu->begin + i]->icon->default_img, NULL, menu_items[i], &tmp_rect);
+    }
+  }
+
+  return menu_items;
+}
+
+/* recursively load sprites and calculate button rects
+   to fit into current screen */
+void render_menu(MenuNode* menu)
+{
+  SDL_Rect menu_rect;
+  SDL_Surface* temp_surf;
+  MenuNode* curr_node;
+  int i, max_text_h = 0, max_text_w = 0;
+  int button_h, button_w;
+  float gap;
+  char filename[buf_size];
+
+  if(NULL == menu)
+  {
+    DEBUGMSG(debug_menu, "render_menu(): NULL pointer, exiting !");
+    return;
+  }
+
+  if(0 == menu->submenu_size)
+  {
+    DEBUGMSG(debug_menu, "render_menu(): no submenu, exiting.");
+    return;
+  }
+
+  menu_rect.x = 0.3 * screen->w;
+  menu_rect.y = 0.25 * screen->h;
+  menu_rect.w = 0.65 * screen->w;
+  menu_rect.h = 0.75 * screen->h;
+
+  for(i = 0; i < menu->submenu_size; i++)
+  {
+    temp_surf = NULL;
+    temp_surf = SimpleText(menu->submenu[i]->title, DEFAULT_MENU_FONT_SIZE, &black);
+    if(temp_surf)
+    {
+      max_text_h = max(max_text_h, temp_surf->h);
+      max_text_w = max(max_text_w, temp_surf->w);
+      SDL_FreeSurface(temp_surf);
+    }
+  }
+
+  button_h = 2 * max_text_h;
+  button_w = max_text_w + 3 * max_text_h;
+
+  gap = 0.2;
+  menu->entries_per_page = (int) ( (menu_rect.h - gap * button_h) / (1.0 + gap) );
+
+  for(i = 0; i < menu->submenu_size; i++)
+  {
+    curr_node = menu->submenu[i];
+    curr_node->button_rect.x = menu_rect.x;
+    curr_node->button_rect.y = menu_rect.y + i * button_h + (i + 1) * gap * button_h;
+    curr_node->button_rect.w = button_w;
+    curr_node->button_rect.h = button_h;
+    curr_node->font_size = DEFAULT_MENU_FONT_SIZE;
+
+    if(curr_node->icon)
+      FreeSprite(curr_node->icon);
+
+    if(curr_node->icon_name)
+    {
+      sprintf(filename, "sprites/%s", curr_node->icon_name);
+      DEBUGMSG(debug_menu, "render_menu(): loading sprite %s for item #%d.\n", filename, i);
+      curr_node->icon = LoadSpriteOfBoundingBox(filename, IMG_ALPHA, button_h, button_h);
+    }
+    else
+      DEBUGMSG(debug_menu, "render_menu(): no sprite for item #%d.\n", i);
+  }
+
+}
+
 /* load menu trees from disk */
 void LoadMenus(void)
 {
@@ -213,22 +415,18 @@
     0 indicates that a choice has been made. */
 int RunLoginMenu(void)
 {
-
+  return 0;
 }
 
-/* run main menu. If this function ends it means that tuxmath is going to quit */ 
+/* run main menu. If this function ends it means that tuxmath is going to quit */
 void RunMainMenu(void)
 {
+  DEBUGMSG(debug_menu, "Entering RunMainMenu()\n");
+  render_menu(menus[MENU_MAIN]);
   run_menu(menus[MENU_MAIN], false);
+  DEBUGMSG(debug_menu, "Leaving RunMainMenu()\n");
 }
 
-/* calculate proper sizes and positions of menu elements,
-   load sprites */
-void RenderMenus(void)
-{
-
-}
-
 /* free all loaded menu trees */
 void UnloadMenus(void)
 {

Modified: tuxmath/trunk/src/menu.h
===================================================================
--- tuxmath/trunk/src/menu.h	2009-07-02 22:26:35 UTC (rev 1135)
+++ tuxmath/trunk/src/menu.h	2009-07-03 00:42:41 UTC (rev 1136)
@@ -15,6 +15,10 @@
 #ifndef MENU_H
 #define MENU_H
 
+#include "SDL.h"
+#include "globals.h"
+#include "loaders.h"
+
 /* these are all menu choices that are available in tuxmath.
    By using a define we can create both an enum and
    a string array without writing these names twice */
@@ -49,15 +53,27 @@
 #undef X
 
 struct mNode {
+  struct mNode* parent;
+
   char* title;
-  char* sprite;
+  int font_size;
 
+  char* icon_name;
+  sprite* icon;
+
+  SDL_Rect button_rect;
+
   /* submenu_size = 0 if no submenu */
   int submenu_size;
   struct mNode** submenu;
 
-  /* available only if submenu_size = 0 */
-  int choice;
+  /* these fields are used only if submenu_size = 0 */
+  int activity;
+
+  /* these fields are used only if submenu_size > 0 */
+  bool display_title;
+  int entries_per_page;
+  int begin;
 };
 
 typedef struct mNode MenuNode;
@@ -66,7 +82,6 @@
 void LoadMenus(void);
 int RunLoginMenu(void);
 void RunMainMenu(void);
-void RenderMenus(void);
 void UnloadMenus(void);
 
 #endif // MENU_H

Modified: tuxmath/trunk/src/titlescreen.c
===================================================================
--- tuxmath/trunk/src/titlescreen.c	2009-07-02 22:26:35 UTC (rev 1135)
+++ tuxmath/trunk/src/titlescreen.c	2009-07-03 00:42:41 UTC (rev 1136)
@@ -374,6 +374,7 @@
     audioMusicLoad("tuxi.ogg", -1);
   }
 
+  //RunMainMenu();
   /* If necessary, have the user log in */
   if (run_login_menu() != -1) {
     /* Finish parsing user options */




More information about the Tux4kids-commits mailing list