# terraform_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: terraform_gui.cpp 18723 2010-01-04 18:49:27Z rubidium $ */
    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 "openttd.h"
    00014 #include "clear_map.h"
    00015 #include "company_func.h"
    00016 #include "company_base.h"
    00017 #include "gui.h"
    00018 #include "window_gui.h"
    00019 #include "window_func.h"
    00020 #include "viewport_func.h"
    00021 #include "gfx_func.h"
    00022 #include "command_func.h"
    00023 #include "signs_func.h"
    00024 #include "variables.h"
    00025 #include "functions.h"
    00026 #include "sound_func.h"
    00027 #include "base_station_base.h"
    00028 #include "unmovable_map.h"
    00029 #include "textbuf_gui.h"
    00030 #include "genworld.h"
    00031 #include "tree_map.h"
    00032 #include "landscape_type.h"
    00033 #include "tilehighlight_func.h"
    00034 #include "strings_func.h"
    00035
    00036 #include "table/sprites.h"
    00037 #include "table/strings.h"
    00038
    00039 void CcTerraform(bool success, TileIndex tile, uint32 p1, uint32 p2)
    00040 {
    00041   if (success) {
    00042     SndPlayTileFx(SND_1F_SPLAT, tile);
    00043   } else {
    00044     extern TileIndex _terraform_err_tile;
    00045     SetRedErrorSquare(_terraform_err_tile);
    00046   }
    00047 }
    00048
    00049
    00051 static void GenerateDesertArea(TileIndex end, TileIndex start)
    00052 {
    00053   if (_game_mode != GM_EDITOR) return;
    00054
    00055   _generating_world = true;
    00056
    00057   TileArea ta(start, end);
    00058   TILE_AREA_LOOP(tile, ta) {
    00059     SetTropicZone(tile, (_ctrl_pressed) ? TROPICZONE_NORMAL : TROPICZONE_DESERT);
    00060     DoCommandP(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
    00061     MarkTileDirtyByTile(tile);
    00062   }
    00063   _generating_world = false;
    00064 }
    00065
    00067 static void GenerateRockyArea(TileIndex end, TileIndex start)
    00068 {
    00069   if (_game_mode != GM_EDITOR) return;
    00070
    00071   bool success = false;
    00072   TileArea ta(start, end);
    00073
    00074   TILE_AREA_LOOP(tile, ta) {
    00075     switch (GetTileType(tile)) {
    00076       case MP_TREES:
    00077         if (GetTreeGround(tile) == TREE_GROUND_SHORE) continue;
    00078       /* FALL THROUGH */
    00079       case MP_CLEAR:
    00080         MakeClear(tile, CLEAR_ROCKS, 3);
    00081         break;
    00082
    00083       default: continue;
    00084     }
    00085     MarkTileDirtyByTile(tile);
    00086     success = true;
    00087   }
    00088
    00089   if (success) SndPlayTileFx(SND_1F_SPLAT, end);
    00090 }
    00091
    00101 bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_tile, TileIndex end_tile)
    00102 {
    00103   if (!_settings_game.construction.freeform_edges) {
    00104     /* When end_tile is MP_VOID, the error tile will not be visible to the
    00105      * user. This happens when terraforming at the southern border. */
    00106     if (TileX(end_tile) == MapMaxX()) end_tile += TileDiffXY(-1, 0);
    00107     if (TileY(end_tile) == MapMaxY()) end_tile += TileDiffXY(0, -1);
    00108   }
    00109
    00110   switch (proc) {
    00111     case DDSP_DEMOLISH_AREA:
    00112       DoCommandP(end_tile, start_tile, 0, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA), CcPlaySound10);
    00113       break;
    00114     case DDSP_RAISE_AND_LEVEL_AREA:
    00115       DoCommandP(end_tile, start_tile, 1, CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_RAISE_LAND_HERE), CcTerraform);
    00116       break;
    00117     case DDSP_LOWER_AND_LEVEL_AREA:
    00118       DoCommandP(end_tile, start_tile, (uint32)-1, CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_LOWER_LAND_HERE), CcTerraform);
    00119       break;
    00120     case DDSP_LEVEL_AREA:
    00121       DoCommandP(end_tile, start_tile, 0, CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_LEVEL_LAND_HERE), CcTerraform);
    00122       break;
    00123     case DDSP_CREATE_ROCKS:
    00124       GenerateRockyArea(end_tile, start_tile);
    00125       break;
    00126     case DDSP_CREATE_DESERT:
    00127       GenerateDesertArea(end_tile, start_tile);
    00128       break;
    00129     default:
    00130       return false;
    00131   }
    00132
    00133   return true;
    00134 }
    00135
    00136 typedef void OnButtonClick(Window *w);
    00137
    00138 static const uint16 _terraform_keycodes[] = {
    00139   'Q',
    00140   'W',
    00141   'E',
    00142   'D',
    00143   'U',
    00144   'I',
    00145   'O',
    00146 };
    00147
    00148 void CcPlaySound1E(bool success, TileIndex tile, uint32 p1, uint32 p2);
    00149
    00150 static void PlaceProc_BuyLand(TileIndex tile)
    00151 {
    00152   DoCommandP(tile, 0, 0, CMD_PURCHASE_LAND_AREA | CMD_MSG(STR_ERROR_CAN_T_PURCHASE_THIS_LAND), CcPlaySound1E);
    00153 }
    00154
    00155 void PlaceProc_DemolishArea(TileIndex tile)
    00156 {
    00157   VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_DEMOLISH_AREA);
    00158 }
    00159
    00160 static void PlaceProc_RaiseLand(TileIndex tile)
    00161 {
    00162   VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_RAISE_AND_LEVEL_AREA);
    00163 }
    00164
    00165 static void PlaceProc_LowerLand(TileIndex tile)
    00166 {
    00167   VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LOWER_AND_LEVEL_AREA);
    00168 }
    00169
    00170 static void PlaceProc_LevelLand(TileIndex tile)
    00171 {
    00172   VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LEVEL_AREA);
    00173 }
    00174
    00176 enum TerraformToolbarWidgets {
    00177   TTW_BUTTONS_START,
    00178   TTW_LOWER_LAND = TTW_BUTTONS_START,
    00179   TTW_RAISE_LAND,
    00180   TTW_LEVEL_LAND,
    00181   TTW_DEMOLISH,
    00182   TTW_BUY_LAND,
    00183   TTW_PLANT_TREES,
    00184   TTW_PLACE_SIGN,
    00185 };
    00186
    00187 static void TerraformClick_Lower(Window *w)
    00188 {
    00189   HandlePlacePushButton(w, TTW_LOWER_LAND, ANIMCURSOR_LOWERLAND, HT_POINT, PlaceProc_LowerLand);
    00190 }
    00191
    00192 static void TerraformClick_Raise(Window *w)
    00193 {
    00194   HandlePlacePushButton(w, TTW_RAISE_LAND, ANIMCURSOR_RAISELAND, HT_POINT, PlaceProc_RaiseLand);
    00195 }
    00196
    00197 static void TerraformClick_Level(Window *w)
    00198 {
    00199   HandlePlacePushButton(w, TTW_LEVEL_LAND, SPR_CURSOR_LEVEL_LAND, HT_POINT, PlaceProc_LevelLand);
    00200 }
    00201
    00202 static void TerraformClick_Dynamite(Window *w)
    00203 {
    00204   HandlePlacePushButton(w, TTW_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT, PlaceProc_DemolishArea);
    00205 }
    00206
    00207 static void TerraformClick_BuyLand(Window *w)
    00208 {
    00209   HandlePlacePushButton(w, TTW_BUY_LAND, SPR_CURSOR_BUY_LAND, HT_RECT, PlaceProc_BuyLand);
    00210 }
    00211
    00212 static void TerraformClick_Trees(Window *w)
    00213 {
    00214   /* This button is NOT a place-push-button, so don't treat it as such */
    00215   ShowBuildTreesToolbar();
    00216 }
    00217
    00218 static void TerraformClick_PlaceSign(Window *w)
    00219 {
    00220   HandlePlacePushButton(w, TTW_PLACE_SIGN, SPR_CURSOR_SIGN, HT_RECT, PlaceProc_Sign);
    00221 }
    00222
    00223 static OnButtonClick * const _terraform_button_proc[] = {
    00224   TerraformClick_Lower,
    00225   TerraformClick_Raise,
    00226   TerraformClick_Level,
    00227   TerraformClick_Dynamite,
    00228   TerraformClick_BuyLand,
    00229   TerraformClick_Trees,
    00230   TerraformClick_PlaceSign,
    00231 };
    00232
    00233 struct TerraformToolbarWindow : Window {
    00234   TerraformToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
    00235   {
    00236     this->InitNested(desc, window_number);
    00237   }
    00238
    00239   ~TerraformToolbarWindow()
    00240   {
    00241   }
    00242
    00243   virtual void OnPaint()
    00244   {
    00245     this->DrawWidgets();
    00246   }
    00247
    00248   virtual void OnClick(Point pt, int widget)
    00249   {
    00250     if (widget >= TTW_BUTTONS_START) _terraform_button_proc[widget - TTW_BUTTONS_START](this);
    00251   }
    00252
    00253   virtual EventState OnKeyPress(uint16 key, uint16 keycode)
    00254   {
    00255     for (uint i = 0; i != lengthof(_terraform_keycodes); i++) {
    00256       if (keycode == _terraform_keycodes[i]) {
    00257         _terraform_button_proc[i](this);
    00258         return ES_HANDLED;
    00259       }
    00260     }
    00261     return ES_NOT_HANDLED;
    00262   }
    00263
    00264   virtual void OnPlaceObject(Point pt, TileIndex tile)
    00265   {
    00266     _place_proc(tile);
    00267   }
    00268
    00269   virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
    00270   {
    00271     VpSelectTilesWithMethod(pt.x, pt.y, select_method);
    00272   }
    00273
    00274   virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number)
    00275   {
    00276     Point pt = GetToolbarAlignedWindowPosition(sm_width);
    00277     pt.y += sm_height;
    00278     return pt;
    00279   }
    00280
    00281   virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
    00282   {
    00283     if (pt.x != -1) {
    00284       switch (select_proc) {
    00285         default: NOT_REACHED();
    00286         case DDSP_DEMOLISH_AREA:
    00287         case DDSP_RAISE_AND_LEVEL_AREA:
    00288         case DDSP_LOWER_AND_LEVEL_AREA:
    00289         case DDSP_LEVEL_AREA:
    00290           GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
    00291           break;
    00292       }
    00293     }
    00294   }
    00295
    00296   virtual void OnPlaceObjectAbort()
    00297   {
    00298     this->RaiseButtons();
    00299   }
    00300 };
    00301
    00302 static const NWidgetPart _nested_terraform_widgets[] = {
    00303   NWidget(NWID_HORIZONTAL),
    00304     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00305     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_LANDSCAPING_TOOLBAR, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00306     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00307   EndContainer(),
    00308   NWidget(NWID_HORIZONTAL),
    00309     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_LOWER_LAND), SetMinimalSize(22,22),
    00310                 SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_DOWN, STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND),
    00311     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_RAISE_LAND), SetMinimalSize(22,22),
    00312                 SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_UP, STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND),
    00313     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_LEVEL_LAND), SetMinimalSize(22,22),
    00314                 SetFill(0, 1), SetDataTip(SPR_IMG_LEVEL_LAND, STR_LANDSCAPING_LEVEL_LAND_TOOLTIP),
    00315
    00316     NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),
    00317
    00318     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_DEMOLISH), SetMinimalSize(22,22),
    00319                 SetFill(0, 1), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00320     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_BUY_LAND), SetMinimalSize(22,22),
    00321                 SetFill(0, 1), SetDataTip(SPR_IMG_BUY_LAND, STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND),
    00322     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_PLANT_TREES), SetMinimalSize(22,22),
    00323                 SetFill(0, 1), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
    00324     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_PLACE_SIGN), SetMinimalSize(22,22),
    00325                 SetFill(0, 1), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
    00326   EndContainer(),
    00327 };
    00328
    00329 static const WindowDesc _terraform_desc(
    00330   WDP_MANUAL, 0, 0,
    00331   WC_SCEN_LAND_GEN, WC_NONE,
    00332   WDF_CONSTRUCTION,
    00333   _nested_terraform_widgets, lengthof(_nested_terraform_widgets)
    00334 );
    00335
    00336 Window *ShowTerraformToolbar(Window *link)
    00337 {
    00338   if (!Company::IsValidID(_local_company)) return NULL;
    00339
    00340   Window *w = AllocateWindowDescFront<TerraformToolbarWindow>(&_terraform_desc, 0);
    00341   if (link == NULL) return w;
    00342
    00343   if (w == NULL) {
    00344     w = FindWindowById(WC_SCEN_LAND_GEN, 0);
    00345     if (w == NULL) return NULL;
    00346   } else {
    00347     w->top -= w->height;
    00348     w->SetDirty();
    00349   }
    00350
    00351   /* Align the terraform toolbar under the main toolbar and put the linked
    00352    * toolbar to left/right of it */
    00353   link->left = w->left + (_dynlang.text_dir == TD_RTL ? w->width : -link->width);
    00354   link->top  = w->top;
    00355   link->SetDirty();
    00356
    00357   return w;
    00358 }
    00359
    00360 void ShowTerraformToolbarWithTool(uint16 key, uint16 keycode)
    00361 {
    00362   Window *w = FindWindowById(WC_SCEN_LAND_GEN, 0);
    00363
    00364   if (w == NULL) w = ShowTerraformToolbar(NULL);
    00365   if (w == NULL) return;
    00366
    00367   w->OnKeyPress(key, keycode);
    00368 }
    00369
    00370 static byte _terraform_size = 1;
    00371
    00381 static void CommonRaiseLowerBigLand(TileIndex tile, int mode)
    00382 {
    00383   int sizex, sizey;
    00384   uint h;
    00385
    00386   if (_terraform_size == 1) {
    00387     StringID msg =
    00388       mode ? STR_ERROR_CAN_T_RAISE_LAND_HERE : STR_ERROR_CAN_T_LOWER_LAND_HERE;
    00389
    00390     DoCommandP(tile, SLOPE_N, (uint32)mode, CMD_TERRAFORM_LAND | CMD_MSG(msg), CcTerraform);
    00391   } else {
    00392     assert(_terraform_size != 0);
    00393     /* check out for map overflows */
    00394     sizex = min(MapSizeX() - TileX(tile), _terraform_size);
    00395     sizey = min(MapSizeY() - TileY(tile), _terraform_size);
    00396
    00397     if (sizex == 0 || sizey == 0) return;
    00398
    00399     SndPlayTileFx(SND_1F_SPLAT, tile);
    00400
    00401     if (mode != 0) {
    00402       /* Raise land */
    00403       h = 15; // XXX - max height
    00404       TILE_LOOP(tile2, sizex, sizey, tile) {
    00405         h = min(h, TileHeight(tile2));
    00406       }
    00407     } else {
    00408       /* Lower land */
    00409       h = 0;
    00410       TILE_LOOP(tile2, sizex, sizey, tile) {
    00411         h = max(h, TileHeight(tile2));
    00412       }
    00413     }
    00414
    00415     TILE_LOOP(tile2, sizex, sizey, tile) {
    00416       if (TileHeight(tile2) == h) {
    00417         DoCommandP(tile2, SLOPE_N, (uint32)mode, CMD_TERRAFORM_LAND);
    00418       }
    00419     }
    00420   }
    00421 }
    00422
    00423 static void PlaceProc_RaiseBigLand(TileIndex tile)
    00424 {
    00425   CommonRaiseLowerBigLand(tile, 1);
    00426 }
    00427
    00428 static void PlaceProc_LowerBigLand(TileIndex tile)
    00429 {
    00430   CommonRaiseLowerBigLand(tile, 0);
    00431 }
    00432
    00433 static void PlaceProc_RockyArea(TileIndex tile)
    00434 {
    00435   VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CREATE_ROCKS);
    00436 }
    00437
    00438 static void PlaceProc_LightHouse(TileIndex tile)
    00439 {
    00440   /* not flat || not(trees || clear without bridge above) */
    00441   if (GetTileSlope(tile, NULL) != SLOPE_FLAT || !(IsTileType(tile, MP_TREES) || (IsTileType(tile, MP_CLEAR) && !IsBridgeAbove(tile)))) {
    00442     return;
    00443   }
    00444
    00445   MakeLighthouse(tile);
    00446   MarkTileDirtyByTile(tile);
    00447   SndPlayTileFx(SND_1F_SPLAT, tile);
    00448 }
    00449
    00450 static void PlaceProc_Transmitter(TileIndex tile)
    00451 {
    00452   /* not flat || not(trees || clear without bridge above) */
    00453   if (GetTileSlope(tile, NULL) != SLOPE_FLAT || !(IsTileType(tile, MP_TREES) || (IsTileType(tile, MP_CLEAR) && !IsBridgeAbove(tile)))) {
    00454     return;
    00455   }
    00456
    00457   MakeTransmitter(tile);
    00458   MarkTileDirtyByTile(tile);
    00459   SndPlayTileFx(SND_1F_SPLAT, tile);
    00460 }
    00461
    00462 static void PlaceProc_DesertArea(TileIndex tile)
    00463 {
    00464   VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CREATE_DESERT);
    00465 }
    00466
    00467 static const int8 _multi_terraform_coords[][2] = {
    00468   {  0, -2},
    00469   {  4,  0}, { -4,  0}, {  0,  2},
    00470   { -8,  2}, { -4,  4}, {  0,  6}, {  4,  4}, {  8,  2},
    00471   {-12,  0}, { -8, -2}, { -4, -4}, {  0, -6}, {  4, -4}, {  8, -2}, { 12,  0},
    00472   {-16,  2}, {-12,  4}, { -8,  6}, { -4,  8}, {  0, 10}, {  4,  8}, {  8,  6}, { 12,  4}, { 16,  2},
    00473   {-20,  0}, {-16, -2}, {-12, -4}, { -8, -6}, { -4, -8}, {  0,-10}, {  4, -8}, {  8, -6}, { 12, -4}, { 16, -2}, { 20,  0},
    00474   {-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},
    00475   {-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},
    00476 };
    00477
    00479 enum EditorTerraformToolbarWidgets {
    00480   ETTW_START = 0,
    00481   ETTW_DOTS = ETTW_START,
    00482   ETTW_BUTTONS_START,
    00483   ETTW_DEMOLISH = ETTW_BUTTONS_START,
    00484   ETTW_LOWER_LAND,
    00485   ETTW_RAISE_LAND,
    00486   ETTW_LEVEL_LAND,
    00487   ETTW_PLACE_ROCKS,
    00488   ETTW_PLACE_DESERT_LIGHTHOUSE,
    00489   ETTW_PLACE_TRANSMITTER,
    00490   ETTW_BUTTONS_END,
    00491   ETTW_INCREASE_SIZE = ETTW_BUTTONS_END,
    00492   ETTW_DECREASE_SIZE,
    00493   ETTW_NEW_SCENARIO,
    00494   ETTW_RESET_LANDSCAPE,
    00495 };
    00496
    00497 static const NWidgetPart _nested_scen_edit_land_gen_widgets[] = {
    00498   NWidget(NWID_HORIZONTAL),
    00499     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00500     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00501     NWidget(WWT_SHADEBOX, COLOUR_DARK_GREEN),
    00502     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00503   EndContainer(),
    00504   NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
    00505     NWidget(NWID_HORIZONTAL), SetPadding(2, 2, 7, 2),
    00506       NWidget(NWID_SPACER), SetFill(1, 0),
    00507       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_DEMOLISH), SetMinimalSize(22, 22),
    00508                     SetFill(0, 1), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00509       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_LOWER_LAND), SetMinimalSize(22, 22),
    00510                     SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_DOWN, STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND),
    00511       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_RAISE_LAND), SetMinimalSize(22, 22),
    00512                     SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_UP, STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND),
    00513       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_LEVEL_LAND), SetMinimalSize(22, 22),
    00514                     SetFill(0, 1), SetDataTip(SPR_IMG_LEVEL_LAND, STR_LANDSCAPING_LEVEL_LAND_TOOLTIP),
    00515       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_PLACE_ROCKS), SetMinimalSize(22, 22),
    00516                     SetFill(0, 1), SetDataTip(SPR_IMG_ROCKS, STR_TERRAFORM_TOOLTIP_PLACE_ROCKY_AREAS_ON_LANDSCAPE),
    00517       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_PLACE_DESERT_LIGHTHOUSE), SetMinimalSize(22, 22),
    00518                     SetFill(0, 1), SetDataTip(SPR_IMG_LIGHTHOUSE_DESERT, STR_NULL),
    00519       NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_PLACE_TRANSMITTER), SetMinimalSize(23, 22),
    00520                     SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER, STR_TERRAFORM_TOOLTIP_PLACE_TRANSMITTER),
    00521       NWidget(NWID_SPACER), SetFill(1, 0),
    00522     EndContainer(),
    00523     NWidget(NWID_HORIZONTAL),
    00524       NWidget(NWID_SPACER), SetFill(1, 0),
    00525       NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, ETTW_DOTS), SetMinimalSize(59, 31), SetDataTip(STR_EMPTY, STR_NULL),
    00526       NWidget(NWID_SPACER), SetFill(1, 0),
    00527       NWidget(NWID_VERTICAL),
    00528         NWidget(NWID_SPACER), SetFill(0, 1),
    00529         NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_INCREASE_SIZE), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_UP, STR_TERRAFORM_TOOLTIP_INCREASE_SIZE_OF_LAND_AREA),
    00530         NWidget(NWID_SPACER), SetMinimalSize(0, 1),
    00531         NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_DECREASE_SIZE), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_DOWN, STR_TERRAFORM_TOOLTIP_DECREASE_SIZE_OF_LAND_AREA),
    00532         NWidget(NWID_SPACER), SetFill(0, 1),
    00533       EndContainer(),
    00534       NWidget(NWID_SPACER), SetMinimalSize(2, 0),
    00535     EndContainer(),
    00536     NWidget(NWID_SPACER), SetMinimalSize(0, 6),
    00537     NWidget(WWT_TEXTBTN, COLOUR_GREY, ETTW_NEW_SCENARIO), SetMinimalSize(160, 12),
    00538                 SetFill(1, 0), SetDataTip(STR_TERRAFORM_SE_NEW_WORLD, STR_TERRAFORM_TOOLTIP_GENERATE_RANDOM_LAND), SetPadding(0, 2, 0, 2),
    00539     NWidget(WWT_TEXTBTN, COLOUR_GREY, ETTW_RESET_LANDSCAPE), SetMinimalSize(160, 12),
    00540                 SetFill(1, 0), SetDataTip(STR_TERRAFORM_RESET_LANDSCAPE, STR_TERRAFORM_RESET_LANDSCAPE_TOOLTIP), SetPadding(1, 2, 2, 2),
    00541   EndContainer(),
    00542 };
    00543
    00548 static void EditorTerraformClick_Dynamite(Window *w)
    00549 {
    00550   HandlePlacePushButton(w, ETTW_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT, PlaceProc_DemolishArea);
    00551 }
    00552
    00553 static void EditorTerraformClick_LowerBigLand(Window *w)
    00554 {
    00555   HandlePlacePushButton(w, ETTW_LOWER_LAND, ANIMCURSOR_LOWERLAND, HT_POINT, PlaceProc_LowerBigLand);
    00556 }
    00557
    00558 static void EditorTerraformClick_RaiseBigLand(Window *w)
    00559 {
    00560   HandlePlacePushButton(w, ETTW_RAISE_LAND, ANIMCURSOR_RAISELAND, HT_POINT, PlaceProc_RaiseBigLand);
    00561 }
    00562
    00563 static void EditorTerraformClick_LevelLand(Window *w)
    00564 {
    00565   HandlePlacePushButton(w, ETTW_LEVEL_LAND, SPR_CURSOR_LEVEL_LAND, HT_POINT, PlaceProc_LevelLand);
    00566 }
    00567
    00568 static void EditorTerraformClick_RockyArea(Window *w)
    00569 {
    00570   HandlePlacePushButton(w, ETTW_PLACE_ROCKS, SPR_CURSOR_ROCKY_AREA, HT_RECT, PlaceProc_RockyArea);
    00571 }
    00572
    00573 static void EditorTerraformClick_DesertLightHouse(Window *w)
    00574 {
    00575   HandlePlacePushButton(w, ETTW_PLACE_DESERT_LIGHTHOUSE, SPR_CURSOR_LIGHTHOUSE, HT_RECT, (_settings_game.game_creation.landscape == LT_TROPIC) ? PlaceProc_DesertArea : PlaceProc_LightHouse);
    00576 }
    00577
    00578 static void EditorTerraformClick_Transmitter(Window *w)
    00579 {
    00580   HandlePlacePushButton(w, ETTW_PLACE_TRANSMITTER, SPR_CURSOR_TRANSMITTER, HT_RECT, PlaceProc_Transmitter);
    00581 }
    00582
    00583 static const uint16 _editor_terraform_keycodes[] = {
    00584   'D',
    00585   'Q',
    00586   'W',
    00587   'E',
    00588   'R',
    00589   'T',
    00590   'Y'
    00591 };
    00592
    00593 typedef void OnButtonClick(Window *w);
    00594 static OnButtonClick * const _editor_terraform_button_proc[] = {
    00595   EditorTerraformClick_Dynamite,
    00596   EditorTerraformClick_LowerBigLand,
    00597   EditorTerraformClick_RaiseBigLand,
    00598   EditorTerraformClick_LevelLand,
    00599   EditorTerraformClick_RockyArea,
    00600   EditorTerraformClick_DesertLightHouse,
    00601   EditorTerraformClick_Transmitter
    00602 };
    00603
    00604
    00608 static void ResetLandscapeConfirmationCallback(Window *w, bool confirmed)
    00609 {
    00610   if (confirmed) {
    00611     /* Set generating_world to true to get instant-green grass after removing
    00612      * company property. */
    00613     _generating_world = true;
    00614
    00615     /* Delete all companies */
    00616     Company *c;
    00617     FOR_ALL_COMPANIES(c) {
    00618       ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
    00619       delete c;
    00620     }
    00621
    00622     _generating_world = false;
    00623
    00624     /* Delete all station signs */
    00625     BaseStation *st;
    00626     FOR_ALL_BASE_STATIONS(st) {
    00627       /* There can be buoys, remove them */
    00628       if (IsBuoyTile(st->xy)) DoCommand(st->xy, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
    00629       if (!st->IsInUse()) delete st;
    00630     }
    00631
    00632     MarkWholeScreenDirty();
    00633   }
    00634 }
    00635
    00636 struct ScenarioEditorLandscapeGenerationWindow : Window {
    00637   ScenarioEditorLandscapeGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
    00638   {
    00639     this->InitNested(desc, window_number);
    00640     this->GetWidget<NWidgetCore>(ETTW_PLACE_DESERT_LIGHTHOUSE)->tool_tip = (_settings_game.game_creation.landscape == LT_TROPIC) ? STR_TERRAFORM_TOOLTIP_DEFINE_DESERT_AREA : STR_TERRAFORM_TOOLTIP_PLACE_LIGHTHOUSE;
    00641   }
    00642
    00643   virtual void OnPaint()
    00644   {
    00645     this->DrawWidgets();
    00646
    00647     if (this->IsWidgetLowered(ETTW_LOWER_LAND) || this->IsWidgetLowered(ETTW_RAISE_LAND)) { // change area-size if raise/lower corner is selected
    00648       SetTileSelectSize(_terraform_size, _terraform_size);
    00649     }
    00650   }
    00651
    00652   virtual void DrawWidget(const Rect &r, int widget) const
    00653   {
    00654     if (widget != ETTW_DOTS) return;
    00655
    00656     int center_x = (r.left + r.right + 1) / 2;
    00657     int center_y = (r.top + r.bottom + 1) / 2;
    00658
    00659     int n = _terraform_size * _terraform_size;
    00660     const int8 *coords = &_multi_terraform_coords[0][0];
    00661
    00662     assert(n != 0);
    00663     do {
    00664       DrawSprite(SPR_WHITE_POINT, PAL_NONE, center_x + coords[0], center_y + coords[1]);
    00665       coords += 2;
    00666     } while (--n);
    00667   }
    00668
    00669   virtual EventState OnKeyPress(uint16 key, uint16 keycode)
    00670   {
    00671     for (uint i = 0; i != lengthof(_editor_terraform_keycodes); i++) {
    00672       if (keycode == _editor_terraform_keycodes[i]) {
    00673         _editor_terraform_button_proc[i](this);
    00674         return ES_HANDLED;
    00675       }
    00676     }
    00677     return ES_NOT_HANDLED;
    00678   }
    00679
    00680   virtual void OnClick(Point pt, int widget)
    00681   {
    00682     if (IsInsideMM(widget, ETTW_BUTTONS_START, ETTW_BUTTONS_END)) {
    00683       _editor_terraform_button_proc[widget - ETTW_BUTTONS_START](this);
    00684     } else {
    00685       switch (widget) {
    00686         case ETTW_INCREASE_SIZE:
    00687         case ETTW_DECREASE_SIZE: { // Increase/Decrease terraform size
    00688           int size = (widget == ETTW_INCREASE_SIZE) ? 1 : -1;
    00689           this->HandleButtonClick(widget);
    00690           size += _terraform_size;
    00691
    00692           if (!IsInsideMM(size, 1, 8 + 1)) return;
    00693           _terraform_size = size;
    00694
    00695           SndPlayFx(SND_15_BEEP);
    00696           this->SetDirty();
    00697         } break;
    00698         case ETTW_NEW_SCENARIO: // gen random land
    00699           this->HandleButtonClick(widget);
    00700           ShowCreateScenario();
    00701           break;
    00702         case ETTW_RESET_LANDSCAPE: // Reset landscape
    00703           ShowQuery(
    00704             STR_QUERY_RESET_LANDSCAPE_CAPTION,
    00705             STR_RESET_LANDSCAPE_CONFIRMATION_TEXT,
    00706             NULL,
    00707             ResetLandscapeConfirmationCallback);
    00708           break;
    00709       }
    00710     }
    00711   }
    00712
    00713   virtual void OnTimeout()
    00714   {
    00715     for (uint i = ETTW_START; i < this->nested_array_size; i++) {
    00716       if (i == ETTW_BUTTONS_START) i = ETTW_BUTTONS_END; // skip the buttons
    00717       if (this->IsWidgetLowered(i)) {
    00718         this->RaiseWidget(i);
    00719         this->SetWidgetDirty(i);
    00720       }
    00721     }
    00722   }
    00723
    00724   virtual void OnPlaceObject(Point pt, TileIndex tile)
    00725   {
    00726     _place_proc(tile);
    00727   }
    00728
    00729   virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
    00730   {
    00731     VpSelectTilesWithMethod(pt.x, pt.y, select_method);
    00732   }
    00733
    00734   virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
    00735   {
    00736     if (pt.x != -1) {
    00737       switch (select_proc) {
    00738         default: NOT_REACHED();
    00739         case DDSP_CREATE_ROCKS:
    00740         case DDSP_CREATE_DESERT:
    00741         case DDSP_RAISE_AND_LEVEL_AREA:
    00742         case DDSP_LOWER_AND_LEVEL_AREA:
    00743         case DDSP_LEVEL_AREA:
    00744         case DDSP_DEMOLISH_AREA:
    00745           GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
    00746           break;
    00747       }
    00748     }
    00749   }
    00750
    00751   virtual void OnPlaceObjectAbort()
    00752   {
    00753     this->RaiseButtons();
    00754     this->SetDirty();
    00755   }
    00756 };
    00757
    00758 static const WindowDesc _scen_edit_land_gen_desc(
    00759   WDP_AUTO, 0, 0,
    00760   WC_SCEN_LAND_GEN, WC_NONE,
    00761   WDF_CONSTRUCTION,
    00762   _nested_scen_edit_land_gen_widgets, lengthof(_nested_scen_edit_land_gen_widgets)
    00763 );
    00764
    00765 Window *ShowEditorTerraformToolbar()
    00766 {
    00767   return AllocateWindowDescFront<ScenarioEditorLandscapeGenerationWindow>(&_scen_edit_land_gen_desc, 0);
    00768 }
    00769
    00770 void ShowEditorTerraformToolbarWithTool(uint16 key, uint16 keycode)
    00771 {
    00772   Window *w = FindWindowById(WC_SCEN_LAND_GEN, 0);
    00773
    00774   if (w == NULL) w = ShowEditorTerraformToolbar();
    00775   if (w == NULL) return;
    00776
    00777   w->OnKeyPress(key, keycode);
    00778 }