diff --git a/src/gs-entbase/shared/func_wall.qc b/src/gs-entbase/shared/func_wall.qc index 5929b264..3c95b10e 100644 --- a/src/gs-entbase/shared/func_wall.qc +++ b/src/gs-entbase/shared/func_wall.qc @@ -27,6 +27,7 @@ On idTech 2 BSPs, it will change texture variants when triggered. # TRIVIA This entity was introduced in Quake (1996). */ + class func_wall:NSRenderableEntity { @@ -39,6 +40,7 @@ public: virtual void Trigger(entity, triggermode_t); #else virtual void Init(void); + virtual bool CanSpawn(bool); #endif }; @@ -86,6 +88,13 @@ func_wall::Respawn(void) ClearAngles(); } #else + +bool +func_wall::CanSpawn(bool clientSide) +{ + return true; +} + void func_wall::Init(void) { diff --git a/src/menu-fn/includes.src b/src/menu-fn/includes.src index ac94b9d6..4ac3dde8 100644 --- a/src/menu-fn/includes.src +++ b/src/menu-fn/includes.src @@ -33,6 +33,11 @@ w_scrollbar.qc w_updatelist.qc w_combobox.qc +w_cvartextbox.qc +w_cvarcheckbox.qc + +layout_script.qc + m_addserver.qc m_advancedcontrols.qc m_advancedcustomize.qc diff --git a/src/menu-fn/layout_script.qc b/src/menu-fn/layout_script.qc new file mode 100644 index 00000000..8ffa9261 --- /dev/null +++ b/src/menu-fn/layout_script.qc @@ -0,0 +1,214 @@ +/* Copyright (c) 2023, Vera Visions, L.L.C. All rights reserved. */ + +/* Layout Script parser for Menu-FN + + Layout scripts are used for the advanced options for server and user settings. + Those are found on the filesystem as 'settings.src' and 'user.scr'. + + The layout is usually this: + + { + + "some_cvar" + { + "Description" + { TYPE [PARAMETERS ...] } + { Default Value } + } + [...] + } + + of which TYPE can be STRING, NUMBER, BOOL and LIST. + + The types for NUMBER specify a range like this: + + [...] + { + "Floating point cvar" + { NUMBER 0.0 1.0 } + { 0.5 } + } + [...] + + And you can set -1 to either min/max to disable a limit on either end. + In the above example we set the default value to something in between + the min/max. + + The types for LIST expect a whitespace separated key/value pair: + + [...] + { + "Damage setting" + { LIST "No damage" "0" "All damage" "1" } + { "1" } + } + [...] + + The default value for a LIST type needs to reference a value, not the key. + The LIST parameter may also span multiple lines. +*/ + +enum +{ + LAYBR_OUT, + LAYBR_CVAR, + LAYBR_DESCR, + LAYBR_VALUE, /* could be either type + params or default value */ +}; + +static vector g_layoutPos; + +static void +Layout_FromFile_Create(CPageTab target, string cvar, string descr, string type, string parms, string defval) +{ + int c = 0; + int x_ofs = 309; + CWidget new = __NULL__; + + //print(sprintf("New widget:\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\n", cvar, descr, type, parms, defval)); + + switch (type) { + case "STRING": + case "NUMBER": + CCVarTextBox txtbox; + new = spawn(CCVarTextBox); + txtbox = (CCVarTextBox)new; + txtbox.m_length = 156; + txtbox.SetCvar(cvar, defval); + break; + case "BOOL": + CCVarCheckBox chkbox; + new = spawn(CCVarCheckBox); + chkbox = (CCVarCheckBox)new; + chkbox.SetCvar(cvar, defval); + x_ofs = 138 + 28; + break; + case "LIST": + //new = spawn(CTextBox); + //break; + default: + print(sprintf("Unknown layout element type %S\n", type)); + } + + if (!new) + return; + + new.SetPos(g_layoutPos[0], g_layoutPos[1]); + target.AddWidget(new); + + /* add the label */ + CLabel lbl = spawn(CLabel); + lbl.SetPos(x_ofs, g_layoutPos[1] + 5); + lbl.SetText(descr, font_label); + lbl.SetTextHeight(14); + target.AddWidget(lbl); + + g_layoutPos[1] += 32; +} + +static void +Layout_FromFile_Parse(string line, CPageTab target) +{ + static string cvar; + static string descr; + static string type; + static string parms; + static string defval; + static int braced; /* what brace level we are in */ + static int depth; /* individual cvar brace depth */ + + int c = 0; + string key = __NULL__; + + c = tokenize_console(line); + + for (int i = 0; i < c; i++) { + key = argv(i); + + if not (key) + continue; + + switch (key) { + case "{": + braced++; + + if (braced > LAYBR_CVAR) + depth++; + break; + case "}": + braced--; + + /* we just got done with one widget */ + if (braced == LAYBR_CVAR) { + Layout_FromFile_Create(target, cvar, descr, type, parms, defval); + c = tokenize_console(line); /* the above function may tokenize */ + cvar = __NULL__; + descr = __NULL__; + type = __NULL__; + parms = __NULL__; + defval = __NULL__; + depth = 0; + } + break; + default: + //if (braced >= LAYBR_CVAR) + // print(sprintf("%i (depth %i): %S\n", braced, depth, key)); + + switch (braced) { + case LAYBR_CVAR: + cvar = key; + break; + case LAYBR_DESCR: + descr = key; + break; + case LAYBR_VALUE: + if (depth == 2) { + if (!type) + type = key; + else { + if (parms) + parms = sprintf("%s %S", parms, key); + else + parms = key; + } + } else if (depth == 3) { + if (defval) + defval = sprintf("%s %S", defval, key); + else + defval = key; + } + break; + default: + } + break; + } + } +} + +void +Layout_FromFile(string filename, CWidget target) +{ + filestream fh; + string line; + + CPageTab tab = spawn(CPageTab); + + //print(sprintf("Now loading: %S\n\n\n", filename)); + + fh = fopen(filename, FILE_READ); + if (fh < 0) { + error(sprintf("Cannot read layout file %S\n", filename)); + return; + } + + /* reset the starting position */ + g_layoutPos = [138, 140]; + + while ((line = fgets(fh))) { + Layout_FromFile_Parse(line, tab); + } + + fclose(fh); + + Widget_Add(target, tab); +} \ No newline at end of file diff --git a/src/menu-fn/m_advancedcustomize.qc b/src/menu-fn/m_advancedcustomize.qc index e0f5eb4a..a28c6b1a 100644 --- a/src/menu-fn/m_advancedcustomize.qc +++ b/src/menu-fn/m_advancedcustomize.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2023 Vera Visions LLC. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -63,6 +63,8 @@ menu_advancedcustomize_init(void) ac_btnCancel.SetExecute(ac_btncancel_start); ac_btnCancel.SetPos(50,172); Widget_Add(fn_advcustomize, ac_btnCancel); + + Layout_FromFile("user.scr", fn_advcustomize); } void diff --git a/src/menu-fn/m_advancedmpoptions.qc b/src/menu-fn/m_advancedmpoptions.qc index 0536cb6c..7f061419 100644 --- a/src/menu-fn/m_advancedmpoptions.qc +++ b/src/menu-fn/m_advancedmpoptions.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2023 Vera Visions LLC. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,17 +14,68 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +CWidget fn_advmpoptions; +CMainButton advmpopt_btnDone; +CMainButton advmpopt_btnCancel; + +void +advmpopt_btndone_start(void) +{ + static void advmpopt_btndone_end(void) { + g_menupage = PAGE_CREATEGAME; + } + localsound("../media/launch_dnmenu1.wav"); + header.SetStartEndPos(45,45,50,172); + header.SetStartEndSize(460,80,156,26); + header.m_lerp = 0.0f; + header.m_visible = TRUE; + header.SetHeader(HEAD_ADVANCED); + header.SetExecute(advmpopt_btndone_end); +} + +void +advmpopt_btncancel_start(void) +{ + static void advmpopt_btncancel_end(void) { + g_menupage = PAGE_CREATEGAME; + } + localsound("../media/launch_dnmenu1.wav"); + header.SetStartEndPos(45,45,50,172); + header.SetStartEndSize(460,80,156,26); + header.m_lerp = 0.0f; + header.m_visible = TRUE; + header.SetHeader(HEAD_ADVANCED); + header.SetExecute(advmpopt_btncancel_end); +} + void menu_advancedmpoptions_init(void) { + fn_advmpoptions = spawn(CWidget); + advmpopt_btnDone = spawn(CMainButton); + advmpopt_btnDone.SetImage(BTN_DONE); + advmpopt_btnDone.SetExecute(advmpopt_btndone_start); + advmpopt_btnDone.SetPos(50,140); + Widget_Add(fn_advmpoptions, advmpopt_btnDone); + + advmpopt_btnCancel = spawn(CMainButton); + advmpopt_btnCancel.SetImage(BTN_CANCEL); + advmpopt_btnCancel.SetExecute(advmpopt_btncancel_start); + advmpopt_btnCancel.SetPos(50,172); + Widget_Add(fn_advmpoptions, advmpopt_btnCancel); + + Layout_FromFile("settings.scr", fn_advmpoptions); } void menu_advancedmpoptions_draw(void) { + Widget_Draw(fn_advmpoptions); + Header_Draw(HEAD_ADVOPTIONS); } void menu_advancedmpoptions_input(float evtype, float scanx, float chary, float devid) { + Widget_Input(fn_advmpoptions, evtype, scanx, chary, devid); } diff --git a/src/menu-fn/m_creategame.qc b/src/menu-fn/m_creategame.qc index e87bc713..c699e869 100644 --- a/src/menu-fn/m_creategame.qc +++ b/src/menu-fn/m_creategame.qc @@ -65,6 +65,21 @@ create_btnok_start(void) header.SetExecute(create_btnok_end); } +void +create_btnadvanced_start(void) +{ + static void create_btnadvanced_end(void) { + g_menupage = PAGE_ADVANCEDMPOPTIONS; + } + localsound("../media/launch_upmenu1.wav"); + header.SetStartEndPos(50,172,45,45); + header.SetStartEndSize(156,26,460,80); + header.m_lerp = 0.0f; + header.m_visible = TRUE; + header.SetHeader(HEAD_ADVANCED); + header.SetExecute(create_btnadvanced_end); +} + void create_btncancel_start(void) { @@ -95,7 +110,7 @@ menu_creategame_init(void) fn_create = spawn(CWidget); create_btnAdv = spawn(CMainButton); create_btnAdv.SetImage(BTN_ADVOPTIONS); - //create_btnAdv.SetExecute(btn_console); + create_btnAdv.SetExecute(create_btnadvanced_start); create_btnAdv.SetPos(50,140); Widget_Add(fn_create, create_btnAdv); diff --git a/src/menu-fn/w_cvarcheckbox.qc b/src/menu-fn/w_cvarcheckbox.qc new file mode 100644 index 00000000..d43bf7fe --- /dev/null +++ b/src/menu-fn/w_cvarcheckbox.qc @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016-2022 Vera Visions LLC. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +class CCVarCheckBox:CWidget +{ + string m_cvar; + float m_value; + int m_hover; + int m_click; + virtual void(float value) m_changed = 0; + + virtual void(void) Draw; + virtual void(float, float, float, float) Input; + + virtual void(string, string) SetCvar; + virtual void _CVarChanged(void); +}; + +void +CCVarCheckBox::_CVarChanged(void) +{ + cvar_set(m_cvar, ftos(m_value)); + //print(sprintf("Cvar %S changed to %d\n", m_cvar, m_value)); +} + +void +CCVarCheckBox::Draw(void) +{ + if (m_click) { + drawpic([g_menuofs[0]+m_x,g_menuofs[1]+m_y], g_bmp[CB_DOWN], + [19,19], [1,1,1], 1.0f, 0); + } else { + if (m_value) { + drawpic([g_menuofs[0]+m_x,g_menuofs[1]+m_y], g_bmp[CB_CHECKED], + [19,19], [1,1,1], 1.0f); + } else { + drawpic([g_menuofs[0]+m_x,g_menuofs[1]+m_y], g_bmp[CB_EMPTY], + [19,19], [1,1,1], 1.0f); + } + } + + if (m_hover) { + drawpic([g_menuofs[0]+m_x,g_menuofs[1]+m_y], g_bmp[CB_OVER], + [19,19], [1,1,1], 1.0f, 1); + } +} +void +CCVarCheckBox::Input(float type, float x, float y, float devid) +{ + if (Util_CheckMouse(m_x, m_y, 19, 19) == TRUE) { + m_hover = TRUE; + } else { + m_hover = FALSE; + } + + if (m_hover && type == IE_KEYDOWN && x == K_MOUSE1) { + m_click = TRUE; + } + + if (type == IE_KEYUP && x == K_MOUSE1) { + if (m_click) { + m_click = FALSE; + m_value = TRUE - m_value; + _CVarChanged(); + } + } +} + +void +CCVarCheckBox::SetCvar(string txt, string defaultvalue) +{ + string stringval = cvar_string(txt); + + if (!stringval) + m_value = stof(defaultvalue); + else + m_value = cvar(txt); + + m_cvar = txt; + _CVarChanged(); +} diff --git a/src/menu-fn/w_cvartextbox.qc b/src/menu-fn/w_cvartextbox.qc new file mode 100644 index 00000000..6f9c03e7 --- /dev/null +++ b/src/menu-fn/w_cvartextbox.qc @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2016-2022 Vera Visions LLC. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +enumflags +{ + TEXTBOX_VISIBLE, + TEXTBOX_HOVER, + TEXTBOX_DOWN, + TEXTBOX_FOCUS, +}; + +class CCVarTextBox:CWidget +{ + string m_text; + int m_length; + int m_flags; + string m_cvar; + + void(void) CCVarTextBox; + virtual void(void) Draw; + virtual void(float, float, float, float) Input; + + virtual void(string, string) SetCvar; + virtual void(int) SetLength; + virtual void _CVarChanged(void); +}; + +void +CCVarTextBox::_CVarChanged(void) +{ + cvar_set(m_cvar, m_text); + //print(sprintf("Cvar %S changed to %S\n", m_cvar, m_text)); +} + +void +CCVarTextBox::CCVarTextBox(void) +{ + m_length = 184; +} + +void +CCVarTextBox::Draw(void) +{ + if (g_focuswidget == this) { + drawfill([g_menuofs[0]+m_x,g_menuofs[1]+m_y], [m_length,24], [0.5,0.5,0.5], 1.0f); + } else { + drawfill([g_menuofs[0]+m_x,g_menuofs[1]+m_y], [m_length,24], [0.25,0.25,0.25], 1.0f); + } + drawfill([g_menuofs[0]+m_x+3,g_menuofs[1]+m_y+3], [m_length-6,18], [0,0,0], 1.0f); + drawfont = Font_GetID(font_label); + + if (m_flags & TEXTBOX_FOCUS) { + if (rint(time*4) & 1) { + drawstring([g_menuofs[0]+m_x+6,g_menuofs[1]+m_y+6], + sprintf("%s|", m_text), [12,12], col_input_text, 1.0f, 0); + return; + } + } + + if (m_text) { + drawstring([g_menuofs[0] + m_x + 6, g_menuofs[1] + m_y + 6], m_text, + [12,12], col_input_text, 1.0f, 0); + } +} + +void +CCVarTextBox::Input(float type, float x, float y, float devid) +{ + if (type == IE_KEYDOWN) { + switch (x) { + case K_MOUSE1: + if (Util_CheckMouse(m_x,m_y,m_length,24)) { + g_focuswidget = this; + m_flags |= TEXTBOX_DOWN; + } + break; + case K_BACKSPACE: + if (m_flags & TEXTBOX_FOCUS) { + m_text = substring(m_text, 0, strlen(m_text) - 1); + } + break; + case K_ENTER: + case K_KP_ENTER: + _CVarChanged(); + break; + case K_ESCAPE: + break; + default: + if (m_flags & TEXTBOX_FOCUS) { + m_text = sprintf("%s%s", m_text, chr2str(y)); + } + } + } else if (type == IE_KEYUP) { + if (x == K_MOUSE1) { + if (m_flags & TEXTBOX_DOWN && Util_CheckMouse(m_x,m_y,m_length,24)) { + m_flags |= TEXTBOX_FOCUS; + } else { + m_flags -= (m_flags & TEXTBOX_FOCUS); + } + m_flags -= (m_flags & TEXTBOX_DOWN); + } + } +} + +void +CCVarTextBox::SetCvar(string txt, string defaultvalue) +{ + m_text = cvar_string(txt); + + if (!m_text) + m_text = defaultvalue; + + m_cvar = txt; + _CVarChanged(); +} + +void +CCVarTextBox::SetLength(int len) +{ + m_length = len; +} diff --git a/src/menu-fn/w_label.qc b/src/menu-fn/w_label.qc index 032daf6a..34574cbb 100644 --- a/src/menu-fn/w_label.qc +++ b/src/menu-fn/w_label.qc @@ -23,8 +23,10 @@ class CLabel:CWidget float m_alpha; int m_font; - void(void) CLabel; - virtual void(void) Draw; + void CLabel(void); + virtual void Draw(void); + virtual void SetText(string, font_s); + virtual void SetTextHeight(int); }; void @@ -36,11 +38,25 @@ CLabel::CLabel(void) m_sx = m_sy = 8; } +void +CLabel::SetText(string txt, font_s font) +{ + m_label = txt; + m_font = Font_GetID(font); + m_sx = m_sy = Font_GetHeight(font); +} + +void +CLabel::SetTextHeight(int val) +{ + m_sx = m_sy = val; +} + void CLabel::Draw(void) { drawfont = m_font; - drawstring([m_x,m_y], m_label, [m_sx,m_sy], m_color, m_alpha, 0); + drawstring([g_menuofs[0] + m_x, g_menuofs[1] + m_y], m_label, [m_sx,m_sy], m_color, m_alpha, 0); } /* Sometimes all you need is a static label */ diff --git a/src/menu-fn/w_pagetab.qc b/src/menu-fn/w_pagetab.qc index 70b786d1..bc5f1d9e 100644 --- a/src/menu-fn/w_pagetab.qc +++ b/src/menu-fn/w_pagetab.qc @@ -1 +1,143 @@ -// TODO +class CPageTab:CWidget +{ + int m_page; + int m_maxpage; + CWidget m_children; + int m_items; + + int m_lbtnstate; + int m_rbtnstate; + + void CPageTab(void); + virtual void Draw(void); + virtual void Input(float, float, float, float); + + virtual void AddWidget(CWidget); +}; + +void +CPageTab::CPageTab(void) +{ + m_page = 1; + m_maxpage = 1; +} + +.string classname; +void +CPageTab::Draw(void) +{ + string lbtn = g_bmp[LARROWDEFAULT]; + string rbtn = g_bmp[RARROWDEFAULT]; + + if (m_lbtnstate & 2) + lbtn = g_bmp[LARROWPRESSED]; + else if (m_lbtnstate & 1) + lbtn = g_bmp[LARROWFLYOVER]; + + if (m_rbtnstate & 2) + rbtn = g_bmp[RARROWPRESSED]; + else if (m_rbtnstate & 1) + rbtn = g_bmp[RARROWFLYOVER]; + + drawpic([g_menuofs[0]+440,g_menuofs[1]+108], lbtn, + [16,16], [1,1,1], 1.0f, 0); + drawpic([g_menuofs[0]+573,g_menuofs[1]+108], rbtn, + [16,16], [1,1,1], 1.0f, 0); + + WLabel_Static(460, 111, sprintf("Page %i of %i", m_page, m_maxpage), 14, 14, [1,1,1], + 1.0, 0, font_label); + + CWidget wNext = m_children; + do { + if (wNext) { + //print(sprintf("%i %s\n", wNext.m_onpage, wNext.classname)); + if (wNext.m_onpage == m_page) + wNext.Draw(); + } + wNext = wNext.m_next; + } while (wNext); +} + +void +CPageTab::Input(float type, float x, float y, float devid) +{ + /* left button hover check */ + if (Util_CheckMouse(440, 108, 26, 26)) + m_lbtnstate |= 1; + else + m_lbtnstate &= ~ 1; + + /* right button hover check */ + if (Util_CheckMouse(573, 108, 26, 26)) + m_rbtnstate |= 1; + else + m_rbtnstate &= ~ 1; + + /* left button click check */ + if ((m_lbtnstate & 1) && type == IE_KEYDOWN && x == K_MOUSE1) { + m_lbtnstate |= 2; + } + + /* right button click check */ + m_rbtnstate = Util_CheckMouse(573, 108, 26, 26) ? 1 : 0; + if ((m_rbtnstate & 1) && type == IE_KEYDOWN && x == K_MOUSE1) { + m_rbtnstate |= 2; + } + + /* unclick + trigger (if need be) */ + if (type == IE_KEYUP && x == K_MOUSE1) { + m_lbtnstate &= ~2; + m_rbtnstate &= ~2; + + if (m_lbtnstate & 1) { + m_page--; + + if (m_page < 1) + m_page = 1; + } + if (m_rbtnstate & 1) { + m_page++; + + if (m_page > m_maxpage) + m_page = m_maxpage; + } + } + + /* pass inputs to our children */ + CWidget wNext = m_children; + do { + if (wNext) { + if (wNext.m_onpage == m_page) + wNext.Input(type, x, y, devid); + } + wNext = wNext.m_next; + } while (wNext); +} + +void +CPageTab::AddWidget(CWidget new) +{ + /* 8 widgets plus their label = 16 items per page */ + m_maxpage = 1 + floor((float)m_items / 16.0); + + new.m_y -= (m_maxpage - 1) * (32*8); + + if (m_children) { + CWidget wNext = m_children; + do { + if (!wNext.m_next) { + wNext.m_next = new; + new.m_onpage = m_maxpage; + //print(sprintf("%d adding %S to page %i\n", num_for_edict(this), new.classname, m_maxpage)); + m_items++; + return; + } + wNext = wNext.m_next; + } while (wNext); + } else { + m_children = new; + new.m_onpage = m_maxpage; + m_items++; + //print(sprintf("%d adding %S to page %i\n", num_for_edict(this), new.classname, m_maxpage)); + } +} \ No newline at end of file diff --git a/src/menu-fn/widgets.qc b/src/menu-fn/widgets.qc index e4a7d508..ab5ff978 100644 --- a/src/menu-fn/widgets.qc +++ b/src/menu-fn/widgets.qc @@ -20,6 +20,7 @@ class CWidget int m_y; CWidget m_next; CWidget m_parent; + int m_onpage; void(void) CWidget; virtual void(void) Draw; @@ -33,6 +34,7 @@ CWidget::CWidget(void) { m_x = g_menuofs[0]; m_y = g_menuofs[1]; + m_onpage = 0; } void