home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / menus.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-04-27  |  7.6 KB  |  284 lines

  1. // menus.cpp: ingame menu system (also used for scores and serverlist)
  2.  
  3. #include "cube.h"
  4.  
  5. struct mitem { char *text, *action, *hoveraction; };
  6.  
  7. struct gmenu
  8. {
  9.     char *name, *title;
  10.     vector<mitem> items;
  11.     int mwidth;
  12.     int menusel;
  13.     char *mdl; // (optional) md2 mdl
  14.     int anim, rotspeed, scale;
  15.     bool allowinput, inited;
  16.     void (__cdecl *refreshfunc)(void *, bool);
  17. };
  18.  
  19. hashtable<char *, gmenu> menus;
  20. gmenu *curmenu = NULL, *lastmenu = NULL;
  21.  
  22. vector<gmenu *> menustack;
  23.  
  24. void menuset(void *m)
  25. {
  26.     if(curmenu==m) return;
  27.     curmenu = (gmenu *)m;
  28.     if(curmenu)
  29.     {
  30.         curmenu->inited = false;
  31.         if(curmenu->allowinput) player1->stopmoving();
  32.         else curmenu->menusel = 0;
  33.     }
  34. }
  35.  
  36. void showmenu(char *name)
  37. {
  38.     if(!name)
  39.     {
  40.         curmenu = NULL;
  41.         return;
  42.     }
  43.     gmenu *m = menus.access(name);
  44.     if(!m) return;
  45.     menuset(m);
  46. }
  47.  
  48. void drawarrow(int dir, int x, int y, int size, float r = 1.0f, float g = 1.0f, float b = 1.0f)
  49. {
  50.     glDisable(GL_BLEND);
  51.     glDisable(GL_TEXTURE_2D);
  52.     glColor3f(r, g, b);
  53.     
  54.     glBegin(GL_POLYGON);
  55.     glVertex2i(x, dir ? y+size : y);
  56.     glVertex2i(x+size/2, dir ? y : y+size);
  57.     glVertex2i(x+size, dir ? y+size : y);
  58.     glEnd();
  59.     xtraverts += 3;
  60.    
  61.     glEnable(GL_TEXTURE_2D);
  62.     glEnable(GL_BLEND);
  63. }
  64.  
  65. void drawmenubg(int x1, int y1, int x2, int y2, bool border)
  66. {
  67.     static Texture *tex = NULL;
  68.     if(!tex) tex = textureload("packages/textures/makke/menu.jpg");
  69.     blendbox(x1, y1, x2, y2, border, tex->id);
  70. };
  71.  
  72. #define MAXMENU 17
  73.  
  74. bool rendermenu()
  75. {
  76.     if(!curmenu) { menustack.setsize(0); return false; }
  77.     
  78.     setscope(false);
  79.     
  80.     gmenu &m = *curmenu;
  81.     if(m.refreshfunc) 
  82.     {
  83.         (*m.refreshfunc)(curmenu, !m.inited);
  84.         m.inited = true;
  85.         if(m.menusel>=m.items.length()) m.menusel = max(m.items.length()-1, 0);
  86.     }
  87.     char *title = m.title;
  88.     if(!title) { static string buf; s_sprintf(buf)("[ %s menu ]", m.name); title = buf; }
  89.     int offset = m.menusel - (m.menusel%MAXMENU), mdisp = min(m.items.length(), MAXMENU), cdisp = min(m.items.length()-offset, MAXMENU);
  90.     if(m.title) text_startcolumns();
  91.     int w = 0;
  92.     loopv(m.items)
  93.     {
  94.         int x = text_width(m.items[i].text);
  95.         if(x>w) w = x;
  96.     }
  97.     int tw = text_width(title);
  98.     if(tw>w) w = tw;
  99.     int step = (FONTH*5)/4;
  100.     int h = (mdisp+2)*step;
  101.     int y = (VIRTH-h)/2;
  102.     int x = (VIRTW-w)/2;
  103.     drawmenubg(x-FONTH*3/2, y-FONTH, x+w+FONTH*3/2, y+h+FONTH, true);
  104.     if(offset>0)                        drawarrow(1, x+w+FONTH*3/2-FONTH*5/6, y-FONTH*5/6, FONTH*2/3);
  105.     if(offset+MAXMENU<m.items.length()) drawarrow(0, x+w+FONTH*3/2-FONTH*5/6, y+h+FONTH/6, FONTH*2/3);
  106.     draw_text(title, x, y);
  107.     y += step*2;
  108.     if(m.allowinput)
  109.     {
  110.         int bh = y+(m.menusel%MAXMENU)*step;
  111.         blendbox(x-FONTH, bh-FONTH/6, x+w+FONTH, bh+FONTH+FONTH/6, false);
  112.     }
  113.     loopj(cdisp)
  114.     {
  115.         draw_text(m.items[offset+j].text, x, y);
  116.         y += step;
  117.     }
  118.     if(m.title) text_endcolumns();
  119.     return true;
  120. }
  121.  
  122. void rendermenumdl()
  123. {
  124.     if(!curmenu) { menustack.setsize(0); return; }
  125.     gmenu &m = *curmenu;
  126.     if(!m.mdl) return;
  127.    
  128.     glPushMatrix ();
  129.    
  130.     float t = (lastmillis-player1->lastaction)/1000.0f;
  131.     if(t >= 1.6f) t = 1.6f;
  132.  
  133.     glLoadIdentity();
  134.     glRotatef(90+180, 0, -1, 0);
  135.     glRotatef(90, -1, 0, 0);
  136.     glScalef(1, -1, 1);
  137.  
  138.     bool isplayermodel = !strncmp(m.mdl, "playermodels", strlen("playermodels"));
  139.  
  140.     vec pos;
  141.     if(isplayermodel) pos = vec(2.0f, 1.2f, -0.4f);
  142.     else pos = vec(2.0f, 0, 1.7f);
  143.  
  144.     float yaw = 1.0f;
  145.     if(m.rotspeed) yaw += lastmillis/5.0f/100.0f*m.rotspeed;
  146.  
  147.     int tex = 0;
  148.     if(isplayermodel)
  149.     {
  150.         s_sprintfd(skin)("packages/models/%s.jpg", m.mdl);
  151.         tex = -(int)textureload(skin)->id;
  152.     }
  153.     rendermodel(isplayermodel ? (char *)"playermodels" : m.mdl, m.anim, tex, 0, pos.x, pos.y, pos.z, yaw, 0, 0, 0, NULL, isplayermodel ? (char*)"weapons/subgun/world" : NULL, m.scale ? m.scale/25.0f : 1.0f);
  154.     
  155.     glPopMatrix();
  156. }
  157.  
  158. void *addmenu(char *name, char *title, bool allowinput, void (__cdecl *refreshfunc)(void *, bool))
  159. {
  160.     name = newstring(name);
  161.     gmenu &menu = menus[name];
  162.     menu.name = name;
  163.     menu.title = title ? newstring(title) : NULL;
  164.     menu.menusel = 0;
  165.     menu.mdl = NULL;
  166.     menu.allowinput = allowinput;
  167.     menu.inited = false;
  168.     menu.refreshfunc = refreshfunc;
  169.     lastmenu = &menu;
  170.     return &menu;
  171. }
  172.  
  173. void newmenu(char *name)
  174. {
  175.     addmenu(name);
  176. }
  177.  
  178. void menumanual(void *menu, int n, char *text, char *action)
  179. {
  180.     gmenu &m = *(gmenu *)menu;
  181.     if(!n) m.items.setsize(0);
  182.     mitem &mitem = m.items.add();
  183.     mitem.text = text;
  184.     mitem.action = action;
  185.     mitem.hoveraction = NULL;
  186. }
  187.  
  188. void menuitem(char *text, char *action, char *hoveraction)
  189. {
  190.     if(!lastmenu) return;
  191.     gmenu &menu = *lastmenu;
  192.     mitem &mi = menu.items.add();
  193.     mi.text = newstring(text);
  194.     mi.action = action[0] ? newstring(action) : mi.text;
  195.     mi.hoveraction = hoveraction[0] ? newstring(hoveraction) : NULL;
  196. }
  197.  
  198. void menumdl(char *mdl, char *anim, char *rotspeed, char *scale)
  199. {
  200.     if(!lastmenu || !mdl || !anim) return;
  201.     gmenu &menu = *lastmenu;
  202.     menu.mdl = newstring(mdl);
  203.     menu.anim = findanim(anim)|ANIM_LOOP;
  204.     menu.rotspeed = max(0, min(atoi(rotspeed), 100));
  205.     menu.scale = max(0, min(atoi(scale), 100));
  206. }
  207.  
  208. void chmenumdl(char *menu, char *mdl, char *anim, char *rotspeed, char *scale)
  209. {
  210.     if(!menu || !mdl || !menus.access(menu)) return;
  211.     gmenu &m = menus[menu];
  212.     DELETEA(m.mdl);
  213.     m.mdl = newstring(mdl);
  214.     m.anim = findanim(anim)|ANIM_LOOP;
  215.     m.rotspeed = max(0, min(atoi(rotspeed), 100));
  216.     m.scale = max(0, min(atoi(scale), 100));
  217. }
  218.     
  219. COMMAND(menuitem, ARG_3STR);
  220. COMMAND(showmenu, ARG_1STR);
  221. COMMAND(newmenu, ARG_1STR);
  222. COMMAND(menumdl, ARG_5STR);
  223. COMMAND(chmenumdl, ARG_6STR);
  224.  
  225. void menuselect(void *menu, int sel)
  226. {
  227.     gmenu &m = *(gmenu *)menu;
  228.  
  229.     if(sel<0) sel = m.items.length()>0 ? m.items.length()-1 : 0;
  230.     else if(sel>=m.items.length()) sel = 0;
  231.  
  232.     if(m.items.inrange(sel))
  233.     {
  234.         int oldsel = m.menusel;
  235.         m.menusel = sel;
  236.         if(m.allowinput)
  237.         {
  238.             char *haction = m.items[sel].hoveraction;
  239.             if(sel!=oldsel && haction) execute(haction);
  240.         }
  241.     }
  242. }
  243.  
  244. bool menukey(int code, bool isdown)
  245. {   
  246.     if(!curmenu) return false;
  247.     int n = curmenu->items.length(), menusel = curmenu->menusel;
  248.     if(isdown)
  249.     {
  250.         if(code==SDLK_PAGEUP) menusel -= MAXMENU;
  251.         else if(code==SDLK_PAGEDOWN)
  252.         {
  253.             if(menusel+MAXMENU>=n && menusel/MAXMENU!=(n-1)/MAXMENU) menusel = n-1;
  254.             else menusel += MAXMENU;
  255.         }
  256.         else if(!curmenu->allowinput) return false;
  257.  
  258.         setscope(false);
  259.  
  260.         if(code==SDLK_ESCAPE || code==-3)
  261.         {
  262.             menuset(menustack.empty() ? NULL : menustack.pop());
  263.             return true;
  264.         }
  265.         else if(code==SDLK_UP || code==-4) menusel--;
  266.         else if(code==SDLK_DOWN || code==-5) menusel++;
  267.  
  268.         menuselect(curmenu, menusel);
  269.     }
  270.     else
  271.     {
  272.         if(!curmenu->allowinput) return false;
  273.         if(code==SDLK_RETURN || code==-1 || code==-2)
  274.         {
  275.             if(!curmenu->items.inrange(menusel)) { menuset(NULL); return true; }
  276.             char *action = curmenu->items[menusel].action;
  277.             menustack.add(curmenu);
  278.             menuset(NULL);
  279.             if(action) execute(action);
  280.         }
  281.     }
  282.     return true;
  283. }
  284.