00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "heightmap.h"
00008 #include "currency.h"
00009 #include "spritecache.h"
00010 #include "gui.h"
00011 #include "window_gui.h"
00012 #include "window_func.h"
00013 #include "textbuf_gui.h"
00014 #include "viewport_func.h"
00015 #include "command_func.h"
00016 #include "news.h"
00017 #include "town.h"
00018 #include "console.h"
00019 #include "signs.h"
00020 #include "waypoint.h"
00021 #include "variables.h"
00022 #include "train.h"
00023 #include "roadveh.h"
00024 #include "bridge_map.h"
00025 #include "screenshot.h"
00026 #include "genworld.h"
00027 #include "vehicle_gui.h"
00028 #include "transparency_gui.h"
00029 #include "newgrf_config.h"
00030 #include "rail_gui.h"
00031 #include "road_gui.h"
00032 #include "date_func.h"
00033 #include "functions.h"
00034 #include "vehicle_func.h"
00035 #include "sound_func.h"
00036 #include "fios.h"
00037 #include "terraform_gui.h"
00038 #include "industry.h"
00039 #include "transparency.h"
00040 #include "strings_func.h"
00041 #include "zoom_func.h"
00042 #include "string_func.h"
00043 #include "player_base.h"
00044 #include "player_func.h"
00045 #include "player_gui.h"
00046 #include "settings_type.h"
00047
00048 #include "network/network.h"
00049 #include "network/network_data.h"
00050 #include "network/network_client.h"
00051 #include "network/network_server.h"
00052 #include "network/network_gui.h"
00053
00054 #include "table/sprites.h"
00055 #include "table/strings.h"
00056
00057 static int _rename_id = 1;
00058 static int _rename_what = -1;
00059
00060 RailType _last_built_railtype;
00061 RoadType _last_built_roadtype;
00062 static int _scengen_town_size = 1;
00063
00064 extern void GenerateIndustries();
00065 extern bool GenerateTowns();
00066
00067 bool _draw_bounding_boxes = false;
00068
00069
00070 void CcGiveMoney(bool success, TileIndex tile, uint32 p1, uint32 p2)
00071 {
00072 #ifdef ENABLE_NETWORK
00073 if (!success || !_patches.give_money) return;
00074
00075 char msg[20];
00076
00077 snprintf(msg, sizeof(msg), "%d", p1);
00078
00079 if (!_network_server) {
00080 SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg);
00081 } else {
00082 NetworkServer_HandleChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg, NETWORK_SERVER_INDEX);
00083 }
00084 #endif
00085 }
00086
00087 void HandleOnEditText(const char *str)
00088 {
00089 int id = _rename_id;
00090 _cmd_text = str;
00091
00092 switch (_rename_what) {
00093 case 1:
00094 if (*str == '\0') return;
00095 DoCommandP(0, id, 0, NULL, CMD_RENAME_WAYPOINT | CMD_MSG(STR_CANT_CHANGE_WAYPOINT_NAME));
00096 break;
00097 #ifdef ENABLE_NETWORK
00098 case 3: {
00099 const Player *p = GetPlayer(_current_player);
00100 Money money = min(p->player_money - p->current_loan, (Money)(atoi(str) / _currency->rate));
00101
00102 uint32 money_c = Clamp(ClampToI32(money), 0, 20000000);
00103
00104
00105 DoCommandP(0, money_c, id, CcGiveMoney, CMD_GIVE_MONEY | CMD_MSG(STR_INSUFFICIENT_FUNDS));
00106 } break;
00107 #endif
00108 default: NOT_REACHED();
00109 }
00110
00111 _rename_id = _rename_what = -1;
00112 }
00113
00125 bool HandlePlacePushButton(Window *w, int widget, CursorID cursor, ViewportHighlightMode mode, PlaceProc *placeproc)
00126 {
00127 if (w->IsWidgetDisabled(widget)) return false;
00128
00129 SndPlayFx(SND_15_BEEP);
00130 SetWindowDirty(w);
00131
00132 if (w->IsWidgetLowered(widget)) {
00133 ResetObjectToPlace();
00134 return false;
00135 }
00136
00137 SetObjectToPlace(cursor, PAL_NONE, mode, w->window_class, w->window_number);
00138 w->LowerWidget(widget);
00139 _place_proc = placeproc;
00140 return true;
00141 }
00142
00143
00144 void CcPlaySound10(bool success, TileIndex tile, uint32 p1, uint32 p2)
00145 {
00146 if (success) SndPlayTileFx(SND_12_EXPLOSION, tile);
00147 }
00148
00149
00150 static void ToolbarPauseClick(Window *w)
00151 {
00152 if (_networking && !_network_server) return;
00153
00154 if (DoCommandP(0, _pause_game ? 0 : 1, 0, NULL, CMD_PAUSE)) SndPlayFx(SND_15_BEEP);
00155 }
00156
00157 static void ToolbarFastForwardClick(Window *w)
00158 {
00159 _fast_forward ^= true;
00160 SndPlayFx(SND_15_BEEP);
00161 }
00162
00163
00164 static void MenuClickSettings(int index)
00165 {
00166 switch (index) {
00167 case 0: ShowGameOptions(); return;
00168 case 1: ShowGameDifficulty(); return;
00169 case 2: ShowPatchesSelection(); return;
00170 case 3: ShowNewGRFSettings(!_networking, true, true, &_grfconfig); return;
00171 case 4: ShowTransparencyToolbar(); break;
00172
00173 case 6: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES); break;
00174 case 7: ToggleBit(_display_opt, DO_SHOW_STATION_NAMES); break;
00175 case 8: ToggleBit(_display_opt, DO_SHOW_SIGNS); break;
00176 case 9: ToggleBit(_display_opt, DO_WAYPOINTS); break;
00177 case 10: ToggleBit(_display_opt, DO_FULL_ANIMATION); break;
00178 case 11: ToggleBit(_display_opt, DO_FULL_DETAIL); break;
00179 case 12: ToggleTransparency(TO_HOUSES); break;
00180 case 13: ToggleTransparency(TO_SIGNS); break;
00181 }
00182 MarkWholeScreenDirty();
00183 }
00184
00185 static void MenuClickSaveLoad(int index)
00186 {
00187 if (_game_mode == GM_EDITOR) {
00188 switch (index) {
00189 case 0: ShowSaveLoadDialog(SLD_SAVE_SCENARIO); break;
00190 case 1: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
00191 case 2: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
00192 case 3: AskExitToGameMenu(); break;
00193 case 5: HandleExitGameRequest(); break;
00194 }
00195 } else {
00196 switch (index) {
00197 case 0: ShowSaveLoadDialog(SLD_SAVE_GAME); break;
00198 case 1: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
00199 case 2: AskExitToGameMenu(); break;
00200 case 3: HandleExitGameRequest(); break;
00201 }
00202 }
00203 }
00204
00205 static void MenuClickMap(int index)
00206 {
00207 switch (index) {
00208 case 0: ShowSmallMap(); break;
00209 case 1: ShowExtraViewPortWindow(); break;
00210 case 2: ShowSignList(); break;
00211 }
00212 }
00213
00214 static void MenuClickTown(int index)
00215 {
00216 ShowTownDirectory();
00217 }
00218
00219 static void MenuClickScenMap(int index)
00220 {
00221 switch (index) {
00222 case 0: ShowSmallMap(); break;
00223 case 1: ShowExtraViewPortWindow(); break;
00224 case 2: ShowSignList(); break;
00225 case 3: ShowTownDirectory(); break;
00226 }
00227 }
00228
00229 static void MenuClickSubsidies(int index)
00230 {
00231 ShowSubsidiesList();
00232 }
00233
00234 static void MenuClickStations(int index)
00235 {
00236 ShowPlayerStations((PlayerID)index);
00237 }
00238
00239 static void MenuClickFinances(int index)
00240 {
00241 ShowPlayerFinances((PlayerID)index);
00242 }
00243
00244 static void MenuClickCompany(int index)
00245 {
00246 if (_networking && index == 0) {
00247 ShowClientList();
00248 } else {
00249 if (_networking) index--;
00250 ShowPlayerCompany((PlayerID)index);
00251 }
00252 }
00253
00254 static void MenuClickGraphs(int index)
00255 {
00256 switch (index) {
00257 case 0: ShowOperatingProfitGraph(); break;
00258 case 1: ShowIncomeGraph(); break;
00259 case 2: ShowDeliveredCargoGraph(); break;
00260 case 3: ShowPerformanceHistoryGraph(); break;
00261 case 4: ShowCompanyValueGraph(); break;
00262 case 5: ShowCargoPaymentRates(); break;
00263 }
00264 }
00265
00266 static void MenuClickLeague(int index)
00267 {
00268 switch (index) {
00269 case 0: ShowCompanyLeagueTable(); break;
00270 case 1: ShowPerformanceRatingDetail(); break;
00271 }
00272 }
00273
00274 static void MenuClickIndustry(int index)
00275 {
00276 switch (index) {
00277 case 0: ShowIndustryDirectory(); break;
00278 case 1: ShowBuildIndustryWindow(); break;
00279 }
00280 }
00281
00282 static void MenuClickShowTrains(int index)
00283 {
00284 ShowVehicleListWindow((PlayerID)index, VEH_TRAIN);
00285 }
00286
00287 static void MenuClickShowRoad(int index)
00288 {
00289 ShowVehicleListWindow((PlayerID)index, VEH_ROAD);
00290 }
00291
00292 static void MenuClickShowShips(int index)
00293 {
00294 ShowVehicleListWindow((PlayerID)index, VEH_SHIP);
00295 }
00296
00297 static void MenuClickShowAir(int index)
00298 {
00299 ShowVehicleListWindow((PlayerID)index, VEH_AIRCRAFT);
00300 }
00301
00302 static void MenuClickBuildRail(int index)
00303 {
00304 _last_built_railtype = (RailType)index;
00305 ShowBuildRailToolbar(_last_built_railtype, -1);
00306 }
00307
00308 static void MenuClickBuildRoad(int index)
00309 {
00310 _last_built_roadtype = (RoadType)index;
00311 ShowBuildRoadToolbar(_last_built_roadtype);
00312 }
00313
00314 static void MenuClickBuildWater(int index)
00315 {
00316 ShowBuildDocksToolbar();
00317 }
00318
00319 static void MenuClickBuildAir(int index)
00320 {
00321 ShowBuildAirToolbar();
00322 }
00323
00324 #ifdef ENABLE_NETWORK
00325 void ShowNetworkGiveMoneyWindow(PlayerID player)
00326 {
00327 _rename_id = player;
00328 _rename_what = 3;
00329 ShowQueryString(STR_EMPTY, STR_NETWORK_GIVE_MONEY_CAPTION, 30, 180, NULL, CS_NUMERAL);
00330 }
00331 #endif
00332
00333 void ShowRenameWaypointWindow(const Waypoint *wp)
00334 {
00335 int id = wp->index;
00336
00337
00338 if (!IsTileType(wp->xy, MP_RAILWAY) || !CheckTileOwnership(wp->xy)) {
00339 ShowErrorMessage(_error_message, STR_CANT_CHANGE_WAYPOINT_NAME,
00340 TileX(wp->xy) * TILE_SIZE, TileY(wp->xy) * TILE_SIZE);
00341 return;
00342 }
00343
00344 _rename_id = id;
00345 _rename_what = 1;
00346 SetDParam(0, id);
00347 ShowQueryString(STR_WAYPOINT_RAW, STR_EDIT_WAYPOINT_NAME, 30, 180, NULL, CS_ALPHANUMERAL);
00348 }
00349
00350 static void SelectSignTool()
00351 {
00352 if (_cursor.sprite == SPR_CURSOR_SIGN) {
00353 ResetObjectToPlace();
00354 } else {
00355 SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, VHM_RECT, WC_MAIN_TOOLBAR, 0);
00356 _place_proc = PlaceProc_Sign;
00357 }
00358 }
00359
00360 static void MenuClickForest(int index)
00361 {
00362 switch (index) {
00363 case 0: ShowTerraformToolbar(); break;
00364 case 1: ShowBuildTreesToolbar(); break;
00365 case 2: SelectSignTool(); break;
00366 }
00367 }
00368
00369 static void MenuClickMusicWindow(int index)
00370 {
00371 ShowMusicWindow();
00372 }
00373
00374 static void MenuClickNewspaper(int index)
00375 {
00376 switch (index) {
00377 case 0: ShowLastNewsMessage(); break;
00378 case 1: ShowMessageOptions(); break;
00379 case 2: ShowMessageHistory(); break;
00380 }
00381 }
00382
00383 static void MenuClickSmallScreenshot()
00384 {
00385 SetScreenshotType(SC_VIEWPORT);
00386 }
00387
00388 static void MenuClickWorldScreenshot()
00389 {
00390 SetScreenshotType(SC_WORLD);
00391 }
00392
00393 static void MenuClickHelp(int index)
00394 {
00395 switch (index) {
00396 case 0: PlaceLandBlockInfo(); break;
00397 case 2: IConsoleSwitch(); break;
00398 case 3: MenuClickSmallScreenshot(); break;
00399 case 4: MenuClickWorldScreenshot(); break;
00400 case 5: ShowAboutWindow(); break;
00401 }
00402 }
00403
00404
00405 typedef void MenuClickedProc(int index);
00406
00407 static MenuClickedProc * const _menu_clicked_procs[] = {
00408 NULL,
00409 NULL,
00410 MenuClickSettings,
00411 MenuClickSaveLoad,
00412 MenuClickMap,
00413 MenuClickTown,
00414 MenuClickSubsidies,
00415 MenuClickStations,
00416 MenuClickFinances,
00417 MenuClickCompany,
00418 MenuClickGraphs,
00419 MenuClickLeague,
00420 MenuClickIndustry,
00421 MenuClickShowTrains,
00422 MenuClickShowRoad,
00423 MenuClickShowShips,
00424 MenuClickShowAir,
00425 MenuClickScenMap,
00426 NULL,
00427 MenuClickBuildRail,
00428 MenuClickBuildRoad,
00429 MenuClickBuildWater,
00430 MenuClickBuildAir,
00431 MenuClickForest,
00432 MenuClickMusicWindow,
00433 MenuClickNewspaper,
00434 MenuClickHelp,
00435 };
00436
00437 static void MenuWndProc(Window *w, WindowEvent *e)
00438 {
00439 switch (e->event) {
00440 case WE_CREATE: w->widget[0].right = w->width - 1; break;
00441
00442 case WE_PAINT: {
00443 int x, y;
00444
00445 byte count = WP(w, menu_d).item_count;
00446 byte sel = WP(w, menu_d).sel_index;
00447 uint16 chk = WP(w, menu_d).checked_items;
00448 StringID string = WP(w, menu_d).string_id;
00449 byte dis = WP(w, menu_d).disabled_items;
00450
00451 DrawWindowWidgets(w);
00452
00453 x = 1;
00454 y = 1;
00455
00456 for (; count != 0; count--, string++, sel--) {
00457 TextColour color = HasBit(dis, 0) ? TC_GREY : (sel == 0) ? TC_WHITE : TC_BLACK;
00458 if (sel == 0) GfxFillRect(x, y, x + w->width - 3, y + 9, 0);
00459
00460 if (HasBit(chk, 0)) DrawString(x + 2, y, STR_CHECKMARK, color);
00461 DrawString(x + 2, y, string, color);
00462
00463 y += 10;
00464 chk >>= 1;
00465 dis >>= 1;
00466 }
00467 } break;
00468
00469 case WE_DESTROY: {
00470 Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0);
00471 v->RaiseWidget(WP(w, menu_d).main_button);
00472 SetWindowDirty(v);
00473 return;
00474 }
00475
00476 case WE_POPUPMENU_SELECT: {
00477 int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
00478 int action_id;
00479
00480
00481 if (index < 0) {
00482 Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
00483 if (GetWidgetFromPos(w2, e->we.popupmenu.pt.x - w2->left, e->we.popupmenu.pt.y - w2->top) == WP(w, menu_d).main_button)
00484 index = WP(w, menu_d).sel_index;
00485 }
00486
00487 action_id = WP(w, menu_d).action_id;
00488 DeleteWindow(w);
00489
00490 if (index >= 0) {
00491 assert((uint)index <= lengthof(_menu_clicked_procs));
00492 _menu_clicked_procs[action_id](index);
00493 }
00494
00495 break;
00496 }
00497
00498 case WE_POPUPMENU_OVER: {
00499 int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
00500
00501 if (index == -1 || index == WP(w, menu_d).sel_index) return;
00502
00503 WP(w, menu_d).sel_index = index;
00504 SetWindowDirty(w);
00505 return;
00506 }
00507 }
00508 }
00509
00510
00511
00512 static const Widget _menu_widgets[] = {
00513 { WWT_PANEL, RESIZE_NONE, 14, 0, 0, 0, 0, 0x0, STR_NULL},
00514 { WIDGETS_END},
00515 };
00516
00517
00518 static const Widget _player_menu_widgets[] = {
00519 { WWT_PANEL, RESIZE_NONE, 14, 0, 240, 0, 81, 0x0, STR_NULL},
00520 { WIDGETS_END},
00521 };
00522
00523
00524 static int GetPlayerIndexFromMenu(int index)
00525 {
00526 if (index >= 0) {
00527 const Player *p;
00528
00529 FOR_ALL_PLAYERS(p) {
00530 if (p->is_active && --index < 0) return p->index;
00531 }
00532 }
00533 return -1;
00534 }
00535
00536 static void UpdatePlayerMenuHeight(Window *w)
00537 {
00538 byte num = ActivePlayerCount();
00539
00540
00541 if (_networking && WP(w, menu_d).main_button == 9) num++;
00542
00543 if (WP(w, menu_d).item_count != num) {
00544 WP(w, menu_d).item_count = num;
00545 SetWindowDirty(w);
00546 num = num * 10 + 2;
00547 w->height = num;
00548 w->widget[0].bottom = w->widget[0].top + num - 1;
00549 SetWindowDirty(w);
00550 }
00551 }
00552
00553 static void PlayerMenuWndProc(Window *w, WindowEvent *e)
00554 {
00555 switch (e->event) {
00556 case WE_PAINT: {
00557 int x,y;
00558 byte sel;
00559 TextColour color;
00560 Player *p;
00561 uint16 chk;
00562
00563 UpdatePlayerMenuHeight(w);
00564 DrawWindowWidgets(w);
00565
00566 x = 1;
00567 y = 1;
00568 sel = WP(w, menu_d).sel_index;
00569 chk = WP(w, menu_d).checked_items;
00570
00571
00572 if (_networking && WP(w, menu_d).main_button == 9) {
00573 if (sel == 0) {
00574 GfxFillRect(x, y, x + 238, y + 9, 0);
00575 }
00576 DrawString(x + 19, y, STR_NETWORK_CLIENT_LIST, TC_FROMSTRING);
00577 y += 10;
00578 sel--;
00579 }
00580
00581 FOR_ALL_PLAYERS(p) {
00582 if (p->is_active) {
00583 if (p->index == sel) {
00584 GfxFillRect(x, y, x + 238, y + 9, 0);
00585 }
00586
00587 DrawPlayerIcon(p->index, x + 2, y + 1);
00588
00589 SetDParam(0, p->index);
00590 SetDParam(1, p->index);
00591
00592 color = (p->index == sel) ? TC_WHITE : TC_BLACK;
00593 if (chk&1) color = TC_GREY;
00594 DrawString(x + 19, y, STR_7021, color);
00595
00596 y += 10;
00597 }
00598 chk >>= 1;
00599 }
00600
00601 break;
00602 }
00603
00604 case WE_DESTROY: {
00605 Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0);
00606 v->RaiseWidget(WP(w, menu_d).main_button);
00607 SetWindowDirty(v);
00608 return;
00609 }
00610
00611 case WE_POPUPMENU_SELECT: {
00612 int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
00613 int action_id = WP(w, menu_d).action_id;
00614
00615
00616
00617 if (_networking && WP(w, menu_d).main_button == 9) {
00618 if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
00619 } else {
00620 index = GetPlayerIndexFromMenu(index);
00621 }
00622
00623 if (index < 0) {
00624 Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
00625 if (GetWidgetFromPos(w2, e->we.popupmenu.pt.x - w2->left, e->we.popupmenu.pt.y - w2->top) == WP(w, menu_d).main_button)
00626 index = WP(w, menu_d).sel_index;
00627 }
00628
00629 DeleteWindow(w);
00630
00631 if (index >= 0) {
00632 assert(index >= 0 && index < 30);
00633 _menu_clicked_procs[action_id](index);
00634 }
00635 break;
00636 }
00637 case WE_POPUPMENU_OVER: {
00638 int index;
00639 UpdatePlayerMenuHeight(w);
00640 index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
00641
00642
00643
00644 if (_networking && WP(w, menu_d).main_button == 9) {
00645 if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
00646 } else {
00647 index = GetPlayerIndexFromMenu(index);
00648 }
00649
00650 if (index == -1 || index == WP(w, menu_d).sel_index) return;
00651
00652 WP(w, menu_d).sel_index = index;
00653 SetWindowDirty(w);
00654 return;
00655 }
00656 }
00657 }
00658
00664 static int GetStringListMaxWidth(StringID base_string, byte count)
00665 {
00666 char buffer[512];
00667 int width, max_width;
00668 byte i;
00669
00670 max_width = 0;
00671 for (i = 0; i != count; i++) {
00672 GetString(buffer, base_string + i, lastof(buffer));
00673 width = GetStringBoundingBox(buffer).width;
00674 if (width > max_width) max_width = width;
00675 }
00676
00677 return max_width;
00678 }
00679
00702 static Window *PopupMainToolbMenu(Window *w, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask)
00703 {
00704 int width;
00705 int x = w->widget[GB(parent_button, 0, 8)].left;
00706
00707 assert(disabled_mask == 0 || item_count <= 8);
00708 w->LowerWidget(parent_button);
00709 w->InvalidateWidget(parent_button);
00710
00711 DeleteWindowById(WC_TOOLBAR_MENU, 0);
00712
00713
00714
00715
00716
00717
00718 width = max(GetStringListMaxWidth(base_string, item_count) + 6, 140);
00719 x = w->left + Clamp(x, 0, w->width - width);
00720
00721 w = AllocateWindow(x, 22, width, item_count * 10 + 2, MenuWndProc, WC_TOOLBAR_MENU, _menu_widgets);
00722 w->widget[0].bottom = item_count * 10 + 1;
00723 w->flags4 &= ~WF_WHITE_BORDER_MASK;
00724
00725 WP(w, menu_d).item_count = item_count;
00726 WP(w, menu_d).sel_index = 0;
00727 WP(w, menu_d).main_button = GB(parent_button, 0, 8);
00728 WP(w, menu_d).action_id = (GB(parent_button, 8, 8) != 0) ? GB(parent_button, 8, 8) : parent_button;
00729 WP(w, menu_d).string_id = base_string;
00730 WP(w, menu_d).checked_items = 0;
00731 WP(w, menu_d).disabled_items = disabled_mask;
00732
00733 _popup_menu_active = true;
00734
00735 SndPlayFx(SND_15_BEEP);
00736 return w;
00737 }
00738
00739 static Window *PopupMainPlayerToolbMenu(Window *w, int main_button, int gray)
00740 {
00741 int x = w->widget[main_button].left + w->left;
00742
00743 w->LowerWidget(main_button);
00744 w->InvalidateWidget(main_button);
00745
00746 DeleteWindowById(WC_TOOLBAR_MENU, 0);
00747 w = AllocateWindow(x, 0x16, 0xF1, 0x52, PlayerMenuWndProc, WC_TOOLBAR_MENU, _player_menu_widgets);
00748 w->flags4 &= ~WF_WHITE_BORDER_MASK;
00749 WP(w, menu_d).item_count = 0;
00750 WP(w, menu_d).sel_index = (_local_player != PLAYER_SPECTATOR) ? _local_player : GetPlayerIndexFromMenu(0);
00751 if (_networking && main_button == 9) {
00752 if (_local_player != PLAYER_SPECTATOR) {
00753 WP(w, menu_d).sel_index++;
00754 } else {
00755
00756 WP(w, menu_d).sel_index = 0;
00757 }
00758 }
00759 WP(w, menu_d).action_id = main_button;
00760 WP(w, menu_d).main_button = main_button;
00761 WP(w, menu_d).checked_items = gray;
00762 WP(w, menu_d).disabled_items = 0;
00763 _popup_menu_active = true;
00764 SndPlayFx(SND_15_BEEP);
00765 return w;
00766 }
00767
00768 static void ToolbarSaveClick(Window *w)
00769 {
00770 PopupMainToolbMenu(w, 3, STR_015C_SAVE_GAME, 4, 0);
00771 }
00772
00773 static void ToolbarMapClick(Window *w)
00774 {
00775 PopupMainToolbMenu(w, 4, STR_02DE_MAP_OF_WORLD, 3, 0);
00776 }
00777
00778 static void ToolbarTownClick(Window *w)
00779 {
00780 PopupMainToolbMenu(w, 5, STR_02BB_TOWN_DIRECTORY, 1, 0);
00781 }
00782
00783 static void ToolbarSubsidiesClick(Window *w)
00784 {
00785 PopupMainToolbMenu(w, 6, STR_02DD_SUBSIDIES, 1, 0);
00786 }
00787
00788 static void ToolbarStationsClick(Window *w)
00789 {
00790 PopupMainPlayerToolbMenu(w, 7, 0);
00791 }
00792
00793 static void ToolbarMoneyClick(Window *w)
00794 {
00795 PopupMainPlayerToolbMenu(w, 8, 0);
00796 }
00797
00798 static void ToolbarPlayersClick(Window *w)
00799 {
00800 PopupMainPlayerToolbMenu(w, 9, 0);
00801 }
00802
00803 static void ToolbarGraphsClick(Window *w)
00804 {
00805 PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6, 0);
00806 }
00807
00808 static void ToolbarLeagueClick(Window *w)
00809 {
00810 PopupMainToolbMenu(w, 11, STR_015A_COMPANY_LEAGUE_TABLE, 2, 0);
00811 }
00812
00813 static void ToolbarIndustryClick(Window *w)
00814 {
00815
00816 PopupMainToolbMenu(w, 12, STR_INDUSTRY_DIR, 2, (_current_player == PLAYER_SPECTATOR) ? (1 << 1) : 0);
00817 }
00818
00819 static void ToolbarTrainClick(Window *w)
00820 {
00821 const Vehicle *v;
00822 int dis = -1;
00823
00824 FOR_ALL_VEHICLES(v) {
00825 if (v->type == VEH_TRAIN && IsFrontEngine(v)) ClrBit(dis, v->owner);
00826 }
00827 PopupMainPlayerToolbMenu(w, 13, dis);
00828 }
00829
00830 static void ToolbarRoadClick(Window *w)
00831 {
00832 const Vehicle *v;
00833 int dis = -1;
00834
00835 FOR_ALL_VEHICLES(v) {
00836 if (v->type == VEH_ROAD && IsRoadVehFront(v)) ClrBit(dis, v->owner);
00837 }
00838 PopupMainPlayerToolbMenu(w, 14, dis);
00839 }
00840
00841 static void ToolbarShipClick(Window *w)
00842 {
00843 const Vehicle *v;
00844 int dis = -1;
00845
00846 FOR_ALL_VEHICLES(v) {
00847 if (v->type == VEH_SHIP) ClrBit(dis, v->owner);
00848 }
00849 PopupMainPlayerToolbMenu(w, 15, dis);
00850 }
00851
00852 static void ToolbarAirClick(Window *w)
00853 {
00854 const Vehicle *v;
00855 int dis = -1;
00856
00857 FOR_ALL_VEHICLES(v) {
00858 if (v->type == VEH_AIRCRAFT) ClrBit(dis, v->owner);
00859 }
00860 PopupMainPlayerToolbMenu(w, 16, dis);
00861 }
00862
00863
00864
00865 bool DoZoomInOutWindow(int how, Window *w)
00866 {
00867 ViewPort *vp;
00868
00869 assert(w != NULL);
00870 vp = w->viewport;
00871
00872 switch (how) {
00873 case ZOOM_IN:
00874 if (vp->zoom == ZOOM_LVL_MIN) return false;
00875 vp->zoom = (ZoomLevel)((int)vp->zoom - 1);
00876 vp->virtual_width >>= 1;
00877 vp->virtual_height >>= 1;
00878
00879 WP(w, vp_d).scrollpos_x += vp->virtual_width >> 1;
00880 WP(w, vp_d).scrollpos_y += vp->virtual_height >> 1;
00881 WP(w, vp_d).dest_scrollpos_x = WP(w,vp_d).scrollpos_x;
00882 WP(w, vp_d).dest_scrollpos_y = WP(w,vp_d).scrollpos_y;
00883 break;
00884 case ZOOM_OUT:
00885 if (vp->zoom == ZOOM_LVL_MAX) return false;
00886 vp->zoom = (ZoomLevel)((int)vp->zoom + 1);
00887
00888 WP(w, vp_d).scrollpos_x -= vp->virtual_width >> 1;
00889 WP(w, vp_d).scrollpos_y -= vp->virtual_height >> 1;
00890 WP(w, vp_d).dest_scrollpos_x = WP(w,vp_d).scrollpos_x;
00891 WP(w, vp_d).dest_scrollpos_y = WP(w,vp_d).scrollpos_y;
00892
00893 vp->virtual_width <<= 1;
00894 vp->virtual_height <<= 1;
00895 break;
00896 }
00897 if (vp != NULL) {
00898 vp->virtual_left = WP(w, vp_d).scrollpos_x;
00899 vp->virtual_top = WP(w, vp_d).scrollpos_y;
00900 }
00901 SetWindowDirty(w);
00902
00903 SendWindowMessageClass(w->window_class, how, w->window_number, 0);
00904 return true;
00905 }
00906
00907 static void ToolbarZoomInClick(Window *w)
00908 {
00909 if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
00910 w->HandleButtonClick(17);
00911 SndPlayFx(SND_15_BEEP);
00912 }
00913 }
00914
00915 static void ToolbarZoomOutClick(Window *w)
00916 {
00917 if (DoZoomInOutWindow(ZOOM_OUT,FindWindowById(WC_MAIN_WINDOW, 0))) {
00918 w->HandleButtonClick(18);
00919 SndPlayFx(SND_15_BEEP);
00920 }
00921 }
00922
00923 static void ToolbarBuildRailClick(Window *w)
00924 {
00925 const Player *p = GetPlayer(_local_player);
00926 Window *w2 = PopupMainToolbMenu(w, 19, STR_1015_RAILROAD_CONSTRUCTION, RAILTYPE_END, ~p->avail_railtypes);
00927 WP(w2, menu_d).sel_index = _last_built_railtype;
00928 }
00929
00930 static void ToolbarBuildRoadClick(Window *w)
00931 {
00932 const Player *p = GetPlayer(_local_player);
00933
00934 Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 2, ~(p->avail_roadtypes | ROADTYPES_ROAD));
00935 WP(w2, menu_d).sel_index = _last_built_roadtype;
00936 }
00937
00938 static void ToolbarBuildWaterClick(Window *w)
00939 {
00940 PopupMainToolbMenu(w, 21, STR_9800_DOCK_CONSTRUCTION, 1, 0);
00941 }
00942
00943 static void ToolbarBuildAirClick(Window *w)
00944 {
00945 PopupMainToolbMenu(w, 22, STR_A01D_AIRPORT_CONSTRUCTION, 1, 0);
00946 }
00947
00948 static void ToolbarForestClick(Window *w)
00949 {
00950 PopupMainToolbMenu(w, 23, STR_LANDSCAPING, 3, 0);
00951 }
00952
00953 static void ToolbarMusicClick(Window *w)
00954 {
00955 PopupMainToolbMenu(w, 24, STR_01D3_SOUND_MUSIC, 1, 0);
00956 }
00957
00958 static void ToolbarNewspaperClick(Window *w)
00959 {
00960 PopupMainToolbMenu(w, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, 3, 0);
00961 }
00962
00963 static void ToolbarHelpClick(Window *w)
00964 {
00965 PopupMainToolbMenu(w, 26, STR_02D5_LAND_BLOCK_INFO, 6, 0);
00966 }
00967
00968 static void ToolbarOptionsClick(Window *w)
00969 {
00970 uint16 x = 0;
00971
00972 w = PopupMainToolbMenu(w, 2, STR_02C4_GAME_OPTIONS, 14, 0);
00973
00974 if (HasBit(_display_opt, DO_SHOW_TOWN_NAMES)) SetBit(x, 6);
00975 if (HasBit(_display_opt, DO_SHOW_STATION_NAMES)) SetBit(x, 7);
00976 if (HasBit(_display_opt, DO_SHOW_SIGNS)) SetBit(x, 8);
00977 if (HasBit(_display_opt, DO_WAYPOINTS)) SetBit(x, 9);
00978 if (HasBit(_display_opt, DO_FULL_ANIMATION)) SetBit(x, 10);
00979 if (HasBit(_display_opt, DO_FULL_DETAIL)) SetBit(x, 11);
00980 if (IsTransparencySet(TO_HOUSES)) SetBit(x, 12);
00981 if (IsTransparencySet(TO_SIGNS)) SetBit(x, 13);
00982 WP(w, menu_d).checked_items = x;
00983 }
00984
00985
00986 static void ToolbarScenSaveOrLoad(Window *w)
00987 {
00988 PopupMainToolbMenu(w, 3, STR_0292_SAVE_SCENARIO, 6, 0);
00989 }
00990
00991 static void ToolbarScenDateBackward(Window *w)
00992 {
00993
00994 if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
00995 w->HandleButtonClick(6);
00996 SetWindowDirty(w);
00997
00998 _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year - 1, MIN_YEAR, MAX_YEAR);
00999 SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
01000 }
01001 _left_button_clicked = false;
01002 }
01003
01004 static void ToolbarScenDateForward(Window *w)
01005 {
01006
01007 if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
01008 w->HandleButtonClick(7);
01009 SetWindowDirty(w);
01010
01011 _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + 1, MIN_YEAR, MAX_YEAR);
01012 SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
01013 }
01014 _left_button_clicked = false;
01015 }
01016
01017 static void ToolbarScenMapTownDir(Window *w)
01018 {
01019
01020 PopupMainToolbMenu(w, 8 | (17 << 8), STR_02DE_MAP_OF_WORLD, 4, 0);
01021 }
01022
01023 static void ToolbarScenZoomIn(Window *w)
01024 {
01025 if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
01026 w->HandleButtonClick(9);
01027 SndPlayFx(SND_15_BEEP);
01028 }
01029 }
01030
01031 static void ToolbarScenZoomOut(Window *w)
01032 {
01033 if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
01034 w->HandleButtonClick(10);
01035 SndPlayFx(SND_15_BEEP);
01036 }
01037 }
01038
01039 void ZoomInOrOutToCursorWindow(bool in, Window *w)
01040 {
01041 ViewPort *vp;
01042 Point pt;
01043
01044 assert(w != 0);
01045
01046 vp = w->viewport;
01047
01048 if (_game_mode != GM_MENU) {
01049 if ((in && vp->zoom == ZOOM_LVL_MIN) || (!in && vp->zoom == ZOOM_LVL_MAX))
01050 return;
01051
01052 pt = GetTileZoomCenterWindow(in,w);
01053 if (pt.x != -1) {
01054 ScrollWindowTo(pt.x, pt.y, w, true);
01055
01056 DoZoomInOutWindow(in ? ZOOM_IN : ZOOM_OUT, w);
01057 }
01058 }
01059 }
01060
01061 static void ToolbarScenGenLand(Window *w)
01062 {
01063 w->HandleButtonClick(11);
01064 SndPlayFx(SND_15_BEEP);
01065
01066 ShowEditorTerraformToolbar();
01067 }
01068
01069 void CcBuildTown(bool success, TileIndex tile, uint32 p1, uint32 p2)
01070 {
01071 if (success) {
01072 SndPlayTileFx(SND_1F_SPLAT, tile);
01073 ResetObjectToPlace();
01074 }
01075 }
01076
01077 static void PlaceProc_Town(TileIndex tile)
01078 {
01079 uint32 size = min(_scengen_town_size, (int)TSM_CITY);
01080 uint32 mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED;
01081 DoCommandP(tile, size, mode, CcBuildTown, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE));
01082 }
01083
01084
01085 static const Widget _scen_edit_town_gen_widgets[] = {
01086 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
01087 { WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_0233_TOWN_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
01088 { WWT_STICKYBOX, RESIZE_NONE, 7, 148, 159, 0, 13, 0x0, STR_STICKY_BUTTON},
01089 { WWT_PANEL, RESIZE_NONE, 7, 0, 159, 14, 94, 0x0, STR_NULL},
01090 { WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 16, 27, STR_0234_NEW_TOWN, STR_0235_CONSTRUCT_NEW_TOWN},
01091 { WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 29, 40, STR_023D_RANDOM_TOWN, STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION},
01092 { WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 42, 53, STR_MANY_RANDOM_TOWNS, STR_RANDOM_TOWNS_TIP},
01093 { WWT_TEXTBTN, RESIZE_NONE, 14, 2, 53, 68, 79, STR_02A1_SMALL, STR_02A4_SELECT_TOWN_SIZE},
01094 { WWT_TEXTBTN, RESIZE_NONE, 14, 54, 105, 68, 79, STR_02A2_MEDIUM, STR_02A4_SELECT_TOWN_SIZE},
01095 { WWT_TEXTBTN, RESIZE_NONE, 14, 106, 157, 68, 79, STR_02A3_LARGE, STR_02A4_SELECT_TOWN_SIZE},
01096 { WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 81, 92, STR_SCENARIO_EDITOR_CITY, STR_02A4_SELECT_TOWN_SIZE},
01097 { WWT_LABEL, RESIZE_NONE, 7, 0, 147, 54, 67, STR_02A5_TOWN_SIZE, STR_NULL},
01098 { WIDGETS_END},
01099 };
01100
01101 static void ScenEditTownGenWndProc(Window *w, WindowEvent *e)
01102 {
01103 switch (e->event) {
01104 case WE_PAINT:
01105 DrawWindowWidgets(w);
01106 break;
01107
01108 case WE_CREATE:
01109 w->LowerWidget(_scengen_town_size + 7);
01110 break;
01111
01112 case WE_CLICK:
01113 switch (e->we.click.widget) {
01114 case 4:
01115 HandlePlacePushButton(w, 4, SPR_CURSOR_TOWN, VHM_RECT, PlaceProc_Town);
01116 break;
01117 case 5: {
01118 Town *t;
01119 uint size = min(_scengen_town_size, (int)TSM_CITY);
01120 TownSizeMode mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED;
01121
01122 w->HandleButtonClick(5);
01123 _generating_world = true;
01124 t = CreateRandomTown(20, mode, size);
01125 _generating_world = false;
01126
01127 if (t == NULL) {
01128 ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0);
01129 } else {
01130 ScrollMainWindowToTile(t->xy);
01131 }
01132
01133 break;
01134 }
01135 case 6: {
01136 w->HandleButtonClick(6);
01137
01138 _generating_world = true;
01139 if (!GenerateTowns()) ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0);
01140 _generating_world = false;
01141 break;
01142 }
01143
01144 case 7: case 8: case 9: case 10:
01145 w->RaiseWidget(_scengen_town_size + 7);
01146 _scengen_town_size = e->we.click.widget - 7;
01147 w->LowerWidget(_scengen_town_size + 7);
01148 SetWindowDirty(w);
01149 break;
01150 }
01151 break;
01152
01153 case WE_TIMEOUT:
01154 w->RaiseWidget(5);
01155 w->RaiseWidget(6);
01156 SetWindowDirty(w);
01157 break;
01158 case WE_PLACE_OBJ:
01159 _place_proc(e->we.place.tile);
01160 break;
01161 case WE_ABORT_PLACE_OBJ:
01162 w->RaiseButtons();
01163 w->LowerWidget(_scengen_town_size + 7);
01164 SetWindowDirty(w);
01165 break;
01166 }
01167 }
01168
01169 static const WindowDesc _scen_edit_town_gen_desc = {
01170 WDP_AUTO, WDP_AUTO, 160, 95, 160, 95,
01171 WC_SCEN_TOWN_GEN, WC_NONE,
01172 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
01173 _scen_edit_town_gen_widgets,
01174 ScenEditTownGenWndProc,
01175 };
01176
01177 static void ToolbarScenGenTown(Window *w)
01178 {
01179 w->HandleButtonClick(12);
01180 SndPlayFx(SND_15_BEEP);
01181
01182 AllocateWindowDescFront(&_scen_edit_town_gen_desc, 0);
01183 }
01184
01185 static void ToolbarScenGenIndustry(Window *w)
01186 {
01187 w->HandleButtonClick(13);
01188 SndPlayFx(SND_15_BEEP);
01189 ShowBuildIndustryWindow();
01190 }
01191
01192 static void ToolbarScenBuildRoad(Window *w)
01193 {
01194 w->HandleButtonClick(14);
01195 SndPlayFx(SND_15_BEEP);
01196 ShowBuildRoadScenToolbar();
01197 }
01198
01199 static void ToolbarScenPlantTrees(Window *w)
01200 {
01201 w->HandleButtonClick(15);
01202 SndPlayFx(SND_15_BEEP);
01203 ShowBuildTreesScenToolbar();
01204 }
01205
01206 static void ToolbarScenPlaceSign(Window *w)
01207 {
01208 w->HandleButtonClick(16);
01209 SndPlayFx(SND_15_BEEP);
01210 SelectSignTool();
01211 }
01212
01213 static void ToolbarBtn_NULL(Window *w)
01214 {
01215 }
01216
01217
01218 typedef void ToolbarButtonProc(Window *w);
01219
01220 static ToolbarButtonProc * const _toolbar_button_procs[] = {
01221 ToolbarPauseClick,
01222 ToolbarFastForwardClick,
01223 ToolbarOptionsClick,
01224 ToolbarSaveClick,
01225 ToolbarMapClick,
01226 ToolbarTownClick,
01227 ToolbarSubsidiesClick,
01228 ToolbarStationsClick,
01229 ToolbarMoneyClick,
01230 ToolbarPlayersClick,
01231 ToolbarGraphsClick,
01232 ToolbarLeagueClick,
01233 ToolbarIndustryClick,
01234 ToolbarTrainClick,
01235 ToolbarRoadClick,
01236 ToolbarShipClick,
01237 ToolbarAirClick,
01238 ToolbarZoomInClick,
01239 ToolbarZoomOutClick,
01240 ToolbarBuildRailClick,
01241 ToolbarBuildRoadClick,
01242 ToolbarBuildWaterClick,
01243 ToolbarBuildAirClick,
01244 ToolbarForestClick,
01245 ToolbarMusicClick,
01246 ToolbarNewspaperClick,
01247 ToolbarHelpClick,
01248 };
01249
01250 static void MainToolbarWndProc(Window *w, WindowEvent *e)
01251 {
01252 switch (e->event) {
01253 case WE_PAINT:
01254
01255 GfxFillRect(0, 0, w->width-1, w->height-1, 0xB2);
01256 GfxFillRect(0, 0, w->width-1, w->height-1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
01257
01258
01259
01260
01261 w->SetWidgetsDisabledState(_current_player == PLAYER_SPECTATOR, 19, 20, 21, 22, 23, WIDGET_LIST_END);
01262
01263 w->SetWidgetsDisabledState(ActivePlayerCount() == 0, 7, 8, 13, 14, 15, 16, WIDGET_LIST_END);
01264
01265 w->SetWidgetDisabledState(19, !CanBuildVehicleInfrastructure(VEH_TRAIN));
01266 w->SetWidgetDisabledState(22, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
01267
01268 DrawWindowWidgets(w);
01269 break;
01270
01271 case WE_CLICK: {
01272 if (_game_mode != GM_MENU && !w->IsWidgetDisabled(e->we.click.widget))
01273 _toolbar_button_procs[e->we.click.widget](w);
01274 } break;
01275
01276 case WE_KEYPRESS: {
01277 switch (e->we.keypress.keycode) {
01278 case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(w); break;
01279 case WKC_F2: ShowGameOptions(); break;
01280 case WKC_F3: MenuClickSaveLoad(0); break;
01281 case WKC_F4: ShowSmallMap(); break;
01282 case WKC_F5: ShowTownDirectory(); break;
01283 case WKC_F6: ShowSubsidiesList(); break;
01284 case WKC_F7: ShowPlayerStations(_local_player); break;
01285 case WKC_F8: ShowPlayerFinances(_local_player); break;
01286 case WKC_F9: ShowPlayerCompany(_local_player); break;
01287 case WKC_F10: ShowOperatingProfitGraph(); break;
01288 case WKC_F11: ShowCompanyLeagueTable(); break;
01289 case WKC_F12: ShowBuildIndustryWindow(); break;
01290 case WKC_SHIFT | WKC_F1: ShowVehicleListWindow(_local_player, VEH_TRAIN); break;
01291 case WKC_SHIFT | WKC_F2: ShowVehicleListWindow(_local_player, VEH_ROAD); break;
01292 case WKC_SHIFT | WKC_F3: ShowVehicleListWindow(_local_player, VEH_SHIP); break;
01293 case WKC_SHIFT | WKC_F4: ShowVehicleListWindow(_local_player, VEH_AIRCRAFT); break;
01294 case WKC_NUM_PLUS:
01295 case WKC_EQUALS:
01296 case WKC_SHIFT | WKC_EQUALS:
01297 case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break;
01298 case WKC_NUM_MINUS:
01299 case WKC_MINUS:
01300 case WKC_SHIFT | WKC_MINUS:
01301 case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break;
01302 case WKC_SHIFT | WKC_F7: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, -1); break;
01303 case WKC_SHIFT | WKC_F8: ShowBuildRoadToolbar(_last_built_roadtype); break;
01304 case WKC_SHIFT | WKC_F9: ShowBuildDocksToolbar(); break;
01305 case WKC_SHIFT | WKC_F10: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
01306 case WKC_SHIFT | WKC_F11: ShowBuildTreesToolbar(); break;
01307 case WKC_SHIFT | WKC_F12: ShowMusicWindow(); break;
01308 case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break;
01309 case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break;
01310 case WKC_CTRL | WKC_ALT | 'C': if (!_networking) ShowCheatWindow(); break;
01311 case 'A': if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, 4); break;
01312 case 'L': ShowTerraformToolbar(); break;
01313 case 'M': ShowSmallMap(); break;
01314 case 'V': ShowExtraViewPortWindow(); break;
01315 default: return;
01316 }
01317 e->we.keypress.cont = false;
01318 } break;
01319
01320 case WE_PLACE_OBJ: {
01321 _place_proc(e->we.place.tile);
01322 } break;
01323
01324 case WE_ABORT_PLACE_OBJ: {
01325 w->RaiseWidget(25);
01326 SetWindowDirty(w);
01327 } break;
01328
01329 case WE_MOUSELOOP:
01330 if (w->IsWidgetLowered(0) != !!_pause_game) {
01331 w->ToggleWidgetLoweredState(0);
01332 w->InvalidateWidget(0);
01333 }
01334
01335 if (w->IsWidgetLowered(1) != !!_fast_forward) {
01336 w->ToggleWidgetLoweredState(1);
01337 w->InvalidateWidget(1);
01338 }
01339 break;
01340
01341 case WE_RESIZE: {
01342
01343 uint button_width;
01344 uint spacing;
01345 if (w->width >= 27 * 22) {
01346 button_width = 22;
01347 spacing = w->width - (27 * button_width);
01348 } else {
01349 button_width = w->width / 27;
01350 spacing = 0;
01351 }
01352 uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 };
01353
01354 for (uint i = 0, x = 0, j = 0; i < 27; i++) {
01355 if (extra_spacing_at[j] == i) {
01356 j++;
01357 uint add = spacing / (lengthof(extra_spacing_at) - j);
01358 spacing -= add;
01359 x += add;
01360 }
01361
01362 w->widget[i].left = x;
01363 x += (spacing != 0) ? button_width : (w->width - x) / (27 - i);
01364 w->widget[i].right = x - 1;
01365 }
01366 } break;
01367
01368 case WE_TIMEOUT: {
01369 uint i;
01370 for (i = 2; i < w->widget_count; i++) {
01371 if (w->IsWidgetLowered(i)) {
01372 w->RaiseWidget(i);
01373 w->InvalidateWidget(i);
01374 }
01375 }
01376 break;
01377 }
01378
01379 case WE_MESSAGE:
01380 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(w, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 17, 18);
01381 break;
01382 }
01383 }
01384
01385 static const Widget _toolb_normal_widgets[] = {
01386 { WWT_IMGBTN, RESIZE_LEFT, 14, 0, 0, 0, 21, SPR_IMG_PAUSE, STR_0171_PAUSE_GAME},
01387 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_FASTFORWARD, STR_FAST_FORWARD},
01388 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SETTINGS, STR_0187_OPTIONS},
01389 { WWT_IMGBTN_2, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SAVE, STR_0172_SAVE_GAME_ABANDON_GAME},
01390
01391 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SMALLMAP, STR_0174_DISPLAY_MAP},
01392 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_TOWN, STR_0176_DISPLAY_TOWN_DIRECTORY},
01393 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SUBSIDIES, STR_02DC_DISPLAY_SUBSIDIES},
01394 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_COMPANY_LIST, STR_0173_DISPLAY_LIST_OF_COMPANY},
01395
01396 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_COMPANY_FINANCE, STR_0177_DISPLAY_COMPANY_FINANCES},
01397 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_COMPANY_GENERAL, STR_0178_DISPLAY_COMPANY_GENERAL},
01398 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_GRAPHS, STR_0179_DISPLAY_GRAPHS},
01399 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_COMPANY_LEAGUE, STR_017A_DISPLAY_COMPANY_LEAGUE},
01400 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_INDUSTRY, STR_0312_FUND_CONSTRUCTION_OF_NEW},
01401
01402 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_TRAINLIST, STR_017B_DISPLAY_LIST_OF_COMPANY},
01403 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_TRUCKLIST, STR_017C_DISPLAY_LIST_OF_COMPANY},
01404 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SHIPLIST, STR_017D_DISPLAY_LIST_OF_COMPANY},
01405 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_AIRPLANESLIST, STR_017E_DISPLAY_LIST_OF_COMPANY},
01406
01407 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_ZOOMIN, STR_017F_ZOOM_THE_VIEW_IN},
01408 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_ZOOMOUT, STR_0180_ZOOM_THE_VIEW_OUT},
01409
01410 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDRAIL, STR_0181_BUILD_RAILROAD_TRACK},
01411 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDROAD, STR_0182_BUILD_ROADS},
01412 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDWATER, STR_0183_BUILD_SHIP_DOCKS},
01413 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDAIR, STR_0184_BUILD_AIRPORTS},
01414 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
01415
01416 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_MUSIC, STR_01D4_SHOW_SOUND_MUSIC_WINDOW},
01417 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_MESSAGES, STR_0203_SHOW_LAST_MESSAGE_NEWS},
01418 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_QUERY, STR_0186_LAND_BLOCK_INFORMATION},
01419 { WIDGETS_END},
01420 };
01421
01422 static const WindowDesc _toolb_normal_desc = {
01423 0, 0, 0, 22, 640, 22,
01424 WC_MAIN_TOOLBAR, WC_NONE,
01425 WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
01426 _toolb_normal_widgets,
01427 MainToolbarWndProc
01428 };
01429
01430
01431 static const Widget _toolb_scen_widgets[] = {
01432 { WWT_IMGBTN, RESIZE_LEFT, 14, 0, 0, 0, 21, SPR_IMG_PAUSE, STR_0171_PAUSE_GAME},
01433 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_FASTFORWARD, STR_FAST_FORWARD},
01434 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SETTINGS, STR_0187_OPTIONS},
01435 {WWT_IMGBTN_2, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SAVE, STR_0297_SAVE_SCENARIO_LOAD_SCENARIO},
01436
01437 { WWT_PANEL, RESIZE_NONE, 14, 0, 0, 0, 21, 0x0, STR_NULL},
01438
01439 { WWT_PANEL, RESIZE_NONE, 14, 0, 129, 0, 21, 0x0, STR_NULL},
01440 { WWT_IMGBTN, RESIZE_NONE, 14, 3, 14, 5, 16, SPR_ARROW_DOWN, STR_029E_MOVE_THE_STARTING_DATE},
01441 { WWT_IMGBTN, RESIZE_NONE, 14, 113, 125, 5, 16, SPR_ARROW_UP, STR_029F_MOVE_THE_STARTING_DATE},
01442
01443 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SMALLMAP, STR_0175_DISPLAY_MAP_TOWN_DIRECTORY},
01444
01445 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_ZOOMIN, STR_017F_ZOOM_THE_VIEW_IN},
01446 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_ZOOMOUT, STR_0180_ZOOM_THE_VIEW_OUT},
01447
01448 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_LANDSCAPING, STR_022E_LANDSCAPE_GENERATION},
01449 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_TOWN, STR_022F_TOWN_GENERATION},
01450 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_INDUSTRY, STR_0230_INDUSTRY_GENERATION},
01451 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDROAD, STR_0231_ROAD_CONSTRUCTION},
01452 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_PLANTTREES, STR_0288_PLANT_TREES},
01453 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SIGN, STR_0289_PLACE_SIGN},
01454
01455 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
01456 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
01457 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
01458 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
01459 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
01460 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
01461 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
01462 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_MUSIC, STR_01D4_SHOW_SOUND_MUSIC_WINDOW},
01463 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
01464 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_QUERY, STR_0186_LAND_BLOCK_INFORMATION},
01465 {WIDGETS_END},
01466 };
01467
01468 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
01469 ToolbarPauseClick,
01470 ToolbarFastForwardClick,
01471 ToolbarOptionsClick,
01472 ToolbarScenSaveOrLoad,
01473 ToolbarBtn_NULL,
01474 ToolbarBtn_NULL,
01475 ToolbarScenDateBackward,
01476 ToolbarScenDateForward,
01477 ToolbarScenMapTownDir,
01478 ToolbarScenZoomIn,
01479 ToolbarScenZoomOut,
01480 ToolbarScenGenLand,
01481 ToolbarScenGenTown,
01482 ToolbarScenGenIndustry,
01483 ToolbarScenBuildRoad,
01484 ToolbarScenPlantTrees,
01485 ToolbarScenPlaceSign,
01486 NULL,
01487 NULL,
01488 NULL,
01489 NULL,
01490 NULL,
01491 NULL,
01492 NULL,
01493 ToolbarMusicClick,
01494 NULL,
01495 ToolbarHelpClick,
01496 };
01497
01498 static void ScenEditToolbarWndProc(Window *w, WindowEvent *e)
01499 {
01500 switch (e->event) {
01501 case WE_PAINT:
01502 w->SetWidgetDisabledState(6, _patches_newgame.starting_year <= MIN_YEAR);
01503 w->SetWidgetDisabledState(7, _patches_newgame.starting_year >= MAX_YEAR);
01504
01505
01506 GfxFillRect(0, 0, w->width-1, w->height-1, 0xB2);
01507 GfxFillRect(0, 0, w->width-1, w->height-1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
01508
01509 DrawWindowWidgets(w);
01510
01511 SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
01512 DrawStringCenteredTruncated(w->widget[6].right, w->widget[7].left, 6, STR_00AF, TC_FROMSTRING);
01513
01514
01515 if (w->widget[4].left != w->widget[4].right) {
01516 DrawStringCenteredTruncated(w->widget[4].left + 1, w->widget[4].right - 1, 1, STR_0221_OPENTTD, TC_FROMSTRING);
01517 DrawStringCenteredTruncated(w->widget[4].left + 1, w->widget[4].right - 1, 11, STR_0222_SCENARIO_EDITOR, TC_FROMSTRING);
01518 }
01519
01520 break;
01521
01522 case WE_CLICK: {
01523 if (_game_mode == GM_MENU) return;
01524 _scen_toolbar_button_procs[e->we.click.widget](w);
01525 } break;
01526
01527 case WE_KEYPRESS:
01528 switch (e->we.keypress.keycode) {
01529 case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(w); break;
01530 case WKC_F2: ShowGameOptions(); break;
01531 case WKC_F3: MenuClickSaveLoad(0); break;
01532 case WKC_F4: ToolbarScenGenLand(w); break;
01533 case WKC_F5: ToolbarScenGenTown(w); break;
01534 case WKC_F6: ToolbarScenGenIndustry(w); break;
01535 case WKC_F7: ToolbarScenBuildRoad(w); break;
01536 case WKC_F8: ToolbarScenPlantTrees(w); break;
01537 case WKC_F9: ToolbarScenPlaceSign(w); break;
01538 case WKC_F10: ShowMusicWindow(); break;
01539 case WKC_F11: PlaceLandBlockInfo(); break;
01540 case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break;
01541 case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break;
01542
01543
01544 case WKC_NUM_PLUS:
01545 case WKC_EQUALS:
01546 case WKC_SHIFT | WKC_EQUALS:
01547 case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break;
01548
01549
01550 case WKC_NUM_MINUS:
01551 case WKC_MINUS:
01552 case WKC_SHIFT | WKC_MINUS:
01553 case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break;
01554
01555 case 'L': ShowEditorTerraformToolbar(); break;
01556 case 'M': ShowSmallMap(); break;
01557 case 'V': ShowExtraViewPortWindow(); break;
01558 default: return;
01559 }
01560 e->we.keypress.cont = false;
01561 break;
01562
01563 case WE_PLACE_OBJ: {
01564 _place_proc(e->we.place.tile);
01565 } break;
01566
01567 case WE_ABORT_PLACE_OBJ: {
01568 w->RaiseWidget(25);
01569 SetWindowDirty(w);
01570 } break;
01571
01572 case WE_RESIZE: {
01573
01574
01575
01576 uint buttons_width;
01577 uint spacing;
01578
01579 static int normal_min_width = (15 * 22) + (2 * 130);
01580 static int one_less_panel_min_width = (15 * 22) + 130;
01581
01582 if (w->width >= one_less_panel_min_width) {
01583 buttons_width = 15 * 22;
01584 spacing = w->width - ((w->width >= normal_min_width) ? normal_min_width : one_less_panel_min_width);
01585 } else {
01586 buttons_width = w->width - 130;
01587 spacing = 0;
01588 }
01589 uint extra_spacing_at[] = { 3, 4, 7, 8, 10, 16, 0 };
01590
01591
01592 for (uint i = 0, x = 0, j = 0, b = 0; i < 27; i++) {
01593 switch (i) {
01594 case 4:
01595 w->widget[i].left = x;
01596 if (w->width < normal_min_width) {
01597 w->widget[i].right = x;
01598 j++;
01599 continue;
01600 }
01601
01602 x += 130;
01603 w->widget[i].right = x - 1;
01604 break;
01605
01606 case 5: {
01607 int offset = x - w->widget[i].left;
01608 w->widget[i + 1].left += offset;
01609 w->widget[i + 1].right += offset;
01610 w->widget[i + 2].left += offset;
01611 w->widget[i + 2].right += offset;
01612 w->widget[i].left = x;
01613 x += 130;
01614 w->widget[i].right = x - 1;
01615 i += 2;
01616 } break;
01617
01618 default:
01619 if (w->widget[i].bottom == 0) continue;
01620
01621 w->widget[i].left = x;
01622 x += buttons_width / (15 - b);
01623 w->widget[i].right = x - 1;
01624 buttons_width -= buttons_width / (15 - b);
01625 b++;
01626 break;
01627 }
01628
01629 if (extra_spacing_at[j] == i) {
01630 j++;
01631 uint add = spacing / (lengthof(extra_spacing_at) - j);
01632 spacing -= add;
01633 x += add;
01634 }
01635 }
01636 } break;
01637
01638 case WE_MOUSELOOP:
01639 if (w->IsWidgetLowered(0) != !!_pause_game) {
01640 w->ToggleWidgetLoweredState(0);
01641 SetWindowDirty(w);
01642 }
01643
01644 if (w->IsWidgetLowered(1) != !!_fast_forward) {
01645 w->ToggleWidgetLoweredState(1);
01646 SetWindowDirty(w);
01647 }
01648 break;
01649
01650 case WE_MESSAGE:
01651 HandleZoomMessage(w, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 9, 10);
01652 break;
01653 }
01654 }
01655
01656 static const WindowDesc _toolb_scen_desc = {
01657 0, 0, 130, 22, 640, 22,
01658 WC_MAIN_TOOLBAR, WC_NONE,
01659 WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
01660 _toolb_scen_widgets,
01661 ScenEditToolbarWndProc
01662 };
01663
01664 extern GetNewsStringCallbackProc * const _get_news_string_callback[];
01665
01666
01667 static bool DrawScrollingStatusText(const NewsItem *ni, int pos, int width)
01668 {
01669 char buf[512];
01670 StringID str;
01671 const char *s, *last;
01672 char *d;
01673 DrawPixelInfo tmp_dpi, *old_dpi;
01674 int x;
01675 char buffer[256];
01676
01677 if (ni->display_mode == NM_CALLBACK) {
01678 str = _get_news_string_callback[ni->callback](ni);
01679 } else {
01680 CopyInDParam(0, ni->params, lengthof(ni->params));
01681 str = ni->string_id;
01682 }
01683
01684 GetString(buf, str, lastof(buf));
01685
01686 s = buf;
01687 d = buffer;
01688 last = lastof(buffer);
01689
01690 for (;;) {
01691 WChar c = Utf8Consume(&s);
01692 if (c == 0) {
01693 break;
01694 } else if (c == 0x0D) {
01695 if (d + 4 >= last) break;
01696 d[0] = d[1] = d[2] = d[3] = ' ';
01697 d += 4;
01698 } else if (IsPrintable(c)) {
01699 if (d + Utf8CharLen(c) >= last) break;
01700 d += Utf8Encode(d, c);
01701 }
01702 }
01703 *d = '\0';
01704
01705 if (!FillDrawPixelInfo(&tmp_dpi, 141, 1, width, 11)) return true;
01706
01707 old_dpi = _cur_dpi;
01708 _cur_dpi = &tmp_dpi;
01709
01710 x = DoDrawString(buffer, pos, 0, TC_LIGHT_BLUE);
01711 _cur_dpi = old_dpi;
01712
01713 return x > 0;
01714 }
01715
01716 static void StatusBarWndProc(Window *w, WindowEvent *e)
01717 {
01718 switch (e->event) {
01719 case WE_PAINT: {
01720 const Player *p = (_local_player == PLAYER_SPECTATOR) ? NULL : GetPlayer(_local_player);
01721
01722 DrawWindowWidgets(w);
01723 SetDParam(0, _date);
01724 DrawStringCentered(
01725 70, 1, (_pause_game || _patches.status_long_date) ? STR_00AF : STR_00AE, TC_FROMSTRING
01726 );
01727
01728 if (p != NULL) {
01729
01730 SetDParam(0, p->player_money);
01731 DrawStringCentered(w->widget[2].left + 70, 1, STR_0004, TC_FROMSTRING);
01732 }
01733
01734
01735 if (w->message.msg) {
01736 DrawStringCenteredTruncated(w->widget[1].left + 1, w->widget[1].right - 1, 1, STR_SAVING_GAME, TC_FROMSTRING);
01737 } else if (_do_autosave) {
01738 DrawStringCenteredTruncated(w->widget[1].left + 1, w->widget[1].right - 1, 1, STR_032F_AUTOSAVE, TC_FROMSTRING);
01739 } else if (_pause_game) {
01740 DrawStringCenteredTruncated(w->widget[1].left + 1, w->widget[1].right - 1, 1, STR_0319_PAUSED, TC_FROMSTRING);
01741 } else if (WP(w, def_d).data_1 > -1280 && FindWindowById(WC_NEWS_WINDOW,0) == NULL && _statusbar_news_item.string_id != 0) {
01742
01743 if (!DrawScrollingStatusText(&_statusbar_news_item, WP(w, def_d).data_1, w->widget[1].right - w->widget[1].left - 2)) {
01744 WP(w, def_d).data_1 = -1280;
01745 if (p != NULL) {
01746
01747 SetDParam(0, p->index);
01748 DrawStringCenteredTruncated(w->widget[1].left + 1, w->widget[1].right - 1, 1, STR_02BA, TC_FROMSTRING);
01749 }
01750 }
01751 } else {
01752 if (p != NULL) {
01753
01754 SetDParam(0, p->index);
01755 DrawStringCenteredTruncated(w->widget[1].left + 1, w->widget[1].right - 1, 1, STR_02BA, TC_FROMSTRING);
01756 }
01757 }
01758
01759 if (WP(w, def_d).data_2 > 0) DrawSprite(SPR_BLOT, PALETTE_TO_RED, w->widget[1].right - 11, 2);
01760 } break;
01761
01762 case WE_MESSAGE:
01763 w->message.msg = e->we.message.msg;
01764 SetWindowDirty(w);
01765 break;
01766
01767 case WE_CLICK:
01768 switch (e->we.click.widget) {
01769 case 1: ShowLastNewsMessage(); break;
01770 case 2: if (_local_player != PLAYER_SPECTATOR) ShowPlayerFinances(_local_player); break;
01771 default: ResetObjectToPlace();
01772 }
01773 break;
01774
01775 case WE_TICK: {
01776 if (_pause_game) return;
01777
01778 if (WP(w, def_d).data_1 > -1280) {
01779 WP(w, def_d).data_1 -= 2;
01780 w->InvalidateWidget(1);
01781 }
01782
01783 if (WP(w, def_d).data_2 > 0) {
01784 WP(w, def_d).data_2 -= 2;
01785 } else if (WP(w, def_d).data_2 < 0) {
01786 WP(w, def_d).data_2 = 0;
01787 w->InvalidateWidget(1);
01788 }
01789
01790 break;
01791 }
01792 }
01793 }
01794
01795 static const Widget _main_status_widgets[] = {
01796 { WWT_PANEL, RESIZE_NONE, 14, 0, 139, 0, 11, 0x0, STR_NULL},
01797 { WWT_PUSHBTN, RESIZE_RIGHT, 14, 140, 179, 0, 11, 0x0, STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS},
01798 { WWT_PUSHBTN, RESIZE_LR, 14, 180, 319, 0, 11, 0x0, STR_NULL},
01799 { WIDGETS_END},
01800 };
01801
01802 static WindowDesc _main_status_desc = {
01803 WDP_CENTER, 0, 320, 12, 640, 12,
01804 WC_STATUS_BAR, WC_NONE,
01805 WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
01806 _main_status_widgets,
01807 StatusBarWndProc
01808 };
01809
01810 extern void UpdateAllStationVirtCoord();
01811
01812 static void MainWindowWndProc(Window *w, WindowEvent *e)
01813 {
01814 int off_x;
01815
01816 switch (e->event) {
01817 case WE_PAINT:
01818 DrawWindowViewport(w);
01819 if (_game_mode == GM_MENU) {
01820 off_x = _screen.width / 2;
01821
01822 DrawSprite(SPR_OTTD_O, PAL_NONE, off_x - 120, 50);
01823 DrawSprite(SPR_OTTD_P, PAL_NONE, off_x - 86, 50);
01824 DrawSprite(SPR_OTTD_E, PAL_NONE, off_x - 53, 50);
01825 DrawSprite(SPR_OTTD_N, PAL_NONE, off_x - 22, 50);
01826
01827 DrawSprite(SPR_OTTD_T, PAL_NONE, off_x + 34, 50);
01828 DrawSprite(SPR_OTTD_T, PAL_NONE, off_x + 65, 50);
01829 DrawSprite(SPR_OTTD_D, PAL_NONE, off_x + 96, 50);
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848 }
01849 break;
01850
01851 case WE_KEYPRESS:
01852 switch (e->we.keypress.keycode) {
01853 case 'Q' | WKC_CTRL:
01854 case 'Q' | WKC_META:
01855 HandleExitGameRequest();
01856 break;
01857 }
01858
01859
01860
01861
01862
01863 if (IsGeneratingWorld()) break;
01864
01865 if (e->we.keypress.keycode == WKC_BACKQUOTE) {
01866 IConsoleSwitch();
01867 e->we.keypress.cont = false;
01868 break;
01869 }
01870
01871 if (e->we.keypress.keycode == ('B' | WKC_CTRL)) {
01872 e->we.keypress.cont = false;
01873 _draw_bounding_boxes = !_draw_bounding_boxes;
01874 MarkWholeScreenDirty();
01875 break;
01876 }
01877
01878 if (_game_mode == GM_MENU) break;
01879
01880 switch (e->we.keypress.keycode) {
01881 case 'C':
01882 case 'Z': {
01883 Point pt = GetTileBelowCursor();
01884 if (pt.x != -1) {
01885 if (e->we.keypress.keycode == 'Z') MaxZoomInOut(ZOOM_IN, w);
01886 ScrollMainWindowTo(pt.x, pt.y);
01887 }
01888 break;
01889 }
01890
01891 case WKC_ESC: ResetObjectToPlace(); break;
01892 case WKC_DELETE: DeleteNonVitalWindows(); break;
01893 case WKC_DELETE | WKC_SHIFT: DeleteAllNonVitalWindows(); break;
01894 case 'R' | WKC_CTRL: MarkWholeScreenDirty(); break;
01895
01896 #if defined(_DEBUG)
01897 case '0' | WKC_ALT:
01898 *(byte*)0 = 0;
01899 break;
01900
01901 case '1' | WKC_ALT:
01902
01903 if (!_networking || !_network_server || !_network_advertise)
01904 DoCommandP(0, 10000000, 0, NULL, CMD_MONEY_CHEAT);
01905 break;
01906
01907 case '2' | WKC_ALT:
01908 UpdateAllStationVirtCoord();
01909 break;
01910 #endif
01911
01912 case '1' | WKC_CTRL:
01913 case '2' | WKC_CTRL:
01914 case '3' | WKC_CTRL:
01915 case '4' | WKC_CTRL:
01916 case '5' | WKC_CTRL:
01917 case '6' | WKC_CTRL:
01918 case '7' | WKC_CTRL:
01919 case '8' | WKC_CTRL:
01920 case '9' | WKC_CTRL:
01921
01922 ToggleTransparency((TransparencyOption)(e->we.keypress.keycode - ('1' | WKC_CTRL)));
01923 MarkWholeScreenDirty();
01924 break;
01925
01926 case 'X' | WKC_CTRL:
01927 ShowTransparencyToolbar();
01928 break;
01929
01930 case 'X':
01931 ResetRestoreAllTransparency();
01932 break;
01933
01934 #ifdef ENABLE_NETWORK
01935 case WKC_RETURN: case 'T':
01936 if (_networking) {
01937 const NetworkClientInfo *cio = NetworkFindClientInfoFromIndex(_network_own_client_index);
01938 bool teamchat = false;
01939
01940 if (cio == NULL) break;
01941
01942
01943 if (_patches.prefer_teamchat && IsValidPlayer(cio->client_playas)) {
01944 const NetworkClientInfo *ci;
01945 FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
01946 if (ci->client_playas == cio->client_playas && ci != cio) {
01947 teamchat = true;
01948 break;
01949 }
01950 }
01951 }
01952
01953 ShowNetworkChatQueryWindow(teamchat ? DESTTYPE_TEAM : DESTTYPE_BROADCAST, cio->client_playas);
01954 }
01955 break;
01956
01957 case WKC_SHIFT | WKC_RETURN: case WKC_SHIFT | 'T':
01958 if (_networking) ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0);
01959 break;
01960
01961 case WKC_CTRL | WKC_RETURN: case WKC_CTRL | 'T':
01962 if (_networking) {
01963 const NetworkClientInfo *cio = NetworkFindClientInfoFromIndex(_network_own_client_index);
01964 if (cio == NULL) break;
01965
01966 ShowNetworkChatQueryWindow(DESTTYPE_TEAM, cio->client_playas);
01967 }
01968 break;
01969 #endif
01970
01971 default: return;
01972 }
01973 e->we.keypress.cont = false;
01974 break;
01975
01976 case WE_SCROLL: {
01977 ViewPort *vp = IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y);
01978
01979 if (vp == NULL) {
01980 _cursor.fix_at = false;
01981 _scrolling_viewport = false;
01982 }
01983
01984 WP(w, vp_d).scrollpos_x += ScaleByZoom(e->we.scroll.delta.x, vp->zoom);
01985 WP(w, vp_d).scrollpos_y += ScaleByZoom(e->we.scroll.delta.y, vp->zoom);
01986 WP(w, vp_d).dest_scrollpos_x = WP(w, vp_d).scrollpos_x;
01987 WP(w, vp_d).dest_scrollpos_y = WP(w, vp_d).scrollpos_y;
01988 } break;
01989
01990 case WE_MOUSEWHEEL:
01991 ZoomInOrOutToCursorWindow(e->we.wheel.wheel < 0, w);
01992 break;
01993
01994 case WE_MESSAGE:
01995
01996 SendWindowMessage(WC_MAIN_TOOLBAR, 0, e->we.message.msg, e->we.message.wparam, e->we.message.lparam);
01997 break;
01998 }
01999 }
02000
02001
02002 void ShowSelectGameWindow();
02003
02004 void SetupColorsAndInitialWindow()
02005 {
02006 uint i;
02007 Window *w;
02008 int width, height;
02009
02010 for (i = 0; i != 16; i++) {
02011 const byte *b = GetNonSprite(PALETTE_RECOLOR_START + i);
02012
02013 assert(b);
02014 memcpy(_colour_gradient[i], b + 0xC6, sizeof(_colour_gradient[i]));
02015 }
02016
02017 width = _screen.width;
02018 height = _screen.height;
02019
02020 w = AllocateWindow(0, 0, width, height, MainWindowWndProc, WC_MAIN_WINDOW, NULL);
02021 AssignWindowViewport(w, 0, 0, width, height, TileXY(32, 32), ZOOM_LVL_VIEWPORT);
02022
02023
02024 switch (_game_mode) {
02025 default: NOT_REACHED();
02026 case GM_MENU:
02027 ShowSelectGameWindow();
02028 break;
02029
02030 case GM_NORMAL:
02031 case GM_EDITOR:
02032 ShowVitalWindows();
02033 break;
02034 }
02035 }
02036
02037 void ShowVitalWindows()
02038 {
02039 Window *w;
02040
02041 w = AllocateWindowDesc((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc);
02042 DoZoomInOutWindow(ZOOM_NONE, w);
02043
02044 CLRBITS(w->flags4, WF_WHITE_BORDER_MASK);
02045
02046 w->SetWidgetDisabledState(0, _networking && !_network_server);
02047 w->SetWidgetDisabledState(1, _networking);
02048
02049
02050 PositionMainToolbar(w);
02051
02052
02053 if (_game_mode == GM_EDITOR) return;
02054
02055 _main_status_desc.top = _screen.height - 12;
02056 w = AllocateWindowDesc(&_main_status_desc);
02057 CLRBITS(w->flags4, WF_WHITE_BORDER_MASK);
02058
02059 WP(w, def_d).data_1 = -1280;
02060 }
02061
02062 void GameSizeChanged()
02063 {
02064 _cur_resolution[0] = _screen.width;
02065 _cur_resolution[1] = _screen.height;
02066 RelocateAllWindows(_screen.width, _screen.height);
02067 ScreenSizeChanged();
02068 MarkWholeScreenDirty();
02069 }
02070
02071 void InitializeMainGui()
02072 {
02073
02074 _last_built_railtype = RAILTYPE_RAIL;
02075 _last_built_roadtype = ROADTYPE_ROAD;
02076 }
02077
02078
02079
02080
02081