]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/menu-div0test/menu.qc
customizable mouse pointer and hotspot
[divverent/nexuiz.git] / qcsrc / menu-div0test / menu.qc
1 ///////////////////////////////////////////////
2 // Menu Source File
3 ///////////////////////
4 // This file belongs to dpmod/darkplaces
5 // AK contains all menu functions (especially the required ones)
6 ///////////////////////////////////////////////
7
8 float mouseButtonsPressed;
9 vector menuMousePos;
10 float menuShiftState;
11 float menuPrevTime;
12 float menuAlpha;
13 float menuLogoAlpha;
14 float prevMenuAlpha;
15 float menuLoadedMaplist;
16 float menuNotTheFirstFrame;
17
18 void SUB_Null() { };
19
20 void() m_init =
21 {
22         dprint_load();
23 }
24
25 void() m_init_delayed =
26 {
27         float fh;
28         string s;
29
30         dprint_load();
31
32         menuLoadedMaplist = 0;
33         MapInfo_Enumerate();
34         if(!MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 1))
35                 return;
36         menuLoadedMaplist = 1;
37
38         GameCommand_Init();
39
40         fh = -1;
41         if(cvar_string("menu_skin") != "")
42         {
43                 draw_currentSkin = strcat("gfx/menu/", cvar_string("menu_skin"));
44                 fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ);
45         }
46         if(fh < 0)
47         {
48                 draw_currentSkin = "gfx/menu/default";
49                 fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ);
50         }
51         draw_currentSkin = strzone(draw_currentSkin);
52         while((s = fgets(fh)))
53                 if(tokenize(s) == 2)
54                         Skin_ApplySetting(argv(0), argv(1));
55         fclose(fh);
56
57         draw_setMousePointer("cursor", SKINSIZE_CURSOR, SKINOFFSET_CURSOR);
58
59         main = spawnMainWindow(); main.configureMainWindow(main);
60         draw_reset();
61         main.resizeNotify(main, draw_shift, draw_scale, draw_shift, draw_scale);
62         main.focused = 1;
63         menuShiftState = 0;
64         menuMousePos = '0.5 0.5 0';
65
66         if(Menu_Active)
67                 m_display(); // delayed menu display
68 };
69
70 void(float key, float ascii) m_keyup =
71 {
72         if(!menuLoadedMaplist)
73                 return;
74         if(!Menu_Active)
75                 return;
76         draw_reset();
77         main.keyUp(main, key, ascii, menuShiftState);
78         if(key >= K_MOUSE1 && key <= K_MOUSE3)
79         {
80                 --mouseButtonsPressed;
81                 if(!mouseButtonsPressed)
82                         main.mouseRelease(main, menuMousePos);
83                 if(mouseButtonsPressed < 0)
84                 {
85                         mouseButtonsPressed = 0;
86                         print("Warning: released an already released button\n");
87                 }
88         }
89         if(key == K_ALT) menuShiftState -= (menuShiftState & S_ALT);
90         if(key == K_CTRL) menuShiftState -= (menuShiftState & S_CTRL);
91         if(key == K_SHIFT) menuShiftState -= (menuShiftState & S_SHIFT);
92 };
93
94 void(float key, float ascii) m_keydown =
95 {
96         if(!menuLoadedMaplist)
97                 return;
98         if(!Menu_Active)
99                 return;
100         if(keyGrabber)
101         {
102                 entity e;
103                 e = keyGrabber;
104                 keyGrabber = NULL;
105                 e.keyGrabbed(e, key, ascii);
106         }
107         else
108         {
109                 draw_reset();
110                 if(!main.keyDown(main, key, ascii, menuShiftState))
111                         if(key == K_ESCAPE)
112                                 if(gamestatus & (GAME_ISSERVER | GAME_CONNECTED)) // don't back out to console only
113                                         m_hide(); // disable menu on unhandled ESC
114                 if(key >= K_MOUSE1 && key <= K_MOUSE3)
115                         if(!mouseButtonsPressed)
116                                 main.mousePress(main, menuMousePos);
117         }
118         if(key >= K_MOUSE1 && key <= K_MOUSE3)
119         {
120                 ++mouseButtonsPressed;
121                 if(mouseButtonsPressed > 10)
122                 {
123                         mouseButtonsPressed = 10;
124                         print("Warning: pressed an already pressed button\n");
125                 }
126         }
127         if(key == K_ALT) menuShiftState |= S_ALT;
128         if(key == K_CTRL) menuShiftState |= S_CTRL;
129         if(key == K_SHIFT) menuShiftState |= S_SHIFT;
130 };
131
132 void() m_draw =
133 {
134         float t;
135         float realFrametime;
136
137         if(!menuNotTheFirstFrame)
138         {
139                 menuNotTheFirstFrame = 1;
140                 if(Menu_Active)
141                 if(!cvar("menu_video_played"))
142                 {
143                         localcmd("set menu_video_played 1; cd loop 1; play sound/announcer/male/welcome.ogg\n");
144                         menuLogoAlpha = -0.8; // no idea why, but when I start this at zero, it jumps instead of fading
145                 }
146         }
147         if(!menuLoadedMaplist)
148         {
149                 // TODO draw an info image about this situation
150                 m_init_delayed();
151                 return;
152         }
153         t = gettime();
154         realFrametime = frametime = min(0.2, t - menuPrevTime);
155         menuPrevTime = t;
156         time += frametime;
157
158         if(Menu_Active)
159         {
160                 if(getmousetarget() == MT_MENU && (getkeydest() == KEY_MENU || getkeydest() == KEY_MENU_GRABBED))
161                         setkeydest(keyGrabber ? KEY_MENU_GRABBED : KEY_MENU);
162                 else
163                         m_hide();
164         }
165
166         if(cvar("cl_capturevideo"))
167                 frametime = 1 / cvar("cl_capturevideo_fps"); // make capturevideo work smoothly
168
169         dprint_load();
170         gamestatus = 0;
171         if(isserver())
172                 gamestatus = gamestatus | GAME_ISSERVER;
173         if(clientstate() == CS_CONNECTED)
174                 gamestatus = gamestatus | GAME_CONNECTED;
175         if(cvar("developer"))
176                 gamestatus = gamestatus | GAME_DEVELOPER;
177
178         prevMenuAlpha = menuAlpha;
179         if(Menu_Active)
180         {
181                 if(menuAlpha == 0 && menuLogoAlpha < 2)
182                 {
183                         menuLogoAlpha = menuLogoAlpha + frametime * 2;
184                 }
185                 else
186                 {
187                         menuAlpha = min(1, menuAlpha + frametime * 5);
188                         menuLogoAlpha = 2;
189                 }
190         }
191         else
192         {
193                 menuAlpha = max(0, menuAlpha - frametime * 5);
194                 menuLogoAlpha = 2;
195         }
196
197         draw_reset();
198
199         if(!(gamestatus & (GAME_CONNECTED | GAME_ISSERVER)) && menuLogoAlpha > 0)
200         {
201                 vector sz;
202                 vector isz;
203                 sz = draw_PictureSize(SKINGFX_BACKGROUND);
204                 // keep aspect of image
205                 if(sz_x * draw_scale_y >= sz_y * draw_scale_x)
206                 {
207                         // that is, sz_x/sz_y >= draw_scale_x/draw_scale_y
208                         // match up the height
209                         isz_y = 1;
210                         isz_x = isz_y * (sz_x / sz_y) * (draw_scale_y / draw_scale_x);
211                 }
212                 else
213                 {
214                         // that is, sz_x/sz_y <= draw_scale_x/draw_scale_y
215                         // match up the width
216                         isz_x = 1;
217                         isz_y = isz_x * (sz_y / sz_x) * (draw_scale_x / draw_scale_y);
218                 }
219                 draw_Picture('0.5 0.5 0' - 0.5 * isz, SKINGFX_BACKGROUND, isz, '1 1 1', bound(0, menuLogoAlpha, 1));
220                 if(menuAlpha <= 0 && SKINALPHA_CURSOR_INTRO > 0)
221                 {
222                         draw_alpha = SKINALPHA_CURSOR_INTRO * bound(0, menuLogoAlpha, 1);
223                         draw_drawMousePointer(menuMousePos);
224                         draw_alpha = 1;
225                 }
226         }
227
228         if(menuAlpha <= 0)
229         {
230                 if(prevMenuAlpha > 0)
231                         main.initializeDialog(main, main.firstChild);
232                 return;
233         }
234
235         draw_alpha *= menuAlpha;
236
237         if(frametime > 0)
238         {
239                 vector dMouse;
240                 dMouse = getmousepos() * (frametime / realFrametime); // for capturevideo
241                 if(dMouse != '0 0 0')
242                 {
243                         dMouse = globalToBoxSize(dMouse, draw_scale);
244                         menuMousePos += dMouse * 1; // TODO use a cvar here
245                         menuMousePos_x = bound(0, menuMousePos_x, 1);
246                         menuMousePos_y = bound(0, menuMousePos_y, 1);
247                         if(mouseButtonsPressed)
248                                 main.mouseDrag(main, menuMousePos);
249                         else
250                                 main.mouseMove(main, menuMousePos);
251                 }
252         }
253         main.draw(main);
254         draw_alpha = max(draw_alpha, SKINALPHA_CURSOR_INTRO * bound(0, menuLogoAlpha, 1));
255         draw_drawMousePointer(menuMousePos);
256
257         frametime = 0;
258 };
259
260 void() m_display =
261 {
262         Menu_Active = true;
263         setkeydest(KEY_MENU);
264         setmousetarget(MT_MENU);
265
266         if(!menuLoadedMaplist)
267                 return;
268
269         if(mouseButtonsPressed)
270                 main.mouseRelease(main, menuMousePos);
271         mouseButtonsPressed = 0;
272
273         main.focusEnter(main);
274         main.showNotify(main);
275 };
276
277 void() m_hide =
278 {
279         Menu_Active = false;
280         setkeydest(KEY_GAME);
281         setmousetarget(MT_CLIENT);
282
283         if(!menuLoadedMaplist)
284                 return;
285
286         main.focusLeave(main);
287         main.hideNotify(main);
288 };
289
290 void() m_toggle =
291 {
292         if(Menu_Active)
293                 m_hide();
294         else
295                 m_display();
296 };
297
298 void() m_shutdown =
299 {
300         m_hide();
301 };
302
303 void(string itemname) m_goto =
304 {
305         entity e;
306         if(!menuLoadedMaplist)
307                 return;
308         if(itemname == "") // this can be called by GameCommand
309         {
310                 if(gamestatus & (GAME_ISSERVER | GAME_CONNECTED))
311                         m_hide();
312                 else
313                 {
314                         main.initializeDialog(main, main.firstChild);
315                         m_display();
316                 }
317         }
318         else
319         {
320                 e = findstring(NULL, name, itemname);
321                 if(e && e.parent == main)
322                 {
323                         m_hide();
324                         main.initializeDialog(main, e);
325                         m_display();
326                 }
327         }
328 }