]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge remote-tracking branch 'origin/master' into BuddyFriendGuy/mapStringFilter
authorTimePath <andrew.hardaker1995@gmail.com>
Sun, 10 May 2015 03:27:55 +0000 (13:27 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Sun, 10 May 2015 03:27:55 +0000 (13:27 +1000)
qcsrc/common/mapinfo.qc
qcsrc/common/mapinfo.qh
qcsrc/menu/xonotic/dialog_multiplayer_create.qc
qcsrc/menu/xonotic/maplist.qc
tooltips.db

index c3f15d1937e4963b06a1f6343c0d896c6ac44ce4..b8e35902653047eda3012894529ed11e9ebddcff 100644 (file)
@@ -187,6 +187,32 @@ float MapInfo_FilterGametype(int pGametype, int pFeatures, int pFlagsRequired, i
 
        return 1;
 }
+void MapInfo_FilterString(string sf)
+{
+       // this function further filters _MapInfo_filtered, which is prepared by MapInfo_FilterGametype by string
+       float i, j;
+       string title;
+
+       for(i = 0, j = -1; i < MapInfo_count; ++i)
+       {
+               if (MapInfo_Get_ByID(i))
+               {
+                       // prepare for keyword filter
+                       if (MapInfo_Map_title && strstrofs(MapInfo_Map_title, "<TITLE>", 0) == -1)
+                               title = MapInfo_Map_title;
+                       else
+                               title = MapInfo_Map_bspname;
+                       // keyword filter
+                       if((strstrofs(strtolower(title), strtolower(sf), 0)) >= 0)
+                               bufstr_set(_MapInfo_filtered, ++j, bufstr_get(_MapInfo_filtered, i));
+               }
+       }
+       MapInfo_count = j + 1;
+       MapInfo_ClearTemps();
+
+       // sometimes the glob isn't sorted nicely, so fix it here...
+       heapsort(MapInfo_count, _MapInfo_FilterList_swap, _MapInfo_FilterList_cmp, world);
+}
 
 void MapInfo_Filter_Free()
 {
index 134103b89f3f9b49ea014916403ea772452ebf4b..3038cce60e70a0ebe8380f2c47f350a779a151ba 100644 (file)
@@ -120,6 +120,7 @@ void MapInfo_Enumerate();
 // filter the info by game type mask (updates MapInfo_count)
 float MapInfo_progress;
 float MapInfo_FilterGametype(float gametype, float features, float pFlagsRequired, float pFlagsForbidden, float pAbortOnGenerate); // 1 on success, 0 on temporary failure (call it again next frame then; use MapInfo_progress as progress indicator)
+void MapInfo_FilterString(string sf); // filter _MapInfo_filtered (created by MapInfo_FilterGametype) with keyword
 int MapInfo_CurrentFeatures(); // retrieves currently required features from cvars
 int MapInfo_CurrentGametype(); // retrieves current gametype from cvars
 int MapInfo_ForbiddenFlags(); // retrieves current flags from cvars
index 13a8e3184bbc3d5c7b67a198132565e342e62895..04526d3f0acf3633fd64a4fe32b014bb9bbda392 100644 (file)
@@ -67,6 +67,8 @@ void XonoticServerCreateTab_fill(entity me)
 {
        entity e, e0;
 
+       // the left half begins here
+
        me.gotoRC(me, 0.5, 0);
                me.TD(me, 1, 3, makeXonoticHeaderLabel(_("Gametype")));
        me.TR(me);
@@ -132,33 +134,60 @@ void XonoticServerCreateTab_fill(entity me)
                        e.configureXonoticTextSliderValues(e);
                        setDependent(e, "bot_number", 0, -1);
 
-       me.gotoRC(me, me.rows - 3.5, 0);
+       me.gotoRC(me, me.rows - 3.8, 0);
                me.TD(me, 1, 3, e0 = makeXonoticTextLabel(0.5, string_null));
                        e0.textEntity = main.mutatorsDialog;
                        e0.allowCut = 1;
                        //e0.allowWrap = 1;
-       me.TR(me);
+
+       // mapListBox is in the right column but the ref is needed for mutators dialog here
+       me.mapListBox = makeXonoticMapList();
+       // here we use the following line instead of me.TR(me) for better visual spacing;
+       // this decision was made in this poll: http://forums.xonotic.org/showthread.php?tid=5445
+       me.gotoRC(me, me.rows - 2.5, 0);
                me.TDempty(me, 0.5);
                me.TD(me, 1, 2, e = makeXonoticButton(_("Mutators"), '0 0 0'));
                        e.onClick = DialogOpenButton_Click;
                        e.onClickEntity = main.mutatorsDialog;
                        main.mutatorsDialog.refilterEntity = me.mapListBox;
 
+       // The right half begins here
+
        me.gotoRC(me, 0.5, 3.2); me.setFirstColumn(me, me.currentColumn);
-               me.mapListBox = makeXonoticMapList();
+               // the maplistbox
                me.TD(me, 1, 3, e = makeXonoticHeaderLabel(_("Maplist")));
                        makeCallback(e, me.mapListBox, me.mapListBox.refilterCallback);
        me.TR(me);
-               me.TD(me, me.rows - 4, 3, me.mapListBox);
-       me.gotoRC(me, me.rows - 2.5, 3.2);
-               me.TDempty(me, 0.375);
-               me.TD(me, 1, 1.125, e = makeXonoticButton(_("Select all"), '0 0 0'));
-                       e.onClick = MapList_All;
+               // we use 5.8 here to visually match the bottom line of the component on the left (Bot Skill)
+               me.TD(me, me.rows - 5.8, 3, me.mapListBox);
+
+       me.gotoRC(me, me.rows - 3.8, me.firstColumn);
+               // string filter label and box
+               me.TD(me, 1, 0.35, e = makeXonoticTextLabel(1, _("Filter:")));
+               me.mapListBox.stringFilterBox = makeXonoticMapListStringFilterBox(me, 0, string_null);
+               me.mapListBox.stringFilterBox.tooltip = getZonedTooltipForIdentifier("XonoticMultiplayerDialog_StringFilterBox");
+               me.TD(me, 1, me.columns - me.firstColumn - 0.35, e = me.mapListBox.stringFilterBox);
+                       e.onChange = MapList_StringFilterBox_Change;
+                       e.keyDown = MapList_StringFilterBox_keyDown;
+                       e.onChangeEntity = me.mapListBox;
+                       me.mapListBox.controlledTextbox = e;
+
+       // here we use the following line instead of me.TR(me) for better visual spacing;
+       // this decision was made in this poll: http://forums.xonotic.org/showthread.php?tid=5445
+       me.gotoRC(me, me.rows - 2.5, me.firstColumn);
+               // the selection buttons
+               me.TD(me, 1, 1, e = makeXonoticButton(_("Add shown"), '0 0 0'));
+                       e.onClick = MapList_Add_Shown;
+                       e.onClickEntity = me.mapListBox;
+               me.TD(me, 1, 1, e = makeXonoticButton(_("Remove shown"), '0 0 0'));
+                       e.onClick = MapList_Remove_Shown;
                        e.onClickEntity = me.mapListBox;
-               me.TD(me, 1, 1.125, e = makeXonoticButton(_("Select none"), '0 0 0'));
-                       e.onClick = MapList_None;
+               me.TD(me, 1, 1, e = makeXonoticButton(_("Remove all"), '0 0 0'));
+                       e.onClick = MapList_Remove_All;
                        e.onClickEntity = me.mapListBox;
 
+       // The big button at the bottom
+
        me.gotoRC(me, me.rows - 1, 0);
                me.TD(me, 1, me.columns, e = makeXonoticButton(_("Start Multiplayer!"), '0 0 0'));
                        e.onClick = MapList_LoadMap;
index ec9aa1f4c7bc104216e3329d0d4c710e88c4e95b..f7da843621a2dff999e2fc153391982e06a1ccf8 100644 (file)
@@ -33,6 +33,9 @@ CLASS(XonoticMapList, XonoticListBox)
        METHOD(XonoticMapList, g_maplistCacheToggle, void(entity, float))
        METHOD(XonoticMapList, g_maplistCacheQuery, float(entity, float))
 
+       ATTRIB(XonoticMapList, stringFilter, string, string_null)
+       ATTRIB(XonoticMapList, stringFilterBox, entity, NULL)
+
        ATTRIB(XonoticMapList, startButton, entity, NULL)
 
        METHOD(XonoticMapList, loadCvars, void(entity))
@@ -45,8 +48,12 @@ CLASS(XonoticMapList, XonoticListBox)
        ATTRIB(XonoticMapList, alphaBG, float, 0)
 ENDCLASS(XonoticMapList)
 entity makeXonoticMapList();
-void MapList_All(entity btn, entity me);
-void MapList_None(entity btn, entity me);
+entity makeXonoticMapListStringFilterBox(entity me, float doEditColorCodes, string theCvar);
+void MapList_StringFilterBox_Change(entity box, entity me);
+float MapList_StringFilterBox_keyDown(entity me, float key, float ascii, float shift);
+void MapList_Add_Shown(entity btn, entity me);
+void MapList_Remove_Shown(entity btn, entity me);
+void MapList_Remove_All(entity btn, entity me);
 void MapList_LoadMap(entity btn, entity me);
 #endif
 
@@ -56,6 +63,10 @@ void XonoticMapList_destroy(entity me)
        MapInfo_Shutdown();
 }
 
+entity makeXonoticMapListStringFilterBox(entity me, float doEditColorCodes, string theCvar)
+{
+       return makeXonoticInputBox(doEditColorCodes, theCvar);
+}
 entity makeXonoticMapList()
 {
        entity me;
@@ -64,6 +75,12 @@ entity makeXonoticMapList()
        return me;
 }
 
+entity MapList_Set_String_Filter_Box(entity me, entity e)
+{
+       me.stringFilterBox = e;
+       return e;
+}
+
 void XonoticMapList_configureXonoticMapList(entity me)
 {
        me.configureXonoticListBox(me);
@@ -75,6 +92,7 @@ void XonoticMapList_loadCvars(entity me)
        me.refilter(me);
 }
 
+
 float XonoticMapList_g_maplistCacheQuery(entity me, float i)
 {
        return stof(substring(me.g_maplistCache, i, 1));
@@ -205,7 +223,10 @@ void XonoticMapList_refilter(entity me)
        gt = MapInfo_CurrentGametype();
        f = MapInfo_CurrentFeatures();
        MapInfo_FilterGametype(gt, f, MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
+       if (me.stringFilter)
+               MapInfo_FilterString(me.stringFilter);
        me.nItems = MapInfo_count;
+
        for(i = 0; i < MapInfo_count; ++i)
                draw_PreloadPicture(strcat("/maps/", MapInfo_BSPName_ByID(i)));
        if(me.g_maplistCache)
@@ -238,19 +259,43 @@ void XonoticMapList_refilterCallback(entity me, entity cb)
        me.refilter(me);
 }
 
-void MapList_All(entity btn, entity me)
+void MapList_StringFilterBox_Change(entity box, entity me)
 {
-       float i;
-       string s;
-       MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, MapInfo_ForbiddenFlags(), 0); // all
-       s = "";
-       for(i = 0; i < MapInfo_count; ++i)
-               s = strcat(s, " ", MapInfo_BSPName_ByID(i));
-       cvar_set("g_maplist", substring(s, 1, strlen(s) - 1));
+       if(me.stringFilter)
+               strunzone(me.stringFilter);
+       if(box.text != "")
+               me.stringFilter = strzone(box.text);
+       else
+               me.stringFilter = string_null;
+       
+       me.refilter(me);
+}
+
+void MapList_Add_Shown(entity btn, entity me)
+{
+       float i, n;
+       n = strlen(me.g_maplistCache);
+       for (i = 0 ; i < n; i++)
+       {
+               if (!me.g_maplistCacheQuery(me, i))
+                       me.g_maplistCacheToggle(me, i);
+       }
+       me.refilter(me);
+}
+
+void MapList_Remove_Shown(entity btn, entity me)
+{
+       float i, n;
+       n = strlen(me.g_maplistCache);
+       for (i = 0 ; i < n; i++)
+       {
+               if (me.g_maplistCacheQuery(me, i))
+                       me.g_maplistCacheToggle(me, i);
+       }
        me.refilter(me);
 }
 
-void MapList_None(entity btn, entity me)
+void MapList_Remove_All(entity btn, entity me)
 {
        cvar_set("g_maplist", "");
        me.refilter(me);
@@ -359,9 +404,38 @@ float XonoticMapList_keyDown(entity me, float scan, float ascii, float shift)
                if(MapInfo_FindName_firstResult >= 0)
                        me.setSelected(me, MapInfo_FindName_firstResult);
        }
+       else if(shift & S_CTRL && scan == 'f') // ctrl-f (as in "F"ind)
+       {
+               me.parent.setFocus(me.parent, me.stringFilterBox);
+       }
+       else if(shift & S_CTRL && scan == 'u') // ctrl-u (remove stringFilter line
+       {
+               me.stringFilterBox.setText(me.stringFilterBox, "");
+               MapList_StringFilterBox_Change(me.stringFilterBox, me);
+       }
        else
                return SUPER(XonoticMapList).keyDown(me, scan, ascii, shift);
        return 1;
 }
 
+float MapList_StringFilterBox_keyDown(entity me, float scan, float ascii, float shift)
+{
+       // in this section, note that onChangeEntity has the ref to mapListBox
+       // we make use of that, instead of extending a class to add one more attrib
+       switch(scan)
+       {
+               case K_KP_ENTER:
+               case K_ENTER:
+                       // move the focus to the mapListBox
+                       me.onChangeEntity.parent.setFocus(me.onChangeEntity.parent, me.onChangeEntity);
+                       return 1;
+               case K_KP_UPARROW:
+               case K_UPARROW:
+               case K_KP_DOWNARROW:
+               case K_DOWNARROW:
+                       // pass the event to the mapListBox (to scroll up and down)
+                       return me.onChangeEntity.keyDown(me.onChangeEntity, scan, ascii, shift);
+       }
+       return SUPER(XonoticInputBox).keyDown(me, scan, ascii, shift);
+}
 #endif
index a0c06485b20cb4b950049f05c5bc00ed9a5be66c..57e22b998a52d6420e2dbdc6fac8b20b85e31cb4 100644 (file)
 \g_instagib\Players will be given the Minstanex, which is a railgun with infinite damage. If the player runs out of ammo, he will have 10 seconds to find some or if he fails to do so, face death. The secondary fire mode is a laser which does not inflict any damage and is good for doing trickjumps.
 \g_nix\No items Xonotic - instead of pickup items, everyone plays with the same weapon. After some time, a countdown will start, after which everyone will switch to another weapon.
 \g_nix_with_laser\Always carry the laser as an additional weapon in Nix
-\XonoticMultiplayerDialog/Select all\Select all maps
-\XonoticMultiplayerDialog/Select none\Unselect all maps
+
+\XonoticMultiplayerDialog_StringFilterBox\Click here or Ctrl-F to provide a keyword to narrow down the maplist above. Ctrl-Delete to clear; Enter when done.
+\XonoticMultiplayerDialog/Add shown\Add the maps shown in Maplist above to your selection
+\XonoticMultiplayerDialog/Remove shown\Remove the maps shown in Maplist above from your selection
+\XonoticMultiplayerDialog/Remove all\Remove all the maps from your selection
 
 
 \XonoticMultiplayerDialog/Timedemo\Benchmark how fast your computer can run the highlighted demo