From 6de087786cbd83ad1cc938d6f68e303cf4e5d0a7 Mon Sep 17 00:00:00 2001 From: patch-import Date: Sun, 2 Aug 2015 10:57:53 +0100 Subject: [PATCH] Import and rebase zoning patch Fix some of the whitespace issues http://www.tt-forums.net/viewtopic.php?p=888801#p888801 --- bin/data/innerhighlight.grf | Bin 0 -> 6953 bytes projects/openttd_vs100.vcxproj | 3 + projects/openttd_vs100.vcxproj.filters | 9 + projects/openttd_vs80.vcproj | 12 + projects/openttd_vs90.vcproj | 12 + source.list | 3 + src/gfxinit.cpp | 2 + src/lang/danish.txt | 1 + src/lang/english.txt | 18 ++ src/table/sprites.h | 12 + src/toolbar_gui.cpp | 4 + src/viewport.cpp | 6 +- src/window_type.h | 1 + src/zoning.h | 39 +++ src/zoning_cmd.cpp | 378 +++++++++++++++++++++++++ src/zoning_gui.cpp | 127 +++++++++ 16 files changed, 626 insertions(+), 1 deletion(-) create mode 100644 bin/data/innerhighlight.grf create mode 100644 src/zoning.h create mode 100644 src/zoning_cmd.cpp create mode 100644 src/zoning_gui.cpp diff --git a/bin/data/innerhighlight.grf b/bin/data/innerhighlight.grf new file mode 100644 index 0000000000000000000000000000000000000000..4118f515d1b0885c54907d5dfe4644bcdb928130 GIT binary patch literal 6953 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 J?umox{uOh1#7O`E literal 0 HcmV?d00001 diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj index 37f9948032..47c821b9dd 100644 --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -660,6 +660,7 @@ + @@ -745,6 +746,7 @@ + @@ -828,6 +830,7 @@ + diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters index 06800ffdaf..911fef1d70 100644 --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -1209,6 +1209,9 @@ Header Files + + Header Files + Core Source Code @@ -1464,6 +1467,9 @@ GUI Source Code + + GUI Source Code + Widgets @@ -1713,6 +1719,9 @@ Command handlers + + Command handlers + Save/Load handlers diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index f859fcf18a..e589269151 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -1914,6 +1914,10 @@ RelativePath=".\..\src\zoom_type.h" > + + + + + + + + + + + + Append() = new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS, OME_SCRIPT_SETTINGS, false); *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS, OME_NEWGRFSETTINGS, false); + *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_ZONING, OME_ZONING, false); *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS, OME_TRANSPARENCIES, false); *list->Append() = new DropDownListItem(-1, false); *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED, OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES)); @@ -347,6 +350,7 @@ static CallBackFunction MenuClickSettings(int index) case OME_SETTINGS: ShowGameSettings(); return CBF_NONE; case OME_SCRIPT_SETTINGS: ShowAIConfigWindow(); return CBF_NONE; case OME_NEWGRFSETTINGS: ShowNewGRFSettings(!_networking && _settings_client.gui.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig); return CBF_NONE; + case OME_ZONING: ShowZoningToolbar(); break; case OME_TRANSPARENCIES: ShowTransparencyToolbar(); break; case OME_SHOW_TOWNNAMES: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES); break; diff --git a/src/viewport.cpp b/src/viewport.cpp index a1bb2c81d1..142738be41 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -80,6 +80,7 @@ #include "waypoint_func.h" #include "window_func.h" #include "tilehighlight_func.h" +#include "zoning.h" #include "window_gui.h" #include "linkgraph/linkgraph_gui.h" #include "viewport_sprite_sorter.h" @@ -1200,7 +1201,10 @@ static void ViewportAddLandscape() _vd.last_foundation_child[1] = NULL; _tile_type_procs[tile_type]->draw_tile_proc(&tile_info); - if (tile_info.tile != INVALID_TILE) DrawTileSelection(&tile_info); + if (tile_info.tile != INVALID_TILE) { + DrawTileSelection(&tile_info); + DrawTileZoning(&tile_info); + } } } } diff --git a/src/window_type.h b/src/window_type.h index 809e81d485..bc4e014964 100644 --- a/src/window_type.h +++ b/src/window_type.h @@ -668,6 +668,7 @@ enum WindowClass { * - 0 = #SpriteAlignerWidgets */ WC_SPRITE_ALIGNER, + WC_ZONING_TOOLBAR, /** * Linkgraph legend; %Window numbers: diff --git a/src/zoning.h b/src/zoning.h new file mode 100644 index 0000000000..01842a91e2 --- /dev/null +++ b/src/zoning.h @@ -0,0 +1,39 @@ +/** @file zoning.h */ + +#ifndef ZONING_H_ +#define ZONING_H_ + +#include "openttd.h" +#include "tile_cmd.h" + +enum EvaluationMode { + CHECKNOTHING = 0, + CHECKOPINION = 1, ///< Check the local authority's opinion. + CHECKBUILD = 2, ///< Check wither or not the player can build. + CHECKSTACATCH = 3, ///< Check catchment area for stations + CHECKINDCATCH = 4, ///< Check catchment area for industries + CHECKBULCATCH = 5, ///< Check catchment area for buildings + CHECKBULUNSER = 6, ///< Check for unserved buildings + CHECKINDUNSER = 7, ///< Check for unserved industries +}; + +struct Zoning { + EvaluationMode inner; + EvaluationMode outer; + int inner_val; + int outer_val; +}; + +VARDEF Zoning _zoning; + +SpriteID TileZoningSpriteEvaluation(TileIndex tile, Owner owner, EvaluationMode ev_mode); + +int TileZoningEvaluation(TileIndex tile, Owner owner, EvaluationMode ev_mode); + +void DrawTileZoning(const TileInfo *ti); + +void ShowZoningToolbar(); + +EvaluationMode GetEvaluationModeFromInt(int ev_mode); + +#endif /*ZONING_H_*/ diff --git a/src/zoning_cmd.cpp b/src/zoning_cmd.cpp new file mode 100644 index 0000000000..671d8c6dc6 --- /dev/null +++ b/src/zoning_cmd.cpp @@ -0,0 +1,378 @@ + +/** @file zoning_cmd.cpp */ + +#include "stdafx.h" +#include "openttd.h" +#include "station_type.h" +#include "station_base.h" +#include "industry.h" +#include "gfx_func.h" +#include "viewport_func.h" +#include "variables.h" +#include "map_func.h" +#include "company_func.h" +#include "town_map.h" +#include "table/sprites.h" +#include "station_func.h" +#include "station_map.h" +#include "town.h" +#include "zoning.h" + +Zoning _zoning; + +/** + * Draw the zoning sprites. + * + * @param SpriteID image + * the image + * @param SpriteID colour + * the colour of the zoning + * @param TileInfo ti + * the tile + */ +void DrawZoningSprites(SpriteID image, SpriteID colour, const TileInfo *ti) { + if ( colour!=INVALID_SPRITE_ID ) + AddSortableSpriteToDraw(image + _tileh_to_sprite[ti->tileh], colour, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7); +} + +/** + * Detect whether this area is within the acceptance of any station. + * + * @param TileArea area + * the area to search by + * @param Owner owner + * the owner of the stations which we need to match again + * @return true if a station is found + */ +bool IsAreaWithinAcceptanceZoneOfStation(TileArea area, Owner owner) { + + // TODO: Actually do owner check. + + int catchment = _settings_game.station.station_spread + (_settings_game.station.modified_catchment ? MAX_CATCHMENT : CA_UNMODIFIED); + + StationFinder morestations(TileArea(TileXY(TileX(area.tile)-catchment/2, TileY(area.tile)-catchment/2), + TileX(area.tile) + area.w + catchment, TileY(area.tile) + area.h + catchment)); + + for ( Station * const *st_iter = morestations.GetStations()->Begin(); st_iter != morestations.GetStations()->End(); ++st_iter ) { + Station *st = *st_iter; + Rect rect = st->GetCatchmentRect(); + return TileArea(TileXY(rect.left, rect.top), TileXY(rect.right, rect.bottom)).Intersects(area); + } + + return false; +} + +/** + * Detect whether this tile is within the acceptance of any station. + * + * @param TileIndex tile + * the tile to search by + * @param Owner owner + * the owner of the stations + * @return true if a station is found + */ +bool IsTileWithinAcceptanceZoneOfStation(TileIndex tile, Owner owner) { + + // TODO: Actually do owner check. + + int catchment = _settings_game.station.station_spread + (_settings_game.station.modified_catchment ? MAX_CATCHMENT : CA_UNMODIFIED); + + StationFinder morestations(TileArea(TileXY(TileX(tile)-catchment/2, TileY(tile)-catchment/2), + catchment, catchment)); + + for ( Station * const *st_iter = morestations.GetStations()->Begin(); st_iter != morestations.GetStations()->End(); ++st_iter ) { + Station *st = *st_iter; + Rect rect = st->GetCatchmentRect(); + if ( (uint)rect.left <= TileX(tile) && TileX(tile) <= (uint)rect.right + && (uint)rect.top <= TileY(tile) && TileY(tile) <= (uint)rect.bottom ) + return true; + } + + return false; +} + +/** + * Check whether the player can build in tile. + * + * @param TileIndex tile + * @param Owner owner + * @return red if they cannot + */ +SpriteID TileZoneCheckBuildEvaluation(TileIndex tile, Owner owner) { + /* Let's first check for the obvious things you cannot build on */ + switch ( GetTileType(tile) ) { + case MP_INDUSTRY: + case MP_UNMOVABLE: + case MP_STATION: + case MP_HOUSE: + case MP_TUNNELBRIDGE: return SPR_PALETTE_ZONING_RED; + /* There are only two things you can own (or some else + * can own) that you can still build on. i.e. roads and + * railways. + * @todo + * Add something more intelligent, check what tool the + * user is currently using (and if none, assume some + * standards), then check it against if owned by some- + * one else (e.g. railway on someone else's road). + * While that being said, it should also check if it + * is not possible to build railway/road on someone + * else's/your own road/railway (e.g. the railway track + * is curved or a cross).*/ + case MP_ROAD: + case MP_RAILWAY: { + if ( GetTileOwner(tile) != owner ) + return SPR_PALETTE_ZONING_RED; + else + return INVALID_SPRITE_ID; + } + default: return INVALID_SPRITE_ID; + } +} + +/** + * Check the opinion of the local authority in the tile. + * + * @param TileIndex tile + * @param Owner owner + * @return black if no opinion, orange if bad, + * light blue if good or invalid if no town + */ +SpriteID TileZoneCheckOpinionEvaluation(TileIndex tile, Owner owner) { + int opinion = 0; // 0: no town, 1: no opinion, 2: bad, 3: good + Town *town = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority); + + if ( town !=NULL ) { + if ( HasBit(town->have_ratings, owner) ) { + opinion = ( town->ratings[owner] > 0 ) ? 3 : 2; + } else { + opinion = 1; + } + } + + switch ( opinion ) { + case 1: return SPR_PALETTE_ZONING_BLACK; // no opinion + case 2: return SPR_PALETTE_ZONING_ORANGE; // bad + case 3: return SPR_PALETTE_ZONING_LIGHT_BLUE; // good + default: return INVALID_SPRITE_ID; // no town + } +} + +/** + * Detect whether the tile is within the 'catchment' zone of an industry. + * + * @param TileIndex tile + * @param Owner owner + * @return The colour depends on the distance to the industry: + * 1-3 White (lorry/bus) + * 4 Blue (train station/some airports) + * 5 Green (docks/some airports) + * 6 Yellow (some airports) + * 7-9 Light blue (international airport) + */ +SpriteID TileZoneCheckIndustryCatchmentEvaluation(TileIndex tile, Owner owner) { + + // TODO: Implement this! + + return INVALID_SPRITE_ID; +} + +/** + * Detect whether the tile is within the catchment zone of a station. + * + * @param TileIndex tile + * @param Owner owner + * @return black if within, light blue if only in acceptance zone + * and nothing if no nearby station. + */ +SpriteID TileZoneCheckStationCatchmentEvaluation(TileIndex tile, Owner owner) { + + //TODO: Actually check owner. + + // Never on a station. + if ( IsTileType(tile, MP_STATION) ) + return INVALID_SPRITE_ID; + + // For provided goods + + StationFinder stations(TileArea(tile, 1, 1)); + + if ( stations.GetStations()->Length() > 0 ) { + return SPR_PALETTE_ZONING_BLACK; + } + + // For accepted goods + + if ( IsTileWithinAcceptanceZoneOfStation(tile, owner) ) + return SPR_PALETTE_ZONING_LIGHT_BLUE; + + return INVALID_SPRITE_ID; +} + +/** + * Detect whether a tile is within the 'catchment' zone of a building. + * + * @param TileIndex tile + * @param Owner owner + * @return The colour depends on the distance to the building: + * 1-3 White (lorry/bus) + * 4 Blue (train station/some airports) + * 5 Green (docks/some airports) + * 6 Yellow (some airports) + * 7-9 Light blue (international airport) + */ +SpriteID TileZoneCheckBuildingCatchmentEvaluation(TileIndex tile, Owner owner) { + // TODO: Implement this! + + return INVALID_SPRITE_ID; +} + +/** + * Detect whether a building is unserved by a station of owner. + * + * @param TileIndex tile + * @param Owner owner + * @return red if unserved, orange if only accepting, nothing if served or not + * a building + */ +SpriteID TileZoneCheckUnservedBuildingsEvaluation(TileIndex tile, Owner owner) { + + //TODO: Actually use owner. + + CargoArray dat; + + if ( IsTileType (tile, MP_HOUSE) + && ( ( memset(&dat, 0, sizeof(dat)), AddAcceptedCargo(tile, dat, NULL), (dat[CT_MAIL] + dat[CT_PASSENGERS] > 0) ) + || ( memset(&dat, 0, sizeof(dat)), AddProducedCargo(tile, dat), (dat[CT_MAIL] + dat[CT_PASSENGERS] > 0) ) ) ) { + StationFinder stations(TileArea(tile, 1, 1)); + + if ( stations.GetStations()->Length() > 0 ) { + return INVALID_SPRITE_ID; + } + + // For accepted goods + + if ( IsTileWithinAcceptanceZoneOfStation(tile, owner) ) + return SPR_PALETTE_ZONING_ORANGE; + + //TODO: Check for stations that does not accept mail/passengers, + //which is currently only truck stops. + + return SPR_PALETTE_ZONING_RED; + } + + return INVALID_SPRITE_ID; +} + +/** + * Detect whether an industry is unserved by a station of owner. + * + * @param TileIndex tile + * @param Owner owner + * @return red if unserved, orange if only accepting, nothing if served or not + * a building + */ +SpriteID TileZoneCheckUnservedIndustriesEvaluation(TileIndex tile, Owner owner) { + + //TODO: Actually use owner. + + if ( IsTileType(tile, MP_INDUSTRY) ) { + Industry *ind = Industry::GetByTile(tile); + StationFinder stations(ind->location); + + if ( stations.GetStations()->Length() > 0 ) { + return INVALID_SPRITE_ID; + } + + // For accepted goods + + if ( IsAreaWithinAcceptanceZoneOfStation(ind->location, owner) ) + return SPR_PALETTE_ZONING_ORANGE; + + //TODO: Check for stations that only accepts mail/passengers, + //which is currently only bus stops. + + return SPR_PALETTE_ZONING_RED; + } + + return INVALID_SPRITE_ID; +} + +/** + * General evaluation function; calls all the other functions depending on + * evaluation mode. + * + * @param TileIndex tile + * Tile to be evaluated. + * @param Owner owner + * The current player + * @param EvaluationMode ev_mode + * The current evaluation mode. + * @return The colour returned by the evaluation functions (none if no ev_mode). + */ +SpriteID TileZoningSpriteEvaluation(TileIndex tile, Owner owner, EvaluationMode ev_mode) { + switch ( ev_mode ) { + case CHECKBUILD: return TileZoneCheckBuildEvaluation(tile, owner); + case CHECKOPINION: return TileZoneCheckOpinionEvaluation(tile, owner); + case CHECKINDCATCH: return TileZoneCheckIndustryCatchmentEvaluation(tile, owner); + case CHECKSTACATCH: return TileZoneCheckStationCatchmentEvaluation(tile, owner); + case CHECKBULCATCH: return TileZoneCheckBuildingCatchmentEvaluation(tile, owner); + case CHECKBULUNSER: return TileZoneCheckUnservedBuildingsEvaluation(tile, owner); + case CHECKINDUNSER: return TileZoneCheckUnservedIndustriesEvaluation(tile, owner); + default: return INVALID_SPRITE_ID; + } +} + +/** + * Same as above, but not return an integer instead of sprite. However, it + * has so far not yet seem a real purpose, so therefore has not been implemented. + * + * @param TileIndex tile + * Tile to be evaluated. + * @param Owner owner + * The current player + * @param EvaluationMode ev_mode + * The current evaluation mode. + * @return Probably an integer based on the evaluation mode. + */ +int TileZoningEvaluation(TileIndex tile, Owner owner, EvaluationMode ev_mode) { + return 0; +} + +/** + * Draw the the zoning on the tile. + * + * @param TileInfo ti + * the tile to draw on. + */ +void DrawTileZoning(const TileInfo *ti) { + if ( IsTileType(ti->tile, MP_VOID) + || _game_mode != GM_NORMAL ) + return; + + if ( _zoning.outer != CHECKNOTHING ) + DrawZoningSprites(SPR_SELECT_TILE, TileZoningSpriteEvaluation(ti->tile, _local_company, _zoning.outer), ti); + + if ( _zoning.inner != CHECKNOTHING ) + DrawZoningSprites(SPR_INNER_HIGHLIGHT_BASE, TileZoningSpriteEvaluation(ti->tile, _local_company, _zoning.inner), ti); +} + +/** + * Get the evaluation mode depending on an integer. Though, this may be better + * implemented so the code does not need to be updated several places everything + * a new type of evaluation is added. + * + * @param int ev_mode + * @return EvaluationMode + */ +EvaluationMode GetEvaluationModeFromInt(int ev_mode) { + switch ( ev_mode ) { + case 1: return CHECKOPINION; + case 2: return CHECKBUILD; + case 3: return CHECKSTACATCH; + case 4: return CHECKINDCATCH; + case 5: return CHECKBULCATCH; + case 6: return CHECKBULUNSER; + case 7: return CHECKINDUNSER; + default: return CHECKNOTHING; + } +} diff --git a/src/zoning_gui.cpp b/src/zoning_gui.cpp new file mode 100644 index 0000000000..42161d1036 --- /dev/null +++ b/src/zoning_gui.cpp @@ -0,0 +1,127 @@ + +/** @file zoning_gui.cpp */ + +#include "stdafx.h" +#include "openttd.h" +#include "widgets/dropdown_func.h" +#include "widget_type.h" +#include "functions.h" +#include "window_func.h" +#include "gui.h" +#include "viewport_func.h" +#include "sound_func.h" +#include "variables.h" +#include "table/sprites.h" +#include "table/strings.h" +#include "strings_func.h" +#include "gfx_func.h" +#include "core/geometry_func.hpp" +#include "core/random_func.hpp" +#include "zoning.h" + +enum ZoningToolbarWidgets { + ZTW_OUTER = 4, + ZTW_OUTER_DROPDOWN, + ZTW_INNER, + ZTW_INNER_DROPDOWN, + ZTW_CAPTION +}; + +const StringID _zone_types[] = { STR_ZONING_NO_ZONING, STR_ZONING_AUTHORITY, STR_ZONING_CAN_BUILD, STR_ZONING_STA_CATCH, STR_ZONING_IND_CATCH, STR_ZONING_BUL_CATCH, STR_ZONING_BUL_UNSER, STR_ZONING_IND_UNSER, INVALID_STRING_ID }; + +struct ZoningWindow : public Window { + + ZoningWindow(const WindowDesc *desc, int window_number) : Window() { + this->InitNested(desc, window_number); + this->InvalidateData(); + } + + virtual void OnPaint() { + this->DrawWidgets(); + } + + virtual void OnClick(Point pt, int widget, int click_count) { + switch ( widget ) { + case ZTW_OUTER_DROPDOWN: + ShowDropDownMenu(this, _zone_types, _zoning.outer_val, ZTW_OUTER_DROPDOWN, 0, 0); + break; + case ZTW_INNER_DROPDOWN: + ShowDropDownMenu(this, _zone_types, _zoning.inner_val, ZTW_INNER_DROPDOWN, 0, 0); + break; + } + } + + virtual void OnDropdownSelect(int widget, int index) { + switch(widget) { + case ZTW_OUTER_DROPDOWN: + _zoning.outer_val = index; + _zoning.outer = GetEvaluationModeFromInt(_zoning.outer_val); + break; + case ZTW_INNER_DROPDOWN: + _zoning.inner_val = index; + _zoning.inner = GetEvaluationModeFromInt(_zoning.inner_val); + break; + } + this->InvalidateData(); + MarkWholeScreenDirty(); + } + + virtual void SetStringParameters(int widget) const { + switch ( widget ) { + case ZTW_OUTER_DROPDOWN: SetDParam(0, _zone_types[_zoning.outer]); break; + case ZTW_INNER_DROPDOWN: SetDParam(0, _zone_types[_zoning.inner]); break; + } + } + + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) { + const StringID *strs = NULL; + switch ( widget ) { + case ZTW_OUTER_DROPDOWN: strs = _zone_types; break; + case ZTW_INNER_DROPDOWN: strs = _zone_types; break; + } + if ( strs != NULL ) { + while ( *strs != INVALID_STRING_ID ) { + *size = maxdim(*size, GetStringBoundingBox(*strs++)); + } + } + size->width += padding.width; + size->height = FONT_HEIGHT_NORMAL + WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM; + } +}; + +static const NWidgetPart _nested_zoning_widgets[] = { + NWidget(NWID_HORIZONTAL), + NWidget(WWT_CLOSEBOX, COLOUR_GREY), + NWidget(WWT_CAPTION, COLOUR_GREY, ZTW_CAPTION), SetDataTip(STR_ZONING_TOOLBAR, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_SHADEBOX, COLOUR_GREY), + NWidget(WWT_STICKYBOX, COLOUR_GREY), + EndContainer(), + + NWidget(WWT_PANEL, COLOUR_GREY), + NWidget(NWID_HORIZONTAL, COLOUR_GREY), SetPIP(10, 3, 10), + NWidget(NWID_VERTICAL, COLOUR_GREY), SetPadding(5, 0, 5, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetDataTip(STR_ZONING_OUTER, STR_NULL), SetResize(1, 0), SetPadding(1, 6, 1, 6), + NWidget(WWT_TEXT, COLOUR_GREY, ZTW_OUTER), + NWidget(WWT_TEXT, COLOUR_GREY), SetDataTip(STR_ZONING_INNER, STR_NULL), SetResize(1, 0), SetPadding(1, 6, 1, 6), + NWidget(WWT_TEXT, COLOUR_GREY, ZTW_INNER), + EndContainer(), + NWidget(NWID_VERTICAL, COLOUR_GREY), SetPadding(5, 0, 5, 0), + NWidget(WWT_DROPDOWN, COLOUR_GREY, ZTW_OUTER_DROPDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), + NWidget(WWT_TEXT, COLOUR_GREY), + NWidget(WWT_DROPDOWN, COLOUR_GREY, ZTW_INNER_DROPDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), + NWidget(WWT_TEXT, COLOUR_GREY), + EndContainer(), + EndContainer(), + EndContainer() +}; + +static const WindowDesc _zoning_desc ( + WDP_CENTER, 0, 0, + WC_ZONING_TOOLBAR, WC_NONE, + 0, + _nested_zoning_widgets, lengthof(_nested_zoning_widgets) +); + +void ShowZoningToolbar() { + AllocateWindowDescFront(&_zoning_desc, 0); +}