4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
10 /** @file terraform_gui.cpp GUI related to terraforming the map. */
13 #include "map/ground.h"
14 #include "company_func.h"
15 #include "company_base.h"
17 #include "window_gui.h"
18 #include "window_func.h"
19 #include "viewport_func.h"
20 #include "command_func.h"
21 #include "signs_func.h"
22 #include "sound_func.h"
23 #include "base_station_base.h"
24 #include "textbuf_gui.h"
26 #include "landscape_type.h"
27 #include "tilehighlight_func.h"
28 #include "strings_func.h"
29 #include "newgrf_object.h"
32 #include "engine_base.h"
33 #include "terraform_gui.h"
34 #include "zoom_func.h"
36 #include "widgets/terraform_widget.h"
38 #include "table/strings.h"
40 void CcTerraform(const CommandCost
&result
, TileIndex tile
, uint32 p1
, uint32 p2
)
42 if (result
.Succeeded()) {
43 if (_settings_client
.sound
.confirm
) SndPlayTileFx(SND_1F_SPLAT_OTHER
, tile
);
45 extern TileIndex _terraform_err_tile
;
46 SetRedErrorSquare(_terraform_err_tile
);
50 void CcTerraformLand(const CommandCost
&result
, TileIndex tile
, uint32 p1
, uint32 p2
)
52 if (HasBit(p2
, 31)) return;
54 CcTerraform(result
, tile
, p1
, p2
);
57 StringID
GetErrTerraformLand (TileIndex tile
, uint32 p1
, uint32 p2
, const char *text
)
59 return HasBit(p2
, 31) ? 0 : HasBit(p2
, 0) ? STR_ERROR_CAN_T_RAISE_LAND_HERE
: STR_ERROR_CAN_T_LOWER_LAND_HERE
;
62 StringID
GetErrLevelLand (TileIndex tile
, uint32 p1
, uint32 p2
, const char *text
)
64 switch (GB(p2
, 1, 2)) {
65 case LM_LEVEL
: return STR_ERROR_CAN_T_LEVEL_LAND_HERE
;
66 case LM_RAISE
: return STR_ERROR_CAN_T_RAISE_LAND_HERE
;
67 case LM_LOWER
: return STR_ERROR_CAN_T_LOWER_LAND_HERE
;
73 /** Scenario editor command that generates desert areas */
74 static void GenerateDesertArea(TileIndex end
, TileIndex start
)
76 if (_game_mode
!= GM_EDITOR
) return;
78 _generating_world
= true;
80 TileArea
ta(start
, end
);
81 TILE_AREA_LOOP(tile
, ta
) {
82 SetTropicZone(tile
, (_ctrl_pressed
) ? TROPICZONE_NORMAL
: TROPICZONE_DESERT
);
83 DoCommandP(tile
, 0, 0, CMD_LANDSCAPE_CLEAR
);
84 MarkTileDirtyByTile(tile
);
86 _generating_world
= false;
87 InvalidateWindowClassesData(WC_TOWN_VIEW
, 0);
90 /** Scenario editor command that generates rocky areas */
91 static void GenerateRockyArea(TileIndex end
, TileIndex start
)
93 if (_game_mode
!= GM_EDITOR
) return;
96 TileArea
ta(start
, end
);
98 TILE_AREA_LOOP(tile
, ta
) {
99 if (!IsGroundTile(tile
)) continue;
100 if (IsTreeTile(tile
) && GetClearGround(tile
) == GROUND_SHORE
) continue;
101 MakeClear(tile
, GROUND_ROCKS
, 3);
102 MarkTileDirtyByTile(tile
);
106 if (success
&& _settings_client
.sound
.confirm
) SndPlayTileFx(SND_1F_SPLAT_OTHER
, end
);
109 /** Placing actions in the terraform window. */
111 PLACE_DEMOLISH_AREA
, ///< Clear area
112 PLACE_LOWER_AREA
, ///< Lower / level area
113 PLACE_RAISE_AREA
, ///< Raise / level area
114 PLACE_LEVEL_AREA
, ///< Level area
115 PLACE_CREATE_ROCKS
, ///< Fill area with rocks
116 PLACE_CREATE_DESERT
, ///< Fill area with desert
117 PLACE_BUY_LAND
, ///< Buy land
118 PLACE_SIGN
, ///< Place a sign
122 * A central place to handle all X_AND_Y dragged GUI functions.
123 * @param proc Procedure related to the dragging
124 * @param start_tile Begin of the dragging
125 * @param end_tile End of the dragging
126 * @return Returns true if the action was found and handled, and false otherwise. This
127 * allows for additional implements that are more local. For example X_Y drag
128 * of convertrail which belongs in rail_gui.cpp and not terraform_gui.cpp
130 static bool GUIPlaceProcDragXY (int proc
, TileIndex start_tile
, TileIndex end_tile
)
132 if (!_settings_game
.construction
.freeform_edges
) {
133 /* When end_tile is void, the error tile will not be visible to the
134 * user. This happens when terraforming at the southern border. */
135 if (TileX(end_tile
) == MapMaxX()) end_tile
+= TileDiffXY(-1, 0);
136 if (TileY(end_tile
) == MapMaxY()) end_tile
+= TileDiffXY(0, -1);
140 case PLACE_DEMOLISH_AREA
:
141 DoCommandP(end_tile
, start_tile
, _ctrl_pressed
? 1 : 0, CMD_CLEAR_AREA
);
143 case PLACE_LOWER_AREA
:
144 DoCommandP(end_tile
, start_tile
, LM_LOWER
<< 1 | (_ctrl_pressed
? 1 : 0), CMD_LEVEL_LAND
);
146 case PLACE_RAISE_AREA
:
147 DoCommandP(end_tile
, start_tile
, LM_RAISE
<< 1 | (_ctrl_pressed
? 1 : 0), CMD_LEVEL_LAND
);
149 case PLACE_LEVEL_AREA
:
150 DoCommandP(end_tile
, start_tile
, LM_LEVEL
<< 1 | (_ctrl_pressed
? 1 : 0), CMD_LEVEL_LAND
);
152 case PLACE_CREATE_ROCKS
:
153 GenerateRockyArea(end_tile
, start_tile
);
155 case PLACE_CREATE_DESERT
:
156 GenerateDesertArea(end_tile
, start_tile
);
165 void HandleDemolishMouseUp (TileIndex start_tile
, TileIndex end_tile
)
167 GUIPlaceProcDragXY (PLACE_DEMOLISH_AREA
, start_tile
, end_tile
);
170 /** Terra form toolbar managing class. */
171 struct TerraformToolbarWindow
: Window
{
172 int placing_action
; ///< Currently active placing action.
174 TerraformToolbarWindow (const WindowDesc
*desc
, WindowNumber window_number
) :
175 Window (desc
), placing_action (-1)
177 /* This is needed as we like to have the tree available on OnInit. */
178 this->CreateNestedTree();
179 this->InitNested(window_number
);
182 ~TerraformToolbarWindow()
186 virtual void OnInit()
188 /* Don't show the place object button when there are no objects to place. */
189 NWidgetStacked
*show_object
= this->GetWidget
<NWidgetStacked
>(WID_TT_SHOW_PLACE_OBJECT
);
190 show_object
->SetDisplayedPlane(ObjectClass::GetUIClassCount() != 0 ? 0 : SZSP_NONE
);
193 virtual void OnClick(Point pt
, int widget
, int click_count
)
195 if (widget
< WID_TT_BUTTONS_START
) return;
198 case WID_TT_LOWER_LAND
: // Lower land button
199 HandlePlacePushButton (this, WID_TT_LOWER_LAND
, ANIMCURSOR_LOWERLAND
, POINTER_CORNER
);
200 this->placing_action
= PLACE_LOWER_AREA
;
203 case WID_TT_RAISE_LAND
: // Raise land button
204 HandlePlacePushButton (this, WID_TT_RAISE_LAND
, ANIMCURSOR_RAISELAND
, POINTER_CORNER
);
205 this->placing_action
= PLACE_RAISE_AREA
;
208 case WID_TT_LEVEL_LAND
: // Level land button
209 HandlePlacePushButton (this, WID_TT_LEVEL_LAND
, SPR_CURSOR_LEVEL_LAND
, POINTER_CORNER
);
210 this->placing_action
= PLACE_LEVEL_AREA
;
213 case WID_TT_DEMOLISH
: // Demolish aka dynamite button
214 HandlePlacePushButton (this, WID_TT_DEMOLISH
, ANIMCURSOR_DEMOLISH
, POINTER_TILE
);
215 this->placing_action
= PLACE_DEMOLISH_AREA
;
218 case WID_TT_BUY_LAND
: // Buy land button
219 HandlePlacePushButton (this, WID_TT_BUY_LAND
, SPR_CURSOR_BUY_LAND
, POINTER_TILE
);
220 this->placing_action
= PLACE_BUY_LAND
;
223 case WID_TT_PLANT_TREES
: // Plant trees button
224 ShowBuildTreesToolbar();
227 case WID_TT_PLACE_SIGN
: // Place sign button
228 HandlePlacePushButton (this, WID_TT_PLACE_SIGN
, SPR_CURSOR_SIGN
, POINTER_TILE
);
229 this->placing_action
= PLACE_SIGN
;
232 case WID_TT_PLACE_OBJECT
: // Place object button
233 ShowBuildObjectPicker();
236 default: NOT_REACHED();
240 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
242 switch (this->placing_action
) {
244 VpStartPlaceSizing (tile
, VPM_X_AND_Y_ROTATED
, this->placing_action
);
248 DoCommandP(tile
, OBJECT_OWNED_LAND
, 0, CMD_BUILD_OBJECT
);
252 PlaceProc_Sign(tile
);
257 virtual Point
OnInitialPosition(int16 sm_width
, int16 sm_height
, int window_number
)
259 Point pt
= GetToolbarAlignedWindowPosition(sm_width
);
264 void OnPlaceMouseUp (int userdata
, Point pt
, TileIndex start_tile
, TileIndex end_tile
) OVERRIDE
268 default: NOT_REACHED();
269 case PLACE_DEMOLISH_AREA
:
270 case PLACE_LOWER_AREA
:
271 case PLACE_RAISE_AREA
:
272 case PLACE_LEVEL_AREA
:
273 GUIPlaceProcDragXY (userdata
, start_tile
, end_tile
);
279 virtual void OnPlaceObjectAbort()
281 this->RaiseButtons();
284 static HotkeyList hotkeys
;
288 * Handler for global hotkeys of the TerraformToolbarWindow.
289 * @param hotkey Hotkey
290 * @return ES_HANDLED if hotkey was accepted.
292 static EventState
TerraformToolbarGlobalHotkeys(int hotkey
)
294 if (_game_mode
!= GM_NORMAL
) return ES_NOT_HANDLED
;
295 Window
*w
= ShowTerraformToolbar(NULL
);
296 if (w
== NULL
) return ES_NOT_HANDLED
;
297 return w
->OnHotkey(hotkey
);
300 static const Hotkey terraform_hotkeys
[] = {
301 Hotkey ("lower", WID_TT_LOWER_LAND
, 'Q' | WKC_GLOBAL_HOTKEY
),
302 Hotkey ("raise", WID_TT_RAISE_LAND
, 'W' | WKC_GLOBAL_HOTKEY
),
303 Hotkey ("level", WID_TT_LEVEL_LAND
, 'E' | WKC_GLOBAL_HOTKEY
),
304 Hotkey ("dynamite", WID_TT_DEMOLISH
, 'D' | WKC_GLOBAL_HOTKEY
),
305 Hotkey ("buyland", WID_TT_BUY_LAND
, 'U'),
306 Hotkey ("trees", WID_TT_PLANT_TREES
, 'I'),
307 Hotkey ("placesign", WID_TT_PLACE_SIGN
, 'O'),
308 Hotkey ("placeobject", WID_TT_PLACE_OBJECT
, 'P'),
310 HotkeyList
TerraformToolbarWindow::hotkeys("terraform", terraform_hotkeys
, TerraformToolbarGlobalHotkeys
);
312 static const NWidgetPart _nested_terraform_widgets
[] = {
313 NWidget(NWID_HORIZONTAL
),
314 NWidget(WWT_CLOSEBOX
, COLOUR_DARK_GREEN
),
315 NWidget(WWT_CAPTION
, COLOUR_DARK_GREEN
), SetDataTip(STR_LANDSCAPING_TOOLBAR
, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS
),
316 NWidget(WWT_STICKYBOX
, COLOUR_DARK_GREEN
),
318 NWidget(NWID_HORIZONTAL
),
319 NWidget(WWT_IMGBTN
, COLOUR_DARK_GREEN
, WID_TT_LOWER_LAND
), SetMinimalSize(22, 22),
320 SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_DOWN
, STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND
),
321 NWidget(WWT_IMGBTN
, COLOUR_DARK_GREEN
, WID_TT_RAISE_LAND
), SetMinimalSize(22, 22),
322 SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_UP
, STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND
),
323 NWidget(WWT_IMGBTN
, COLOUR_DARK_GREEN
, WID_TT_LEVEL_LAND
), SetMinimalSize(22, 22),
324 SetFill(0, 1), SetDataTip(SPR_IMG_LEVEL_LAND
, STR_LANDSCAPING_LEVEL_LAND_TOOLTIP
),
326 NWidget(WWT_PANEL
, COLOUR_DARK_GREEN
), SetMinimalSize(4, 22), EndContainer(),
328 NWidget(WWT_IMGBTN
, COLOUR_DARK_GREEN
, WID_TT_DEMOLISH
), SetMinimalSize(22, 22),
329 SetFill(0, 1), SetDataTip(SPR_IMG_DYNAMITE
, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC
),
330 NWidget(WWT_IMGBTN
, COLOUR_DARK_GREEN
, WID_TT_BUY_LAND
), SetMinimalSize(22, 22),
331 SetFill(0, 1), SetDataTip(SPR_IMG_BUY_LAND
, STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND
),
332 NWidget(WWT_PUSHIMGBTN
, COLOUR_DARK_GREEN
, WID_TT_PLANT_TREES
), SetMinimalSize(22, 22),
333 SetFill(0, 1), SetDataTip(SPR_IMG_PLANTTREES
, STR_SCENEDIT_TOOLBAR_PLANT_TREES
),
334 NWidget(WWT_IMGBTN
, COLOUR_DARK_GREEN
, WID_TT_PLACE_SIGN
), SetMinimalSize(22, 22),
335 SetFill(0, 1), SetDataTip(SPR_IMG_SIGN
, STR_SCENEDIT_TOOLBAR_PLACE_SIGN
),
336 NWidget(NWID_SELECTION
, INVALID_COLOUR
, WID_TT_SHOW_PLACE_OBJECT
),
337 NWidget(WWT_PUSHIMGBTN
, COLOUR_DARK_GREEN
, WID_TT_PLACE_OBJECT
), SetMinimalSize(22, 22),
338 SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER
, STR_SCENEDIT_TOOLBAR_PLACE_OBJECT
),
343 static WindowDesc::Prefs
_terraform_prefs ("toolbar_landscape");
345 static const WindowDesc
_terraform_desc(
347 WC_SCEN_LAND_GEN
, WC_NONE
,
349 _nested_terraform_widgets
, lengthof(_nested_terraform_widgets
),
350 &_terraform_prefs
, &TerraformToolbarWindow::hotkeys
354 * Show the toolbar for terraforming in the game.
355 * @param link The toolbar we might want to link to.
356 * @return The allocated toolbar if the window was newly opened, else \c NULL.
358 Window
*ShowTerraformToolbar(Window
*link
)
360 if (!Company::IsValidID(_local_company
)) return NULL
;
364 w
= AllocateWindowDescFront
<TerraformToolbarWindow
>(&_terraform_desc
, 0);
368 /* Delete the terraform toolbar to place it again. */
369 DeleteWindowById(WC_SCEN_LAND_GEN
, 0, true);
370 w
= AllocateWindowDescFront
<TerraformToolbarWindow
>(&_terraform_desc
, 0);
371 /* Align the terraform toolbar under the main toolbar. */
374 /* Put the linked toolbar to the left / right of it. */
375 link
->left
= w
->left
+ (_current_text_dir
== TD_RTL
? w
->width
: -link
->width
);
382 static byte _terraform_size
= 1;
385 * Raise/Lower a bigger chunk of land at the same time in the editor. When
386 * raising get the lowest point, when lowering the highest point, and set all
387 * tiles in the selection to that height.
388 * @todo : Incorporate into game itself to allow for ingame raising/lowering of
389 * larger chunks at the same time OR remove altogether, as we have 'level land' ?
390 * @param tile The top-left tile where the terraforming will start
391 * @param mode true for raising, false for lowering land
393 static void CommonRaiseLowerBigLand (TileIndex tile
, bool mode
)
395 assert (_terraform_size
!= 0);
396 assert (_terraform_size
!= 1);
398 TileArea
ta (tile
, _terraform_size
, _terraform_size
);
401 if (ta
.w
== 0 || ta
.h
== 0) return;
403 if (_settings_client
.sound
.confirm
) SndPlayTileFx (SND_1F_SPLAT_OTHER
, tile
);
409 TILE_AREA_LOOP(tile2
, ta
) {
410 h
= min (h
, TileHeight(tile2
));
415 TILE_AREA_LOOP(tile2
, ta
) {
416 h
= max (h
, TileHeight(tile2
));
420 TILE_AREA_LOOP(tile2
, ta
) {
421 if (TileHeight(tile2
) == h
) {
422 DoCommandP (tile2
, SLOPE_N
, (mode
? 1 : 0) | (1 << 31), CMD_TERRAFORM_LAND
);
427 static const int8 _multi_terraform_coords
[][2] = {
429 { 4, 0}, { -4, 0}, { 0, 2},
430 { -8, 2}, { -4, 4}, { 0, 6}, { 4, 4}, { 8, 2},
431 {-12, 0}, { -8, -2}, { -4, -4}, { 0, -6}, { 4, -4}, { 8, -2}, { 12, 0},
432 {-16, 2}, {-12, 4}, { -8, 6}, { -4, 8}, { 0, 10}, { 4, 8}, { 8, 6}, { 12, 4}, { 16, 2},
433 {-20, 0}, {-16, -2}, {-12, -4}, { -8, -6}, { -4, -8}, { 0,-10}, { 4, -8}, { 8, -6}, { 12, -4}, { 16, -2}, { 20, 0},
434 {-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},
435 {-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},
438 static const NWidgetPart _nested_scen_edit_land_gen_widgets
[] = {
439 NWidget(NWID_HORIZONTAL
),
440 NWidget(WWT_CLOSEBOX
, COLOUR_DARK_GREEN
),
441 NWidget(WWT_CAPTION
, COLOUR_DARK_GREEN
), SetDataTip(STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION
, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS
),
442 NWidget(WWT_SHADEBOX
, COLOUR_DARK_GREEN
),
443 NWidget(WWT_STICKYBOX
, COLOUR_DARK_GREEN
),
445 NWidget(WWT_PANEL
, COLOUR_DARK_GREEN
),
446 NWidget(NWID_HORIZONTAL
), SetPadding(2, 2, 7, 2),
447 NWidget(NWID_SPACER
), SetFill(1, 0),
448 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_ETT_DEMOLISH
), SetMinimalSize(22, 22),
449 SetFill(0, 1), SetDataTip(SPR_IMG_DYNAMITE
, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC
),
450 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_ETT_LOWER_LAND
), SetMinimalSize(22, 22),
451 SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_DOWN
, STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND
),
452 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_ETT_RAISE_LAND
), SetMinimalSize(22, 22),
453 SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_UP
, STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND
),
454 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_ETT_LEVEL_LAND
), SetMinimalSize(22, 22),
455 SetFill(0, 1), SetDataTip(SPR_IMG_LEVEL_LAND
, STR_LANDSCAPING_LEVEL_LAND_TOOLTIP
),
456 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_ETT_PLACE_ROCKS
), SetMinimalSize(22, 22),
457 SetFill(0, 1), SetDataTip(SPR_IMG_ROCKS
, STR_TERRAFORM_TOOLTIP_PLACE_ROCKY_AREAS_ON_LANDSCAPE
),
458 NWidget(NWID_SELECTION
, INVALID_COLOUR
, WID_ETT_SHOW_PLACE_DESERT
),
459 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_ETT_PLACE_DESERT
), SetMinimalSize(22, 22),
460 SetFill(0, 1), SetDataTip(SPR_IMG_DESERT
, STR_TERRAFORM_TOOLTIP_DEFINE_DESERT_AREA
),
462 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_ETT_PLACE_OBJECT
), SetMinimalSize(23, 22),
463 SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER
, STR_SCENEDIT_TOOLBAR_PLACE_OBJECT
),
464 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_ETT_PLACE_HOUSE
), SetMinimalSize(23, 22),
465 SetFill(0, 1), SetDataTip(SPR_IMG_TOWN
, STR_SCENEDIT_TOOLBAR_PLACE_HOUSE
),
466 NWidget(NWID_SPACER
), SetFill(1, 0),
468 NWidget(NWID_HORIZONTAL
),
469 NWidget(NWID_SPACER
), SetFill(1, 0),
470 NWidget(WWT_EMPTY
, COLOUR_DARK_GREEN
, WID_ETT_DOTS
), SetMinimalSize(59, 31), SetDataTip(STR_EMPTY
, STR_NULL
),
471 NWidget(NWID_SPACER
), SetFill(1, 0),
472 NWidget(NWID_VERTICAL
),
473 NWidget(NWID_SPACER
), SetFill(0, 1),
474 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_ETT_INCREASE_SIZE
), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_UP
, STR_TERRAFORM_TOOLTIP_INCREASE_SIZE_OF_LAND_AREA
),
475 NWidget(NWID_SPACER
), SetMinimalSize(0, 1),
476 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_ETT_DECREASE_SIZE
), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_DOWN
, STR_TERRAFORM_TOOLTIP_DECREASE_SIZE_OF_LAND_AREA
),
477 NWidget(NWID_SPACER
), SetFill(0, 1),
479 NWidget(NWID_SPACER
), SetMinimalSize(2, 0),
481 NWidget(NWID_SPACER
), SetMinimalSize(0, 6),
482 NWidget(WWT_TEXTBTN
, COLOUR_GREY
, WID_ETT_NEW_SCENARIO
), SetMinimalSize(160, 12),
483 SetFill(1, 0), SetDataTip(STR_TERRAFORM_SE_NEW_WORLD
, STR_TERRAFORM_TOOLTIP_GENERATE_RANDOM_LAND
), SetPadding(0, 2, 0, 2),
484 NWidget(WWT_TEXTBTN
, COLOUR_GREY
, WID_ETT_RESET_LANDSCAPE
), SetMinimalSize(160, 12),
485 SetFill(1, 0), SetDataTip(STR_TERRAFORM_RESET_LANDSCAPE
, STR_TERRAFORM_RESET_LANDSCAPE_TOOLTIP
), SetPadding(1, 2, 2, 2),
490 * Callback function for the scenario editor 'reset landscape' confirmation window
491 * @param w Window unused
492 * @param confirmed boolean value, true when yes was clicked, false otherwise
494 static void ResetLandscapeConfirmationCallback(Window
*w
, bool confirmed
)
497 /* Set generating_world to true to get instant-green grass after removing
498 * company property. */
499 _generating_world
= true;
501 /* Delete all companies */
503 FOR_ALL_COMPANIES(c
) {
504 ChangeOwnershipOfCompanyItems(c
->index
, INVALID_OWNER
);
508 _generating_world
= false;
510 /* Delete all station signs */
512 FOR_ALL_BASE_STATIONS(st
) {
513 /* There can be buoys, remove them */
514 if (IsBuoyTile(st
->xy
)) DoCommand(st
->xy
, 0, 0, DC_EXEC
| DC_BANKRUPT
, CMD_LANDSCAPE_CLEAR
);
515 if (!st
->IsInUse()) delete st
;
518 /* Now that all vehicles are gone, we can reset the engine pool. Maybe it reduces some NewGRF changing-mess */
519 EngineOverrideManager::ResetToCurrentNewGRFConfig();
521 MarkWholeScreenDirty();
525 /** Landscape generation window handler in the scenario editor. */
526 struct ScenarioEditorLandscapeGenerationWindow
: Window
{
527 int placing_action
; ///< Currently active placing action.
529 ScenarioEditorLandscapeGenerationWindow (const WindowDesc
*desc
, WindowNumber window_number
) :
530 Window (desc
), placing_action (-1)
532 this->CreateNestedTree();
533 NWidgetStacked
*show_desert
= this->GetWidget
<NWidgetStacked
>(WID_ETT_SHOW_PLACE_DESERT
);
534 show_desert
->SetDisplayedPlane(_settings_game
.game_creation
.landscape
== LT_TROPIC
? 0 : SZSP_NONE
);
535 this->InitNested(window_number
);
538 void OnPaint (BlitArea
*dpi
) OVERRIDE
540 this->DrawWidgets (dpi
);
542 if (this->IsWidgetLowered(WID_ETT_LOWER_LAND
) || this->IsWidgetLowered(WID_ETT_RAISE_LAND
)) { // change area-size if raise/lower corner is selected
543 SetTileSelectSize(_terraform_size
, _terraform_size
);
547 virtual void UpdateWidgetSize(int widget
, Dimension
*size
, const Dimension
&padding
, Dimension
*fill
, Dimension
*resize
)
549 if (widget
!= WID_ETT_DOTS
) return;
551 size
->width
= max
<uint
>(size
->width
, ScaleGUITrad(59));
552 size
->height
= max
<uint
>(size
->height
, ScaleGUITrad(31));
555 void DrawWidget (BlitArea
*dpi
, const Rect
&r
, int widget
) const OVERRIDE
557 if (widget
!= WID_ETT_DOTS
) return;
559 int center_x
= RoundDivSU(r
.left
+ r
.right
, 2);
560 int center_y
= RoundDivSU(r
.top
+ r
.bottom
, 2);
562 int n
= _terraform_size
* _terraform_size
;
563 const int8
*coords
= &_multi_terraform_coords
[0][0];
567 DrawSprite (dpi
, SPR_WHITE_POINT
, PAL_NONE
, center_x
+ ScaleGUITrad(coords
[0]), center_y
+ ScaleGUITrad(coords
[1]));
572 virtual void OnClick(Point pt
, int widget
, int click_count
)
574 if (widget
< WID_ETT_BUTTONS_START
) return;
577 case WID_ETT_DEMOLISH
: // Demolish aka dynamite button
578 HandlePlacePushButton (this, WID_ETT_DEMOLISH
, ANIMCURSOR_DEMOLISH
, POINTER_TILE
);
579 this->placing_action
= PLACE_DEMOLISH_AREA
;
582 case WID_ETT_LOWER_LAND
: // Lower land button
583 HandlePlacePushButton (this, WID_ETT_LOWER_LAND
, ANIMCURSOR_LOWERLAND
, POINTER_CORNER
);
584 this->placing_action
= PLACE_LOWER_AREA
;
587 case WID_ETT_RAISE_LAND
: // Raise land button
588 HandlePlacePushButton (this, WID_ETT_RAISE_LAND
, ANIMCURSOR_RAISELAND
, POINTER_CORNER
);
589 this->placing_action
= PLACE_RAISE_AREA
;
592 case WID_ETT_LEVEL_LAND
: // Level land button
593 HandlePlacePushButton (this, WID_ETT_LEVEL_LAND
, SPR_CURSOR_LEVEL_LAND
, POINTER_CORNER
);
594 this->placing_action
= PLACE_LEVEL_AREA
;
597 case WID_ETT_PLACE_ROCKS
: // Place rocks button
598 HandlePlacePushButton (this, WID_ETT_PLACE_ROCKS
, SPR_CURSOR_ROCKY_AREA
, POINTER_TILE
);
599 this->placing_action
= PLACE_CREATE_ROCKS
;
602 case WID_ETT_PLACE_DESERT
: // Place desert button (in tropical climate)
603 HandlePlacePushButton (this, WID_ETT_PLACE_DESERT
, SPR_CURSOR_DESERT
, POINTER_TILE
);
604 this->placing_action
= PLACE_CREATE_DESERT
;
607 case WID_ETT_PLACE_OBJECT
: // Place transmitter button
608 ShowBuildObjectPicker();
611 case WID_ETT_PLACE_HOUSE
: // Place house button
612 ShowBuildHousePicker();
615 case WID_ETT_INCREASE_SIZE
:
616 case WID_ETT_DECREASE_SIZE
: { // Increase/Decrease terraform size
617 int size
= (widget
== WID_ETT_INCREASE_SIZE
) ? 1 : -1;
618 this->HandleButtonClick(widget
);
619 size
+= _terraform_size
;
621 if (!IsInsideMM(size
, 1, 8 + 1)) return;
622 _terraform_size
= size
;
624 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
629 case WID_ETT_NEW_SCENARIO
: // gen random land
630 this->HandleButtonClick(widget
);
631 ShowCreateScenario();
634 case WID_ETT_RESET_LANDSCAPE
: // Reset landscape
635 ShowQuery(STR_QUERY_RESET_LANDSCAPE_CAPTION
, STR_RESET_LANDSCAPE_CONFIRMATION_TEXT
, NULL
, ResetLandscapeConfirmationCallback
);
638 default: NOT_REACHED();
642 virtual void OnTimeout()
644 for (uint i
= WID_ETT_START
; i
< this->nested_array_size
; i
++) {
645 if (this->IsWidgetLowered(i
)) {
646 this->RaiseWidget(i
);
647 this->SetWidgetDirty(i
);
652 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
654 switch (this->placing_action
) {
655 case PLACE_LOWER_AREA
:
656 case PLACE_RAISE_AREA
:
657 if (_terraform_size
!= 1) {
658 CommonRaiseLowerBigLand (tile
, this->placing_action
== PLACE_RAISE_AREA
);
663 VpStartPlaceSizing (tile
, VPM_X_AND_Y_ROTATED
, this->placing_action
);
666 case PLACE_CREATE_ROCKS
:
667 case PLACE_CREATE_DESERT
:
668 VpStartPlaceSizing (tile
, VPM_X_AND_Y
, this->placing_action
);
673 void OnPlaceMouseUp (int userdata
, Point pt
, TileIndex start_tile
, TileIndex end_tile
) OVERRIDE
677 default: NOT_REACHED();
678 case PLACE_DEMOLISH_AREA
:
679 case PLACE_LOWER_AREA
:
680 case PLACE_RAISE_AREA
:
681 case PLACE_LEVEL_AREA
:
682 case PLACE_CREATE_ROCKS
:
683 case PLACE_CREATE_DESERT
:
684 GUIPlaceProcDragXY (userdata
, start_tile
, end_tile
);
690 virtual void OnPlaceObjectAbort()
692 this->RaiseButtons();
696 static HotkeyList hotkeys
;
700 * Handler for global hotkeys of the ScenarioEditorLandscapeGenerationWindow.
701 * @param hotkey Hotkey
702 * @return ES_HANDLED if hotkey was accepted.
704 static EventState
TerraformToolbarEditorGlobalHotkeys(int hotkey
)
706 if (_game_mode
!= GM_EDITOR
) return ES_NOT_HANDLED
;
707 Window
*w
= ShowEditorTerraformToolbar();
708 if (w
== NULL
) return ES_NOT_HANDLED
;
709 return w
->OnHotkey(hotkey
);
712 static const Hotkey terraform_editor_hotkeys
[] = {
713 Hotkey ("dynamite", WID_ETT_DEMOLISH
, 'D' | WKC_GLOBAL_HOTKEY
),
714 Hotkey ("lower", WID_ETT_LOWER_LAND
, 'Q' | WKC_GLOBAL_HOTKEY
),
715 Hotkey ("raise", WID_ETT_RAISE_LAND
, 'W' | WKC_GLOBAL_HOTKEY
),
716 Hotkey ("level", WID_ETT_LEVEL_LAND
, 'E' | WKC_GLOBAL_HOTKEY
),
717 Hotkey ("rocky", WID_ETT_PLACE_ROCKS
, 'R'),
718 Hotkey ("desert", WID_ETT_PLACE_DESERT
, 'T'),
719 Hotkey ("object", WID_ETT_PLACE_OBJECT
, 'O'),
720 Hotkey ("house", WID_ETT_PLACE_HOUSE
, 'H'),
723 HotkeyList
ScenarioEditorLandscapeGenerationWindow::hotkeys("terraform_editor", terraform_editor_hotkeys
, TerraformToolbarEditorGlobalHotkeys
);
725 static WindowDesc::Prefs
_scen_edit_land_gen_prefs ("toolbar_landscape_scen");
727 static const WindowDesc
_scen_edit_land_gen_desc(
729 WC_SCEN_LAND_GEN
, WC_NONE
,
731 _nested_scen_edit_land_gen_widgets
, lengthof(_nested_scen_edit_land_gen_widgets
),
732 &_scen_edit_land_gen_prefs
, &ScenarioEditorLandscapeGenerationWindow::hotkeys
736 * Show the toolbar for terraforming in the scenario editor.
737 * @return The allocated toolbar if the window was newly opened, else \c NULL.
739 Window
*ShowEditorTerraformToolbar()
741 return AllocateWindowDescFront
<ScenarioEditorLandscapeGenerationWindow
>(&_scen_edit_land_gen_desc
, 0);