summaryrefslogtreecommitdiff
path: root/src/underground_gui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/underground_gui.cpp')
-rw-r--r--src/underground_gui.cpp294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/underground_gui.cpp b/src/underground_gui.cpp
new file mode 100644
index 000000000..958ddb2b0
--- /dev/null
+++ b/src/underground_gui.cpp
@@ -0,0 +1,294 @@
+/* $Id: terraform_gui.cpp 23547 2011-12-16 18:21:13Z truebrain $ */
+
+/*
+ * This file is part of OpenTTD.
+ * 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.
+ * 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.
+ * 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/>.
+ */
+
+/** @file terraform_gui.cpp GUI related to terraforming the map. */
+
+#include "stdafx.h"
+#include "clear_map.h"
+#include "company_func.h"
+#include "company_base.h"
+#include "gui.h"
+#include "window_gui.h"
+#include "window_func.h"
+#include "layer_func.h"
+#include "viewport_func.h"
+#include "command_func.h"
+#include "signs_func.h"
+#include "sound_func.h"
+#include "base_station_base.h"
+#include "textbuf_gui.h"
+#include "genworld.h"
+#include "tree_map.h"
+#include "landscape_type.h"
+#include "tilehighlight_func.h"
+#include "strings_func.h"
+#include "newgrf_object.h"
+#include "newgrf_station.h"
+#include "object.h"
+#include "hotkeys.h"
+#include "engine_base.h"
+
+#include "widgets/underground_widget.h"
+
+#include "table/strings.h"
+#include "error.h"
+
+void ShowError(TileIndex tile, CommandCost res, uint32 cmd)
+{
+ int x = TileX(tile) * TILE_SIZE;
+ int y = TileY(tile) * TILE_SIZE;
+ StringID error_part1 = GB(cmd, 16, 16);
+
+ if (IsLocalCompany() && error_part1 != 0) {
+ ShowErrorMessage(error_part1, res.GetErrorMessage(), WL_INFO, x, y, res.GetTextRefStackSize(), res.GetTextRefStack());
+ }
+}
+
+
+/**
+ * Place a escalator.
+ * @param tile Position to place or start dragging a station.
+ */
+static void PlaceUnderground_Escalator(TileIndex tile)
+{
+ RailType railtype = RAILTYPE_RAIL;
+ Axis orientation = AXIS_X;
+ StationClassID station_class = STAT_CLASS_DFLT;
+ byte station_type = 0;
+
+ uint32 p1 = railtype | orientation << 4 | 1 << 8 | 1 << 16 | _ctrl_pressed << 24;
+ uint32 p2 = station_class | station_type << 8 | INVALID_STATION << 16;
+
+ int w = 1;
+ int h = 1;
+
+ uint top_tile = TopTile(tile);
+ uint base_tile = tile;
+ bool from_top = false; // Строим от верхнего слоя
+
+ if (top_tile == base_tile)
+ {
+ from_top = true;
+ base_tile += LayerSize();
+ };
+
+ uint32 cmdS = CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_UNDERGROUND_CAN_T_BUILD_PART);
+ uint32 cmdT = CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_UNDERGROUND_CAN_T_BUILD_TOP_PART);
+ uint32 cmdB = CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_UNDERGROUND_CAN_T_BUILD_BOTTOM_PART);
+ CommandContainer cmdTop = { top_tile, p1, p2, cmdT, CcStation, "" };
+ CommandContainer cmdBase = { base_tile, p1, p2, cmdB, CcStation, "" };
+
+ DoCommandFlag flags = DC_AUTO | DC_NO_WATER;
+ CommandCost resTop;
+ CommandCost res;
+
+ // Проверяем возможность постройки верха и низа:
+ resTop=DoCommand(&cmdTop, flags | DC_QUERY_COST);
+ if (resTop.Failed())
+ {
+ ShowError(tile, resTop, cmdT);
+ return;
+ }
+
+ res=DoCommand(&cmdBase, flags | DC_QUERY_COST);
+ if (res.Failed())
+ {
+ ShowError(tile, res, cmdB);
+ return;
+ }
+
+ res.AddCost(resTop.GetCost());
+ if (_shift_pressed || !CheckCompanyHasMoney(res))
+ {
+ if (res.Failed()) ShowError(tile, res, cmdS);
+ else ShowEstimatedCostOrIncome(res.GetCost(), TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE);
+ return;
+ }
+
+ // Станции могут быть сверху и снизу.
+ // Чтобы не было конфликта, нужно строить от активного слоя
+ CommandContainer *cmd1 = from_top ? &cmdTop : &cmdBase;
+ CommandContainer *cmd2 = from_top ? &cmdBase : &cmdTop;
+
+ // Строим уровень (в активном слое)
+ res=DoCommand(cmd1, flags | DC_EXEC);
+ assert(!res.Failed());
+
+ // Уточняем параметры
+ StationID station = GetStationIndex(cmd1->tile);
+ cmd2->p2 = station_class | station_type << 8 | station << 16;
+
+ // Строим уровень (в другом слое)
+ res=DoCommand(cmd2, flags | DC_EXEC);
+ assert(!res.Failed());
+}
+
+/** Underground toolbar managing class. */
+struct UndergroundToolbarWindow : Window {
+ int last_user_action; ///< Last started user action.
+
+ UndergroundToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
+ {
+ /* This is needed as we like to have the tree available on OnInit. */
+ this->CreateNestedTree(desc);
+ this->FinishInitNested(desc, window_number);
+ this->last_user_action = WIDGET_LIST_END;
+ }
+
+ ~UndergroundToolbarWindow()
+ {
+ }
+
+ virtual void OnInit()
+ {
+ }
+
+ virtual void OnClick(Point pt, int widget, int click_count)
+ {
+ switch (widget) {
+ case WID_UT_BUILD_ESCALATOR: // WID_TT_BUILD_ESCALATOR
+ HandlePlacePushButton(this, WID_UT_BUILD_ESCALATOR, SPR_CURSOR_RAIL_STATION, HT_RECT);
+ this->last_user_action = widget;
+ break;
+
+ case WID_UT_DEMOLISH: // Demolish aka dynamite button
+ HandlePlacePushButton(this, WID_UT_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT | HT_DIAGONAL);
+ this->last_user_action = widget;
+ break;
+
+ default: NOT_REACHED();
+ }
+ }
+
+ virtual void OnTimeout()
+ {
+ }
+
+ virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+ {
+ int num = CheckHotkeyMatch(underground_hotkeys, keycode, this);
+ if (num == -1) return ES_NOT_HANDLED;
+ this->OnClick(Point(), num, 1);
+ return ES_HANDLED;
+ }
+
+ virtual void OnPlaceObject(Point pt, TileIndex tile)
+ {
+ switch (this->last_user_action) {
+ case WID_UT_BUILD_ESCALATOR:
+ PlaceUnderground_Escalator(tile);
+ break;
+
+ case WID_UT_DEMOLISH: // Demolish aka dynamite button
+ PlaceProc_DemolishArea(tile);
+ break;
+
+ default: NOT_REACHED();
+ }
+ }
+
+ virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
+ {
+ VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+ }
+
+ virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number)
+ {
+ Point pt = GetToolbarAlignedWindowPosition(sm_width);
+ pt.y += sm_height;
+ return pt;
+ }
+
+ virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+ {
+ if (pt.x != -1) {
+ switch (select_proc) {
+ default: NOT_REACHED();
+ case DDSP_DEMOLISH_AREA:
+ GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
+ break;
+ }
+ }
+ }
+
+ virtual void OnPlaceObjectAbort()
+ {
+ DeleteWindowById(WC_BUILD_OBJECT, 0);
+ this->RaiseButtons();
+ }
+
+ static Hotkey<UndergroundToolbarWindow> underground_hotkeys[];
+};
+
+Hotkey<UndergroundToolbarWindow> UndergroundToolbarWindow::underground_hotkeys[] = {
+ Hotkey<UndergroundToolbarWindow>('D' | WKC_GLOBAL_HOTKEY, "dynamite", WID_UT_DEMOLISH),
+ Hotkey<UndergroundToolbarWindow>('0', "placeescalator", WID_UT_BUILD_ESCALATOR),
+ HOTKEY_LIST_END(UndergroundToolbarWindow)
+};
+Hotkey<UndergroundToolbarWindow> *_underground_hotkeys = UndergroundToolbarWindow::underground_hotkeys;
+
+static const NWidgetPart _nested_underground_widgets[] = {
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
+ NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_UNDERGROUND_BUILD, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+ NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_UT_BUILD_ESCALATOR),
+ SetFill(0, 1), SetMinimalSize(42, 22), SetDataTip(SPR_IMG_RAIL_STATION, STR_UNDERGROUND_TOOLTIP_ESCALATOR),
+ NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(64, 22), EndContainer(),
+ NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_UT_DEMOLISH), SetMinimalSize(22, 22),
+ SetFill(0, 1), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
+ EndContainer(),
+};
+
+static const WindowDesc _underground_desc(
+ WDP_MANUAL, 0, 0,
+ WC_UNDERGROUND, WC_NONE,
+ WDF_CONSTRUCTION,
+ _nested_underground_widgets, lengthof(_nested_underground_widgets)
+);
+
+/**
+ * Show the toolbar for terraforming in the game.
+ * @param link The toolbar we might want to link to.
+ * @return The allocated toolbar.
+ */
+Window *ShowUndergroundToolbar(Window *link)
+{
+ if (!Company::IsValidID(_local_company)) return NULL;
+
+ Window *w;
+ if (link == NULL) {
+ w = AllocateWindowDescFront<UndergroundToolbarWindow>(&_underground_desc, 0);
+ return w;
+ }
+
+ /* Delete the terraform toolbar to place it again. */
+ DeleteWindowById(WC_UNDERGROUND, 0, true);
+ w = AllocateWindowDescFront<UndergroundToolbarWindow>(&_underground_desc, 0);
+ /* Align the terraform toolbar under the main toolbar. */
+ w->top -= w->height;
+ w->SetDirty();
+ /* Put the linked toolbar to the left / right of it. */
+ link->left = w->left + (_current_text_dir == TD_RTL ? w->width : -link->width);
+ link->top = w->top;
+ link->SetDirty();
+
+ return w;
+}
+
+EventState UndergroundToolbarGlobalHotkeys(uint16 key, uint16 keycode)
+{
+ int num = CheckHotkeyMatch<UndergroundToolbarWindow>(_underground_hotkeys, keycode, NULL, true);
+ if (num == -1) return ES_NOT_HANDLED;
+ Window *w = ShowUndergroundToolbar(NULL);
+ if (w == NULL) return ES_NOT_HANDLED;
+ return w->OnKeyPress(key, keycode);
+}