]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/menu/nexuiz/keybinder.c
-scmenu; make mapinfo default
[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         if(me.pressed == 0 || me.pressed == 1) // keyboard or scrolling - skip unselectable items
213         {
214                 if(i > me.previouslySelected)
215                 {
216                         while((i < me.nItems - 1) && (Nexuiz_KeyBinds_Functions[i] == ""))
217                                 ++i;
218                 }
219                 while((i > 0) && (Nexuiz_KeyBinds_Functions[i] == ""))
220                         --i;
221                 while((i < me.nItems - 1) && (Nexuiz_KeyBinds_Functions[i] == ""))
222                         ++i;
223         }
224         if(me.pressed == 3) // released the mouse - fall back to last valid item
225         {
226                 if(Nexuiz_KeyBinds_Functions[i] == "")
227                         i = me.previouslySelected;
228         }
229         if(Nexuiz_KeyBinds_Functions[i] != "")
230                 me.previouslySelected = i;
231         if(me.userbindEditButton)
232                 me.userbindEditButton.disabled = (substring(Nexuiz_KeyBinds_Descriptions[i], 0, 1) != "$");
233         setSelectedListBox(me, i);
234 }
235 float keyDownNexuizKeyBinder(entity me, float key, float ascii, float shift)
236 {
237         float r;
238         r = 1;
239         switch(key)
240         {
241                 case K_ENTER:
242                 case K_SPACE:
243                         KeyBinder_Bind_Change(me, me);
244                         break;
245                 case K_DEL:
246                 case K_BACKSPACE:
247                         KeyBinder_Bind_Clear(me, me);
248                         break;
249                 default:
250                         r = keyDownListBox(me, key, ascii, shift);
251                         break;
252         }
253         return r;
254 }
255 void drawListBoxItemNexuizKeyBinder(entity me, float i, vector absSize, float isSelected)
256 {
257         string s;
258         float j, k, n;
259         vector theColor;
260         float theAlpha;
261         string func, descr;
262         float extraMargin;
263
264         descr = Nexuiz_KeyBinds_Descriptions[i];
265         func = Nexuiz_KeyBinds_Functions[i];
266
267         if(func == "")
268         {
269                 theAlpha = 1;
270                 theColor = '1 1 1';
271                 extraMargin = 0;
272         }
273         else
274         {
275                 if(isSelected)
276                 {
277                         if(keyGrabber == me)
278                                 draw_Fill('0 0 0', '1 1 0', '1 0 0', 0.5);
279                         else
280                                 draw_Fill('0 0 0', '1 1 0', '0 0 1', 0.5);
281                 }
282                 theAlpha = 0.7;
283                 theColor = '1 1 1';
284                 extraMargin = me.realFontSize_x * 0.5;
285         }
286
287         if(substring(descr, 0, 1) == "$")
288         {
289                 s = substring(descr, 1, strlen(descr) - 1);
290                 descr = cvar_string(strcat(s, "_description"));
291                 if(descr == "")
292                         descr = s;
293                 if(cvar_string(strcat(s, "_press")) == "")
294                         if(cvar_string(strcat(s, "_release")) == "")
295                                 theAlpha *= 0.5;
296         }
297
298         draw_Text(me.realUpperMargin * eY + extraMargin * eX, descr, me.realFontSize, theColor, theAlpha, 0);
299         if(func != "")
300         {
301                 n = tokenize(findkeysforcommand(func));
302                 s = "";
303                 for(j = 0; j < n; ++j)
304                 {
305                         k = stof(argv(j));
306                         if(k != -1)
307                         {
308                                 if(s != "")
309                                         s = strcat(s, ", ");
310                                 s = strcat(s, keynumtostring(k));
311                         }
312                 }
313                 s = draw_TextShortenToWidth(s, me.columnKeysSize / me.realFontSize_x, 0);
314                 draw_CenterText(me.realUpperMargin * eY + (me.columnKeysOrigin + 0.5 * me.columnKeysSize) * eX, s, me.realFontSize, theColor, theAlpha, 0);
315         }
316 }
317 #endif