From a5d0e0409def05a18dc7a79f1ba4e3934a92a89a Mon Sep 17 00:00:00 2001 From: faded <> Date: Sun, 2 Feb 2003 17:53:57 +0000 Subject: [PATCH] further work on xmlmenus : - fixed the open window stack - added support for tga/png/* textures - made the lmp load permanent (not through Draw_CachePic anymore) - added highlight of the current selected element --- gl_draw.c | 60 +++++-------- xmlmenu.c | 250 ++++++++++++++++++++++++++++++++++++++++-------------- xmlmenu.h | 5 ++ 3 files changed, 214 insertions(+), 101 deletions(-) diff --git a/gl_draw.c b/gl_draw.c index 4bc5234..204381d 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -625,6 +625,22 @@ void Draw_DebugChar (char num) { } + + +void Draw_GLPic (int x, int y, int xs, int ys, glpic_t *gl) +{ + GL_Bind (gl->texnum); + glBegin (GL_QUADS); + glTexCoord2f (gl->sl, gl->tl); + glVertex2f (x, y); + glTexCoord2f (gl->sh, gl->tl); + glVertex2f (xs, y); + glTexCoord2f (gl->sh, gl->th); + glVertex2f (xs, ys); + glTexCoord2f (gl->sl, gl->th); + glVertex2f (x, ys); + glEnd (); +} /* ============= Draw_AlphaPic @@ -642,17 +658,7 @@ void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha) // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glCullFace(GL_FRONT); glColor4f (1,1,1,alpha); - GL_Bind (gl->texnum); - glBegin (GL_QUADS); - glTexCoord2f (gl->sl, gl->tl); - glVertex2f (x, y); - glTexCoord2f (gl->sh, gl->tl); - glVertex2f (x+pic->width, y); - glTexCoord2f (gl->sh, gl->th); - glVertex2f (x+pic->width, y+pic->height); - glTexCoord2f (gl->sl, gl->th); - glVertex2f (x, y+pic->height); - glEnd (); + Draw_GLPic (x, y, x+pic->width, y+pic->height, gl); glColor4f (1,1,1,1); glEnable(GL_ALPHA_TEST); glDisable (GL_BLEND); @@ -672,17 +678,7 @@ void Draw_Pic (int x, int y, qpic_t *pic) Scrap_Upload (); gl = (glpic_t *)pic->data; glColor4f (1,1,1,1); - GL_Bind (gl->texnum); - glBegin (GL_QUADS); - glTexCoord2f (gl->sl, gl->tl); - glVertex2f (x, y); - glTexCoord2f (gl->sh, gl->tl); - glVertex2f (x+pic->width, y); - glTexCoord2f (gl->sh, gl->th); - glVertex2f (x+pic->width, y+pic->height); - glTexCoord2f (gl->sl, gl->th); - glVertex2f (x, y+pic->height); - glEnd (); + Draw_GLPic (x, y, x+pic->width, y+pic->height, gl); } @@ -716,19 +712,9 @@ void Draw_PicFilled (int x, int y, int xs, int ys, qpic_t *pic) Scrap_Upload (); gl = (glpic_t *)pic->data; glColor4f (1,1,1,1); - GL_Bind (gl->texnum); - glBegin (GL_QUADS); - glTexCoord2f (gl->sl, gl->tl); - glVertex2f (x, y); - glTexCoord2f (gl->sh, gl->tl); - glVertex2f (xs, y); - glTexCoord2f (gl->sh, gl->th); - glVertex2f (xs, ys); - glTexCoord2f (gl->sl, gl->th); - glVertex2f (x, ys); - glEnd (); + Draw_GLPic (x, y, xs, ys, gl); } - + /* =================== Draw_TransPicFilled @@ -736,17 +722,17 @@ Draw_TransPicFilled */ void Draw_TransPicFilled (int x, int y, int xs, int ys, qpic_t *pic) { + if (x < 0 || (unsigned)(xs) > vid.width || y < 0 || (unsigned)(ys) > vid.height) { Sys_Error ("Draw_TransPic: bad coordinates (%d ,%d )\n", x, y); } - + Draw_PicFilled (x, y, xs, ys, pic); } - - + /* ============= Draw_TransPicTranslate diff --git a/xmlmenu.c b/xmlmenu.c index 1a339d1..dc5d7c7 100644 --- a/xmlmenu.c +++ b/xmlmenu.c @@ -36,12 +36,75 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_MLABEL 128 +// ------------------------------------------------------------------------------------- + +// --X--X--X-- WARNING WARNING WARNING --X--X--X-- + +// FIXME : +// copy & pasted from gl_draw.c +// update me accordingly or better, move me in glquake.h +// while I'm still supported + +typedef struct +{ + int texnum; + float sl, tl, sh, th; +} glpic_t; + +// --X--X--X-- WARNING WARNING WARNING --X--X--X-- + +void GL_LoadPic (char *src, glpic_t *target) +{ + typedef struct _TargaHeader + { + unsigned char id_length, colormap_type, image_type; + unsigned short colormap_index, colormap_length; + unsigned char colormap_size; + unsigned short x_origin, y_origin, width, height; + unsigned char pixel_size, attributes; + } TargaHeader; + + extern TargaHeader targa_header; + extern byte *targa_rgba; + qpic_t *pic; + + int len = strlen(src); + + if (strncmp(src+len-4,".lmp",4)){ + + // load file in memory + LoadTexture (src, 4); + // assign it to a texture object + target->texnum = GL_LoadTexture (src, targa_header.width, targa_header.height, targa_rgba, false, true, false); + free (targa_rgba); + + } + else { + // lump file + // FIXME : drop lump file support in the future + pic = (qpic_t *) COM_LoadTempFile (src); + if (!pic) + Sys_Error ("GL_LoadPic: failed to load %s", src); + SwapPic (pic); + target->texnum = GL_LoadTexture (src, pic->width, pic->height, pic->data, false, true, false); + } + target->sl = 0; + target->sh = 1; + target->tl = 0; + target->th = 1; +} + +// ------------------------------------------------------------------------------------- + cvar_t m_debug = {"m_debug","0"}; typedef struct xmlimagedata_s { - char src[MAX_OSPATH]; + char src[MAX_OSPATH]; + glpic_t pic; + int width; + int height; } xmlimagedata_t; @@ -103,6 +166,7 @@ typedef struct xmlwindowdata_s typedef struct qwindow_s { char file[MAX_OSPATH]; qwidget_t *widget; + qwidget_t *focused; struct qwindow_s *stack; // visible window stack struct qwindow_s *next; // available window list } qwindow_t; @@ -555,9 +619,9 @@ qwindow_t *windows = NULL; qwindow_t *visible_window; -qwidget_t *focused; +glpic_t focus_pic; // ------------------------------------------------------------------------------------- @@ -613,6 +677,8 @@ void treeiterator_prev (qwiterator_t *self) // ------------------------------------------------------------------------------------- +#define SLIDER_RANGE 10 + qboolean m_entersound; // play after drawing a frame, so caching // won't disrupt the sound qboolean m_recursiveDraw; @@ -655,9 +721,22 @@ void M_Quit_f (void) } +void M_CloseWindow_f (void) +{ + qwindow_t *temp = visible_window; + if (visible_window != NULL){ + visible_window = visible_window->stack; + temp->stack = NULL; + } + if (visible_window == NULL) + key_dest = key_game; +} + + void M_OpenWindow_f (void) { qwindow_t *w = windows; + qwindow_t *temp = visible_window; char *name; if (Cmd_Argc() != 2) { @@ -674,29 +753,29 @@ void M_OpenWindow_f (void) Con_Printf ("openwindow : no such window '%s'\n", name); return; } - if (visible_window != w){ - w->stack = visible_window; - visible_window = w; - focused = w->widget; + + while (temp && (temp!=w)) + temp = temp->stack; + + if (temp == w){ + // which one ? + // - close all opened windows back to w + // - close all opened windows from w and stack up w + // * close all opened windows then stack up w + // - change the whole damn window code + while (visible_window) + M_CloseWindow_f (); + } + w->stack = visible_window; + visible_window = w; + if (w->focused == NULL) { + w->focused = w->widget; M_CycleFocusNext (); } key_dest = key_menu; m_state = m_menu; } -void M_CloseWindow_f (void) -{ - if (visible_window != NULL){ - visible_window = visible_window->stack; - } - if (visible_window == NULL) - key_dest = key_game; - else { - focused = visible_window->widget; - M_CycleFocusNext (); - } - -} void M_WindowList_f (void) { @@ -719,22 +798,25 @@ void M_Init (void) // let's load the whole stuff now COM_FindAllExt ("menu", "xul", M_LoadXmlWindowFile); + GL_LoadPic ("menu/focus.png",&focus_pic); } /* ======== M_Menu_Main_f +M_Menu_Options_f M_Menu_Quit_f -both functions are used in another part of the code (console.c) so I implemented them as stub to +these functions are used in another part of the code (console.c, vid_glnt.c, vid_glsdl.c) so I implemented them as stub to the console commands they are bound to originally to concentrate the menus change in one file. So basically here we're just expecting that some other part of the game will have defined these commands/aliases/whatever -(xmlmenu should make them as aliases : check out M_LoadXmlWindow). +(the menus should create the corresponding windows). ======== */ + void M_Menu_Main_f (void) { - Cbuf_AddText ("menu_main\n"); + Cbuf_AddText ("openwindow main\n"); } void M_Menu_Quit_f (void) @@ -742,6 +824,13 @@ void M_Menu_Quit_f (void) M_Quit_f (); } +void M_Menu_Options_f (void) +{ + Cbuf_AddText ("openwindow help\n"); +} + +void (*vid_menudrawfn)(void); +void (*vid_menukeyfn)(int key); /* ======== @@ -752,11 +841,11 @@ recursive function set : this one is at top level, and calls the focused widget */ void M_Keydown (int key) { + qwidget_t *focused = visible_window->focused; if (focused && focused->HandleKey) M_XmlElementKey (focused,key); - else + else // current window get the key M_XmlElementKey (visible_window->widget, key); - // current window get the key } // ------------------------------------------------------------------------------------- @@ -781,6 +870,8 @@ void M_DrawPic (int x, int y, qpic_t *pic) Draw_Pic (x + ((vid.width - 320)>>1), y, pic); } + + byte identityTable[256]; byte translationTable[256]; @@ -828,11 +919,11 @@ void M_DrawTextBox (int x, int y, int width, int lines) p = Draw_CachePic ("gfx/box_ml.lmp"); for (n = 0; n < lines; n++) { - cy += 8; + cy += 16; M_DrawTransPic (cx, cy, p); } p = Draw_CachePic ("gfx/box_bl.lmp"); - M_DrawTransPic (cx, cy+8, p); + M_DrawTransPic (cx, cy+16, p); // draw middle cx += 8; @@ -844,13 +935,13 @@ void M_DrawTextBox (int x, int y, int width, int lines) p = Draw_CachePic ("gfx/box_mm.lmp"); for (n = 0; n < lines; n++) { - cy += 8; + cy += 16; if (n == 1) p = Draw_CachePic ("gfx/box_mm2.lmp"); M_DrawTransPic (cx, cy, p); } p = Draw_CachePic ("gfx/box_bm.lmp"); - M_DrawTransPic (cx, cy+8, p); + M_DrawTransPic (cx, cy+16, p); width -= 2; cx += 16; } @@ -894,6 +985,7 @@ void M_ToggleMenu_f (void) } } + // ------------------------------------------------------------------------------------- void M_XmlButtonCommand (qwidget_t *self) @@ -934,11 +1026,11 @@ qwidget_t *M_PreviousXmlElement (qwidget_t *w) void M_CycleFocus (qwidget_t *(*next_f)(qwidget_t *)) { - qwidget_t *w = focused; + qwidget_t *w = visible_window->focused; do { w = next_f (w); - } while ((w != focused) && !(w->focusable)); - focused = w; + } while ((w != visible_window->focused) && !(w->focusable)); + visible_window->focused = w; } // ------------------------------------------------------------------------------------- @@ -980,7 +1072,7 @@ qboolean M_XmlCheckBoxKey (qwidget_t *self, int k) // (un)check the checkbox S_LocalSound ("misc/menu2.wav"); data->checked = !data->checked; - Cvar_SetValue (self->name, data->checked); + Cvar_SetValue (self->id, data->checked); break; default: return false; @@ -1030,11 +1122,12 @@ qboolean M_XmlSliderKey (qwidget_t *self, int k) case K_LEFTARROW: // reduce cvar value S_LocalSound ("misc/menu3.wav"); - + data->range -= 1/SLIDER_RANGE; break; case K_RIGHTARROW: // augment cvar value S_LocalSound ("misc/menu3.wav"); + data->range += 1/SLIDER_RANGE; break; default: return false; @@ -1054,9 +1147,10 @@ qboolean M_XmlMenuKey (qwidget_t *self, int k) qboolean M_XmlElementKey (qwidget_t *widget, int k) { - // start from the current focused widget + // start from widget // and propagate the key up the parents tree - // until it has been consumed + // until it has been consumed or it reaches the + // tree root while (widget){ if (widget->HandleKey) if (widget->HandleKey (widget, k)) @@ -1071,10 +1165,17 @@ qboolean M_XmlElementKey (qwidget_t *widget, int k) /* ================ Draw_StringN + +draws the str string of length len in the (x1,y1,x2,y2) frame ================ */ -int Draw_StringN (int x, int y, char *str, int len) +int Draw_StringN (int x1, int y1, int x2, int y2, char *str, int len) { + // calculate string width and height, center it + int w = len * 8; + int h = 16; + int x = x1 + (x2 - x1 - w)/2; + int y = y1 + (y2 - y1 - h)/2; while (*str && len) { Draw_Character (x, y, (*str)+128); @@ -1085,7 +1186,6 @@ int Draw_StringN (int x, int y, char *str, int len) return x; } - void M_Draw (void) { @@ -1117,7 +1217,7 @@ void M_Draw (void) } // draw current window - M_DrawXmlNestedWidget (visible_window->widget, 0, 0); + M_DrawVisibleWindow (); if (m_entersound) { @@ -1134,19 +1234,22 @@ void M_Draw (void) void M_DrawXmlButton (qwidget_t *self, int x, int y) { xmlbuttondata_t *data = self->data; - Draw_StringN (x, y, data->label, sizeof(data->label)); + Draw_StringN (x, y, x+self->width.absolute, y+self->height.absolute, data->label, sizeof(data->label)); } void M_DrawXmlImage (qwidget_t *self, int x, int y) { xmlimagedata_t *data = self->data; - Draw_TransPicFilled (x, y, x+self->width.absolute, y+self->height.absolute, Draw_CachePic (data->src)); + if (data->pic.texnum == 0) + GL_LoadPic (data->src, &(data->pic)); + glColor4f (1,1,1,1); + Draw_GLPic (x, y, x+self->width.absolute, y+self->height.absolute, &(data->pic)); } void M_DrawXmlLabel (qwidget_t *self, int x, int y) { xmllabeldata_t *data = self->data; - Draw_StringN (x, y, data->text, sizeof(data->text)); + Draw_StringN (x, y, x+self->width.absolute, y+self->height.absolute, data->text, sizeof(data->text)); } void M_DrawXmlBox (qwidget_t *self, int x, int y) @@ -1159,7 +1262,7 @@ void M_DrawXmlRadio (qwidget_t *self, int x, int y) { xmlradiodata_t *data = self->data; qboolean on = data->selected; - Draw_StringN (x, y, data->label, sizeof(data->label)); + Draw_StringN (x, y, x+self->width.absolute, y+self->height.absolute, data->label, sizeof(data->label)); if (on) M_Print (x, y, "(o)"); else @@ -1173,22 +1276,19 @@ void M_DrawXmlRadioGroup (qwidget_t *self, int x, int y) // almost pasted from menu.c -#define SLIDER_RANGE 10 - void M_DrawXmlSlider (qwidget_t *self, int x, int y) { int i; xmlsliderdata_t *data = self->data; int range = data->range; - x += 8; - if (range < 0) range = 0; if (range > 1) range = 1; - Draw_Character (x-8, y, 128); + Draw_Character (x, y, 128); + x += 8; for (i=0 ; idata; qboolean on = data->checked; - x = Draw_StringN (x, y, data->label, sizeof(data->label)); + x = Draw_StringN (x, y, x+self->width.absolute, y+self->height.absolute, data->label, sizeof(data->label)); if (on) M_Print (x, y, "[x]"); @@ -1216,6 +1316,24 @@ void M_DrawXmlWindow (qwidget_t *self,int x, int y) // draw a border ? } + +void M_DrawFocus (qwidget_t *self, int x, int y){ + + int xs = x+self->width.absolute; + int ys = y+self->height.absolute; + + if (focus_pic.texnum == 0) + GL_LoadPic ("menu/focus.png",&focus_pic); + + glDisable (GL_ALPHA_TEST); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f (0.5,0.5,0.5,0.5); + Draw_GLPic (x, y, xs, ys, &focus_pic); + glDisable (GL_BLEND); + glEnable (GL_ALPHA_TEST); +} + /* -DC- FIXME : doesn't work at all So this function is a little hack to display widget outline @@ -1224,19 +1342,14 @@ void M_DrawXmlWindow (qwidget_t *self,int x, int y) cause I don't know much about OpenGL (shame on me ^^;) */ -void M_DrawFocus (qwidget_t *self, int x, int y){ - //Draw_TransPicFilled (x, y, x+self->width.absolute, y+self->height.absolute, Draw_CachePic ("menu/focus.png")); -} - - void M_DrawOutlines (qwidget_t *self, int x, int y){ + int xs = x + self->width.absolute; int ys = x + self->height.absolute; - GLint color[4]; + GLfloat color[4]; GLint shademodel; - GL_DisableMultitexture (); - glGetIntegerv(GL_CURRENT_COLOR, color); - glColor4b(1,1,1,1); + glGetFloatv(GL_CURRENT_COLOR, color); + glColor4f(1,1,1,1); //glGetIntegerv(GL_SHADE_MODEL, &shademodel); //glShadeModel (GL_FLAT); glBegin (GL_LINE_STRIP); @@ -1246,7 +1359,7 @@ void M_DrawOutlines (qwidget_t *self, int x, int y){ glVertex2f (x, ys); glEnd (); //glShadeModel (shademodel); - glColor4iv(color); + glColor4fv(color); GL_EnableMultitexture (); } @@ -1267,9 +1380,11 @@ void M_DrawXmlNestedWidget (qwidget_t *widget, int xpos, int ypos) if (widget->Draw){ widget->Draw (widget, xpos, ypos); } - if (widget == focused){ + + if (widget == visible_window->focused){ M_DrawFocus (widget, xpos, ypos); } + if (m_debug.value) { // draw outlines M_DrawOutlines (widget, xpos, ypos); @@ -1332,6 +1447,13 @@ void M_DrawXmlNestedWidget (qwidget_t *widget, int xpos, int ypos) } +void M_DrawVisibleWindow () +{ + int w = vid.width - visible_window->widget->width.absolute; + int h = vid.height - visible_window->widget->height.absolute; + M_DrawXmlNestedWidget (visible_window->widget, w/2, h/2); +} + // ------------------------------------------------------------------------------------- int M_ReadXmlPropAsInt (xmlNodePtr node, char *name, int defvalue) @@ -1653,14 +1775,14 @@ void M_LoadXmlImage (qwidget_t *widget, xmlNodePtr node) * --- unsupported : - onerror = callback - onload = callback + onerror = string + onload = string validate = {always|never} : load image from cache */ xmlimagedata_t *data = widget->data; - - M_ReadXmlPropAsString (node, "src", data->src, sizeof (data->src)); + M_ReadXmlPropAsString (node, "src", data->src, sizeof (data->src)); + //GL_LoadPic (data->src,&(data->pic)); } @@ -1729,7 +1851,7 @@ void M_LoadXmlCheckBox (qwidget_t *widget, xmlNodePtr node) temp = M_CompareXmlProp (node, "disabled", xmlbool, 2); if (temp != -1) data->disabled = temp; - + data->checked = Cvar_VariableValue (widget->id); } void M_LoadXmlRadio (qwidget_t *widget, xmlNodePtr node) diff --git a/xmlmenu.h b/xmlmenu.h index 46cdcd4..101071c 100644 --- a/xmlmenu.h +++ b/xmlmenu.h @@ -65,6 +65,11 @@ typedef struct qwidget_s void *data; } qwidget_t; + +void M_OpenWindow_f (void); +void M_CloseWindow_f (void); +void M_DrawVisibleWindow (void); + void M_LoadXmlBox (qwidget_t *widget, xmlNodePtr node); void M_LoadXmlVBox (qwidget_t *widget, xmlNodePtr node); void M_LoadXmlLabel (qwidget_t *widget, xmlNodePtr node);