diff options
author | Erich Eckner <git@eckner.net> | 2018-10-30 11:13:12 +0100 |
---|---|---|
committer | Erich Eckner <git@eckner.net> | 2018-10-30 15:28:03 +0100 |
commit | a34d095259409cf1454d9777deabbc00bcdb9407 (patch) | |
tree | 9e7c37ed33f5bd6b3c2f41cf248dcb656b2a4afa /src/underground_gui.cpp | |
parent | 6647cb917963c4e0d6d633b7a92af78167050893 (diff) | |
download | openttd-underground-plus-others-original.tar.xz |
underground patch appliedunderground-plus-others-original
Diffstat (limited to 'src/underground_gui.cpp')
-rw-r--r-- | src/underground_gui.cpp | 294 |
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); +} |