Xonotic
maplist.qc
Go to the documentation of this file.
1 #include "maplist.qh"
2 
3 #include <common/mapinfo.qh>
5 #include "mainwindow.qh"
6 #include "inputbox.qh"
7 
8 .bool disabled;
9 
11 {
13 }
14 
16 {
17  entity me;
18  me = NEW(XonoticMapList);
19  me.configureXonoticMapList(me);
20  return me;
21 }
22 
24 {
25  me.stringFilterBox = e;
26  return e;
27 }
28 
30 {
31  me.configureXonoticListBox(me);
32  me.refilter(me);
33 }
34 
36 {
37  me.refilter(me);
38 }
39 
40 
42 {
43  return stof(substring(me.g_maplistCache, i, 1));
44 }
46 {
47  string a, b, c, s, bspname;
48  float n;
49  s = me.g_maplistCache;
50  if (!s)
51  return;
52  b = substring(s, i, 1);
53  if(b == "0")
54  b = "1";
55  else if(b == "1")
56  b = "0";
57  else
58  return; // nothing happens
59  a = substring(s, 0, i);
60  c = substring(s, i+1, strlen(s) - (i+1));
61  strunzone(s);
62  me.g_maplistCache = strzone(strcat(a, b, c));
63  // TODO also update the actual cvar
64  if (!((bspname = MapInfo_BSPName_ByID(i))))
65  return;
66  if(b == "1")
67  cvar_set("g_maplist", strcat(bspname, " ", cvar_string("g_maplist")));
68  else
69  {
70  s = "";
71  n = tokenize_console(cvar_string("g_maplist"));
72  for(i = 0; i < n; ++i)
73  if(argv(i) != bspname)
74  s = strcat(s, " ", argv(i));
75  cvar_set("g_maplist", substring(s, 1, strlen(s) - 1));
76  }
77 }
78 
80 {
81  if(me.startButton)
82  me.startButton.disabled = ((me.selectedItem < 0) || (me.selectedItem >= me.nItems));
83  SUPER(XonoticMapList).draw(me);
84 }
85 
86 void XonoticMapList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
87 {
88  me.itemAbsSize = '0 0 0';
89  SUPER(XonoticMapList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
90 
91  me.itemAbsSize.y = absSize.y * me.itemHeight;
92  me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
93  me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
94  me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
95  me.realUpperMargin1 = 0.5 * (1 - 2.5 * me.realFontSize.y);
96  me.realUpperMargin2 = me.realUpperMargin1 + 1.5 * me.realFontSize.y;
97 
98  me.columnPreviewOrigin = 0;
99  me.columnPreviewSize = me.itemAbsSize.y / me.itemAbsSize.x * 4 / 3;
100  me.columnNameOrigin = me.columnPreviewOrigin + me.columnPreviewSize + me.realFontSize.x;
101  me.columnNameSize = 1 - me.columnPreviewSize - 2 * me.realFontSize.x;
102 
103  me.checkMarkSize = (eX * (me.itemAbsSize.y / me.itemAbsSize.x) + eY) * 0.5;
104  me.checkMarkOrigin = eY + eX * (me.columnPreviewOrigin + me.columnPreviewSize) - me.checkMarkSize;
105 }
106 
108 {
109  if(where.x <= me.columnPreviewOrigin + me.columnPreviewSize)
110  if(where.x >= 0)
111  {
113  me.g_maplistCacheToggle(me, i);
114  }
115 }
116 
118 {
119  if(where.x >= me.columnNameOrigin)
120  if(where.x <= 1)
121  {
122  // pop up map info screen
124  main.mapInfoDialog.loadMapInfo(main.mapInfoDialog, i, me);
125  DialogOpenButton_Click_withCoords(NULL, main.mapInfoDialog, me.origin + eX * (me.columnNameOrigin * me.size.x) + eY * ((me.itemHeight * i - me.scrollPos) * me.size.y), eY * me.itemAbsSize.y + eX * (me.itemAbsSize.x * me.columnNameSize));
126  }
127 }
128 
129 void XonoticMapList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
130 {
131  // layout: Ping, Map name, Map name, NP, TP, MP
132  string s;
133  float theAlpha;
134  float included;
135 
136  if(!MapInfo_Get_ByID(i))
137  return;
138 
139  included = me.g_maplistCacheQuery(me, i);
140  if(included || isSelected)
141  theAlpha = SKINALPHA_MAPLIST_INCLUDEDFG;
142  else
143  theAlpha = SKINALPHA_MAPLIST_NOTINCLUDEDFG;
144 
145  if(isSelected)
146  draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
147  else
148  {
149  if(included)
150  draw_Fill('0 0 0', '1 1 0', SKINCOLOR_MAPLIST_INCLUDEDBG, SKINALPHA_MAPLIST_INCLUDEDBG);
151  if(isFocused)
152  {
153  me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
154  draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
155  }
156  }
157 
158  if(draw_PictureSize(strcat("/maps/", MapInfo_Map_bspname)) == '0 0 0')
159  draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
160  else
161  draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", MapInfo_Map_bspname), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
162 
163  if(included)
164  draw_Picture(me.checkMarkOrigin, "checkmark", me.checkMarkSize, '1 1 1', 1);
165  s = draw_TextShortenToWidth(strdecolorize(MapInfo_Map_titlestring), me.columnNameSize, 0, me.realFontSize);
166  draw_Text(me.realUpperMargin1 * eY + (me.columnNameOrigin + 0.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, SKINCOLOR_MAPLIST_TITLE, theAlpha, 0);
167  s = draw_TextShortenToWidth(strdecolorize(MapInfo_Map_author), me.columnNameSize, 0, me.realFontSize);
168  draw_Text(me.realUpperMargin2 * eY + (me.columnNameOrigin + 1.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, SKINCOLOR_MAPLIST_AUTHOR, theAlpha, 0);
169 
171 }
172 
174 {
175  float i, j, n;
176  string s;
178  int f = MapInfo_CurrentFeatures();
180  if (me.stringFilter)
181  MapInfo_FilterString(me.stringFilter);
182  me.nItems = MapInfo_count;
183 
184  for(i = 0; i < MapInfo_count; ++i)
186  s = "0";
187  for(i = 1; i < MapInfo_count; i *= 2)
188  s = strcat(s, s);
189  n = tokenize_console(cvar_string("g_maplist"));
190  for(i = 0; i < n; ++i)
191  {
192  j = MapInfo_FindName(argv(i));
193  if(j >= 0)
194  {
195  // double check that the two mapnames are "identical", not just share the same prefix
196  if (strlen(MapInfo_BSPName_ByID(j)) == strlen(argv(i)))
197  s = strcat(
198  substring(s, 0, j),
199  "1",
200  substring(s, j+1, MapInfo_count - (j+1))
201  );
202  }
203  }
204  strcpy(me.g_maplistCache, s);
205  if(gt != me.lastGametype || f != me.lastFeatures)
206  {
207  me.lastGametype = gt;
208  me.lastFeatures = f;
209  me.setSelected(me, 0);
210  }
211 }
212 
214 {
215  me.refilter(me);
216 }
217 
219 {
220  strfree(me.stringFilter);
221  if(box.text != "")
222  me.stringFilter = strzone(box.text);
223 
224  me.refilter(me);
225 }
226 
228 {
229  float i, n;
230  n = strlen(me.g_maplistCache);
231  for (i = 0 ; i < n; i++)
232  {
233  if (!me.g_maplistCacheQuery(me, i))
234  me.g_maplistCacheToggle(me, i);
235  }
236  me.refilter(me);
237 }
238 
240 {
241  float i, n;
242  n = strlen(me.g_maplistCache);
243  for (i = 0 ; i < n; i++)
244  {
245  if (me.g_maplistCacheQuery(me, i))
246  me.g_maplistCacheToggle(me, i);
247  }
248  me.refilter(me);
249 }
250 
252 {
253  float i;
254  string s;
256  s = "";
257  for(i = 0; i < MapInfo_count; ++i)
258  s = strcat(s, " ", MapInfo_BSPName_ByID(i));
259  cvar_set("g_maplist", substring(s, 1, strlen(s) - 1));
260  me.refilter(me);
261 }
262 
264 {
265  cvar_set("g_maplist", "");
266  me.refilter(me);
267 }
268 
270 {
271  string m;
272  float i;
273 
274  i = me.selectedItem;
275 
276  if(btn.parent.instanceOfXonoticMapInfoDialog)
277  {
278  i = btn.parent.currentMapIndex;
279  Dialog_Close(btn, btn.parent);
280  }
281 
282  if(i >= me.nItems || i < 0)
283  return;
284 
285  m = MapInfo_BSPName_ByID(i);
286  if (!m)
287  {
288  LOG_INFO(_("Huh? Can't play this (m is NULL). Refiltering so this won't happen again."));
289  me.refilter(me);
290  return;
291  }
292  if(MapInfo_CheckMap(m))
293  {
294  localcmd("\nmenu_loadmap_prepare\n");
295  if(cvar("menu_use_default_hostname"))
296  localcmd("hostname \"", sprintf(_("%s's Xonotic Server"), strdecolorize(cvar_string("_cl_name"))), "\"\n");
297  MapInfo_LoadMap(m, 1);
298  }
299  else
300  {
301  LOG_INFO(_("Huh? Can't play this (invalid game type). Refiltering so this won't happen again."));
302  me.refilter(me);
303  return;
304  }
305 }
306 
307 float XonoticMapList_keyDown(entity me, float scan, float ascii, float shift)
308 {
309  string ch, save;
310  if(me.nItems <= 0)
311  return SUPER(XonoticMapList).keyDown(me, scan, ascii, shift);
312  if(scan == K_MOUSE2 || scan == K_SPACE || scan == K_ENTER || scan == K_KP_ENTER)
313  {
314  // pop up map info screen
316  main.mapInfoDialog.loadMapInfo(main.mapInfoDialog, me.selectedItem, me);
317  DialogOpenButton_Click_withCoords(NULL, main.mapInfoDialog, me.origin + eX * (me.columnNameOrigin * me.size.x) + eY * ((me.itemHeight * me.selectedItem - me.scrollPos) * me.size.y), eY * me.itemAbsSize.y + eX * (me.itemAbsSize.x * me.columnNameSize));
318  }
319  else if(scan == K_MOUSE3 || scan == K_INS || scan == K_KP_INS)
320  {
322  me.g_maplistCacheToggle(me, me.selectedItem);
323  }
324  else if(ascii == 43) // +
325  {
326  if (!me.g_maplistCacheQuery(me, me.selectedItem))
327  {
329  me.g_maplistCacheToggle(me, me.selectedItem);
330  }
331  }
332  else if(ascii == 45) // -
333  {
334  if(me.g_maplistCacheQuery(me, me.selectedItem))
335  {
337  me.g_maplistCacheToggle(me, me.selectedItem);
338  }
339  }
340  else if(scan == K_BACKSPACE)
341  {
342  if(time < me.typeToSearchTime)
343  {
344  save = substring(me.typeToSearchString, 0, strlen(me.typeToSearchString) - 1);
345  strcpy(me.typeToSearchString, save);
346  me.typeToSearchTime = time + 0.5;
347  if(strlen(me.typeToSearchString))
348  {
349  MapInfo_FindName(me.typeToSearchString);
351  me.setSelected(me, MapInfo_FindName_firstResult);
352  }
353  }
354  }
355  else if(ascii >= 32 && ascii != 127)
356  {
357  ch = chr(ascii);
358  if(time > me.typeToSearchTime)
359  save = ch;
360  else
361  save = strcat(me.typeToSearchString, ch);
362  strcpy(me.typeToSearchString, save);
363  me.typeToSearchTime = time + 0.5;
364  MapInfo_FindName(me.typeToSearchString);
366  me.setSelected(me, MapInfo_FindName_firstResult);
367  }
368  else if((shift & S_CTRL) && scan == 'f') // ctrl-f (as in "F"ind)
369  {
370  me.parent.setFocus(me.parent, me.stringFilterBox);
371  }
372  else if((shift & S_CTRL) && scan == 'u') // ctrl-u (remove stringFilter line
373  {
374  me.stringFilterBox.setText(me.stringFilterBox, "");
375  MapList_StringFilterBox_Change(me.stringFilterBox, me);
376  }
377  else
378  return SUPER(XonoticMapList).keyDown(me, scan, ascii, shift);
379  return 1;
380 }
381 
382 float MapList_StringFilterBox_keyDown(entity me, float scan, float ascii, float shift)
383 {
384  // in this section, note that onChangeEntity has the ref to mapListBox
385  // we make use of that, instead of extending a class to add one more attrib
386  switch(scan)
387  {
388  case K_KP_ENTER:
389  case K_ENTER:
390  // move the focus to the mapListBox
391  me.onChangeEntity.parent.setFocus(me.onChangeEntity.parent, me.onChangeEntity);
392  return 1;
393  case K_KP_UPARROW:
394  case K_UPARROW:
395  case K_KP_DOWNARROW:
396  case K_DOWNARROW:
397  // pass the event to the mapListBox (to scroll up and down)
398  return me.onChangeEntity.keyDown(me.onChangeEntity, scan, ascii, shift);
399  }
400  return SUPER(XonoticInputBox).keyDown(me, scan, ascii, shift);
401 }
float K_UPARROW
Definition: keycodes.qc:15
int MapInfo_RequiredFlags()
Definition: mapinfo.qc:1339
void XonoticMapList_doubleClickListBoxItem(entity me, float i, vector where)
Definition: maplist.qc:117
float XonoticMapList_keyDown(entity me, float scan, float ascii, float shift)
Definition: maplist.qc:307
float K_KP_INS
Definition: keycodes.qc:49
void MapList_Remove_All(entity btn, entity me)
Definition: maplist.qc:263
entity MapList_Set_String_Filter_Box(entity me, entity e)
Definition: maplist.qc:23
float MapList_StringFilterBox_keyDown(entity me, float scan, float ascii, float shift)
Definition: maplist.qc:382
void XonoticMapList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
Definition: maplist.qc:129
const vector eY
Definition: vector.qh:45
#define NEW(cname,...)
Definition: oo.qh:105
void MapList_StringFilterBox_Change(entity box, entity me)
Definition: maplist.qc:218
float K_DOWNARROW
Definition: keycodes.qc:16
void MapList_Remove_Shown(entity btn, entity me)
Definition: maplist.qc:239
float K_KP_DOWNARROW
Definition: keycodes.qc:53
int MAPINFO_TYPE_ALL
Definition: mapinfo.qh:26
float K_MOUSE3
Definition: keycodes.qc:131
entity() spawn
void DialogOpenButton_Click_withCoords(entity button, entity tab, vector theOrigin, vector theSize)
bool disabled
Definition: maplist.qc:8
bool MapInfo_Get_ByID(int i)
Definition: mapinfo.qc:256
void XonoticMapList_refilter(entity me)
Definition: maplist.qc:173
int MapInfo_ForbiddenFlags()
Definition: mapinfo.qc:1324
void MapList_Add_Shown(entity btn, entity me)
Definition: maplist.qc:227
void XonoticMapList_refilterCallback(entity me, entity cb)
Definition: maplist.qc:213
float K_SPACE
Definition: keycodes.qc:10
void MapList_LoadMap(entity btn, entity me)
Definition: maplist.qc:269
float K_KP_ENTER
Definition: keycodes.qc:74
#define strcpy(this, s)
Definition: string.qh:49
string MapInfo_Map_author
Definition: mapinfo.qh:10
#define SUPER(cname)
Definition: oo.qh:219
void XonoticMapList_g_maplistCacheToggle(entity me, float i)
Definition: maplist.qc:45
float K_BACKSPACE
Definition: keycodes.qc:14
float MapInfo_count
Definition: mapinfo.qh:144
Gametype MapInfo_CurrentGametype()
Definition: mapinfo.qc:1150
int MapInfo_CurrentFeatures()
Definition: mapinfo.qc:1140
void XonoticMapList_draw(entity me)
Definition: maplist.qc:79
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
void XonoticMapList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
Definition: maplist.qc:86
float K_MOUSE2
Definition: keycodes.qc:130
#define NULL
Definition: post.qh:17
#define LOG_INFO(...)
Definition: log.qh:70
float MapInfo_CheckMap(string s)
Definition: mapinfo.qc:1170
void XonoticMapList_loadCvars(entity me)
Definition: maplist.qc:35
void MapInfo_ClearTemps()
Definition: mapinfo.qc:1299
void XonoticMapList_clickListBoxItem(entity me, float i, vector where)
Definition: maplist.qc:107
vector(float skel, float bonenum) _skel_get_boneabs_hidden
float MapInfo_FindName_firstResult
Definition: mapinfo.qh:169
float MapInfo_FindName(string s)
Definition: mapinfo.qc:1086
#define tokenize_console
Definition: dpextensions.qh:24
const vector eX
Definition: vector.qh:44
string MapInfo_Map_bspname
Definition: mapinfo.qh:6
void MapInfo_FilterString(string sf)
Definition: mapinfo.qc:194
void XonoticMapList_destroy(entity me)
Definition: maplist.qc:10
void XonoticMapList_configureXonoticMapList(entity me)
Definition: maplist.qc:29
float XonoticMapList_g_maplistCacheQuery(entity me, float i)
Definition: maplist.qc:41
#define strfree(this)
Definition: string.qh:56
float K_ENTER
Definition: keycodes.qc:8
const int S_CTRL
Definition: hud.qh:128
float _MapInfo_FilterGametype(int pGametype, int pFeatures, int pFlagsRequired, int pFlagsForbidden, bool pAbortOnGenerate)
Definition: mapinfo.qc:162
void MapInfo_LoadMap(string s, float reinit)
Definition: mapinfo.qc:1183
float MapInfo_FilterGametype(Gametype pGametype, int pFeatures, int pFlagsRequired, int pFlagsForbidden, bool pAbortOnGenerate)
Definition: mapinfo.qc:158
float K_INS
Definition: keycodes.qc:37
float time
Definition: csprogsdefs.qc:16
entity makeXonoticMapList()
Definition: maplist.qc:15
void MapInfo_Shutdown()
Definition: mapinfo.qc:1311
float K_KP_UPARROW
Definition: keycodes.qc:64
string MapInfo_BSPName_ByID(float i)
Definition: mapinfo.qc:231
void MapList_Add_All(entity btn, entity me)
Definition: maplist.qc:251
string MapInfo_Map_titlestring
Definition: mapinfo.qh:8