Use a list for switching between game settings
authorTimePath <andrew.hardaker1995@gmail.com>
Tue, 25 Aug 2015 11:35:25 +0000 (21:35 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Tue, 25 Aug 2015 11:36:14 +0000 (21:36 +1000)
15 files changed:
qcsrc/client/progs.src
qcsrc/lib/Lazy.qh [new file with mode: 0644]
qcsrc/lib/_all.inc [new file with mode: 0644]
qcsrc/menu/gamesettings.qh [new file with mode: 0644]
qcsrc/menu/item/inputcontainer.qc
qcsrc/menu/progs.src
qcsrc/menu/xonotic/dialog_settings.qc
qcsrc/menu/xonotic/dialog_settings_game.qc
qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc
qcsrc/menu/xonotic/dialog_settings_game_hud.qc
qcsrc/menu/xonotic/dialog_settings_game_messages.qc
qcsrc/menu/xonotic/dialog_settings_game_model.qc
qcsrc/menu/xonotic/dialog_settings_game_view.qc
qcsrc/menu/xonotic/dialog_settings_game_weapons.qc
qcsrc/server/progs.src

index 0c030de..ce31eb6 100644 (file)
@@ -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 (file)
index 0000000..bf29049
--- /dev/null
@@ -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 (file)
index 0000000..ad82078
--- /dev/null
@@ -0,0 +1 @@
+#include "Lazy.qh"
diff --git a/qcsrc/menu/gamesettings.qh b/qcsrc/menu/gamesettings.qh
new file mode 100644 (file)
index 0000000..5085d3b
--- /dev/null
@@ -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
index 660bc2d..8e7f24f 100644 (file)
@@ -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)
index 2bde451..44bd627 100644 (file)
@@ -5,6 +5,8 @@
 ../dpdefs/keycodes.qh
 ../common/util-post.qh
 
+../lib/_all.inc
+
 oo/classes.qc
 
 draw.qc
index eb57476..e776411 100644 (file)
@@ -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()));
index 2dcdebc..497e1e5 100644 (file)
 #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
index db197d6..7a5db16 100644 (file)
@@ -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
index c9fc6d8..2c4903b 100644 (file)
@@ -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
index 764d7ef..09aed22 100644 (file)
@@ -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
index f91f7f0..7b0794b 100644 (file)
@@ -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
index 939fd0d..207c87b 100644 (file)
@@ -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
index aab91c7..c3dbac3 100644 (file)
@@ -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
index f10b721..e5b443e 100644 (file)
@@ -7,6 +7,8 @@ sys-pre.qh
 sys-post.qh
 ../common/util-post.qh
 
+../lib/_all.inc
+
 anticheat.qc
 antilag.qc
 campaign.qc