Declare more ints as ints
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / xonotic / demolist.qc
1 #ifdef INTERFACE
2 CLASS(XonoticDemoList) EXTENDS(XonoticListBox)
3         METHOD(XonoticDemoList, configureXonoticDemoList, void(entity))
4         ATTRIB(XonoticDemoList, rowsPerItem, float, 1)
5         METHOD(XonoticDemoList, resizeNotify, void(entity, vector, vector, vector, vector))
6         METHOD(XonoticDemoList, drawListBoxItem, void(entity, float, vector, float))
7         METHOD(XonoticDemoList, getDemos, void(entity))
8         METHOD(XonoticDemoList, startDemo, void(entity))
9         METHOD(XonoticDemoList, timeDemo, void(entity))
10         METHOD(XonoticDemoList, demoName, string(entity, float))
11         METHOD(XonoticDemoList, doubleClickListBoxItem, void(entity, float, vector))
12         METHOD(XonoticDemoList, keyDown, float(entity, float, float, float))
13         METHOD(XonoticDemoList, destroy, void(entity))
14         METHOD(XonoticDemoList, showNotify, void(entity))
15
16         ATTRIB(XonoticDemoList, listDemo, float, -1)
17         ATTRIB(XonoticDemoList, realFontSize, vector, '0 0 0')
18         ATTRIB(XonoticDemoList, columnNameOrigin, float, 0)
19         ATTRIB(XonoticDemoList, columnNameSize, float, 0)
20         ATTRIB(XonoticDemoList, realUpperMargin, float, 0)
21         ATTRIB(XonoticDemoList, origin, vector, '0 0 0')
22         ATTRIB(XonoticDemoList, itemAbsSize, vector, '0 0 0')
23
24         ATTRIB(XonoticDemoList, filterString, string, string_null)
25 ENDCLASS(XonoticDemoList)
26
27 entity demolist; // for reference elsewhere
28 entity makeXonoticDemoList();
29 void DemoList_Refresh_Click(entity btn, entity me);
30 void DemoList_Filter_Change(entity box, entity me);
31 #endif
32
33 #ifdef IMPLEMENTATION
34
35 entity makeXonoticDemoList()
36 {
37         entity me;
38         me = spawnXonoticDemoList();
39         me.configureXonoticDemoList(me);
40         return me;
41 }
42
43 void XonoticDemoList_configureXonoticDemoList(entity me)
44 {
45         me.configureXonoticListBox(me);
46         me.getDemos(me);
47 }
48
49 string XonoticDemoList_demoName(entity me, float i)
50 {
51         string s;
52         s = bufstr_get(me.listDemo, i);
53
54         if(substring(s, 0, 1) == "/")
55                 s = substring(s, 1, strlen(s) - 1);  // remove the first forward slash
56
57         return s;
58 }
59
60 // if subdir is true look in subdirectories too (1 level)
61 void getDemos_for_ext(entity me, string ext, float subdir)
62 {
63         string s;
64         if (subdir)
65                 s="demos/*/";
66         else
67                 s="demos/";
68         if(me.filterString)
69                 s=strcat(s, me.filterString, ext);
70         else
71                 s=strcat(s, "*", ext);
72
73         float list, i, n;
74         list = search_begin(s, false, true);
75         if(list >= 0)
76         {
77                 n = search_getsize(list);
78                 for(i = 0; i < n; ++i)
79                 {
80                         s = search_getfilename(list, i); // get initial full file name
81                         s = substring(s, 6, (strlen(s) - 6 - 4)); // remove "demos/" prefix and ".dem" suffix
82                         s = strdecolorize(s); // remove any pre-existing colors
83                         if(subdir)
84                         {
85                                 s = strreplace("/", "^7/", s); // clear colors at the forward slash
86                                 s = strcat("/", rgb_to_hexcolor(SKINCOLOR_DEMOLIST_SUBDIR), s); // add a forward slash for sorting, then color
87                                 bufstr_add(me.listDemo, s, true);
88                         }
89                         else { bufstr_add(me.listDemo, s, true); }
90                 }
91                 search_end(list);
92         }
93
94         if (subdir)
95                 getDemos_for_ext(me, ext, false);
96 }
97
98 void XonoticDemoList_getDemos(entity me)
99 {
100         if (me.listDemo >= 0)
101                 buf_del(me.listDemo);
102         me.listDemo = buf_create();
103         if (me.listDemo < 0)
104         {
105                 me.nItems = 0;
106                 return;
107         }
108         getDemos_for_ext(me, ".dem", true);
109         me.nItems = buf_getsize(me.listDemo);
110         if(me.nItems > 0)
111                 buf_sort(me.listDemo, 128, false);
112 }
113
114 void XonoticDemoList_destroy(entity me)
115 {
116         if(me.nItems > 0)
117                 buf_del(me.listDemo);
118 }
119
120 void XonoticDemoList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
121 {
122         me.itemAbsSize = '0 0 0';
123         SUPER(XonoticDemoList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
124
125         me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
126         me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
127         me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
128
129         me.columnNameOrigin = me.realFontSize.x;
130         me.columnNameSize = 1 - 2 * me.realFontSize.x;
131 }
132
133 void XonoticDemoList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
134 {
135         string s;
136         if(isSelected)
137                 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
138
139         s = me.demoName(me,i);
140         s = draw_TextShortenToWidth(s, me.columnNameSize, 0, me.realFontSize);
141         draw_Text(me.realUpperMargin * eY + (me.columnNameOrigin + 0.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, SKINCOLOR_TEXT, SKINALPHA_TEXT, 1);
142 }
143
144 void XonoticDemoList_showNotify(entity me)
145 {
146         me.getDemos(me);
147 }
148
149 void DemoList_Refresh_Click(entity btn, entity me)
150 {
151         me.getDemos(me);
152         me.setSelected(me, 0); //always select the first element after a list update
153 }
154
155 void DemoList_Filter_Change(entity box, entity me)
156 {
157         if(me.filterString)
158                 strunzone(me.filterString);
159
160         if(box.text != "")
161         {
162                 if (strstrofs(box.text, "*", 0) >= 0 || strstrofs(box.text, "?", 0) >= 0)
163                         me.filterString = strzone(box.text);
164                 else
165                         me.filterString = strzone(strcat("*", box.text, "*"));
166         }
167         else
168                 me.filterString = string_null;
169
170         me.getDemos(me);
171 }
172
173 void XonoticDemoList_startDemo(entity me)
174 {
175         string s;
176         s = me.demoName(me, me.selectedItem);
177         s = strdecolorize(s);
178
179         localcmd("playdemo \"demos/", s, ".dem\" \nwait \ntogglemenu\n");
180 }
181
182 void XonoticDemoList_timeDemo(entity me)
183 {
184         string s;
185         s = me.demoName(me, me.selectedItem);
186         s = strdecolorize(s);
187
188         localcmd("timedemo \"demos/", s, ".dem\" \nwait \ntogglemenu\n");
189 }
190
191 void DemoConfirm_ListClick_Check_Gamestatus(entity me)
192 {
193         if(!(gamestatus & (GAME_CONNECTED | GAME_ISSERVER))) // we're not in a match, lets watch the demo
194         {
195                 me.startDemo(me);
196         }
197         else // already in a match, player has to confirm
198         {
199                 DialogOpenButton_Click_withCoords(
200                         me,
201                         main.demostartconfirmDialog,
202                         boxToGlobal(eY * (me.selectedItem * me.itemHeight - me.scrollPos), me.origin, me.size),
203                         boxToGlobalSize(eY * me.itemHeight + eX * (1 - me.controlWidth), me.size)
204                 );
205         }
206 }
207
208 void XonoticDemoList_doubleClickListBoxItem(entity me, float i, vector where)
209 {
210         DemoConfirm_ListClick_Check_Gamestatus(me);
211 }
212
213 float XonoticDemoList_keyDown(entity me, float scan, float ascii, float shift)
214 {
215         if(scan == K_ENTER || scan == K_KP_ENTER)
216         {
217                 DemoConfirm_ListClick_Check_Gamestatus(me);
218                 return 1;
219         }
220         else
221         {
222                 return SUPER(XonoticDemoList).keyDown(me, scan, ascii, shift);
223         }
224 }
225 #endif
226