]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/draw.qc
Merge remote branch 'origin/master' into mirceakitsune/preview_images
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / draw.qc
1 string draw_mousepointer;
2 vector draw_mousepointer_offset;
3 vector draw_mousepointer_size;
4
5 void draw_setMousePointer(string pic, vector theSize, vector theOffset)
6 {
7         draw_mousepointer = strzone(draw_UseSkinFor(pic));
8         draw_mousepointer_size = theSize;
9         draw_mousepointer_offset = eX * (theOffset_x * theSize_x) + eY * (theOffset_y * theSize_y);
10 }
11
12 void draw_drawMousePointer(vector where)
13 {
14         drawpic(boxToGlobal(where, draw_shift, draw_scale) - draw_mousepointer_offset, draw_mousepointer, draw_mousepointer_size, '1 1 1', draw_alpha, 0);
15 }
16
17 void draw_reset(float cw, float ch, float ox, float oy)
18 {
19         drawfont = FONT_USER+0;
20         draw_shift = '1 0 0' * ox + '0 1 0' * oy;
21         draw_scale = '1 0 0' * cw + '0 1 0' * ch;
22         draw_alpha = 1;
23         draw_fontscale = '1 1 0';
24 }
25
26 vector globalToBox(vector v, vector theOrigin, vector theScale)
27 {
28         v -= theOrigin;
29         v_x /= theScale_x;
30         v_y /= theScale_y;
31         return v;
32 }
33
34 vector globalToBoxSize(vector v, vector theScale)
35 {
36         v_x /= theScale_x;
37         v_y /= theScale_y;
38         return v;
39 }
40
41 vector boxToGlobal(vector v, vector theOrigin, vector theScale)
42 {
43         v_x *= theScale_x;
44         v_y *= theScale_y;
45         v += theOrigin;
46         return v;
47 }
48
49 vector boxToGlobalSize(vector v, vector theScale)
50 {
51         v_x *= theScale_x;
52         v_y *= theScale_y;
53         return v;
54 }
55
56 string draw_PreloadPicture(string pic)
57 {
58         pic = draw_UseSkinFor(pic);
59         return precache_pic(pic);
60 }
61
62 void draw_Picture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
63 {
64         if(theSize_x == 0 || theSize_y <= 0) // no default sizing please
65                 return;
66         pic = draw_UseSkinFor(pic);
67         drawpic(boxToGlobal(theOrigin, draw_shift, draw_scale), pic, boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0);
68 }
69
70 vector draw_PictureSize(string pic)
71 {
72         pic = draw_UseSkinFor(pic);
73         return drawgetimagesize(pic);
74 }
75
76 void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha)
77 {
78         drawfill(boxToGlobal(theOrigin, draw_shift, draw_scale), boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0);
79 }
80
81 // a button picture is a texture containing three parts:
82 //   1/4 width: left part
83 //   1/2 width: middle part (stretched)
84 //   1/4 width: right part
85 // it is assumed to be 4x as wide as high for aspect ratio purposes, which
86 // means, the parts are a square, two squares and a square.
87 void draw_ButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
88 {
89         vector square;
90         vector width, height;
91         vector bW;
92         pic = draw_UseSkinFor(pic);
93         theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
94         theSize = boxToGlobalSize(theSize, draw_scale);
95         theAlpha *= draw_alpha;
96         width = eX * theSize_x;
97         height = eY * theSize_y;
98         if(theSize_x <= theSize_y * 2)
99         {
100                 // button not wide enough
101                 // draw just left and right part then
102                 square = eX * theSize_x * 0.5;
103                 bW = eX * (0.25 * theSize_x / (theSize_y * 2));
104                 drawsubpic(theOrigin,          square + height, pic, '0 0 0', eY + bW, theColor, theAlpha, 0);
105                 drawsubpic(theOrigin + square, square + height, pic, eX - bW, eY + bW, theColor, theAlpha, 0);
106         }
107         else
108         {
109                 square = eX * theSize_y;
110                 drawsubpic(theOrigin,                  height  +     square, pic, '0    0 0', '0.25 1 0', theColor, theAlpha, 0);
111                 drawsubpic(theOrigin +         square, theSize - 2 * square, pic, '0.25 0 0', '0.5  1 0', theColor, theAlpha, 0);
112                 drawsubpic(theOrigin + width - square, height  +     square, pic, '0.75 0 0', '0.25 1 0', theColor, theAlpha, 0);
113         }
114 }
115
116 // a vertical button picture is a texture containing three parts:
117 //   1/4 height: left part
118 //   1/2 height: middle part (stretched)
119 //   1/4 height: right part
120 // it is assumed to be 4x as high as wide for aspect ratio purposes, which
121 // means, the parts are a square, two squares and a square.
122 void draw_VertButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
123 {
124         vector square;
125         vector width, height;
126         vector bH;
127         pic = draw_UseSkinFor(pic);
128         theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
129         theSize = boxToGlobalSize(theSize, draw_scale);
130         theAlpha *= draw_alpha;
131         width = eX * theSize_x;
132         height = eY * theSize_y;
133         if(theSize_y <= theSize_x * 2)
134         {
135                 // button not high enough
136                 // draw just upper and lower part then
137                 square = eY * theSize_y * 0.5;
138                 bH = eY * (0.25 * theSize_y / (theSize_x * 2));
139                 drawsubpic(theOrigin,          square + width, pic, '0 0 0', eX + bH, theColor, theAlpha, 0);
140                 drawsubpic(theOrigin + square, square + width, pic, eY - bH, eX + bH, theColor, theAlpha, 0);
141         }
142         else
143         {
144                 square = eY * theSize_x;
145                 drawsubpic(theOrigin,                   width   +     square, pic, '0 0    0', '1 0.25 0', theColor, theAlpha, 0);
146                 drawsubpic(theOrigin +          square, theSize - 2 * square, pic, '0 0.25 0', '1 0.5  0', theColor, theAlpha, 0);
147                 drawsubpic(theOrigin + height - square, width   +     square, pic, '0 0.75 0', '1 0.25 0', theColor, theAlpha, 0);
148         }
149 }
150
151 // a border picture is a texture containing nine parts:
152 //   1/4 width: left part
153 //   1/2 width: middle part (stretched)
154 //   1/4 width: right part
155 // divided into
156 //   1/4 height: top part
157 //   1/2 height: middle part (stretched)
158 //   1/4 height: bottom part
159 void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
160 {
161         vector dX, dY;
162         vector width, height;
163         vector bW, bH;
164         pic = draw_UseSkinFor(pic);
165         theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
166         theSize = boxToGlobalSize(theSize, draw_scale);
167         theBorderSize = boxToGlobalSize(theBorderSize, draw_scale);
168         theAlpha *= draw_alpha;
169         width = eX * theSize_x;
170         height = eY * theSize_y;
171         // zero size? bail out, we cannot handle this
172         if(theSize_x <= 0 || theSize_y <= 0)
173                 return;
174         if(theBorderSize_x <= 0) // no x border
175         {
176                 if(theBorderSize_y <= 0)
177                 {
178                         drawsubpic(theOrigin,                            width          + height,          pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
179                 }
180                 else if(theSize_y <= theBorderSize_y * 2)
181                 {
182                         // not high enough... draw just top and bottom then
183                         bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
184                         drawsubpic(theOrigin,                             width          + height * 0.5, pic, '0.25 0 0',           '0.5  0 0' + bH, theColor, theAlpha, 0);
185                         drawsubpic(theOrigin              + height * 0.5, width          + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5  0 0' + bH, theColor, theAlpha, 0);
186                 }
187                 else
188                 {
189                         dY = theBorderSize_y * eY;
190                         drawsubpic(theOrigin,                            width                   +     dY, pic, '0.25 0    0', '0.5  0.25 0', theColor, theAlpha, 0);
191                         drawsubpic(theOrigin          + dY,              width          + height - 2 * dY, pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
192                         drawsubpic(theOrigin + height - dY,              width                   +     dY, pic, '0.25 0.75 0', '0.5  0.25 0', theColor, theAlpha, 0);
193                 }
194         }
195         else if(theSize_x <= theBorderSize_x * 2)
196         {
197                 // not wide enough... draw just left and right then
198                 bW = eX * (0.25 * theSize_x / (theBorderSize_x * 2));
199                 if(theBorderSize_y <= 0)
200                 {
201                         drawsubpic(theOrigin,                             width * 0.5 + height,          pic, '0 0.25 0',           '0 0.5  0' + bW, theColor, theAlpha, 0);
202                         drawsubpic(theOrigin + width * 0.5,               width * 0.5 + height,          pic, '0 0.25 0' + eX - bW, '0 0.5  0' + bW, theColor, theAlpha, 0);
203                 }
204                 else if(theSize_y <= theBorderSize_y * 2)
205                 {
206                         // not high enough... draw just corners
207                         bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
208                         drawsubpic(theOrigin,                 width * 0.5 + height * 0.5, pic, '0 0 0',           bW + bH, theColor, theAlpha, 0);
209                         drawsubpic(theOrigin + width   * 0.5, width * 0.5 + height * 0.5, pic, eX - bW,           bW + bH, theColor, theAlpha, 0);
210                         drawsubpic(theOrigin + height  * 0.5, width * 0.5 + height * 0.5, pic, eY - bH,           bW + bH, theColor, theAlpha, 0);
211                         drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
212                 }
213                 else
214                 {
215                         dY = theBorderSize_y * eY;
216                         drawsubpic(theOrigin,                             width * 0.5          +     dY, pic, '0 0    0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
217                         drawsubpic(theOrigin + width * 0.5,               width * 0.5          +     dY, pic, '0 0    0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
218                         drawsubpic(theOrigin                        + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0',           '0 0.5  0' + bW, theColor, theAlpha, 0);
219                         drawsubpic(theOrigin + width * 0.5          + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0' + eX - bW, '0 0.5  0' + bW, theColor, theAlpha, 0);
220                         drawsubpic(theOrigin               + height - dY, width * 0.5          +     dY, pic, '0 0.75 0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
221                         drawsubpic(theOrigin + width * 0.5 + height - dY, width * 0.5          +     dY, pic, '0 0.75 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
222                 }
223         }
224         else
225         {
226                 if(theBorderSize_y <= 0)
227                 {
228                         dX = theBorderSize_x * eX;
229                         drawsubpic(theOrigin,                                        dX + height,          pic, '0    0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
230                         drawsubpic(theOrigin                       + dX, width - 2 * dX + height,          pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
231                         drawsubpic(theOrigin               + width - dX,             dX + height,          pic, '0.75 0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
232                 }
233                 else if(theSize_y <= theBorderSize_y * 2)
234                 {
235                         // not high enough... draw just top and bottom then
236                         bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
237                         dX = theBorderSize_x * eX;
238                         drawsubpic(theOrigin,                                         dX + height * 0.5, pic, '0    0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
239                         drawsubpic(theOrigin + dX,                        width - 2 * dX + height * 0.5, pic, '0.25 0 0',           '0.5  0 0' + bH, theColor, theAlpha, 0);
240                         drawsubpic(theOrigin + width - dX,                            dX + height * 0.5, pic, '0.75 0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
241                         drawsubpic(theOrigin              + height * 0.5,             dX + height * 0.5, pic, '0    0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
242                         drawsubpic(theOrigin + dX         + height * 0.5, width - 2 * dX + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5  0 0' + bH, theColor, theAlpha, 0);
243                         drawsubpic(theOrigin + width - dX + height * 0.5,             dX + height * 0.5, pic, '0.75 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
244                 }
245                 else
246                 {
247                         dX = theBorderSize_x * eX;
248                         dY = theBorderSize_y * eY;
249                         drawsubpic(theOrigin,                                        dX          +     dY, pic, '0    0    0', '0.25 0.25 0', theColor, theAlpha, 0);
250                         drawsubpic(theOrigin                  + dX,      width - 2 * dX          +     dY, pic, '0.25 0    0', '0.5  0.25 0', theColor, theAlpha, 0);
251                         drawsubpic(theOrigin          + width - dX,                  dX          +     dY, pic, '0.75 0    0', '0.25 0.25 0', theColor, theAlpha, 0);
252                         drawsubpic(theOrigin          + dY,                          dX + height - 2 * dY, pic, '0    0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
253                         drawsubpic(theOrigin          + dY         + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
254                         drawsubpic(theOrigin          + dY + width - dX,             dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
255                         drawsubpic(theOrigin + height - dY,                          dX          +     dY, pic, '0    0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
256                         drawsubpic(theOrigin + height - dY         + dX, width - 2 * dX          +     dY, pic, '0.25 0.75 0', '0.5  0.25 0', theColor, theAlpha, 0);
257                         drawsubpic(theOrigin + height - dY + width - dX,             dX          +     dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
258                 }
259         }
260 }
261 void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
262 {
263         if(theSize_x <= 0 || theSize_y <= 0)
264                 error("Drawing zero size text?\n");
265
266         //float wi;
267         //wi = draw_TextWidth(theText, ICanHasKallerz, theSize);
268         //draw_Fill(theOrigin, '1 0 0' * wi + '0 1 0' * theSize_y, '1 0 0', 0.3);
269
270         if(ICanHasKallerz)
271                 drawcolorcodedstring(boxToGlobal(theOrigin, draw_shift, draw_scale), theText, globalToBoxSize(boxToGlobalSize(theSize, draw_scale), draw_fontscale), theAlpha * draw_alpha, 0);
272         else
273                 drawstring(boxToGlobal(theOrigin, draw_shift, draw_scale), theText, globalToBoxSize(boxToGlobalSize(theSize, draw_scale), draw_fontscale), theColor, theAlpha * draw_alpha, 0);
274 }
275 void draw_CenterText(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
276 {
277         //dprint(strcat("orig = ", vtos(theOrigin) ," tx = ", ftos(draw_TextWidth(theText, ICanHasKallerz, theSize)), "\n"));
278         draw_Text(theOrigin - eX * 0.5 * draw_TextWidth(theText, ICanHasKallerz, theSize), theText, theSize, theColor, theAlpha, ICanHasKallerz);
279 }
280
281 float draw_TextWidth(string theText, float ICanHasKallerz, vector SizeThxBye)
282 {
283         //return strlen(theText);
284         //dprint("draw_TextWidth \"", theText, "\"\n");
285         vector v;
286         v = '0 0 0';
287         //float r;
288         v_x = stringwidth(theText, ICanHasKallerz, globalToBoxSize(boxToGlobalSize(SizeThxBye, draw_scale), draw_fontscale));
289         v = globalToBoxSize(v, draw_scale);
290         return v_x;
291 }
292
293 float draw_clipSet;
294 void draw_SetClip()
295 {
296         if(draw_clipSet)
297                 error("Already clipping, no stack implemented here, sorry");
298         drawsetcliparea(draw_shift_x, draw_shift_y, draw_scale_x, draw_scale_y);
299         draw_clipSet = 1;
300 }
301
302 void draw_SetClipRect(vector theOrigin, vector theScale)
303 {
304         vector o, s;
305         if(draw_clipSet)
306                 error("Already clipping, no stack implemented here, sorry");
307         o = boxToGlobal(theOrigin, draw_shift, draw_scale);
308         s = boxToGlobalSize(theScale, draw_scale);
309         drawsetcliparea(o_x, o_y, s_x, s_y);
310         draw_clipSet = 1;
311 }
312
313 void draw_ClearClip()
314 {
315         if(!draw_clipSet)
316                 error("Not clipping, can't clear it then");
317         drawresetcliparea();
318         draw_clipSet = 0;
319 }
320
321 string draw_TextShortenToWidth(string theText, float maxWidth, float ICanHasKallerz, vector SizeThxBye)
322 {
323         /*
324         if(draw_TextWidth(theText, ICanHasKallerz, SizeThxBye) <= maxWidth)
325                 return theText;
326         else
327                 return strcat(substring(theText, 0, draw_TextLengthUpToWidth(theText, maxWidth - draw_TextWidth("...", ICanHasKallerz, SizeThxBye), ICanHasKallerz, SizeThxBye)), "...");
328         */
329         if(ICanHasKallerz)
330                 return textShortenToWidth(theText, maxWidth, SizeThxBye, draw_TextWidth_WithColors);
331         else
332                 return textShortenToWidth(theText, maxWidth, SizeThxBye, draw_TextWidth_WithoutColors);
333 }
334
335 float draw_TextWidth_WithColors(string s, vector theFontSize)
336 {
337         return draw_TextWidth(s, TRUE, theFontSize);
338 }
339
340 float draw_TextWidth_WithoutColors(string s, vector theFontSize)
341 {
342         return draw_TextWidth(s, FALSE, theFontSize);
343 }
344
345 float draw_TextLengthUpToWidth(string theText, float maxWidth, float allowColorCodes, vector theFontSize)
346 {
347         if(allowColorCodes)
348                 return textLengthUpToWidth(theText, maxWidth, theFontSize, draw_TextWidth_WithColors);
349         else
350                 return textLengthUpToWidth(theText, maxWidth, theFontSize, draw_TextWidth_WithoutColors);
351 }