From a8a845350f16ddf8c2b1a71e79abb7066741403c Mon Sep 17 00:00:00 2001 From: TimePath Date: Tue, 25 Aug 2015 21:35:25 +1000 Subject: [PATCH] Use a list for switching between game settings --- qcsrc/client/progs.src | 2 + qcsrc/lib/Lazy.qh | 15 ++ qcsrc/lib/_all.inc | 1 + qcsrc/menu/gamesettings.qh | 15 ++ qcsrc/menu/item/inputcontainer.qc | 33 ++-- qcsrc/menu/progs.src | 2 + qcsrc/menu/xonotic/dialog_settings.qc | 2 +- qcsrc/menu/xonotic/dialog_settings_game.qc | 169 +++++++++++++----- .../xonotic/dialog_settings_game_crosshair.qc | 3 + .../menu/xonotic/dialog_settings_game_hud.qc | 3 + .../xonotic/dialog_settings_game_messages.qc | 3 + .../xonotic/dialog_settings_game_model.qc | 3 + .../menu/xonotic/dialog_settings_game_view.qc | 3 + .../xonotic/dialog_settings_game_weapons.qc | 3 + qcsrc/server/progs.src | 2 + 15 files changed, 191 insertions(+), 68 deletions(-) create mode 100644 qcsrc/lib/Lazy.qh create mode 100644 qcsrc/lib/_all.inc create mode 100644 qcsrc/menu/gamesettings.qh diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src index 0c030de33..ce31eb647 100644 --- a/qcsrc/client/progs.src +++ b/qcsrc/client/progs.src @@ -4,6 +4,8 @@ ../dpdefs/csprogsdefs.qh ../common/util-post.qh +../lib/_all.inc + announcer.qc bgmscript.qc casings.qc diff --git a/qcsrc/lib/Lazy.qh b/qcsrc/lib/Lazy.qh new file mode 100644 index 000000000..bf29049e7 --- /dev/null +++ b/qcsrc/lib/Lazy.qh @@ -0,0 +1,15 @@ +#ifndef LAZY_H +#define LAZY_H +CLASS(Lazy, Object) + ATTRIB(Lazy, m_get, entity(), func_null); + CONSTRUCTOR(Lazy, entity() _compute) { this.m_get = _compute; } +ENDCLASS(Lazy) + +#define LAZY(id) __lazy_##id +#define LAZY_NEW(id, compute) entity LAZY(id)() { \ + static bool done; \ + static entity it; \ + if (!done) { it = compute; done = true; } \ + return it; \ +} +#endif diff --git a/qcsrc/lib/_all.inc b/qcsrc/lib/_all.inc new file mode 100644 index 000000000..ad82078a1 --- /dev/null +++ b/qcsrc/lib/_all.inc @@ -0,0 +1 @@ +#include "Lazy.qh" diff --git a/qcsrc/menu/gamesettings.qh b/qcsrc/menu/gamesettings.qh new file mode 100644 index 000000000..5085d3b4a --- /dev/null +++ b/qcsrc/menu/gamesettings.qh @@ -0,0 +1,15 @@ +#ifdef MENUQC +#ifndef GAMESETTINGS_H +#define GAMESETTINGS_H + +void RegisterSettings(); +const int MAX_SETTINGS = 24; +Lazy SETTINGS[MAX_SETTINGS], SETTINGS_first, SETTINGS_last; +int SETTINGS_COUNT; +#define REGISTER_SETTINGS(id, impl) \ + LAZY_NEW(id, impl) \ + REGISTER(RegisterSettings, MENU, SETTINGS, SETTINGS_COUNT, id, m_id, NEW(Lazy, LAZY(id))) +REGISTER_REGISTRY(RegisterSettings) + +#endif +#endif diff --git a/qcsrc/menu/item/inputcontainer.qc b/qcsrc/menu/item/inputcontainer.qc index 660bc2d1b..8e7f24f73 100644 --- a/qcsrc/menu/item/inputcontainer.qc +++ b/qcsrc/menu/item/inputcontainer.qc @@ -10,7 +10,7 @@ CLASS(InputContainer, Container) METHOD(InputContainer, focusLeave, void(entity)); METHOD(InputContainer, resizeNotify, void(entity, vector, vector, vector, vector)); - METHOD(InputContainer, _changeFocusXY, float(entity, vector)); + METHOD(InputContainer, _changeFocusXY, bool(entity this, vector pos)); ATTRIB(InputContainer, mouseFocusedChild, entity, NULL) ATTRIB(InputContainer, isTabRoot, float, 0) ENDCLASS(InputContainer) @@ -104,26 +104,21 @@ float InputContainer_keyDown(entity me, float scan, float ascii, float shift) return 0; } -float InputContainer__changeFocusXY(entity me, vector pos) +bool InputContainer__changeFocusXY(entity this, vector pos) { - entity e, ne; - e = me.mouseFocusedChild; - ne = me.itemFromPoint(me, pos); - if(ne) - if (!ne.focusable) - ne = NULL; - me.mouseFocusedChild = ne; - if(ne) - if(ne != e) - { - me.setFocus(me, ne); - if(ne.instanceOfInputContainer) - { - ne.focusedChild = NULL; - ne._changeFocusXY(e, globalToBox(pos, ne.Container_origin, ne.Container_size)); - } + entity e = this.itemFromPoint(this, pos); + if (e && !e.focusable) e = NULL; + entity prev = this.mouseFocusedChild; + this.mouseFocusedChild = e; + if (!e) return false; // keep focus when hovering over non-focusable elements + if (e != prev) { + this.setFocus(this, e); + if (e.instanceOfInputContainer) { + e.focusedChild = NULL; + e._changeFocusXY(e, globalToBox(pos, e.Container_origin, e.Container_size)); } - return (ne != NULL); + } + return true; // have focus } float InputContainer_mouseDrag(entity me, vector pos) diff --git a/qcsrc/menu/progs.src b/qcsrc/menu/progs.src index 2bde451f8..44bd62722 100644 --- a/qcsrc/menu/progs.src +++ b/qcsrc/menu/progs.src @@ -5,6 +5,8 @@ ../dpdefs/keycodes.qh ../common/util-post.qh +../lib/_all.inc + oo/classes.qc draw.qc diff --git a/qcsrc/menu/xonotic/dialog_settings.qc b/qcsrc/menu/xonotic/dialog_settings.qc index eb57476af..e776411f2 100644 --- a/qcsrc/menu/xonotic/dialog_settings.qc +++ b/qcsrc/menu/xonotic/dialog_settings.qc @@ -21,7 +21,7 @@ void XonoticSettingsDialog_fill(entity me) me.TD(me, 1, 2, mc.makeTabButton(mc, _("Effects"), makeXonoticEffectsSettingsTab())); me.TD(me, 1, 2, mc.makeTabButton(mc, _("Audio"), makeXonoticAudioSettingsTab())); me.TR(me); - me.TD(me, 1, 1.5, mc.makeTabButton(mc, _("Game"), makeXonoticGameSettingsTab())); + me.TD(me, 1, 1.5, mc.makeTabButton(mc, _("Game"), NEW(XonoticGameSettingsTab))); me.TD(me, 1, 1.5, mc.makeTabButton(mc, _("Input"), makeXonoticInputSettingsTab())); me.TD(me, 1, 1.5, mc.makeTabButton(mc, _("User"), makeXonoticUserSettingsTab())); me.TD(me, 1, 1.5, mc.makeTabButton(mc, _("Misc"), makeXonoticMiscSettingsTab())); diff --git a/qcsrc/menu/xonotic/dialog_settings_game.qc b/qcsrc/menu/xonotic/dialog_settings_game.qc index 2dcdebca9..497e1e5e7 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game.qc @@ -1,55 +1,128 @@ #ifndef DIALOG_SETTINGS_GAME_H #define DIALOG_SETTINGS_GAME_H + +#include "../gamesettings.qh" + +#include "datasource.qc" +CLASS(SettingSource, DataSource) + METHOD(SettingSource, getEntry, entity(int i, void(string name, string icon) returns)) + { + Lazy l = SETTINGS[i]; + entity it = l.m_get(); + if (returns) returns(it.title, string_null); + return it; + } + METHOD(SettingSource, reload, int(string filter)) { return SETTINGS_COUNT; } +ENDCLASS(SettingSource) + +#include "listbox.qc" +CLASS(XonoticRegisteredSettingsList, XonoticListBox) + ATTRIB(XonoticRegisteredSettingsList, alphaBG, float, 0) + ATTRIB(XonoticRegisteredSettingsList, itemAbsSize, vector, '0 0 0') + ATTRIB(XonoticRegisteredSettingsList, origin, vector, '0 0 0') + ATTRIB(XonoticRegisteredSettingsList, realFontSize, vector, '0 0 0') + ATTRIB(XonoticRegisteredSettingsList, realUpperMargin, float, 0) + ATTRIB(XonoticRegisteredSettingsList, rowsPerItem, float, 2) + ATTRIB(XonoticRegisteredSettingsList, stringFilterBox, entity, NULL) + ATTRIB(XonoticRegisteredSettingsList, stringFilter, string, string_null) + ATTRIB(XonoticRegisteredSettingsList, typeToSearchString, string, string_null) + ATTRIB(XonoticRegisteredSettingsList, typeToSearchTime, float, 0) + ATTRIB(XonoticRegisteredSettingsList, source, DataSource, NULL) + ATTRIB(XonoticRegisteredSettingsList, onChange, void(entity, entity), func_null) + ATTRIB(XonoticRegisteredSettingsList, onChangeEntity, entity, NULL) + string XonoticRegisteredSettingsList_cb_name; + void XonoticRegisteredSettingsList_cb(string _name, string _icon) + { + XonoticRegisteredSettingsList_cb_name = _name; + } + METHOD(XonoticRegisteredSettingsList, drawListBoxItem, void(entity this, int i, vector absSize, bool isSelected, bool isFocused)) + { + if (!this.source) return; + if (!this.source.getEntry(i, XonoticRegisteredSettingsList_cb)) return; + string name = XonoticRegisteredSettingsList_cb_name; + if (isSelected) { + draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED); + } else if (isFocused) { + this.focusedItemAlpha = getFadedAlpha(this.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED); + draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, this.focusedItemAlpha); + } + string s = draw_TextShortenToWidth(strdecolorize(name), 1, 0, this.realFontSize); + draw_Text(this.realUpperMargin * eY + (0.5 * this.realFontSize.x) * eX, s, this.realFontSize, '1 1 1', SKINALPHA_TEXT, 0); + } + METHOD(XonoticRegisteredSettingsList, refilter, void(entity this)) + { + if (!this.source) { + this.nItems = 0; + return; + } + this.nItems = this.source.reload(this.stringFilter); + } + METHOD(XonoticRegisteredSettingsList, resizeNotify, void(entity this, vector relOrigin, vector relSize, vector absOrigin, vector absSize)) + { + super.resizeNotify(this, relOrigin, relSize, absOrigin, absSize); + + this.itemAbsSize = '0 0 0'; + this.realFontSize_y = this.fontSize / (this.itemAbsSize_y = (absSize.y * this.itemHeight)); + this.realFontSize_x = this.fontSize / (this.itemAbsSize_x = (absSize.x * (1 - this.controlWidth))); + this.realUpperMargin = 0.5 * (1 - this.realFontSize.y); + } + METHOD(XonoticRegisteredSettingsList, setSelected, void(entity this, int i)) + { + super.setSelected(this, i); + this.onChange(this, this.onChangeEntity); + } + CONSTRUCTOR(XonoticRegisteredSettingsList, DataSource _source) { + CONSTRUCT(XonoticRegisteredSettingsList); + this.source = _source; + this.configureXonoticListBox(this); + this.refilter(this); + } +ENDCLASS(XonoticRegisteredSettingsList) + #include "tab.qc" CLASS(XonoticGameSettingsTab, XonoticTab) - METHOD(XonoticGameSettingsTab, fill, void(entity)); ATTRIB(XonoticGameSettingsTab, intendedWidth, float, 0.9) - ATTRIB(XonoticGameSettingsTab, rows, float, 15.5) - ATTRIB(XonoticGameSettingsTab, columns, float, 6.5) -ENDCLASS(XonoticGameSettingsTab) -entity makeXonoticGameSettingsTab(); -#endif + ATTRIB(XonoticGameSettingsTab, rows, float, 15.5) + ATTRIB(XonoticGameSettingsTab, columns, float, 6.5) + ATTRIB(XonoticGameSettingsTab, topicList, entity, NEW(XonoticRegisteredSettingsList, NEW(SettingSource))) + ATTRIB(XonoticGameSettingsTab, currentPanel, entity, NEW(XonoticTab)) + ATTRIB(XonoticGameSettingsTab, currentItem, entity, NULL) + METHOD(XonoticGameSettingsTab, topicChangeNotify, void(entity, entity this)) + { + entity c = this.currentPanel; + entity removing = this.currentItem; + entity adding = this.topicList.source.getEntry(this.topicList.selectedItem, func_null); + if (removing == adding) return; + if (removing) { + this.currentItem = NULL; + c.removeItem(c, removing); + } + if (adding) { + this.currentItem = adding; + adding.resizeNotify(adding, '0 0 0', c.size, '0 0 0', c.size); + c.addItem(c, adding, '0 0 0', '1 1 0', 1); + } + } + METHOD(XonoticGameSettingsTab, fill, void(entity this)) + { + entity topics = this.topicList; + topics.onChange = this.topicChangeNotify; + topics.onChangeEntity = this; + + int + col = 0, width = 1.5; + this.gotoRC(this, 0, col); + this.TD(this, this.rows, width, topics); -#ifdef IMPLEMENTATION -entity makeXonoticGameSettingsTab() -{ - entity me; - me = NEW(XonoticGameSettingsTab); - me.configureDialog(me); - return me; -} - -void XonoticGameSettingsTab_fill(entity me) -{ - entity mc; - mc = makeXonoticTabController(me.rows - 2.5); - - me.TR(me); - me.TDempty(me, 0.25); - me.TD(me, 1, 1, mc.makeTabButton(mc, _("View"), makeXonoticGameViewSettingsTab())); - me.TD(me, 1, 1, mc.makeTabButton(mc, _("Crosshair"), makeXonoticGameCrosshairSettingsTab())); - me.TD(me, 1, 1, mc.makeTabButton(mc, _("HUD"), makeXonoticGameHUDSettingsTab())); - me.TD(me, 1, 1, mc.makeTabButton(mc, _("Messages"), makeXonoticGameMessageSettingsTab())); - me.TD(me, 1, 1, mc.makeTabButton(mc, _("Weapons"), makeXonoticGameWeaponsSettingsTab())); - me.TD(me, 1, 1, mc.makeTabButton(mc, _("Models"), makeXonoticGameModelSettingsTab())); - - me.gotoRC(me, 1.5, 0); - me.TD(me, me.rows - 1.5, me.columns, mc); - - /* - - makeXonoticGameViewSettingsTab())); - makeXonoticGameGeneralSettingsTab())); - makeXonoticGameCrosshairSettingsTab())); - - makeXonoticGameWeaponSettingsTab())); - l"), makeXonoticGamePlayermodelSettingsTab())); - makeXonoticGameHUDSettingsTab())); - on"), makeXonoticGameNotificationSettingsTab())); - - - me.TR(me); - me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_gentle", _("Disable gore effects and harsh language"))); // also set sv_gentle - */ -} + col += width, width = this.columns - col; + this.gotoRC(this, 0, col); this.setFirstColumn(this, this.currentColumn); + this.TD(this, this.rows, width, this.currentPanel); + + this.topicChangeNotify(topics, this); + } + INIT(XonoticGameSettingsTab) + { + this.configureDialog(this); + } +ENDCLASS(XonoticGameSettingsTab) #endif diff --git a/qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc b/qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc index db197d604..7a5db16f3 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc @@ -4,11 +4,14 @@ CLASS(XonoticGameCrosshairSettingsTab, XonoticTab) METHOD(XonoticGameCrosshairSettingsTab, fill, void(entity)); METHOD(XonoticGameCrosshairSettingsTab, showNotify, void(entity)); + ATTRIB(XonoticGameCrosshairSettingsTab, title, string, _("Crosshair")) ATTRIB(XonoticGameCrosshairSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticGameCrosshairSettingsTab, rows, float, 13) ATTRIB(XonoticGameCrosshairSettingsTab, columns, float, 6.2) ENDCLASS(XonoticGameCrosshairSettingsTab) entity makeXonoticGameCrosshairSettingsTab(); +#include "../gamesettings.qh" +REGISTER_SETTINGS(Crosshair, makeXonoticGameCrosshairSettingsTab()); #endif #ifdef IMPLEMENTATION diff --git a/qcsrc/menu/xonotic/dialog_settings_game_hud.qc b/qcsrc/menu/xonotic/dialog_settings_game_hud.qc index c9fc6d821..2c4903b0d 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game_hud.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game_hud.qc @@ -4,12 +4,15 @@ CLASS(XonoticGameHUDSettingsTab, XonoticTab) METHOD(XonoticGameHUDSettingsTab, fill, void(entity)); METHOD(XonoticGameHUDSettingsTab, showNotify, void(entity)); + ATTRIB(XonoticGameHUDSettingsTab, title, string, _("HUD")) ATTRIB(XonoticGameHUDSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticGameHUDSettingsTab, rows, float, 13) ATTRIB(XonoticGameHUDSettingsTab, columns, float, 6.2) ENDCLASS(XonoticGameHUDSettingsTab) entity makeXonoticGameHUDSettingsTab(); void HUDSetup_Start(entity me, entity btn); +#include "../gamesettings.qh" +REGISTER_SETTINGS(HUD, makeXonoticGameHUDSettingsTab()); #endif #ifdef IMPLEMENTATION diff --git a/qcsrc/menu/xonotic/dialog_settings_game_messages.qc b/qcsrc/menu/xonotic/dialog_settings_game_messages.qc index 764d7ef50..09aed22ba 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game_messages.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game_messages.qc @@ -4,12 +4,15 @@ CLASS(XonoticGameMessageSettingsTab, XonoticTab) METHOD(XonoticGameMessageSettingsTab, fill, void(entity)); METHOD(XonoticGameMessageSettingsTab, showNotify, void(entity)); + ATTRIB(XonoticGameMessageSettingsTab, title, string, _("Messages")) ATTRIB(XonoticGameMessageSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticGameMessageSettingsTab, rows, float, 13) ATTRIB(XonoticGameMessageSettingsTab, columns, float, 6) ATTRIB(XonoticGameMessageSettingsTab, weaponsList, entity, NULL) ENDCLASS(XonoticGameMessageSettingsTab) entity makeXonoticGameMessageSettingsTab(); +#include "../gamesettings.qh" +REGISTER_SETTINGS(Messages, makeXonoticGameMessageSettingsTab()); #endif #ifdef IMPLEMENTATION diff --git a/qcsrc/menu/xonotic/dialog_settings_game_model.qc b/qcsrc/menu/xonotic/dialog_settings_game_model.qc index f91f7f039..7b0794bdd 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game_model.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game_model.qc @@ -4,11 +4,14 @@ CLASS(XonoticGameModelSettingsTab, XonoticTab) METHOD(XonoticGameModelSettingsTab, fill, void(entity)); METHOD(XonoticGameModelSettingsTab, showNotify, void(entity)); + ATTRIB(XonoticGameModelSettingsTab, title, string, _("Models")) ATTRIB(XonoticGameModelSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticGameModelSettingsTab, rows, float, 13) ATTRIB(XonoticGameModelSettingsTab, columns, float, 5) ENDCLASS(XonoticGameModelSettingsTab) entity makeXonoticGameModelSettingsTab(); +#include "../gamesettings.qh" +REGISTER_SETTINGS(Models, makeXonoticGameModelSettingsTab()); #endif #ifdef IMPLEMENTATION diff --git a/qcsrc/menu/xonotic/dialog_settings_game_view.qc b/qcsrc/menu/xonotic/dialog_settings_game_view.qc index 939fd0dc9..207c87b9e 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game_view.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game_view.qc @@ -4,11 +4,14 @@ CLASS(XonoticGameViewSettingsTab, XonoticTab) METHOD(XonoticGameViewSettingsTab, fill, void(entity)); METHOD(XonoticGameViewSettingsTab, showNotify, void(entity)); + ATTRIB(XonoticGameViewSettingsTab, title, string, _("View")) ATTRIB(XonoticGameViewSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticGameViewSettingsTab, rows, float, 13) ATTRIB(XonoticGameViewSettingsTab, columns, float, 6.2) ENDCLASS(XonoticGameViewSettingsTab) entity makeXonoticGameViewSettingsTab(); +#include "../gamesettings.qh" +REGISTER_SETTINGS(View, makeXonoticGameViewSettingsTab()); #endif #ifdef IMPLEMENTATION diff --git a/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc b/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc index aab91c748..c3dbac338 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc @@ -4,12 +4,15 @@ CLASS(XonoticGameWeaponsSettingsTab, XonoticTab) METHOD(XonoticGameWeaponsSettingsTab, fill, void(entity)); METHOD(XonoticGameWeaponsSettingsTab, showNotify, void(entity)); + ATTRIB(XonoticGameWeaponsSettingsTab, title, string, _("Weapons")) ATTRIB(XonoticGameWeaponsSettingsTab, intendedWidth, float, 0.9) ATTRIB(XonoticGameWeaponsSettingsTab, rows, float, 13) ATTRIB(XonoticGameWeaponsSettingsTab, columns, float, 6) ATTRIB(XonoticGameWeaponsSettingsTab, weaponsList, entity, NULL) ENDCLASS(XonoticGameWeaponsSettingsTab) entity makeXonoticGameWeaponsSettingsTab(); +#include "../gamesettings.qh" +REGISTER_SETTINGS(Weapons, makeXonoticGameWeaponsSettingsTab()); #endif #ifdef IMPLEMENTATION diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index f10b721ae..e5b443e96 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -7,6 +7,8 @@ sys-pre.qh sys-post.qh ../common/util-post.qh +../lib/_all.inc + anticheat.qc antilag.qc campaign.qc -- 2.39.2