]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/menu-div0test/draw.qc
fix selection bugs when enabling/disabling the checkboxes
[divverent/nexuiz.git] / data / qcsrc / menu-div0test / draw.qc
1 float drawfont;
2 string draw_mousepointer;
3
4 void draw_setMousePointer(string pic)
5 {
6         draw_mousepointer = pic;
7 }
8
9 void draw_drawMousePointer(vector where)
10 {
11         drawpic(boxToGlobal(where, draw_shift, draw_scale), draw_mousepointer, '32 32 0', '1 1 1', draw_alpha, 0);
12 }
13
14 void draw_reset()
15 {
16         drawfont = 8;
17         draw_shift = '0 0 0';
18         draw_scale = '1 0 0' * cvar("vid_conwidth") + '0 1 0' * cvar("vid_conheight");
19         draw_alpha = 1;
20 }
21
22 vector globalToBox(vector v, vector theOrigin, vector theScale)
23 {
24         v -= theOrigin;
25         v_x /= theScale_x;
26         v_y /= theScale_y;
27         return v;
28 }
29
30 vector globalToBoxSize(vector v, vector theScale)
31 {
32         v_x /= theScale_x;
33         v_y /= theScale_y;
34         return v;
35 }
36
37 vector boxToGlobal(vector v, vector theOrigin, vector theScale)
38 {
39         v_x *= theScale_x;
40         v_y *= theScale_y;
41         v += theOrigin;
42         return v;
43 }
44
45 vector boxToGlobalSize(vector v, vector theScale)
46 {
47         v_x *= theScale_x;
48         v_y *= theScale_y;
49         return v;
50 }
51
52 void draw_Picture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
53 {
54         drawpic(boxToGlobal(theOrigin, draw_shift, draw_scale), pic, boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0);
55 }
56
57 void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha)
58 {
59         drawfill(boxToGlobal(theOrigin, draw_shift, draw_scale), boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0);
60 }
61
62 // a button picture is a texture containing three parts:
63 //   1/4 width: left part
64 //   1/2 width: middle part (stretched)
65 //   1/4 width: right part
66 // it is assumed to be 4x as wide as high for aspect ratio purposes, which
67 // means, the parts are a square, two squares and a square.
68 void draw_ButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
69 {
70         vector square;
71         vector width, height;
72         vector bW;
73         theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
74         theSize = boxToGlobalSize(theSize, draw_scale);
75         theAlpha *= draw_alpha;
76         width = eX * theSize_x;
77         height = eY * theSize_y;
78         if(theSize_x <= theSize_y * 2)
79         {
80                 // button not wide enough
81                 // draw just left and right part then
82                 square = eX * theSize_x * 0.5;
83                 bW = eX * (0.25 * theSize_x / (theSize_y * 2));
84                 drawsubpic(theOrigin,          square + height, pic, '0 0 0', eY + bW, theColor, theAlpha, 0);
85                 drawsubpic(theOrigin + square, square + height, pic, eX - bW, eY + bW, theColor, theAlpha, 0);
86         }
87         else
88         {
89                 square = eX * theSize_y;
90                 drawsubpic(theOrigin,                  height  +     square, pic, '0    0 0', '0.25 1 0', theColor, theAlpha, 0);
91                 drawsubpic(theOrigin +         square, theSize - 2 * square, pic, '0.25 0 0', '0.5  1 0', theColor, theAlpha, 0);
92                 drawsubpic(theOrigin + width - square, height  +     square, pic, '0.75 0 0', '0.25 1 0', theColor, theAlpha, 0);
93         }
94 }
95
96 // a vertical button picture is a texture containing three parts:
97 //   1/4 height: left part
98 //   1/2 height: middle part (stretched)
99 //   1/4 height: right part
100 // it is assumed to be 4x as high as wide for aspect ratio purposes, which
101 // means, the parts are a square, two squares and a square.
102 void draw_VertButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
103 {
104         vector square;
105         vector width, height;
106         vector bH;
107         theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
108         theSize = boxToGlobalSize(theSize, draw_scale);
109         theAlpha *= draw_alpha;
110         width = eX * theSize_x;
111         height = eY * theSize_y;
112         if(theSize_y <= theSize_x * 2)
113         {
114                 // button not high enough
115                 // draw just upper and lower part then
116                 square = eY * theSize_y * 0.5;
117                 bH = eY * (0.25 * theSize_y / (theSize_x * 2));
118                 drawsubpic(theOrigin,          square + width, pic, '0 0 0', eX + bH, theColor, theAlpha, 0);
119                 drawsubpic(theOrigin + square, square + width, pic, eY - bH, eX + bH, theColor, theAlpha, 0);
120         }
121         else
122         {
123                 square = eY * theSize_x;
124                 drawsubpic(theOrigin,                   width   +     square, pic, '0 0    0', '1 0.25 0', theColor, theAlpha, 0);
125                 drawsubpic(theOrigin +          square, theSize - 2 * square, pic, '0 0.25 0', '1 0.5  0', theColor, theAlpha, 0);
126                 drawsubpic(theOrigin + height - square, width   +     square, pic, '0 0.75 0', '1 0.25 0', theColor, theAlpha, 0);
127         }
128 }
129
130 // a border picture is a texture containing nine parts:
131 //   1/4 width: left part
132 //   1/2 width: middle part (stretched)
133 //   1/4 width: right part
134 // divided into
135 //   1/4 height: top part
136 //   1/2 height: middle part (stretched)
137 //   1/4 height: bottom part
138 void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
139 {
140         vector dX, dY;
141         vector width, height;
142         vector bW, bH;
143         theOrigin = boxToGlobal(theOrigin, draw_shift, draw_scale);
144         theSize = boxToGlobalSize(theSize, draw_scale);
145         theBorderSize = boxToGlobalSize(theBorderSize, draw_scale);
146         theAlpha *= draw_alpha;
147         width = eX * theSize_x;
148         height = eY * theSize_y;
149         if(theSize_x <= theBorderSize_x * 2)
150         {
151                 // not wide enough... draw just left and right then
152                 bW = eX * (0.25 * theSize_x / (theBorderSize_x * 2));
153                 if(theSize_y <= theBorderSize_y * 2)
154                 {
155                         // not high enough... draw just corners
156                         bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
157                         drawsubpic(theOrigin,                 width * 0.5 + height * 0.5, pic, '0 0 0',           bW + bH, theColor, theAlpha, 0);
158                         drawsubpic(theOrigin + width   * 0.5, width * 0.5 + height * 0.5, pic, eX - bW,           bW + bH, theColor, theAlpha, 0);
159                         drawsubpic(theOrigin + height  * 0.5, width * 0.5 + height * 0.5, pic, eY - bH,           bW + bH, theColor, theAlpha, 0);
160                         drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
161                 }
162                 else
163                 {
164                         dY = theBorderSize_x * eY;
165                         drawsubpic(theOrigin,                             width * 0.5          +     dY, pic, '0 0    0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
166                         drawsubpic(theOrigin + width * 0.5,               width * 0.5          +     dY, pic, '0 0    0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
167                         drawsubpic(theOrigin                        + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0',           '0 0.5  0' + bW, theColor, theAlpha, 0);
168                         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);
169                         drawsubpic(theOrigin               + height - dY, width * 0.5          +     dY, pic, '0 0.75 0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
170                         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);
171                 }
172         }
173         else
174         {
175                 if(theSize_y <= theBorderSize_y * 2)
176                 {
177                         // not high enough... draw just top and bottom then
178                         bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
179                         dX = theBorderSize_x * eX;
180                         drawsubpic(theOrigin,                                         dX + height * 0.5, pic, '0    0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
181                         drawsubpic(theOrigin + dX,                        width - 2 * dX + height * 0.5, pic, '0.25 0 0',           '0.5  0 0' + bH, theColor, theAlpha, 0);
182                         drawsubpic(theOrigin + width - dX,                            dX + height * 0.5, pic, '0.75 0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
183                         drawsubpic(theOrigin              + height * 0.5,             dX + height * 0.5, pic, '0    0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
184                         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);
185                         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);
186                 }
187                 else
188                 {
189                         dX = theBorderSize_x * eX;
190                         dY = theBorderSize_x * eY;
191                         drawsubpic(theOrigin,                                        dX          +     dY, pic, '0    0    0', '0.25 0.25 0', theColor, theAlpha, 0);
192                         drawsubpic(theOrigin                  + dX,      width - 2 * dX          +     dY, pic, '0.25 0    0', '0.5  0.25 0', theColor, theAlpha, 0);
193                         drawsubpic(theOrigin          + width - dX,                  dX          +     dY, pic, '0.75 0    0', '0.25 0.25 0', theColor, theAlpha, 0);
194                         drawsubpic(theOrigin          + dY,                          dX + height - 2 * dY, pic, '0    0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
195                         drawsubpic(theOrigin          + dY         + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
196                         drawsubpic(theOrigin          + dY + width - dX,             dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
197                         drawsubpic(theOrigin + height - dY,                          dX          +     dY, pic, '0    0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
198                         drawsubpic(theOrigin + height - dY         + dX, width - 2 * dX          +     dY, pic, '0.25 0.75 0', '0.5  0.25 0', theColor, theAlpha, 0);
199                         drawsubpic(theOrigin + height - dY + width - dX,             dX          +     dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
200                 }
201         }
202 }
203 void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha)
204 {
205         if(theSize_x <= 0 || theSize_y <= 0)
206                 error("Drawing zero size text?\n");
207         drawstring(boxToGlobal(theOrigin, draw_shift, draw_scale), theText, boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0);
208 }
209
210 float draw_TextWidth(string theText)
211 {
212         //return strlen(theText);
213         //print("draw_TextWidth \"", theText, "\"\n");
214         return stringwidth(theText, 0);
215 }
216
217 float draw_clipSet;
218 void draw_SetClip()
219 {
220         if(draw_clipSet)
221                 error("Already clipping, no stack implemented here, sorry");
222         drawsetcliparea(draw_shift_x, draw_shift_y, draw_scale_x, draw_scale_y);
223         draw_clipSet = 1;
224 }
225
226 void draw_ClearClip()
227 {
228         if(!draw_clipSet)
229                 error("Not clipping, can't clear it then");
230         drawresetcliparea();
231         draw_clipSet = 0;
232 }
233
234 string draw_TextShortenToWidth(string theText, float maxWidth)
235 {
236         // STOP.
237         // The following function is SLOW.
238         // For your safety and for the protection of those around you...
239         // DO NOT CALL THIS AT HOME.
240         // No really, don't.
241         if(draw_TextWidth(theText) <= maxWidth)
242                 return theText; // yeah!
243
244         // binary search for right place to cut string
245         float left, right, middle; // this always works
246         left = 0;
247         right = strlen(theText); // this always fails
248         do
249         {
250                 middle = floor((left + right) / 2);
251                 if(draw_TextWidth(strcat(substring(theText, 0, middle), "...")) <= maxWidth)
252                         left = middle;
253                 else
254                         right = middle;
255         }
256         while(left < right - 1);
257
258         // NOTE: when color codes are involved, this binary search is,
259         // mathematically, BROKEN. However, it is obviously guaranteed to
260         // terminate, as the range still halves each time - but nevertheless, it is
261         // guaranteed that it finds ONE valid cutoff place (where "left" is in
262         // range, and "right" is outside).
263
264         return strcat(substring(theText, 0, left), "...");
265 }