# terraform_gui.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "clear_map.h"
    00014 #include "company_func.h"
    00015 #include "company_base.h"
    00016 #include "gui.h"
    00017 #include "window_gui.h"
    00018 #include "window_func.h"
    00019 #include "viewport_func.h"
    00020 #include "command_func.h"
    00021 #include "signs_func.h"
    00022 #include "sound_func.h"
    00023 #include "base_station_base.h"
    00024 #include "textbuf_gui.h"
    00025 #include "genworld.h"
    00026 #include "tree_map.h"
    00027 #include "landscape_type.h"
    00028 #include "tilehighlight_func.h"
    00029 #include "strings_func.h"
    00030 #include "newgrf_object.h"
    00031 #include "object.h"
    00032 #include "hotkeys.h"
    00033 #include "engine_base.h"
    00034
    00035 #include "table/strings.h"
    00036
    00037 void CcTerraform(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
    00038 {
    00039   if (result.Succeeded()) {
    00040     SndPlayTileFx(SND_1F_SPLAT, tile);
    00041   } else {
    00042     extern TileIndex _terraform_err_tile;
    00043     SetRedErrorSquare(_terraform_err_tile);
    00044   }
    00045 }
    00046
    00047
    00049 static void GenerateDesertArea(TileIndex end, TileIndex start)
    00050 {
    00051   if (_game_mode != GM_EDITOR) return;
    00052
    00053   _generating_world = true;
    00054
    00055   TileArea ta(start, end);
    00056   TILE_AREA_LOOP(tile, ta) {
    00057     SetTropicZone(tile, (_ctrl_pressed) ? TROPICZONE_NORMAL : TROPICZONE_DESERT);
    00058     DoCommandP(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
    00059     MarkTileDirtyByTile(tile);
    00060   }
    00061   _generating_world = false;
    00062   InvalidateWindowClassesData(WC_TOWN_VIEW, 0);
    00063 }
    00064
    00066 static void GenerateRockyArea(TileIndex end, TileIndex start)
    00067 {
    00068   if (_game_mode != GM_EDITOR) return;
    00069
    00070   bool success = false;
    00071   TileArea ta(start, end);
    00072
    00073   TILE_AREA_LOOP(tile, ta) {
    00074     switch (GetTileType(tile)) {
    00075       case MP_TREES:
    00076         if (GetTreeGround(tile) == TREE_GROUND_SHORE) continue;
    00077         /* FALL THROUGH */
    00078       case MP_CLEAR:
    00079         MakeClear(tile, CLEAR_ROCKS, 3);
    00080         break;
    00081
    00082       default: continue;
    00083     }
    00084     MarkTileDirtyByTile(tile);
    00085     success = true;
    00086   }
    00087
    00088   if (success) SndPlayTileFx(SND_1F_SPLAT, end);
    00089 }
    00090
    00100 bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_tile, TileIndex end_tile)
    00101 {
    00102   if (!_settings_game.construction.freeform_edges) {
    00103     /* When end_tile is MP_VOID, the error tile will not be visible to the
    00104      * user. This happens when terraforming at the southern border. */
    00105     if (TileX(end_tile) == MapMaxX()) end_tile += TileDiffXY(-1, 0);
    00106     if (TileY(end_tile) == MapMaxY()) end_tile += TileDiffXY(0, -1);
    00107   }
    00108
    00109   switch (proc) {
    00110     case DDSP_DEMOLISH_AREA:
    00111       DoCommandP(end_tile, start_tile, _ctrl_pressed ? 1 : 0, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA), CcPlaySound10);
    00112       break;
    00113     case DDSP_RAISE_AND_LEVEL_AREA:
    00114       DoCommandP(end_tile, start_tile, LM_RAISE << 1 | (_ctrl_pressed ? 1 : 0), CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_RAISE_LAND_HERE), CcTerraform);
    00115       break;
    00116     case DDSP_LOWER_AND_LEVEL_AREA:
    00117       DoCommandP(end_tile, start_tile, LM_LOWER << 1 | (_ctrl_pressed ? 1 : 0), CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_LOWER_LAND_HERE), CcTerraform);
    00118       break;
    00119     case DDSP_LEVEL_AREA:
    00120       DoCommandP(end_tile, start_tile, LM_LEVEL << 1 | (_ctrl_pressed ? 1 : 0), CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_LEVEL_LAND_HERE), CcTerraform);
    00121       break;
    00122     case DDSP_CREATE_ROCKS:
    00123       GenerateRockyArea(end_tile, start_tile);
    00124       break;
    00125     case DDSP_CREATE_DESERT:
    00126       GenerateDesertArea(end_tile, start_tile);
    00127       break;
    00128     default:
    00129       return false;
    00130   }
    00131
    00132   return true;
    00133 }
    00134
    00139 void PlaceProc_DemolishArea(TileIndex tile)
    00140 {
    00141   VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_DEMOLISH_AREA);
    00142 }
    00143
    00145 enum TerraformToolbarWidgets {
    00146   TTW_SHOW_PLACE_OBJECT,
    00147   TTW_BUTTONS_START,
    00148   TTW_LOWER_LAND = TTW_BUTTONS_START,
    00149   TTW_RAISE_LAND,
    00150   TTW_LEVEL_LAND,
    00151   TTW_DEMOLISH,
    00152   TTW_BUY_LAND,
    00153   TTW_PLANT_TREES,
    00154   TTW_PLACE_SIGN,
    00155   TTW_PLACE_OBJECT,
    00156 };
    00157
    00159 struct TerraformToolbarWindow : Window {
    00160   int last_user_action;
    00161
    00162   TerraformToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
    00163   {
    00164     /* This is needed as we like to have the tree available on OnInit. */
    00165     this->CreateNestedTree(desc);
    00166     this->FinishInitNested(desc, window_number);
    00167     this->last_user_action = WIDGET_LIST_END;
    00168   }
    00169
    00170   ~TerraformToolbarWindow()
    00171   {
    00172   }
    00173
    00174   virtual void OnInit()
    00175   {
    00176     /* Don't show the place object button when there are no objects to place. */
    00177     NWidgetStacked *show_object = this->GetWidget<NWidgetStacked>(TTW_SHOW_PLACE_OBJECT);
    00178     show_object->SetDisplayedPlane(ObjectClass::GetCount() != 0 ? 0 : SZSP_NONE);
    00179   }
    00180
    00181   virtual void OnClick(Point pt, int widget, int click_count)
    00182   {
    00183     if (widget < TTW_BUTTONS_START) return;
    00184
    00185     switch (widget) {
    00186       case TTW_LOWER_LAND: // Lower land button
    00187         HandlePlacePushButton(this, TTW_LOWER_LAND, ANIMCURSOR_LOWERLAND, HT_POINT | HT_DIAGONAL);
    00188         this->last_user_action = widget;
    00189         break;
    00190
    00191       case TTW_RAISE_LAND: // Raise land button
    00192         HandlePlacePushButton(this, TTW_RAISE_LAND, ANIMCURSOR_RAISELAND, HT_POINT | HT_DIAGONAL);
    00193         this->last_user_action = widget;
    00194         break;
    00195
    00196       case TTW_LEVEL_LAND: // Level land button
    00197         HandlePlacePushButton(this, TTW_LEVEL_LAND, SPR_CURSOR_LEVEL_LAND, HT_POINT | HT_DIAGONAL);
    00198         this->last_user_action = widget;
    00199         break;
    00200
    00201       case TTW_DEMOLISH: // Demolish aka dynamite button
    00202         HandlePlacePushButton(this, TTW_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT | HT_DIAGONAL);
    00203         this->last_user_action = widget;
    00204         break;
    00205
    00206       case TTW_BUY_LAND: // Buy land button
    00207         HandlePlacePushButton(this, TTW_BUY_LAND, SPR_CURSOR_BUY_LAND, HT_RECT);
    00208         this->last_user_action = widget;
    00209         break;
    00210
    00211       case TTW_PLANT_TREES: // Plant trees button
    00212         /* This button is NOT a place-push-button, so don't treat it as such */
    00213         this->HandleButtonClick(TTW_PLANT_TREES);
    00214         ShowBuildTreesToolbar();
    00215         break;
    00216
    00217       case TTW_PLACE_SIGN: // Place sign button
    00218         HandlePlacePushButton(this, TTW_PLACE_SIGN, SPR_CURSOR_SIGN, HT_RECT);
    00219         this->last_user_action = widget;
    00220         break;
    00221
    00222       case TTW_PLACE_OBJECT: // Place object button
    00223         /* Don't show the place object button when there are no objects to place. */
    00224         if (ObjectClass::GetCount() == 0) return;
    00225         if (HandlePlacePushButton(this, TTW_PLACE_OBJECT, SPR_CURSOR_TRANSMITTER, HT_RECT)) {
    00226           ShowBuildObjectPicker(this);
    00227           this->last_user_action = widget;
    00228         }
    00229         break;
    00230
    00231       default: NOT_REACHED();
    00232     }
    00233   }
    00234
    00235   virtual void OnTimeout()
    00236   {
    00237     this->RaiseWidget(TTW_PLANT_TREES);
    00238     this->SetWidgetDirty(TTW_PLANT_TREES);
    00239   }
    00240
    00241   virtual EventState OnKeyPress(uint16 key, uint16 keycode)
    00242   {
    00243     int num = CheckHotkeyMatch(terraform_hotkeys, keycode, this);
    00244     if (num == -1) return ES_NOT_HANDLED;
    00245     this->OnClick(Point(), num, 1);
    00246     return ES_HANDLED;
    00247   }
    00248
    00249   virtual void OnPlaceObject(Point pt, TileIndex tile)
    00250   {
    00251     switch (this->last_user_action) {
    00252       case TTW_LOWER_LAND: // Lower land button
    00253         VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LOWER_AND_LEVEL_AREA);
    00254         break;
    00255
    00256       case TTW_RAISE_LAND: // Raise land button
    00257         VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_RAISE_AND_LEVEL_AREA);
    00258         break;
    00259
    00260       case TTW_LEVEL_LAND: // Level land button
    00261         VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LEVEL_AREA);
    00262         break;
    00263
    00264       case TTW_DEMOLISH: // Demolish aka dynamite button
    00265         PlaceProc_DemolishArea(tile);
    00266         break;
    00267
    00268       case TTW_BUY_LAND: // Buy land button
    00269         DoCommandP(tile, OBJECT_OWNED_LAND, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_PURCHASE_THIS_LAND), CcPlaySound1E);
    00270         break;
    00271
    00272       case TTW_PLACE_SIGN: // Place sign button
    00273         PlaceProc_Sign(tile);
    00274         break;
    00275
    00276       case TTW_PLACE_OBJECT: // Place object button
    00277         PlaceProc_Object(tile);
    00278         break;
    00279
    00280       default: NOT_REACHED();
    00281     }
    00282   }
    00283
    00284   virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
    00285   {
    00286     VpSelectTilesWithMethod(pt.x, pt.y, select_method);
    00287   }
    00288
    00289   virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number)
    00290   {
    00291     Point pt = GetToolbarAlignedWindowPosition(sm_width);
    00292     pt.y += sm_height;
    00293     return pt;
    00294   }
    00295
    00296   virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
    00297   {
    00298     if (pt.x != -1) {
    00299       switch (select_proc) {
    00300         default: NOT_REACHED();
    00301         case DDSP_DEMOLISH_AREA:
    00302         case DDSP_RAISE_AND_LEVEL_AREA:
    00303         case DDSP_LOWER_AND_LEVEL_AREA:
    00304         case DDSP_LEVEL_AREA:
    00305           GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
    00306           break;
    00307       }
    00308     }
    00309   }
    00310
    00311   virtual void OnPlaceObjectAbort()
    00312   {
    00313     DeleteWindowById(WC_BUILD_OBJECT, 0);
    00314     this->RaiseButtons();
    00315   }
    00316
    00317   static Hotkey<TerraformToolbarWindow> terraform_hotkeys[];
    00318 };
    00319
    00320 Hotkey<TerraformToolbarWindow> TerraformToolbarWindow::terraform_hotkeys[] = {
    00321   Hotkey<TerraformToolbarWindow>('Q' | WKC_GLOBAL_HOTKEY, "lower", TTW_LOWER_LAND),
    00322   Hotkey<TerraformToolbarWindow>('W' | WKC_GLOBAL_HOTKEY, "raise", TTW_RAISE_LAND),
    00323   Hotkey<TerraformToolbarWindow>('E' | WKC_GLOBAL_HOTKEY, "level", TTW_LEVEL_LAND),
    00324   Hotkey<TerraformToolbarWindow>('D' | WKC_GLOBAL_HOTKEY, "dynamite", TTW_DEMOLISH),
    00325   Hotkey<TerraformToolbarWindow>('U', "buyland", TTW_BUY_LAND),
    00326   Hotkey<TerraformToolbarWindow>('I', "trees", TTW_PLANT_TREES),
    00327   Hotkey<TerraformToolbarWindow>('O', "placesign", TTW_PLACE_SIGN),
    00328   Hotkey<TerraformToolbarWindow>('P', "placeobject", TTW_PLACE_OBJECT),
    00329   HOTKEY_LIST_END(TerraformToolbarWindow)
    00330 };
    00331 Hotkey<TerraformToolbarWindow> *_terraform_hotkeys = TerraformToolbarWindow::terraform_hotkeys;
    00332
    00333 static const NWidgetPart _nested_terraform_widgets[] = {
    00334   NWidget(NWID_HORIZONTAL),
    00335     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00336     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_LANDSCAPING_TOOLBAR, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00337     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00338   EndContainer(),
    00339   NWidget(NWID_HORIZONTAL),
    00340     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_LOWER_LAND), SetMinimalSize(22, 22),
    00341                 SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_DOWN, STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND),
    00342     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_RAISE_LAND), SetMinimalSize(22, 22),
    00343                 SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_UP, STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND),
    00344     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_LEVEL_LAND), SetMinimalSize(22, 22),
    00345                 SetFill(0, 1), SetDataTip(SPR_IMG_LEVEL_LAND, STR_LANDSCAPING_LEVEL_LAND_TOOLTIP),
    00346
    00347     NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),
    00348
    00349     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_DEMOLISH), SetMinimalSize(22, 22),
    00350                 SetFill(0, 1), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00351     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_BUY_LAND), SetMinimalSize(22, 22),
    00352                 SetFill(0, 1), SetDataTip(SPR_IMG_BUY_LAND, STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND),
    00353     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_PLANT_TREES), SetMinimalSize(22, 22),
    00354                 SetFill(0, 1), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
    00355     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_PLACE_SIGN), SetMinimalSize(22, 22),
    00356                 SetFill(0, 1), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
    00357     NWidget(NWID_SELECTION, INVALID_COLOUR, TTW_SHOW_PLACE_OBJECT),
    00358       NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_PLACE_OBJECT), SetMinimalSize(22, 22),
    00359                 SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER, STR_SCENEDIT_TOOLBAR_PLACE_OBJECT),
    00360     EndContainer(),
    00361   EndContainer(),
    00362 };
    00363
    00364 static const WindowDesc _terraform_desc(
    00365   WDP_MANUAL, 0, 0,
    00366   WC_SCEN_LAND_GEN, WC_NONE,
    00367   WDF_CONSTRUCTION,
    00368   _nested_terraform_widgets, lengthof(_nested_terraform_widgets)
    00369 );
    00370
    00371 Window *ShowTerraformToolbar(Window *link)
    00372 {
    00373   if (!Company::IsValidID(_local_company)) return NULL;
    00374
    00375   Window *w;
    00376   if (link == NULL) {
    00377     w = AllocateWindowDescFront<TerraformToolbarWindow>(&_terraform_desc, 0);
    00378     return w;
    00379   }
    00380
    00381   /* Delete the terraform toolbar to place it again. */
    00382   DeleteWindowById(WC_SCEN_LAND_GEN, 0, true);
    00383   w = AllocateWindowDescFront<TerraformToolbarWindow>(&_terraform_desc, 0);
    00384   /* Align the terraform toolbar under the main toolbar. */
    00385   w->top -= w->height;
    00386   w->SetDirty();
    00387   /* Put the linked toolbar to the left / right of it. */
    00388   link->left = w->left + (_current_text_dir == TD_RTL ? w->width : -link->width);
    00389   link->top  = w->top;
    00390   link->SetDirty();
    00391
    00392   return w;
    00393 }
    00394
    00395 EventState TerraformToolbarGlobalHotkeys(uint16 key, uint16 keycode)
    00396 {
    00397   int num = CheckHotkeyMatch<TerraformToolbarWindow>(_terraform_hotkeys, keycode, NULL, true);
    00398   if (num == -1) return ES_NOT_HANDLED;
    00399   Window *w = ShowTerraformToolbar(NULL);
    00400   if (w == NULL) return ES_NOT_HANDLED;
    00401   return w->OnKeyPress(key, keycode);
    00402 }
    00403
    00404 static byte _terraform_size = 1;
    00405
    00415 static void CommonRaiseLowerBigLand(TileIndex tile, int mode)
    00416 {
    00417   if (_terraform_size == 1) {
    00418     StringID msg =
    00419       mode ? STR_ERROR_CAN_T_RAISE_LAND_HERE : STR_ERROR_CAN_T_LOWER_LAND_HERE;
    00420
    00421     DoCommandP(tile, SLOPE_N, (uint32)mode, CMD_TERRAFORM_LAND | CMD_MSG(msg), CcTerraform);
    00422   } else {
    00423     assert(_terraform_size != 0);
    00424     TileArea ta(tile, _terraform_size, _terraform_size);
    00425     ta.ClampToMap();
    00426
    00427     if (ta.w == 0 || ta.h == 0) return;
    00428
    00429     SndPlayTileFx(SND_1F_SPLAT, tile);
    00430
    00431     uint h;
    00432     if (mode != 0) {
    00433       /* Raise land */
    00434       h = MAX_TILE_HEIGHT;
    00435       TILE_AREA_LOOP(tile2, ta) {
    00436         h = min(h, TileHeight(tile2));
    00437       }
    00438     } else {
    00439       /* Lower land */
    00440       h = 0;
    00441       TILE_AREA_LOOP(tile2, ta) {
    00442         h = max(h, TileHeight(tile2));
    00443       }
    00444     }
    00445
    00446     TILE_AREA_LOOP(tile2, ta) {
    00447       if (TileHeight(tile2) == h) {
    00448         DoCommandP(tile2, SLOPE_N, (uint32)mode, CMD_TERRAFORM_LAND);
    00449       }
    00450     }
    00451   }
    00452 }
    00453
    00454 static const int8 _multi_terraform_coords[][2] = {
    00455   {  0, -2},
    00456   {  4,  0}, { -4,  0}, {  0,  2},
    00457   { -8,  2}, { -4,  4}, {  0,  6}, {  4,  4}, {  8,  2},
    00458   {-12,  0}, { -8, -2}, { -4, -4}, {  0, -6}, {  4, -4}, {  8, -2}, { 12,  0},
    00459   {-16,  2}, {-12,  4}, { -8,  6}, { -4,  8}, {  0, 10}, {  4,  8}, {  8,  6}, { 12,  4}, { 16,  2},
    00460   {-20,  0}, {-16, -2}, {-12, -4}, { -8, -6}, { -4, -8}, {  0,-10}, {  4, -8}, {  8, -6}, { 12, -4}, { 16, -2}, { 20,  0},
    00461   {-24,  2}, {-20,  4}, {-16,  6}, {-12,  8}, { -8, 10}, { -4, 12}, {  0, 14}, {  4, 12}, {  8, 10}, { 12,  8}, { 16,  6}, { 20,  4}, { 24,  2},
    00462   {-28,  0}, {-24, -2}, {-20, -4}, {-16, -6}, {-12, -8}, { -8,-10}, { -4,-12}, {  0,-14}, {  4,-12}, {  8,-10}, { 12, -8}, { 16, -6}, { 20, -4}, { 24, -2}, { 28,  0},
    00463 };
    00464
    00466 enum EditorTerraformToolbarWidgets {
    00467   ETTW_SHOW_PLACE_DESERT,
    00468   ETTW_START,
    00469   ETTW_DOTS = ETTW_START,
    00470   ETTW_BUTTONS_START,
    00471   ETTW_DEMOLISH = ETTW_BUTTONS_START,
    00472   ETTW_LOWER_LAND,
    00473   ETTW_RAISE_LAND,
    00474   ETTW_LEVEL_LAND,
    00475   ETTW_PLACE_ROCKS,
    00476   ETTW_PLACE_DESERT,
    00477   ETTW_PLACE_OBJECT,
    00478   ETTW_BUTTONS_END,
    00479   ETTW_INCREASE_SIZE = ETTW_BUTTONS_END,
    00480   ETTW_DECREASE_SIZE,
    00481   ETTW_NEW_SCENARIO,
    00482   ETTW_RESET_LANDSCAPE,
    00483 };
    00484
    00485 static const NWidgetPart _nested_scen_edit_land_gen_widgets[] = {
    00486   NWidget(NWID_HORIZONTAL),
    00487     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00488     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00489     NWidget(WWT_SHADEBOX, COLOUR_DARK_GREEN),
    00490     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00491   EndContainer(),
    00492   NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
    00493     NWidget(NWID_HORIZONTAL), SetPadding(2, 2, 7, 2),
    00494       NWidget(NWID_SPACER), SetFill(1, 0),
    00495       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_DEMOLISH), SetMinimalSize(22, 22),
    00496                     SetFill(0, 1), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00497       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_LOWER_LAND), SetMinimalSize(22, 22),
    00498                     SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_DOWN, STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND),
    00499       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_RAISE_LAND), SetMinimalSize(22, 22),
    00500                     SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_UP, STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND),
    00501       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_LEVEL_LAND), SetMinimalSize(22, 22),
    00502                     SetFill(0, 1), SetDataTip(SPR_IMG_LEVEL_LAND, STR_LANDSCAPING_LEVEL_LAND_TOOLTIP),
    00503       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_PLACE_ROCKS), SetMinimalSize(22, 22),
    00504                     SetFill(0, 1), SetDataTip(SPR_IMG_ROCKS, STR_TERRAFORM_TOOLTIP_PLACE_ROCKY_AREAS_ON_LANDSCAPE),
    00505       NWidget(NWID_SELECTION, INVALID_COLOUR, ETTW_SHOW_PLACE_DESERT),
    00506         NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_PLACE_DESERT), SetMinimalSize(22, 22),
    00507                       SetFill(0, 1), SetDataTip(SPR_IMG_DESERT, STR_TERRAFORM_TOOLTIP_DEFINE_DESERT_AREA),
    00508       EndContainer(),
    00509       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_PLACE_OBJECT), SetMinimalSize(23, 22),
    00510                     SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER, STR_SCENEDIT_TOOLBAR_PLACE_OBJECT),
    00511       NWidget(NWID_SPACER), SetFill(1, 0),
    00512     EndContainer(),
    00513     NWidget(NWID_HORIZONTAL),
    00514       NWidget(NWID_SPACER), SetFill(1, 0),
    00515       NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, ETTW_DOTS), SetMinimalSize(59, 31), SetDataTip(STR_EMPTY, STR_NULL),
    00516       NWidget(NWID_SPACER), SetFill(1, 0),
    00517       NWidget(NWID_VERTICAL),
    00518         NWidget(NWID_SPACER), SetFill(0, 1),
    00519         NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_INCREASE_SIZE), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_UP, STR_TERRAFORM_TOOLTIP_INCREASE_SIZE_OF_LAND_AREA),
    00520         NWidget(NWID_SPACER), SetMinimalSize(0, 1),
    00521         NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_DECREASE_SIZE), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_DOWN, STR_TERRAFORM_TOOLTIP_DECREASE_SIZE_OF_LAND_AREA),
    00522         NWidget(NWID_SPACER), SetFill(0, 1),
    00523       EndContainer(),
    00524       NWidget(NWID_SPACER), SetMinimalSize(2, 0),
    00525     EndContainer(),
    00526     NWidget(NWID_SPACER), SetMinimalSize(0, 6),
    00527     NWidget(WWT_TEXTBTN, COLOUR_GREY, ETTW_NEW_SCENARIO), SetMinimalSize(160, 12),
    00528                 SetFill(1, 0), SetDataTip(STR_TERRAFORM_SE_NEW_WORLD, STR_TERRAFORM_TOOLTIP_GENERATE_RANDOM_LAND), SetPadding(0, 2, 0, 2),
    00529     NWidget(WWT_TEXTBTN, COLOUR_GREY, ETTW_RESET_LANDSCAPE), SetMinimalSize(160, 12),
    00530                 SetFill(1, 0), SetDataTip(STR_TERRAFORM_RESET_LANDSCAPE, STR_TERRAFORM_RESET_LANDSCAPE_TOOLTIP), SetPadding(1, 2, 2, 2),
    00531   EndContainer(),
    00532 };
    00533
    00539 static void ResetLandscapeConfirmationCallback(Window *w, bool confirmed)
    00540 {
    00541   if (confirmed) {
    00542     /* Set generating_world to true to get instant-green grass after removing
    00543      * company property. */
    00544     _generating_world = true;
    00545
    00546     /* Delete all companies */
    00547     Company *c;
    00548     FOR_ALL_COMPANIES(c) {
    00549       ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
    00550       delete c;
    00551     }
    00552
    00553     _generating_world = false;
    00554
    00555     /* Delete all station signs */
    00556     BaseStation *st;
    00557     FOR_ALL_BASE_STATIONS(st) {
    00558       /* There can be buoys, remove them */
    00559       if (IsBuoyTile(st->xy)) DoCommand(st->xy, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
    00560       if (!st->IsInUse()) delete st;
    00561     }
    00562
    00563     /* Now that all vehicles are gone, we can reset the engine pool. Maybe it reduces some NewGRF changing-mess */
    00564     EngineOverrideManager::ResetToCurrentNewGRFConfig();
    00565
    00566     MarkWholeScreenDirty();
    00567   }
    00568 }
    00569
    00571 struct ScenarioEditorLandscapeGenerationWindow : Window {
    00572   int last_user_action;
    00573
    00574   ScenarioEditorLandscapeGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
    00575   {
    00576     this->CreateNestedTree(desc);
    00577     NWidgetStacked *show_desert = this->GetWidget<NWidgetStacked>(ETTW_SHOW_PLACE_DESERT);
    00578     show_desert->SetDisplayedPlane(_settings_game.game_creation.landscape == LT_TROPIC ? 0 : SZSP_NONE);
    00579     this->FinishInitNested(desc, window_number);
    00580     this->last_user_action = WIDGET_LIST_END;
    00581   }
    00582
    00583   virtual void OnPaint()
    00584   {
    00585     this->DrawWidgets();
    00586
    00587     if (this->IsWidgetLowered(ETTW_LOWER_LAND) || this->IsWidgetLowered(ETTW_RAISE_LAND)) { // change area-size if raise/lower corner is selected
    00588       SetTileSelectSize(_terraform_size, _terraform_size);
    00589     }
    00590   }
    00591
    00592   virtual void DrawWidget(const Rect &r, int widget) const
    00593   {
    00594     if (widget != ETTW_DOTS) return;
    00595
    00596     int center_x = RoundDivSU(r.left + r.right, 2);
    00597     int center_y = RoundDivSU(r.top + r.bottom, 2);
    00598
    00599     int n = _terraform_size * _terraform_size;
    00600     const int8 *coords = &_multi_terraform_coords[0][0];
    00601
    00602     assert(n != 0);
    00603     do {
    00604       DrawSprite(SPR_WHITE_POINT, PAL_NONE, center_x + coords[0], center_y + coords[1]);
    00605       coords += 2;
    00606     } while (--n);
    00607   }
    00608
    00609   virtual EventState OnKeyPress(uint16 key, uint16 keycode)
    00610   {
    00611     int num = CheckHotkeyMatch(terraform_editor_hotkeys, keycode, this);
    00612     if (num == -1) return ES_NOT_HANDLED;
    00613     this->OnClick(Point(), num, 1);
    00614     return ES_HANDLED;
    00615   }
    00616
    00617   virtual void OnClick(Point pt, int widget, int click_count)
    00618   {
    00619     if (widget < ETTW_BUTTONS_START) return;
    00620
    00621     switch (widget) {
    00622       case ETTW_DEMOLISH: // Demolish aka dynamite button
    00623         HandlePlacePushButton(this, ETTW_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT | HT_DIAGONAL);
    00624         this->last_user_action = widget;
    00625         break;
    00626
    00627       case ETTW_LOWER_LAND: // Lower land button
    00628         HandlePlacePushButton(this, ETTW_LOWER_LAND, ANIMCURSOR_LOWERLAND, HT_POINT);
    00629         this->last_user_action = widget;
    00630         break;
    00631
    00632       case ETTW_RAISE_LAND: // Raise land button
    00633         HandlePlacePushButton(this, ETTW_RAISE_LAND, ANIMCURSOR_RAISELAND, HT_POINT);
    00634         this->last_user_action = widget;
    00635         break;
    00636
    00637       case ETTW_LEVEL_LAND: // Level land button
    00638         HandlePlacePushButton(this, ETTW_LEVEL_LAND, SPR_CURSOR_LEVEL_LAND, HT_POINT | HT_DIAGONAL);
    00639         this->last_user_action = widget;
    00640         break;
    00641
    00642       case ETTW_PLACE_ROCKS: // Place rocks button
    00643         HandlePlacePushButton(this, ETTW_PLACE_ROCKS, SPR_CURSOR_ROCKY_AREA, HT_RECT);
    00644         this->last_user_action = widget;
    00645         break;
    00646
    00647       case ETTW_PLACE_DESERT: // Place desert button (in tropical climate)
    00648         HandlePlacePushButton(this, ETTW_PLACE_DESERT, SPR_CURSOR_DESERT, HT_RECT);
    00649         this->last_user_action = widget;
    00650         break;
    00651
    00652       case ETTW_PLACE_OBJECT: // Place transmitter button
    00653         if (HandlePlacePushButton(this, ETTW_PLACE_OBJECT, SPR_CURSOR_TRANSMITTER, HT_RECT)) {
    00654           ShowBuildObjectPicker(this);
    00655           this->last_user_action = widget;
    00656         }
    00657         break;
    00658
    00659       case ETTW_INCREASE_SIZE:
    00660       case ETTW_DECREASE_SIZE: { // Increase/Decrease terraform size
    00661         int size = (widget == ETTW_INCREASE_SIZE) ? 1 : -1;
    00662         this->HandleButtonClick(widget);
    00663         size += _terraform_size;
    00664
    00665         if (!IsInsideMM(size, 1, 8 + 1)) return;
    00666         _terraform_size = size;
    00667
    00668         SndPlayFx(SND_15_BEEP);
    00669         this->SetDirty();
    00670         break;
    00671       }
    00672
    00673       case ETTW_NEW_SCENARIO: // gen random land
    00674         this->HandleButtonClick(widget);
    00675         ShowCreateScenario();
    00676         break;
    00677
    00678       case ETTW_RESET_LANDSCAPE: // Reset landscape
    00679         ShowQuery(STR_QUERY_RESET_LANDSCAPE_CAPTION, STR_RESET_LANDSCAPE_CONFIRMATION_TEXT, NULL, ResetLandscapeConfirmationCallback);
    00680         break;
    00681
    00682       default: NOT_REACHED();
    00683     }
    00684   }
    00685
    00686   virtual void OnTimeout()
    00687   {
    00688     for (uint i = ETTW_START; i < this->nested_array_size; i++) {
    00689       if (i == ETTW_BUTTONS_START) i = ETTW_BUTTONS_END; // skip the buttons
    00690       if (this->IsWidgetLowered(i)) {
    00691         this->RaiseWidget(i);
    00692         this->SetWidgetDirty(i);
    00693       }
    00694     }
    00695   }
    00696
    00697   virtual void OnPlaceObject(Point pt, TileIndex tile)
    00698   {
    00699     switch (this->last_user_action) {
    00700       case ETTW_DEMOLISH: // Demolish aka dynamite button
    00701         PlaceProc_DemolishArea(tile);
    00702         break;
    00703
    00704       case ETTW_LOWER_LAND: // Lower land button
    00705         CommonRaiseLowerBigLand(tile, 0);
    00706         break;
    00707
    00708       case ETTW_RAISE_LAND: // Raise land button
    00709         CommonRaiseLowerBigLand(tile, 1);
    00710         break;
    00711
    00712       case ETTW_LEVEL_LAND: // Level land button
    00713         VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LEVEL_AREA);
    00714         break;
    00715
    00716       case ETTW_PLACE_ROCKS: // Place rocks button
    00717         VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CREATE_ROCKS);
    00718         break;
    00719
    00720       case ETTW_PLACE_DESERT: // Place desert button (in tropical climate)
    00721         VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CREATE_DESERT);
    00722         break;
    00723
    00724       case ETTW_PLACE_OBJECT: // Place transmitter button
    00725         PlaceProc_Object(tile);
    00726         break;
    00727
    00728       default: NOT_REACHED();
    00729     }
    00730   }
    00731
    00732   virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
    00733   {
    00734     VpSelectTilesWithMethod(pt.x, pt.y, select_method);
    00735   }
    00736
    00737   virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
    00738   {
    00739     if (pt.x != -1) {
    00740       switch (select_proc) {
    00741         default: NOT_REACHED();
    00742         case DDSP_CREATE_ROCKS:
    00743         case DDSP_CREATE_DESERT:
    00744         case DDSP_RAISE_AND_LEVEL_AREA:
    00745         case DDSP_LOWER_AND_LEVEL_AREA:
    00746         case DDSP_LEVEL_AREA:
    00747         case DDSP_DEMOLISH_AREA:
    00748           GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
    00749           break;
    00750       }
    00751     }
    00752   }
    00753
    00754   virtual void OnPlaceObjectAbort()
    00755   {
    00756     this->RaiseButtons();
    00757     this->SetDirty();
    00758     DeleteWindowById(WC_BUILD_OBJECT, 0);
    00759   }
    00760
    00761   static Hotkey<ScenarioEditorLandscapeGenerationWindow> terraform_editor_hotkeys[];
    00762 };
    00763
    00764 Hotkey<ScenarioEditorLandscapeGenerationWindow> ScenarioEditorLandscapeGenerationWindow::terraform_editor_hotkeys[] = {
    00765   Hotkey<ScenarioEditorLandscapeGenerationWindow>('D' | WKC_GLOBAL_HOTKEY, "dynamite", ETTW_DEMOLISH),
    00766   Hotkey<ScenarioEditorLandscapeGenerationWindow>('Q' | WKC_GLOBAL_HOTKEY, "lower", ETTW_LOWER_LAND),
    00767   Hotkey<ScenarioEditorLandscapeGenerationWindow>('W' | WKC_GLOBAL_HOTKEY, "raise", ETTW_RAISE_LAND),
    00768   Hotkey<ScenarioEditorLandscapeGenerationWindow>('E' | WKC_GLOBAL_HOTKEY, "level", ETTW_LEVEL_LAND),
    00769   Hotkey<ScenarioEditorLandscapeGenerationWindow>('R', "rocky", ETTW_PLACE_ROCKS),
    00770   Hotkey<ScenarioEditorLandscapeGenerationWindow>('T', "desert", ETTW_PLACE_DESERT),
    00771   Hotkey<ScenarioEditorLandscapeGenerationWindow>('O', "object", ETTW_PLACE_OBJECT),
    00772   HOTKEY_LIST_END(ScenarioEditorLandscapeGenerationWindow)
    00773 };
    00774
    00775 Hotkey<ScenarioEditorLandscapeGenerationWindow> *_terraform_editor_hotkeys = ScenarioEditorLandscapeGenerationWindow::terraform_editor_hotkeys;
    00776
    00777 static const WindowDesc _scen_edit_land_gen_desc(
    00778   WDP_AUTO, 0, 0,
    00779   WC_SCEN_LAND_GEN, WC_NONE,
    00780   WDF_CONSTRUCTION,
    00781   _nested_scen_edit_land_gen_widgets, lengthof(_nested_scen_edit_land_gen_widgets)
    00782 );
    00783
    00784 Window *ShowEditorTerraformToolbar()
    00785 {
    00786   return AllocateWindowDescFront<ScenarioEditorLandscapeGenerationWindow>(&_scen_edit_land_gen_desc, 0);
    00787 }
    00788
    00789 EventState TerraformToolbarEditorGlobalHotkeys(uint16 key, uint16 keycode)
    00790 {
    00791   int num = CheckHotkeyMatch<ScenarioEditorLandscapeGenerationWindow>(_terraform_editor_hotkeys, keycode, NULL, true);
    00792   if (num == -1) return ES_NOT_HANDLED;
    00793   Window *w = ShowEditorTerraformToolbar();
    00794   if (w == NULL) return ES_NOT_HANDLED;
    00795   return w->OnKeyPress(key, keycode);
    00796 }