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