]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - data/qcsrc/menu/voret/keybinder.c
Actually, set the gametype in the .instantaction file
[voretournament/voretournament.git] / data / qcsrc / menu / voret / keybinder.c
1 #ifdef INTERFACE\r
2 CLASS(VoretKeyBinder) EXTENDS(VoretListBox)\r
3         METHOD(VoretKeyBinder, configureVoretKeyBinder, void(entity))\r
4         ATTRIB(VoretKeyBinder, rowsPerItem, float, 1)\r
5         METHOD(VoretKeyBinder, drawListBoxItem, void(entity, float, vector, float))\r
6         METHOD(VoretKeyBinder, clickListBoxItem, void(entity, float, vector))\r
7         METHOD(VoretKeyBinder, resizeNotify, void(entity, vector, vector, vector, vector))\r
8         METHOD(VoretKeyBinder, setSelected, void(entity, float))\r
9         METHOD(VoretKeyBinder, keyDown, float(entity, float, float, float))\r
10         METHOD(VoretKeyBinder, keyGrabbed, void(entity, float, float))\r
11 \r
12         ATTRIB(VoretKeyBinder, realFontSize, vector, '0 0 0')\r
13         ATTRIB(VoretKeyBinder, realUpperMargin, float, 0)\r
14         ATTRIB(VoretKeyBinder, columnFunctionOrigin, float, 0)\r
15         ATTRIB(VoretKeyBinder, columnFunctionSize, float, 0)\r
16         ATTRIB(VoretKeyBinder, columnKeysOrigin, float, 0)\r
17         ATTRIB(VoretKeyBinder, columnKeysSize, float, 0)\r
18 \r
19         ATTRIB(VoretKeyBinder, lastClickedKey, float, -1)\r
20         ATTRIB(VoretKeyBinder, lastClickedTime, float, 0)\r
21         ATTRIB(VoretKeyBinder, previouslySelected, float, -1)\r
22         ATTRIB(VoretKeyBinder, inMouseHandler, float, 0)\r
23         ATTRIB(VoretKeyBinder, userbindEditButton, entity, NULL)\r
24         ATTRIB(VoretKeyBinder, keyGrabButton, entity, NULL)\r
25         ATTRIB(VoretKeyBinder, userbindEditDialog, entity, NULL)\r
26         METHOD(VoretKeyBinder, editUserbind, void(entity, string, string, string))\r
27 ENDCLASS(VoretKeyBinder)\r
28 entity makeVoretKeyBinder();\r
29 void KeyBinder_Bind_Change(entity btn, entity me);\r
30 void KeyBinder_Bind_Clear(entity btn, entity me);\r
31 void KeyBinder_Bind_Edit(entity btn, entity me);\r
32 #endif\r
33 \r
34 #ifdef IMPLEMENTATION\r
35 \r
36 #define MAX_KEYS_PER_FUNCTION 2\r
37 #define MAX_KEYBINDS 256\r
38 string Voret_KeyBinds_Functions[MAX_KEYBINDS];\r
39 string Voret_KeyBinds_Descriptions[MAX_KEYBINDS];\r
40 var float Voret_KeyBinds_Count = -1;\r
41 \r
42 void Voret_KeyBinds_Read()\r
43 {\r
44         float fh;\r
45         string s;\r
46 \r
47         Voret_KeyBinds_Count = 0;\r
48         fh = fopen("keybinds.txt", FILE_READ);\r
49         if(fh < 0)\r
50                 return;\r
51         while((s = fgets(fh)))\r
52         {\r
53                 if(tokenize_console(s) != 2)\r
54                         continue;\r
55                 Voret_KeyBinds_Functions[Voret_KeyBinds_Count] = strzone(argv(0));\r
56                 Voret_KeyBinds_Descriptions[Voret_KeyBinds_Count] = strzone(argv(1));\r
57                 ++Voret_KeyBinds_Count;\r
58                 if(Voret_KeyBinds_Count >= MAX_KEYBINDS)\r
59                         break;\r
60         }\r
61         fclose(fh);\r
62 }\r
63 \r
64 entity makeVoretKeyBinder()\r
65 {\r
66         entity me;\r
67         me = spawnVoretKeyBinder();\r
68         me.configureVoretKeyBinder(me);\r
69         return me;\r
70 }\r
71 void configureVoretKeyBinderVoretKeyBinder(entity me)\r
72 {\r
73         me.configureVoretListBox(me);\r
74         if(Voret_KeyBinds_Count < 0)\r
75                 Voret_KeyBinds_Read();\r
76         me.nItems = Voret_KeyBinds_Count;\r
77         me.setSelected(me, 0);\r
78 }\r
79 void resizeNotifyVoretKeyBinder(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)\r
80 {\r
81         resizeNotifyVoretListBox(me, relOrigin, relSize, absOrigin, absSize);\r
82 \r
83         me.realFontSize_y = me.fontSize / (absSize_y * me.itemHeight);\r
84         me.realFontSize_x = me.fontSize / (absSize_x * (1 - me.controlWidth));\r
85         me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);\r
86 \r
87         me.columnFunctionOrigin = 0;\r
88         me.columnKeysSize = me.realFontSize_x * 12;\r
89         me.columnFunctionSize = 1 - me.columnKeysSize - 2 * me.realFontSize_x;\r
90         me.columnKeysOrigin = me.columnFunctionOrigin + me.columnFunctionSize + me.realFontSize_x;\r
91 \r
92         if(me.userbindEditButton)\r
93                 me.userbindEditButton.disabled = (substring(Voret_KeyBinds_Descriptions[me.selectedItem], 0, 1) != "$");\r
94 }\r
95 void KeyBinder_Bind_Change(entity btn, entity me)\r
96 {\r
97         string func;\r
98 \r
99         func = Voret_KeyBinds_Functions[me.selectedItem];\r
100         if(func == "")\r
101                 return;\r
102 \r
103         me.keyGrabButton.forcePressed = 1;\r
104         keyGrabber = me;\r
105 }\r
106 void keyGrabbedVoretKeyBinder(entity me, float key, float ascii)\r
107 {\r
108         float n, j, k, nvalid;\r
109         string func;\r
110 \r
111         me.keyGrabButton.forcePressed = 0;\r
112         if(key == K_ESCAPE)\r
113                 return;\r
114 \r
115         func = Voret_KeyBinds_Functions[me.selectedItem];\r
116         if(func == "")\r
117                 return;\r
118 \r
119         n = tokenize(findkeysforcommand(func)); // uses '...' strings\r
120         nvalid = 0;\r
121         for(j = 0; j < n; ++j)\r
122         {\r
123                 k = stof(argv(j));\r
124                 if(k != -1)\r
125                         ++nvalid;\r
126         }\r
127         if(nvalid >= MAX_KEYS_PER_FUNCTION)\r
128         {\r
129                 for(j = 0; j < n; ++j)\r
130                 {\r
131                         k = stof(argv(j));\r
132                         if(k != -1)\r
133                                 localcmd("\nunbind \"", keynumtostring(k), "\"\n");\r
134                 }\r
135         }\r
136         localcmd("\nbind \"", keynumtostring(key), "\" \"", func, "\"\n");\r
137 }\r
138 void editUserbindVoretKeyBinder(entity me, string theName, string theCommandPress, string theCommandRelease)\r
139 {\r
140         string func, descr;\r
141 \r
142         if(!me.userbindEditDialog)\r
143                 return;\r
144         \r
145         func = Voret_KeyBinds_Functions[me.selectedItem];\r
146         if(func == "")\r
147                 return;\r
148         \r
149         descr = Voret_KeyBinds_Descriptions[me.selectedItem];\r
150         if(substring(descr, 0, 1) != "$")\r
151                 return;\r
152         descr = substring(descr, 1, strlen(descr) - 1);\r
153 \r
154         // Hooray! It IS a user bind!\r
155         cvar_set(strcat(descr, "_description"), theName);\r
156         cvar_set(strcat(descr, "_press"), theCommandPress);\r
157         cvar_set(strcat(descr, "_release"), theCommandRelease);\r
158 }\r
159 void KeyBinder_Bind_Edit(entity btn, entity me)\r
160 {\r
161         string func, descr;\r
162 \r
163         if(!me.userbindEditDialog)\r
164                 return;\r
165         \r
166         func = Voret_KeyBinds_Functions[me.selectedItem];\r
167         if(func == "")\r
168                 return;\r
169         \r
170         descr = Voret_KeyBinds_Descriptions[me.selectedItem];\r
171         if(substring(descr, 0, 1) != "$")\r
172                 return;\r
173         descr = substring(descr, 1, strlen(descr) - 1);\r
174 \r
175         // Hooray! It IS a user bind!\r
176         me.userbindEditDialog.loadUserBind(me.userbindEditDialog, cvar_string(strcat(descr, "_description")), cvar_string(strcat(descr, "_press")), cvar_string(strcat(descr, "_release")));\r
177 \r
178         DialogOpenButton_Click(btn, me.userbindEditDialog);\r
179 }\r
180 void KeyBinder_Bind_Clear(entity btn, entity me)\r
181 {\r
182         float n, j, k;\r
183         string func;\r
184 \r
185         func = Voret_KeyBinds_Functions[me.selectedItem];\r
186         if(func == "")\r
187                 return;\r
188 \r
189         n = tokenize(findkeysforcommand(func)); // uses '...' strings\r
190         for(j = 0; j < n; ++j)\r
191         {\r
192                 k = stof(argv(j));\r
193                 if(k != -1)\r
194                         localcmd("\nunbind \"", keynumtostring(k), "\"\n");\r
195         }\r
196 \r
197 }\r
198 void clickListBoxItemVoretKeyBinder(entity me, float i, vector where)\r
199 {\r
200         if(i == me.lastClickedServer)\r
201                 if(time < me.lastClickedTime + 0.3)\r
202                 {\r
203                         // DOUBLE CLICK!\r
204                         KeyBinder_Bind_Change(NULL, me);\r
205                 }\r
206         me.lastClickedServer = i;\r
207         me.lastClickedTime = time;\r
208 }\r
209 void setSelectedVoretKeyBinder(entity me, float i)\r
210 {\r
211         // handling of "unselectable" items\r
212         i = floor(0.5 + bound(0, i, me.nItems - 1));\r
213         if(me.pressed == 0 || me.pressed == 1) // keyboard or scrolling - skip unselectable items\r
214         {\r
215                 if(i > me.previouslySelected)\r
216                 {\r
217                         while((i < me.nItems - 1) && (Voret_KeyBinds_Functions[i] == ""))\r
218                                 ++i;\r
219                 }\r
220                 while((i > 0) && (Voret_KeyBinds_Functions[i] == ""))\r
221                         --i;\r
222                 while((i < me.nItems - 1) && (Voret_KeyBinds_Functions[i] == ""))\r
223                         ++i;\r
224         }\r
225         if(me.pressed == 3) // released the mouse - fall back to last valid item\r
226         {\r
227                 if(Voret_KeyBinds_Functions[i] == "")\r
228                         i = me.previouslySelected;\r
229         }\r
230         if(Voret_KeyBinds_Functions[i] != "")\r
231                 me.previouslySelected = i;\r
232         if(me.userbindEditButton)\r
233                 me.userbindEditButton.disabled = (substring(Voret_KeyBinds_Descriptions[i], 0, 1) != "$");\r
234         setSelectedListBox(me, i);\r
235 }\r
236 float keyDownVoretKeyBinder(entity me, float key, float ascii, float shift)\r
237 {\r
238         float r;\r
239         r = 1;\r
240         switch(key)\r
241         {\r
242                 case K_ENTER:\r
243                 case K_SPACE:\r
244                         KeyBinder_Bind_Change(me, me);\r
245                         break;\r
246                 case K_DEL:\r
247                 case K_BACKSPACE:\r
248                         KeyBinder_Bind_Clear(me, me);\r
249                         break;\r
250                 default:\r
251                         r = keyDownListBox(me, key, ascii, shift);\r
252                         break;\r
253         }\r
254         return r;\r
255 }\r
256 void drawListBoxItemVoretKeyBinder(entity me, float i, vector absSize, float isSelected)\r
257 {\r
258         string s;\r
259         float j, k, n;\r
260         vector theColor;\r
261         float theAlpha;\r
262         string func, descr;\r
263         float extraMargin;\r
264 \r
265         descr = Voret_KeyBinds_Descriptions[i];\r
266         func = Voret_KeyBinds_Functions[i];\r
267 \r
268         if(func == "")\r
269         {\r
270                 theAlpha = 1;\r
271                 theColor = SKINCOLOR_KEYGRABBER_TITLES;\r
272                 theAlpha = SKINALPHA_KEYGRABBER_TITLES;\r
273                 extraMargin = 0;\r
274         }\r
275         else\r
276         {\r
277                 if(isSelected)\r
278                 {\r
279                         if(keyGrabber == me)\r
280                                 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_WAITING, SKINALPHA_LISTBOX_WAITING);\r
281                         else\r
282                                 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);\r
283                 }\r
284                 theAlpha = SKINALPHA_KEYGRABBER_KEYS;\r
285                 theColor = SKINCOLOR_KEYGRABBER_KEYS;\r
286                 extraMargin = me.realFontSize_x * 0.5;\r
287         }\r
288 \r
289         if(substring(descr, 0, 1) == "$")\r
290         {\r
291                 s = substring(descr, 1, strlen(descr) - 1);\r
292                 descr = cvar_string(strcat(s, "_description"));\r
293                 if(descr == "")\r
294                         descr = s;\r
295                 if(cvar_string(strcat(s, "_press")) == "")\r
296                         if(cvar_string(strcat(s, "_release")) == "")\r
297                                 theAlpha *= SKINALPHA_DISABLED;\r
298         }\r
299 \r
300         draw_Text(me.realUpperMargin * eY + extraMargin * eX, descr, me.realFontSize, theColor, theAlpha, 0);\r
301         if(func != "")\r
302         {\r
303                 n = tokenize(findkeysforcommand(func)); // uses '...' strings\r
304                 s = "";\r
305                 for(j = 0; j < n; ++j)\r
306                 {\r
307                         k = stof(argv(j));\r
308                         if(k != -1)\r
309                         {\r
310                                 if(s != "")\r
311                                         s = strcat(s, ", ");\r
312                                 s = strcat(s, keynumtostring(k));\r
313                         }\r
314                 }\r
315                 s = draw_TextShortenToWidth(s, me.columnKeysSize, 0, me.realFontSize);\r
316                 draw_CenterText(me.realUpperMargin * eY + (me.columnKeysOrigin + 0.5 * me.columnKeysSize) * eX, s, me.realFontSize, theColor, theAlpha, 0);\r
317         }\r
318 }\r
319 #endif\r