From d75ef3c308b7964b09ae8b513571cfa7718a8207 Mon Sep 17 00:00:00 2001 From: Fabian Greffrath Date: Tue, 28 Feb 2023 17:14:49 +0100 Subject: [PATCH] some fixes to the dynamic HUD implementation (#916) * build and align text widgets in HU_Ticker(), drawn then in HU_Drawer() * fix widget scope * fix clang build * minor fix * simplify * back to alignment in HU_Drawer() * fix the widgets jumping around when switching from status bar to fullscreen --- src/hu_lib.c | 79 +++++++++++++------------- src/hu_lib.h | 32 ++++++----- src/hu_stuff.c | 150 +++++++++++++++++++++++++++---------------------- src/hu_stuff.h | 2 +- src/m_menu.c | 2 +- src/r_main.c | 3 + 6 files changed, 146 insertions(+), 122 deletions(-) diff --git a/src/hu_lib.c b/src/hu_lib.c index d1dc9adf..71942315 100644 --- a/src/hu_lib.c +++ b/src/hu_lib.c @@ -96,13 +96,14 @@ void HUlib_clearTextLine(hu_textline_t* t) // void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t ***f, int sc, - char *cr) //jff 2/16/98 add color range parameter + char *cr, void (*builder)(void)) //jff 2/16/98 add color range parameter { t->x = x; t->y = y; t->f = f; t->sc = sc; t->cr = cr; + t->builder = builder; HUlib_clearTextLine(t); } @@ -186,52 +187,44 @@ static boolean HUlib_delCharFromTextLine(hu_textline_t* t) // Returns nothing // -void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor) -{ - HUlib_drawTextLineAt(l, l->x, l->y, drawcursor); -} - #define HU_GAPX 2 #define HU_GAPX_L (HU_GAPX - WIDESCREENDELTA) #define HU_GAPX_R (ORIGWIDTH - HU_GAPX_L) -void HUlib_drawTextLineAligned(hu_textline_t *l, align_t align, boolean drawcursor) +static void HUlib_alignWidget(hu_textline_t *l, align_t align) { patch_t *const *const f = *l->f; const int font_height = SHORT(f['A'-HU_FONTSTART]->height) + 1; - if (l->visible) + if (align == align_topleft) { - if (align == align_topleft) - { - HUlib_drawTextLineAt(l, l->x = HU_GAPX_L, l->y = align_offset[align], drawcursor); - align_offset[align] += font_height; - } - else if (align == align_topright) - { - HUlib_drawTextLineAt(l, l->x = HU_GAPX_R - l->width, l->y = align_offset[align], drawcursor); - align_offset[align] += font_height; - } - else if (align == align_bottomleft) - { - align_offset[align] -= font_height; - HUlib_drawTextLineAt(l, l->x = HU_GAPX_L, l->y = align_offset[align], drawcursor); - } - else if (align == align_bottomright) - { - align_offset[align] -= font_height; - HUlib_drawTextLineAt(l, l->x = HU_GAPX_R - l->width, l->y = align_offset[align], drawcursor); - } - else - { - HUlib_drawTextLineAt(l, l->x, l->y, drawcursor); - } + l->x = HU_GAPX_L; + l->y = align_offset[align]; + align_offset[align] += font_height; + } + else if (align == align_topright) + { + l->x = HU_GAPX_R - l->width; + l->y = align_offset[align]; + align_offset[align] += font_height; + } + else if (align == align_bottomleft) + { + align_offset[align] -= font_height; + l->x = HU_GAPX_L; + l->y = align_offset[align]; + } + else if (align == align_bottomright) + { + align_offset[align] -= font_height; + l->x = HU_GAPX_R - l->width; + l->y = align_offset[align]; } } -void HUlib_drawTextLineAt(hu_textline_t *l, int x, int y, boolean drawcursor) +static void HUlib_drawTextLineAligned(hu_textline_t *l, boolean drawcursor) { - int i; // killough 1/18/98 -- support multiple lines + int i, x = l->x, y = l->y; // killough 1/18/98 -- support multiple lines unsigned char c; char *oc = l->cr; //jff 2/17/98 remember default color patch_t *const *const f = *l->f; @@ -280,6 +273,12 @@ void HUlib_drawTextLineAt(hu_textline_t *l, int x, int y, boolean drawcursor) V_DrawPatchDirect(x, y, FG, f['_' - l->sc]); } +void HUlib_drawTextLine(hu_textline_t *l, align_t align, boolean drawcursor) +{ + HUlib_alignWidget(l, align); + HUlib_drawTextLineAligned(l, drawcursor); +} + // // HUlib_eraseTextLine() // @@ -348,7 +347,7 @@ void HUlib_initSText(hu_stext_t *s, int x, int y, int h, patch_t ***font, s->cl = 0; for (i=0;il+i, x, y - i*(SHORT((*font[0])->height)+1), - font, startchar, cr); + font, startchar, cr, NULL); } // @@ -406,7 +405,7 @@ void HUlib_drawSText(hu_stext_t* s, align_t align) if (idx < 0) idx += s->h; // handle queue of lines // need a decision made here on whether to skip the draw - HUlib_drawTextLineAligned(&s->l[idx], align, false); // no cursor, please + HUlib_drawTextLine(&s->l[idx], align, false); // no cursor, please } } @@ -466,7 +465,7 @@ void HUlib_initMText(hu_mtext_t *m, int x, int y, patch_t ***font, y += HU_REFRESHSPACING * hud_msg_lines; for (i=0; il[i], x, y, font, startchar, cr); + HUlib_initTextLine(&m->l[i], x, y, font, startchar, cr, NULL); } // @@ -540,7 +539,7 @@ void HUlib_drawMText(hu_mtext_t* m, align_t align) m->l[idx].y = i * HU_REFRESHSPACING; - HUlib_drawTextLineAligned(&m->l[idx], align, false); // no cursor, please + HUlib_drawTextLine(&m->l[idx], align, false); // no cursor, please } } @@ -587,7 +586,7 @@ void HUlib_initIText(hu_itext_t *it, int x, int y, patch_t ***font, it->lm = 0; // default left margin is start of text it->on = on; it->laston = true; - HUlib_initTextLine(&it->l, x, y, font, startchar, cr); + HUlib_initTextLine(&it->l, x, y, font, startchar, cr, NULL); } // The following deletion routines adhere to the left margin restriction @@ -658,7 +657,7 @@ void HUlib_drawIText(hu_itext_t *it, align_t align) { hu_textline_t *l = &it->l; if ((l->visible = *it->on)) - HUlib_drawTextLineAligned(l, align, true); // draw the line w/ cursor + HUlib_drawTextLine(l, align, true); // draw the line w/ cursor } // diff --git a/src/hu_lib.h b/src/hu_lib.h index 19a45393..2cb233bb 100644 --- a/src/hu_lib.h +++ b/src/hu_lib.h @@ -47,15 +47,6 @@ //jff 2/26/98 maximum number of messages allowed in refresh list #define HU_MAXMESSAGES 8 -typedef enum { - align_topleft, - align_topright, - align_bottomleft, - align_bottomright, - align_direct, - num_aligns, -} align_t; - // // Typedefs of widgets // @@ -84,9 +75,24 @@ typedef struct int width; boolean visible; + void (*builder) (void); } hu_textline_t; +typedef enum { + align_topleft, + align_topright, + align_bottomleft, + align_bottomright, + align_direct, + num_aligns, +} align_t; + +typedef struct { + hu_textline_t *line; + align_t align; + int x, y; +} widget_t; // Scrolling Text window widget @@ -158,7 +164,8 @@ void HUlib_initTextLine int y, patch_t ***f, int sc, - char *cr //jff 2/16/98 add color range parameter + char *cr, //jff 2/16/98 add color range parameter + void (*builder)(void) ); // returns success @@ -166,11 +173,8 @@ boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch); void HUlib_addStringToTextLine(hu_textline_t *t, char *s); // draws tline -void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor); -void HUlib_drawTextLineAt(hu_textline_t *l, int x, int y, boolean drawcursor); - +void HUlib_drawTextLine(hu_textline_t *l, align_t align, boolean drawcursor); void HUlib_resetAlignOffsets(); -void HUlib_drawTextLineAligned(hu_textline_t *l, align_t align, boolean drawcursor); // erases text line void HUlib_eraseTextLine(hu_textline_t *l); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 0374d56a..0efc86ae 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -128,12 +128,6 @@ static hu_textline_t w_sttime; // time above status bar #define MAX_HUDS 3 #define MAX_WIDGETS 12 -typedef struct { - hu_textline_t *widget; - align_t align; - int x, y; -} widget_t; - static widget_t widgets[MAX_HUDS][MAX_WIDGETS] = { { {&w_title, align_bottomleft}, @@ -174,6 +168,8 @@ static widget_t widgets[MAX_HUDS][MAX_WIDGETS] = { } }; +static widget_t *widget = *widgets; + static void HU_ParseHUD (void); static boolean always_off = false; @@ -495,19 +491,27 @@ void HU_Init(void) HU_ResetMessageColors(); } -void HU_ResetWidgets (void) +static inline void HU_enableWidget (hu_textline_t *line, boolean cond) { - widget_t *widget = widgets[hud_active]; - - while (widget->widget) + if (cond) { - if (widget->align == align_direct) + line->visible = true; + } +} + +void HU_disableAllWidgets (void) +{ + widget_t *w = widget; + + while (w->line) + { + if (w->align == align_direct) { - widget->widget->x = widget->x; - widget->widget->y = widget->y; + w->line->x = w->x; + w->line->y = w->y; } - widget->widget->visible = false; - widget++; + w->line->visible = false; + w++; } } @@ -534,6 +538,17 @@ void HU_Stop(void) // // Passed nothing, returns nothing // + +static void HU_widget_build_fps (void); +static void HU_widget_build_coord (void); +static void HU_widget_build_sttime(void); +static void HU_widget_build_monsec(void); +static void HU_widget_build_keys (void); +static void HU_widget_build_weapon (void); +static void HU_widget_build_armor (void); +static void HU_widget_build_health (void); +static void HU_widget_build_ammo (void); + void HU_Start(void) { int i; @@ -592,32 +607,32 @@ void HU_Start(void) //jff 2/16/98 added some HUD widgets // create the map title widget - map title display in lower left of automap HUlib_initTextLine(&w_title, HU_TITLEX, HU_TITLEY, &hu_font, - HU_FONTSTART, colrngs[hudcolor_titl]); + HU_FONTSTART, colrngs[hudcolor_titl], NULL); // create the hud health widget - HUlib_initTextLine(&w_health, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GREEN]); + HUlib_initTextLine(&w_health, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GREEN], HU_widget_build_health); // create the hud armor widget - HUlib_initTextLine(&w_armor, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GREEN]); + HUlib_initTextLine(&w_armor, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GREEN], HU_widget_build_armor); // create the hud ammo widget - HUlib_initTextLine(&w_ammo, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GOLD]); + HUlib_initTextLine(&w_ammo, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GOLD], HU_widget_build_ammo); // create the hud weapons widget - HUlib_initTextLine(&w_weapon, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GRAY]); + HUlib_initTextLine(&w_weapon, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GRAY], HU_widget_build_weapon); // create the hud keys widget - HUlib_initTextLine(&w_keys, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GRAY]); + HUlib_initTextLine(&w_keys, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GRAY], HU_widget_build_keys); // create the hud monster/secret widget - HUlib_initTextLine(&w_monsec, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GRAY]); + HUlib_initTextLine(&w_monsec, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GRAY], HU_widget_build_monsec); - HUlib_initTextLine(&w_sttime, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GRAY]); + HUlib_initTextLine(&w_sttime, 0, 0, &hu_font2, HU_FONTSTART, colrngs[CR_GRAY], HU_widget_build_sttime); // create the automaps coordinate widget - HUlib_initTextLine(&w_coord, 0, 0, &hu_font2, HU_FONTSTART, colrngs[hudcolor_xyco]); + HUlib_initTextLine(&w_coord, 0, 0, &hu_font2, HU_FONTSTART, colrngs[hudcolor_xyco], HU_widget_build_coord); - HUlib_initTextLine(&w_fps, 0, 0, &hu_font2, HU_FONTSTART, colrngs[hudcolor_xyco]); + HUlib_initTextLine(&w_fps, 0, 0, &hu_font2, HU_FONTSTART, colrngs[hudcolor_xyco], HU_widget_build_fps); // initialize the automap's level title widget if (gamemapinfo && gamemapinfo->levelname) @@ -685,7 +700,7 @@ void HU_Start(void) sprintf(hud_keysstr, "%s %c%c", deathmatch ? "FRG" : "KEY", '\x1b', '0'+CR_RED); HUlib_addStringToTextLine(&w_keys, hud_keysstr); - HU_ResetWidgets(); + HU_disableAllWidgets(); // init crosshair if (hud_crosshair) @@ -1343,9 +1358,11 @@ int hud_level_stats, hud_level_time; // void HU_Drawer(void) { - widget_t *widget = widgets[hud_active]; + widget_t *w = widget; align_t align_text = message_centered ? align_direct : align_topleft; + HUlib_resetAlignOffsets(); + // jff 4/24/98 Erase current lines before drawing current // needed when screen not fullsize // killough 11/98: only do it when not fullsize @@ -1355,8 +1372,6 @@ void HU_Drawer(void) HU_Erase(); } - HUlib_resetAlignOffsets(); - if (message_list) HUlib_drawMText(&w_rtext, align_text); else @@ -1372,10 +1387,13 @@ void HU_Drawer(void) ST_Drawer (false, true); } - while (widget->widget) + while (w->line) { - HUlib_drawTextLineAligned(widget->widget, widget->align, false); - widget++; + if (w->line->visible) + { + HUlib_drawTextLine(w->line, w->align, false); + } + w++; } } @@ -1384,9 +1402,11 @@ void WI_DrawTimeWidget(void) { if (hud_level_time) { + w_sttime.x = HU_HUDX; + w_sttime.y = 0; // leveltime is already added to totalleveltimes before WI_Start() //HU_widget_build_sttime(); - HUlib_drawTextLineAt(&w_sttime, HU_HUDX, 0, false); + HUlib_drawTextLine(&w_sttime, align_direct, false); } } @@ -1437,9 +1457,10 @@ int M_StringWidth(char *string); void HU_Ticker(void) { + widget_t *w = widget = widgets[hud_active]; plr = &players[displayplayer]; // killough 3/7/98 - HU_ResetWidgets(); + HU_disableAllWidgets(); draw_crispy_hud = false; hu_invul = (plr->powers[pw_invulnerability] > 4*32 || @@ -1582,25 +1603,18 @@ void HU_Ticker(void) if (automapactive) { // map title - w_title.visible = true; + HU_enableWidget(&w_title, true); - if (map_level_stats) - HU_widget_build_monsec(); - - if (map_level_time) - HU_widget_build_sttime(); - - if (STRICTMODE(map_player_coords)) - HU_widget_build_coord(); + HU_enableWidget(&w_monsec, map_level_stats); + HU_enableWidget(&w_sttime, map_level_time); + HU_enableWidget(&w_coord, STRICTMODE(map_player_coords)); } else { - if (STRICTMODE(map_player_coords) == 2) - HU_widget_build_coord(); + HU_enableWidget(&w_coord, STRICTMODE(map_player_coords) == 2); } - if (plr->powers[pw_showfps]) - HU_widget_build_fps(); + HU_enableWidget(&w_fps, plr->powers[pw_showfps]); if (hud_displayed && scaledviewheight == SCREENHEIGHT && @@ -1613,28 +1627,32 @@ void HU_Ticker(void) } else { - HU_widget_build_weapon(); - HU_widget_build_armor(); - HU_widget_build_health(); - HU_widget_build_ammo(); - HU_widget_build_keys(); + HU_enableWidget(&w_weapon, true); + HU_enableWidget(&w_armor, true); + HU_enableWidget(&w_health, true); + HU_enableWidget(&w_ammo, true); + HU_enableWidget(&w_keys, true); } - if (hud_level_stats) - HU_widget_build_monsec(); - - if (hud_level_time) - HU_widget_build_sttime(); + HU_enableWidget(&w_monsec, hud_level_stats); + HU_enableWidget(&w_sttime, hud_level_time); } else if (scaledviewheight && scaledviewheight < SCREENHEIGHT && automap_off) { - if (hud_level_stats) - HU_widget_build_monsec(); + HU_enableWidget(&w_monsec, hud_level_stats); + HU_enableWidget(&w_sttime, hud_level_time); + } - if (hud_level_time) - HU_widget_build_sttime(); + while (w->line) + { + if (w->line->visible) + { + if (w->line->builder) + w->line->builder(); + } + w++; } // update crosshair properties @@ -1855,7 +1873,7 @@ boolean HU_Responder(event_t *ev) static const struct { const char *name, *altname; - hu_textline_t *const widget; + hu_textline_t *const line; } w_names[] = { {"title", "levelname", &w_title}, {"armor", NULL, &w_armor}, @@ -1880,7 +1898,7 @@ static boolean HU_AddToWidgets (hu_textline_t *widget, int hud, align_t align, i for (i = 0; i < MAX_WIDGETS - 1; i++) { - if (widgets[hud][i].widget == NULL) + if (widgets[hud][i].line == NULL) { break; } @@ -1891,12 +1909,12 @@ static boolean HU_AddToWidgets (hu_textline_t *widget, int hud, align_t align, i return false; } - widgets[hud][i].widget = widget; + widgets[hud][i].line = widget; widgets[hud][i].align = align; widgets[hud][i].x = x; widgets[hud][i].y = y; - widgets[hud][i + 1].widget = NULL; + widgets[hud][i + 1].line = NULL; return true; } @@ -1910,7 +1928,7 @@ static hu_textline_t *HU_WidgetByName (const char *name) if (strcasecmp(name, w_names[i].name) == 0 || (w_names[i].altname && strcasecmp(name, w_names[i].altname) == 0)) { - return w_names[i].widget; + return w_names[i].line; } } diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 07a51c45..ad3075de 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -55,7 +55,7 @@ extern patch_t **hu_font; // void HU_Init(void); void HU_Start(void); -void HU_ResetWidgets (void); +void HU_disableAllWidgets (void); boolean HU_Responder(event_t* ev); diff --git a/src/m_menu.c b/src/m_menu.c index 38432ace..1af13462 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5553,7 +5553,7 @@ boolean M_Responder (event_t* ev) { hud_displayed = 1; //jff 3/3/98 turn hud on hud_active = (hud_active + 1) % 3; // cycle hud_active - HU_ResetWidgets(); + HU_disableAllWidgets(); } return true; } diff --git a/src/r_main.c b/src/r_main.c index 328d59e0..ed3d820e 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -38,6 +38,7 @@ #include "r_sky.h" #include "v_video.h" #include "st_stuff.h" +#include "hu_stuff.h" // Fineangles in the SCREENWIDTH wide window. #define FIELDOFVIEW 2048 @@ -550,6 +551,8 @@ void R_ExecuteSetViewSize (void) } } + HU_disableAllWidgets(); + // [crispy] forcefully initialize the status bar backing screen ST_refreshBackground(true);