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