]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/item/inputbox.qc
Merge MR 'Various Q3 and QL map entity features and fixes'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / item / inputbox.qc
1 #include "inputbox.qh"
2
3 .float cb_offset;
4 .string cb_src;
5
6         void InputBox_configureInputBox(entity me, string theText, float theCursorPos, float theFontSize, string gfx)
7         {
8                 SUPER(InputBox).configureLabel(me, theText, theFontSize, 0.0);
9                 me.src = gfx;
10                 me.cursorPos = theCursorPos;
11         }
12         void InputBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
13         {
14                 SUPER(InputBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
15                 if (me.enableClearButton)
16                 {
17                         me.cb_width = absSize.y / absSize.x;
18                         me.cb_offset = bound(-1, me.cb_offset, 0) * me.cb_width;  // bound to range -1, 0
19                         me.keepspaceRight = me.keepspaceRight - me.cb_offset + me.cb_width;
20                 }
21         }
22
23         void InputBox_setText(entity me, string txt)
24         {
25                 strfree(me.text);
26                 SUPER(InputBox).setText(me, strzone(txt));
27         }
28
29         float over_ClearButton(entity me, vector pos)
30         {
31                 if (me.text == "")
32                         return 0;
33                 if (pos.x >= 1 + me.cb_offset - me.cb_width)
34                         if (pos.x < 1 + me.cb_offset)
35                                 if (pos.y >= 0)
36                                         if (pos.y < 1) return 1;
37                 return 0;
38         }
39
40         float InputBox_mouseMove(entity me, vector pos)
41         {
42                 if (me.enableClearButton)
43                 {
44                         if (over_ClearButton(me, pos))
45                         {
46                                 me.cb_focused = 1;
47                                 return 1;
48                         }
49                         me.cb_focused = 0;
50                 }
51                 return 1;
52         }
53
54         float InputBox_mouseDrag(entity me, vector pos)
55         {
56                 float p;
57                 if (me.pressed)
58                 {
59                         me.dragScrollPos = pos;
60                         p = me.scrollPos + pos.x - me.keepspaceLeft;
61                         me.cursorPos = draw_TextLengthUpToWidth(me.text, p, 0, me.realFontSize);
62                         me.lastChangeTime = time;
63                 }
64                 else if (me.enableClearButton)
65                 {
66                         if (over_ClearButton(me, pos))
67                         {
68                                 me.cb_pressed = 1;
69                                 return 1;
70                         }
71                 }
72                 me.cb_pressed = 0;
73                 return 1;
74         }
75
76         METHOD(InputBox, mousePress, bool(InputBox this, vector pos))
77         {
78                 if (this.enableClearButton)
79                         if (over_ClearButton(this, pos))
80                         {
81                                 this.cb_pressed = 1;
82                                 return true;
83                         }
84                 this.dragScrollTimer = time;
85                 this.pressed = 1;
86                 return InputBox_mouseDrag(this, pos);
87         }
88
89         float InputBox_mouseRelease(entity me, vector pos)
90         {
91                 if (me.cb_pressed)
92                         if (over_ClearButton(me, pos))
93                         {
94                                 m_play_click_sound(MENU_SOUND_CLEAR);
95                                 me.setText(me, "");
96                                 if(me.applyButton)
97                                         me.applyButton.disabled = false;
98                                 me.cb_pressed = 0;
99                                 return 1;
100                         }
101                 float r = InputBox_mouseDrag(me, pos);
102                 // reset cb_pressed after mouseDrag, mouseDrag could set cb_pressed in this case:
103                 // mouse press out of the clear button, drag and then mouse release over the clear button
104                 me.cb_pressed = 0;
105                 me.pressed = 0;
106                 return r;
107         }
108
109         void InputBox_enterText(entity me, string ch)
110         {
111                 int len = strlen(ch);
112                 for (int i = 0; i < len; ++i)
113                         if (strstrofs(me.forbiddenCharacters, substring(ch, i, 1), 0) > -1) return;
114                 if (me.maxLength > 0)
115                 {
116                         if (len + strlen(me.text) > me.maxLength) return;
117                 }
118                 else if (me.maxLength < 0)
119                 {
120                         if (u8_strsize(ch) + u8_strsize(me.text) > -me.maxLength) return;
121                 }
122                 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), ch, substring(me.text, me.cursorPos, strlen(me.text) - me.cursorPos)));
123                 me.cursorPos += len;
124         }
125
126         float InputBox_keyDown(entity me, float key, float ascii, float shift)
127         {
128                 me.lastChangeTime = time;
129                 me.dragScrollTimer = time;
130                 if (ascii >= 32 && ascii != 127)
131                 {
132                         me.enterText(me, chr(ascii));
133                         if(me.applyButton)
134                                 me.applyButton.disabled = false;
135                         return 1;
136                 }
137                 switch (key)
138                 {
139                         case K_KP_LEFTARROW:
140                         case K_LEFTARROW:
141                                 me.cursorPos -= 1;
142                                 return 1;
143                         case K_KP_RIGHTARROW:
144                         case K_RIGHTARROW:
145                                 me.cursorPos += 1;
146                                 return 1;
147                         case K_KP_HOME:
148                         case K_HOME:
149                                 me.cursorPos = 0;
150                                 return 1;
151                         case K_KP_END:
152                         case K_END:
153                                 me.cursorPos = strlen(me.text);
154                                 return 1;
155                         case K_BACKSPACE:
156                                 if (me.cursorPos > 0)
157                                 {
158                                         me.cursorPos -= 1;
159                                         me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
160                                         if(me.applyButton)
161                                                 me.applyButton.disabled = false;
162                                 }
163                                 return 1;
164                         case K_KP_DEL:
165                         case K_DEL:
166                                 if (shift & S_CTRL)
167                                 {
168                                         m_play_click_sound(MENU_SOUND_CLEAR);
169                                         me.setText(me, "");
170                                 }
171                                 else
172                                         me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
173                                 if(me.applyButton)
174                                         me.applyButton.disabled = false;
175                                 return 1;
176                 }
177                 return 0;
178         }
179
180         void InputBox_draw(entity me)
181         {
182                 string CURSOR = "_";
183                 float cursorPosInWidths, totalSizeInWidths;
184
185                 if (me.pressed) me.mouseDrag(me, me.dragScrollPos);  // simulate mouseDrag event
186
187                 if (me.recalcPos) me.recalcPositionWithText(me, me.text);
188
189                 me.focusable = !me.disabled;
190                 if (me.disabled) draw_alpha *= me.disabledAlpha;
191
192                 if (me.src)
193                 {
194                         if (me.focused && !me.disabled) draw_ButtonPicture('0 0 0', strcat(me.src, "_f"), '1 1 0', me.colorF, 1);
195                         else draw_ButtonPicture('0 0 0', strcat(me.src, "_n"), '1 1 0', me.color, 1);
196                 }
197
198                 me.cursorPos = bound(0, me.cursorPos, strlen(me.text));
199                 cursorPosInWidths = draw_TextWidth(substring(me.text, 0, me.cursorPos), 0, me.realFontSize);
200                 totalSizeInWidths = draw_TextWidth(strcat(me.text, CURSOR), 0, me.realFontSize);
201
202                 if (me.dragScrollTimer < time)
203                 {
204                         float save;
205                         save = me.scrollPos;
206                         me.scrollPos = bound(cursorPosInWidths - (0.875 - me.keepspaceLeft - me.keepspaceRight), me.scrollPos, cursorPosInWidths - 0.125);
207                         if (me.scrollPos != save) me.dragScrollTimer = time + 0.2;
208                 }
209                 me.scrollPos = min(me.scrollPos, totalSizeInWidths - (1 - me.keepspaceRight - me.keepspaceLeft));
210                 me.scrollPos = max(0, me.scrollPos);
211
212                 draw_SetClipRect(eX * me.keepspaceLeft, eX * (1 - me.keepspaceLeft - me.keepspaceRight) + eY);
213                 if (me.editColorCodes)
214                 {
215                         vector p = me.realOrigin - eX * me.scrollPos;
216                         vector theColor = '1 1 1';
217                         float theAlpha = 1;
218
219                         for (int i = 0, n = strlen(me.text); i < n; ++i)
220                         {
221                                 string ch = substring(me.text, i, 1);
222                                 if (ch == "^")
223                                 {
224                                         float w;
225                                         string ch2 = substring(me.text, i + 1, 1);
226                                         w = draw_TextWidth(strcat(ch, ch2), 0, me.realFontSize);
227                                         float fill_alpha = 0.4;
228                                         if (ch2 == "^")
229                                         {
230                                                 if (me.cursorPos > i && me.cursorPos <= i + 2)
231                                                         fill_alpha = 0.6;
232                                                 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', fill_alpha);
233                                                 draw_Text(p + eX * 0.25 * w, "^", me.realFontSize, theColor, theAlpha, 0);
234                                         }
235                                         else if (IS_DIGIT(ch2))
236                                         {
237                                                 theAlpha = 1;
238                                                 switch (stof(ch2))
239                                                 {
240                                                         case 0: theColor = '0 0 0'; break;
241                                                         case 1: theColor = '1 0 0'; break;
242                                                         case 2: theColor = '0 1 0'; break;
243                                                         case 3: theColor = '1 1 0'; break;
244                                                         case 4: theColor = '0 0 1'; break;
245                                                         case 5: theColor = '0 1 1'; break;
246                                                         case 6: theColor = '1 0 1'; break;
247                                                         case 7: theColor = '1 1 1'; break;
248                                                         case 8: theColor = '1 1 1'; theAlpha = 0.5; break;
249                                                         case 9: theColor = '0.5 0.5 0.5'; break;
250                                                 }
251                                                 if (me.cursorPos > i && me.cursorPos <= i + 2)
252                                                         fill_alpha = 0.6;
253                                                 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', fill_alpha);
254                                                 draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
255                                         }
256                                         else if (ch2 == "x")  // ^x found
257                                         {
258                                                 vector theTempColor;
259                                                 theColor = '1 1 1';
260                                                 float component = HEXDIGIT_TO_DEC(substring(me.text, i + 2, 1));
261                                                 if (component >= 0)  // ^xr found
262                                                 {
263                                                         theTempColor.x = component / 15;
264
265                                                         component = HEXDIGIT_TO_DEC(substring(me.text, i + 3, 1));
266                                                         if (component >= 0)  // ^xrg found
267                                                         {
268                                                                 theTempColor.y = component / 15;
269
270                                                                 component = HEXDIGIT_TO_DEC(substring(me.text, i + 4, 1));
271                                                                 if (component >= 0)  // ^xrgb found
272                                                                 {
273                                                                         theTempColor.z = component / 15;
274                                                                         theColor = theTempColor;
275                                                                         w = draw_TextWidth(substring(me.text, i, 5), 0, me.realFontSize);
276
277                                                                         if (me.cursorPos > i && me.cursorPos <= i + 5)
278                                                                                 fill_alpha = 0.8;
279                                                                         draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', fill_alpha);
280                                                                         draw_Text(p, substring(me.text, i, 5), me.realFontSize, theColor, 1, 0);
281                                                                         i += 3;
282                                                                 }
283                                                                 else
284                                                                 {
285                                                                         // blue missing
286                                                                         w = draw_TextWidth(substring(me.text, i, 4), 0, me.realFontSize);
287                                                                         draw_Fill(p, eX * w + eY * me.realFontSize.y, eZ, fill_alpha);
288                                                                         draw_Text(p, substring(me.text, i, 4), me.realFontSize, '1 1 1', theAlpha, 0);
289                                                                         i += 2;
290                                                                 }
291                                                         }
292                                                         else
293                                                         {
294                                                                 // green missing
295                                                                 w = draw_TextWidth(substring(me.text, i, 3), 0, me.realFontSize);
296                                                                 draw_Fill(p, eX * w + eY * me.realFontSize.y, eY, fill_alpha);
297                                                                 draw_Text(p, substring(me.text, i, 3), me.realFontSize, '1 1 1', theAlpha, 0);
298                                                                 i += 1;
299                                                         }
300                                                 }
301                                                 else
302                                                 {
303                                                         // red missing
304                                                         // w = draw_TextWidth(substring(me.text, i, 2), 0) * me.realFontSize_x;
305                                                         draw_Fill(p, eX * w + eY * me.realFontSize.y, eX, fill_alpha);
306                                                         draw_Text(p, substring(me.text, i, 2), me.realFontSize, '1 1 1', theAlpha, 0);
307                                                 }
308                                         }
309                                         else
310                                         {
311                                                 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', fill_alpha);
312                                                 draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
313                                         }
314                                         p += w * eX;
315                                         ++i;
316                                         continue;
317                                 }
318                                 draw_Text(p, ch, me.realFontSize, theColor, theAlpha, 0);
319                                 p += eX * draw_TextWidth(ch, 0, me.realFontSize);
320                         }
321                 }
322                 else
323                 {
324                         draw_Text(me.realOrigin - eX * me.scrollPos, me.text, me.realFontSize, '1 1 1', 1, 0);
325                 }
326
327                 if (!me.focused || (time - me.lastChangeTime) < floor(time - me.lastChangeTime) + 0.5)
328                         draw_Text(me.realOrigin + eX * (cursorPosInWidths - me.scrollPos), CURSOR, me.realFontSize, '1 1 1', 1, 0);
329
330                 draw_ClearClip();
331
332                 if (me.enableClearButton && me.text != "")
333                 {
334                         if (me.focused && me.cb_pressed)
335                                 draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_c"), eX * me.cb_width + eY, me.cb_colorC, 1);
336                         else if (me.focused && me.cb_focused)
337                                 draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_f"), eX * me.cb_width + eY, me.cb_colorF, 1);
338                         else
339                                 draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_n"), eX * me.cb_width + eY, me.cb_color, 1);
340                 }
341
342                 // skipping SUPER(InputBox).draw(me);
343                 MenuItem_draw(me);
344         }
345
346         void InputBox_showNotify(entity me)
347         {
348                 me.focusable = !me.disabled;
349         }