00001
00025 #include "menu.h"
00026
00027 #ifdef WIN32
00028
00029 #undef RemoveMenu
00030 #define RemoveMenu _RemoveMenu_win32_
00031 #endif
00032
00033 #include "genconmac.h"
00034 #include "color.h"
00035 #include "states.h"
00036 #include "message.h"
00037 #include "net.h"
00038 #include <stdlib.h>
00039 #include <assert.h>
00040
00041 #ifdef WIN32
00042
00043 #undef RemoveMenu
00044 #define RemoveMenu _RemoveMenu_tank_
00045 #endif
00046
00047
00051 #define MENU_MARGIN 96
00052
00056 #define MARKER_THICKNESS 3
00057
00061 #define MARKER_LENGTH 24
00062
00063 extern RenderItem background;
00064
00070 static MenuItem *items;
00071
00077 static int focus;
00078
00084 static int numItems;
00085
00090 static RenderItem *markers;
00091
00092 static void PlaceMarkers() {
00093 int loop;
00094 RenderItem *mark;
00095 for (mark = markers, loop = 8; loop > 0; mark++, loop--) {
00096
00097 if (loop & 2) {
00098 mark->loc.x = items[focus].region.x - MARKER_THICKNESS;
00099 }
00100
00101 else {
00102 mark->loc.x = items[focus].region.x + items[focus].region.w
00103 + MARKER_THICKNESS - mark->loc.w;
00104 }
00105
00106 if (loop & 4) {
00107 mark->loc.y = items[focus].region.y - MARKER_THICKNESS;
00108 }
00109
00110 else {
00111 mark->loc.y = items[focus].region.y + items[focus].region.h
00112 + MARKER_THICKNESS - mark->loc.h;
00113 }
00114
00115 PlaceRenderItem(mark);
00116 }
00117 }
00118
00127 static Bool ResizeMenu(int winW, int winH) {
00128 MenuItem *item;
00129 int loop;
00130 int w, h = MARKER_THICKNESS;
00131 int y;
00132 int x;
00133
00134 if ((w = winW - MENU_MARGIN * 2) < (MENU_MARGIN * 2)) {
00135
00136 return FALSE;
00137 }
00138
00139
00140 for (item = items, loop = numItems; loop > 0; item++, loop--) {
00141
00142 assert(item->update != NULL);
00143
00144 assert((item->minWidth > 0) && (item->minHeight > 0));
00145
00146 if (item->minWidth > (winW - MARKER_THICKNESS * 2)) {
00147
00148 w = winW - MARKER_THICKNESS * 2;
00149 }
00150
00151 if (item->minWidth > w) {
00152
00153 w = item->minWidth;
00154 }
00155
00156 h += item->minHeight + MARKER_THICKNESS;
00157 }
00158
00159 x = (winW - w) >> 1;
00160
00161 if (h > (loop = winH - TOP_MARGIN - BOTTOM_MARGIN * 2 -
00162 textItems[TEXTITEM_TITLE].loc.h)) {
00163
00164 loop += textItems[TEXTITEM_TITLE].loc.h + TOP_MARGIN - BOTTOM_MARGIN;
00165
00166 ClearRenderItem(&(textItems[TEXTITEM_TITLE]));
00167
00168 if (h <= loop) {
00169
00170 y = winH - h - BOTTOM_MARGIN;
00171 }
00172 else if ((y = winH - (h >> 1)) < 0) {
00173 y = 0;
00174 }
00175
00176 h = 0;
00177 }
00178
00179 else {
00180
00181 y = TOP_MARGIN + BOTTOM_MARGIN + textItems[TEXTITEM_TITLE].loc.h;
00182
00183 h = winH - y - BOTTOM_MARGIN - h;
00184
00185 textItems[TEXTITEM_TITLE].loc.x =
00186 (winW >> 1) - (textItems[TEXTITEM_TITLE].loc.w >> 1);
00187 PlaceRenderItem(&(textItems[TEXTITEM_TITLE]));
00188 }
00189
00190 for (item = items, loop = numItems; loop > 0; item++, loop--) {
00191
00192 item->region.x = x;
00193
00194 item->region.y = y;
00195
00196 item->region.w = w;
00197
00198 item->region.h = item->minHeight;
00199
00200 if (item->expandHeight) {
00201
00202 item->region.h += h;
00203 }
00204
00205 y += item->region.h + MARKER_THICKNESS;
00206
00207 item->isPlaced = FALSE;
00208 }
00209
00210 PlaceMarkers();
00211
00212 return TRUE;
00213 }
00214
00215 void SetupMenu(MenuItem *menu, int first, int count) {
00216 int loop;
00217 RenderItem *mark;
00218
00219
00220 assert((first >= 0) && (first < count));
00221
00222 items = menu;
00223 numItems = count;
00224 focus = first;
00225
00226 items[focus].hasFocus = TRUE;
00227
00228 background.renderer = SolidFillRenderer;
00229 background.data = &(colorVals[COLOR_REGBACK]);
00230 background.loc.w = dInfo.pw;
00231 background.loc.h = dInfo.ph;
00232 AddRenderItem(&background, LAYER_BACKGROUND);
00233 PlaceRenderItem(&background);
00234
00235 textItems[TEXTITEM_TITLE].loc.y = TOP_MARGIN;
00236
00237 markers = calloc(8, sizeof(RenderItem));
00238 for (mark = markers, loop = 8; loop > 0; mark++, loop--) {
00239
00240 if (loop & 1) {
00241 mark->loc.w = MARKER_THICKNESS;
00242 mark->loc.h = MARKER_LENGTH;
00243 }
00244
00245 else {
00246 mark->loc.w = MARKER_LENGTH;
00247 mark->loc.h = MARKER_THICKNESS;
00248 }
00249
00250 mark->renderer = SolidFillRenderer;
00251
00252 mark->data = &(colorVals[COLOR_OBSTACLE]);
00253
00254 AddRenderItem(mark, LAYER_OBSTACLES);
00255 }
00256
00257 ResizeMenu(dInfo.pw, dInfo.ph);
00258
00259 SDL_EnableUNICODE(TRUE);
00260 }
00261
00262 void RemoveMenu() {
00263 int loop;
00264
00265 for (loop = 0; loop < 8; loop++) {
00266 RemoveRenderItem(&(markers[loop]));
00267 }
00268
00269 free(markers);
00270 RemoveRenderItem(&background);
00271
00272 SDL_EnableUNICODE(FALSE);
00273 }
00274
00275 int MenuRun() {
00276 int loop, state = 0;
00277 MenuItem *item;
00278 SDL_Event event;
00279 rtsa_char keyval = 0;
00280
00281
00282 eventState[EC_FORWARD] = eventState[EC_BACKWARD] = 0;
00283
00284 while (SDL_PollEvent(&event)) {
00285
00286 switch (event.type) {
00287 case SDL_QUIT:
00288 return STATE_QUIT;
00289 break;
00290 case SDL_ACTIVEEVENT:
00291
00292
00293
00294
00295
00296
00297
00298 break;
00299 case SDL_KEYDOWN:
00300
00301 switch (event.key.keysym.sym) {
00302 case SDLK_ESCAPE:
00303 return STATE_QUIT;
00304 break;
00305 case SDLK_UP:
00306 eventState[EC_FORWARD] |= 1;
00307 break;
00308 case SDLK_DOWN:
00309 eventState[EC_BACKWARD] |= 1;
00310 break;
00311 case SDLK_TAB:
00312 if (event.key.keysym.mod & KMOD_SHIFT) {
00313 eventState[EC_FORWARD] |= 1;
00314 }
00315 else {
00316 eventState[EC_BACKWARD] |= 1;
00317 }
00318 break;
00319 case SDLK_LEFT:
00320 eventState[EC_ROTLEFT] |= 1;
00321 break;
00322 case SDLK_RIGHT:
00323 eventState[EC_ROTRIGHT] |= 1;
00324 break;
00325 case SDLK_SPACE:
00326 keyval = ' ';
00327 eventState[EC_CHARACTER] |= 1;
00328 case SDLK_RETURN:
00329 eventState[EC_FIRE] |= 1;
00330 break;
00331 default:
00332 #ifdef USE_GETTEXT
00333 eventState[EC_CHARACTER] |= 1;
00334
00335 keyval = event.key.keysym.unicode;
00336
00337
00338
00339
00340
00341
00342 #else
00343
00344 if ((event.key.keysym.unicode & 0xFF80) == 0) {
00345 eventState[EC_CHARACTER] |= 1;
00346 keyval = (rtsa_char)event.key.keysym.unicode;
00347 }
00348 #endif
00349 break;
00350 }
00351 break;
00352 case SDL_KEYUP:
00353 switch (event.key.keysym.sym) {
00354 case SDLK_LEFT:
00355 eventState[EC_ROTLEFT] = 0;
00356 break;
00357 case SDLK_RIGHT:
00358 eventState[EC_ROTRIGHT] = 0;
00359 break;
00360 case SDLK_SPACE:
00361 eventState[EC_CHARACTER] = 0;
00362 case SDLK_RETURN:
00363 eventState[EC_FIRE] = 0;
00364 break;
00365 case SDLK_BACKSPACE:
00366 return STATE_SPLASH;
00367 default:
00368 if (event.key.keysym.unicode) {
00369 eventState[EC_CHARACTER] = 0;
00370 }
00371 break;
00372 }
00373 break;
00374 case SDL_JOYAXISMOTION:
00375 if (!(SDL_GetAppState() & SDL_APPINPUTFOCUS)) break;
00376
00377 if (event.jaxis.axis == 0) {
00378
00379 if (event.jaxis.value > 16384) {
00380 eventState[EC_ROTRIGHT] |= 1;
00381 eventState[EC_ROTLEFT] = 0;
00382 }
00383
00384 else if (event.jaxis.value < -16384) {
00385 eventState[EC_ROTLEFT] |= 1;
00386 eventState[EC_ROTRIGHT] = 0;
00387 }
00388
00389 else {
00390 eventState[EC_ROTLEFT] = 0;
00391 eventState[EC_ROTRIGHT] = 0;
00392 }
00393 }
00394
00395 else if (event.jaxis.axis == 1) {
00396
00397 if (event.jaxis.value > 16384) {
00398 eventState[EC_BACKWARD] |= 1;
00399 eventState[EC_FORWARD] = 0;
00400 }
00401
00402 else if (event.jaxis.value < -16384) {
00403 eventState[EC_FORWARD] |= 1;
00404 eventState[EC_BACKWARD] = 0;
00405 }
00406
00407 else {
00408 eventState[EC_FORWARD] = 0;
00409 eventState[EC_BACKWARD] = 0;
00410 }
00411 }
00412 break;
00413 case SDL_JOYBUTTONDOWN:
00414 if (!(SDL_GetAppState() & SDL_APPINPUTFOCUS)) break;
00415 eventState[EC_FIRE] |= 1;
00416 break;
00417 case SDL_JOYBUTTONUP:
00418 if (!(SDL_GetAppState() & SDL_APPINPUTFOCUS)) break;
00419 eventState[EC_FIRE] = 0;
00420 break;
00421 case SDL_VIDEORESIZE:
00422
00423 if (ResizeMenu(event.resize.w, event.resize.h)) {
00424
00425 ResizeWindow(event.resize.w, event.resize.h);
00426
00427 SetupColorVals();
00428
00429 background.loc.w = dInfo.pw;
00430 background.loc.h = dInfo.ph;
00431 PlaceRenderItem(&background);
00432 }
00433 default:
00434 break;
00435 }
00436 }
00437
00438 ProcessNetworkMessages();
00439
00440 if ((numItems > 1) && !items[focus].lockFocus) {
00441
00442 if (eventState[EC_BACKWARD]) {
00443
00444 for (loop = focus + 1; loop < numItems; loop++) {
00445
00446 if (items[loop].active) {
00447
00448 items[focus].hasFocus = FALSE;
00449 if (items[focus].focus) {
00450 (*(items[focus].focus))(&(items[focus]));
00451 }
00452
00453 items[focus = loop].hasFocus = TRUE;
00454 if (items[focus].focus) {
00455 (*(items[focus].focus))(&(items[focus]));
00456 }
00457
00458 PlaceMarkers();
00459 break;
00460 }
00461 }
00462 }
00463
00464 else if (eventState[EC_FORWARD]) {
00465
00466 for (loop = focus - 1; loop >= 0; loop--) {
00467
00468 if (items[loop].active) {
00469
00470 items[focus].hasFocus = FALSE;
00471 if (items[focus].focus) {
00472 (*(items[focus].focus))(&(items[focus]));
00473 }
00474
00475 items[focus = loop].hasFocus = TRUE;
00476 if (items[focus].focus) {
00477 (*(items[focus].focus))(&(items[focus]));
00478 }
00479
00480 PlaceMarkers();
00481 break;
00482 }
00483 }
00484 }
00485 }
00486
00487 if (items[focus].input) {
00488
00489 if ((state = (*(items[focus].input))(&(items[focus]), eventState,
00490 keyval)) != 0) {
00491 return state;
00492 }
00493 }
00494
00495 for (item = items, loop = numItems; loop > 0; item++, loop--) {
00496
00497 if ((state = (*(item->update))(item)) != 0) {
00498 return state;
00499 }
00500 }
00501
00502 return STATE_MENUROOT;
00503 }
00504