tron@2186: /* $Id$ */ tron@2186: rubidium@9111: /** @file dock_gui.cpp GUI to create amazing water objects. */ belugas@6125: truelight@0: #include "stdafx.h" Darkvater@1891: #include "openttd.h" rubidium@8108: #include "tile_map.h" rubidium@8786: #include "station_type.h" truelight@0: #include "gui.h" rubidium@8205: #include "terraform_gui.h" rubidium@8107: #include "window_gui.h" rubidium@8107: #include "station_gui.h" rubidium@8116: #include "command_func.h" rubidium@8270: #include "settings_type.h" rubidium@7948: #include "water.h" rubidium@8131: #include "window_func.h" rubidium@8144: #include "vehicle_func.h" rubidium@8157: #include "sound_func.h" rubidium@8224: #include "viewport_func.h" rubidium@8224: #include "gfx_func.h" rubidium@8254: #include "player_func.h" frosch@8413: #include "slope_func.h" rubidium@9127: #include "tilehighlight_func.h" truelight@0: rubidium@8264: #include "table/sprites.h" rubidium@8264: #include "table/strings.h" rubidium@8264: frosch@9338: static void ShowBuildDockStationPicker(Window *parent); frosch@9338: static void ShowBuildDocksDepotPicker(Window *parent); truelight@0: tron@3157: static Axis _ship_depot_direction; truelight@0: tron@1977: void CcBuildDocks(bool success, TileIndex tile, uint32 p1, uint32 p2) truelight@0: { truelight@0: if (success) { tron@541: SndPlayTileFx(SND_02_SPLAT, tile); truelight@0: ResetObjectToPlace(); truelight@0: } truelight@0: } truelight@0: tron@1977: void CcBuildCanal(bool success, TileIndex tile, uint32 p1, uint32 p2) truelight@0: { tron@541: if (success) SndPlayTileFx(SND_02_SPLAT, tile); truelight@0: } truelight@0: truelight@0: tron@1977: static void PlaceDocks_Dock(TileIndex tile) truelight@0: { rubidium@7521: DoCommandP(tile, _ctrl_pressed, 0, CcBuildDocks, CMD_BUILD_DOCK | CMD_MSG(STR_9802_CAN_T_BUILD_DOCK_HERE)); truelight@0: } truelight@0: tron@1977: static void PlaceDocks_Depot(TileIndex tile) truelight@0: { rubidium@7521: DoCommandP(tile, _ship_depot_direction, 0, CcBuildDocks, CMD_BUILD_SHIP_DEPOT | CMD_MSG(STR_3802_CAN_T_BUILD_SHIP_DEPOT)); truelight@0: } truelight@0: tron@1977: static void PlaceDocks_Buoy(TileIndex tile) truelight@0: { rubidium@7521: DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_BUOY | CMD_MSG(STR_9835_CAN_T_POSITION_BUOY_HERE)); truelight@0: } truelight@0: tron@1977: static void PlaceDocks_BuildCanal(TileIndex tile) truelight@0: { maedhros@6670: VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_CREATE_WATER); truelight@0: } truelight@0: tron@1977: static void PlaceDocks_BuildLock(TileIndex tile) truelight@0: { rubidium@7521: DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_MSG(STR_CANT_BUILD_LOCKS)); truelight@0: } truelight@0: smatz@9327: /** Enum referring to the widgets of the build dock toolbar */ smatz@9327: enum DockToolbarWidgets { smatz@9327: DTW_BEGIN = 0, ///< Start of toolbar widgets smatz@9327: DTW_CLOSEBOX = DTW_BEGIN, ///< Close window button smatz@9327: DTW_CAPTION, ///< Window caption smatz@9327: DTW_STICKY, ///< Sticky window button smatz@9327: DTW_BUTTONS_BEGIN, ///< Begin of clickable buttons (except seperating panel) smatz@9327: DTW_CANAL = DTW_BUTTONS_BEGIN, ///< Build canal button smatz@9327: DTW_LOCK, ///< Build lock button smatz@9327: DTW_SEPERATOR, ///< Seperating panel between lock and demolish smatz@9327: DTW_DEMOLISH, ///< Demolish aka dynamite button smatz@9327: DTW_DEPOT, ///< Build depot button smatz@9327: DTW_STATION, ///< Build station button smatz@9327: DTW_BUOY, ///< Build buoy button smatz@9327: DTW_END, ///< End of toolbar widgets tron@5147: }; tron@5147: tron@5147: dominik@606: static void BuildDocksClick_Canal(Window *w) truelight@0: { rubidium@7889: HandlePlacePushButton(w, DTW_CANAL, SPR_CURSOR_CANAL, VHM_RECT, PlaceDocks_BuildCanal); truelight@0: } truelight@0: dominik@606: static void BuildDocksClick_Lock(Window *w) truelight@0: { rubidium@7889: HandlePlacePushButton(w, DTW_LOCK, SPR_CURSOR_LOCK, VHM_RECT, PlaceDocks_BuildLock); truelight@0: } truelight@0: truelight@0: static void BuildDocksClick_Demolish(Window *w) truelight@0: { belugas@9123: HandlePlacePushButton(w, DTW_DEMOLISH, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceProc_DemolishArea); truelight@0: } truelight@0: dominik@606: static void BuildDocksClick_Depot(Window *w) truelight@0: { rubidium@7086: if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return; frosch@9338: if (HandlePlacePushButton(w, DTW_DEPOT, SPR_CURSOR_SHIP_DEPOT, VHM_RECT, PlaceDocks_Depot)) ShowBuildDocksDepotPicker(w); truelight@0: } truelight@0: dominik@606: static void BuildDocksClick_Dock(Window *w) truelight@0: { rubidium@7086: if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return; frosch@9338: if (HandlePlacePushButton(w, DTW_STATION, SPR_CURSOR_DOCK, VHM_SPECIAL, PlaceDocks_Dock)) ShowBuildDockStationPicker(w); truelight@0: } truelight@0: dominik@606: static void BuildDocksClick_Buoy(Window *w) truelight@0: { rubidium@7086: if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return; rubidium@7889: HandlePlacePushButton(w, DTW_BUOY, SPR_CURSOR_BOUY, VHM_RECT, PlaceDocks_Buoy); truelight@0: } truelight@0: truelight@0: truelight@0: typedef void OnButtonClick(Window *w); truelight@0: static OnButtonClick * const _build_docks_button_proc[] = { truelight@0: BuildDocksClick_Canal, truelight@0: BuildDocksClick_Lock, tron@2548: NULL, dominik@606: BuildDocksClick_Demolish, dominik@606: BuildDocksClick_Depot, dominik@606: BuildDocksClick_Dock, tron@5682: BuildDocksClick_Buoy truelight@0: }; truelight@0: rubidium@9303: struct BuildDocksToolbarWindow : Window { rubidium@9303: BuildDocksToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) rubidium@9303: { rubidium@9303: this->FindWindowPlacementAndResize(desc); rubidium@9354: if (_settings.gui.link_terraform_toolbar) ShowTerraformToolbar(this); truelight@0: } truelight@0: rubidium@9303: ~BuildDocksToolbarWindow() rubidium@9303: { rubidium@9354: if (_settings.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); rubidium@9303: } rubidium@9303: rubidium@9303: virtual void OnPaint() rubidium@9303: { smatz@9327: this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_SHIP), DTW_DEPOT, DTW_STATION, DTW_BUOY, WIDGET_LIST_END); rubidium@9303: this->DrawWidgets(); rubidium@9303: } rubidium@9303: rubidium@9303: virtual void OnClick(Point pt, int widget) rubidium@9303: { smatz@9327: if (widget >= DTW_BUTTONS_BEGIN && widget != DTW_SEPERATOR) _build_docks_button_proc[widget - DTW_BUTTONS_BEGIN](this); rubidium@9303: } rubidium@9303: rubidium@9303: virtual EventState OnKeyPress(uint16 key, uint16 keycode) rubidium@9303: { rubidium@9303: switch (keycode) { rubidium@9303: case '1': BuildDocksClick_Canal(this); break; rubidium@9303: case '2': BuildDocksClick_Lock(this); break; rubidium@9303: case '3': BuildDocksClick_Demolish(this); break; rubidium@9303: case '4': BuildDocksClick_Depot(this); break; rubidium@9303: case '5': BuildDocksClick_Dock(this); break; rubidium@9303: case '6': BuildDocksClick_Buoy(this); break; rubidium@9303: default: return ES_NOT_HANDLED; rubidium@9303: } rubidium@9303: return ES_HANDLED; rubidium@9303: } rubidium@9303: rubidium@9303: virtual void OnPlaceObject(Point pt, TileIndex tile) rubidium@9303: { rubidium@9303: _place_proc(tile); rubidium@9303: } rubidium@9303: rubidium@9303: virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) rubidium@9303: { rubidium@9303: VpSelectTilesWithMethod(pt.x, pt.y, select_method); rubidium@9303: } rubidium@9303: rubidium@9303: virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) rubidium@9303: { rubidium@9303: if (pt.x != -1) { rubidium@9303: switch (select_proc) { maedhros@6670: case DDSP_DEMOLISH_AREA: rubidium@9303: GUIPlaceProcDragXY(select_proc, start_tile, end_tile); maedhros@6669: break; maedhros@6670: case DDSP_CREATE_WATER: rubidium@9303: DoCommandP(end_tile, start_tile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_MSG(STR_CANT_BUILD_CANALS)); maedhros@6669: break; rubidium@9303: maedhros@6669: default: break; tron@2549: } truelight@0: } rubidium@9303: } truelight@0: rubidium@9303: virtual void OnPlaceObjectAbort() rubidium@9303: { rubidium@9303: this->RaiseButtons(); truelight@0: rubidium@9238: delete FindWindowById(WC_BUILD_STATION, 0); rubidium@9238: delete FindWindowById(WC_BUILD_DEPOT, 0); rubidium@9303: } truelight@193: rubidium@9303: virtual void OnPlacePresize(Point pt, TileIndex tile_from) rubidium@9303: { frosch@8413: DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile_from, NULL)); rubidium@9303: TileIndex tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile_from, ReverseDiagDir(dir)) : tile_from); frosch@8413: truelight@0: VpSetPresizeRange(tile_from, tile_to); truelight@0: } rubidium@9303: }; truelight@0: truelight@0: static const Widget _build_docks_toolb_widgets[] = { smatz@9327: { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // DTW_CLOSEBOX smatz@9327: { WWT_CAPTION, RESIZE_NONE, 7, 11, 123, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // DTW_CAPTION smatz@9327: { WWT_STICKYBOX, RESIZE_NONE, 7, 124, 135, 0, 13, 0x0, STR_STICKY_BUTTON}, // DTW_STICKY smatz@9327: { WWT_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_BUILD_CANAL, STR_BUILD_CANALS_TIP}, // DTW_CANAL smatz@9327: { WWT_IMGBTN, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_BUILD_LOCK, STR_BUILD_LOCKS_TIP}, // DTW_LOCK dominik@606: smatz@9327: { WWT_PANEL, RESIZE_NONE, 7, 44, 47, 14, 35, 0x0, STR_NULL}, // DTW_SEPERATOR dominik@606: smatz@9327: { WWT_IMGBTN, RESIZE_NONE, 7, 48, 69, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC}, // DTW_DEMOLISH smatz@9327: { WWT_IMGBTN, RESIZE_NONE, 7, 70, 91, 14, 35, SPR_IMG_SHIP_DEPOT, STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING}, // DTW_DEPOT smatz@9327: { WWT_IMGBTN, RESIZE_NONE, 7, 92, 113, 14, 35, SPR_IMG_SHIP_DOCK, STR_981D_BUILD_SHIP_DOCK}, // DTW_STATION smatz@9327: { WWT_IMGBTN, RESIZE_NONE, 7, 114, 135, 14, 35, SPR_IMG_BOUY, STR_9834_POSITION_BUOY_WHICH_CAN}, // DTW_BUOY darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _build_docks_toolbar_desc = { rubidium@7341: WDP_ALIGN_TBR, 22, 136, 36, 136, 36, rubidium@5893: WC_BUILD_TOOLBAR, WC_NONE, darkvater@756: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, truelight@0: _build_docks_toolb_widgets, truelight@0: }; truelight@0: rubidium@6247: void ShowBuildDocksToolbar() truelight@0: { Darkvater@5005: if (!IsValidPlayer(_current_player)) return; Darkvater@5005: rubidium@9080: DeleteWindowByClass(WC_BUILD_TOOLBAR); rubidium@9303: AllocateWindowDescFront(&_build_docks_toolbar_desc, TRANSPORT_WATER); truelight@0: } truelight@0: glx@9279: struct BuildDocksStationWindow : public PickerWindowBase { glx@9279: private: glx@9279: enum BuildDockStationWidgets { glx@9279: BDSW_CLOSE, glx@9279: BDSW_CAPTION, glx@9279: BDSW_BACKGROUND, glx@9279: BDSW_LT_OFF, glx@9279: BDSW_LT_ON, glx@9279: BDSW_INFO, glx@9279: }; belugas@4719: glx@9279: public: frosch@9338: BuildDocksStationWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) glx@9279: { glx@9279: this->LowerWidget(_station_show_coverage + BDSW_LT_OFF); glx@9279: this->FindWindowPlacementAndResize(desc); glx@9279: } glx@9279: glx@9279: virtual void OnPaint() glx@9279: { rubidium@9354: int rad = (_settings.station.modified_catchment) ? CA_DOCK : CA_UNMODIFIED; dominik@713: glx@9279: this->DrawWidgets(); tron@2631: rubidium@6829: if (_station_show_coverage) { rubidium@6829: SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad); rubidium@6829: } else { rubidium@6829: SetTileSelectSize(1, 1); rubidium@6829: } dominik@713: rubidium@8846: int text_end = DrawStationCoverageAreaText(4, 50, SCT_ALL, rad, false); rubidium@8846: text_end = DrawStationCoverageAreaText(4, text_end + 4, SCT_ALL, rad, true) + 4; glx@9279: if (text_end != this->widget[BDSW_BACKGROUND].bottom) { glx@9279: this->SetDirty(); glx@9279: ResizeWindowForWidget(this, 2, 0, text_end - this->widget[BDSW_BACKGROUND].bottom); glx@9279: this->SetDirty(); peter1138@8423: } tron@2639: } truelight@0: glx@9279: virtual void OnClick(Point pt, int widget) glx@9279: { glx@9279: switch (widget) { glx@9279: case BDSW_LT_OFF: glx@9279: case BDSW_LT_ON: glx@9279: this->RaiseWidget(_station_show_coverage + BDSW_LT_OFF); glx@9279: _station_show_coverage = (widget != BDSW_LT_OFF); glx@9279: this->LowerWidget(_station_show_coverage + BDSW_LT_OFF); tron@2639: SndPlayFx(SND_15_BEEP); glx@9279: this->SetDirty(); tron@2639: break; truelight@0: } glx@9279: } truelight@0: glx@9279: virtual void OnTick() glx@9279: { glx@9279: CheckRedrawStationCoverage(this); truelight@193: } glx@9279: }; truelight@0: truelight@0: static const Widget _build_dock_station_widgets[] = { glx@9279: { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // BDSW_CLOSE glx@9279: { WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3068_DOCK, STR_018C_WINDOW_TITLE_DRAG_THIS}, // BDSW_CAPTION glx@9279: { WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 74, 0x0, STR_NULL}, // BDSW_BACKGROUND glx@9279: { WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 30, 40, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE}, // BDSW_LT_OFF glx@9279: { WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 30, 40, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA}, // BDSW_LT_ON glx@9279: { WWT_LABEL, RESIZE_NONE, 7, 0, 147, 17, 30, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL}, // BDSW_INFO darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _build_dock_station_desc = { rubidium@7341: WDP_AUTO, WDP_AUTO, 148, 75, 148, 75, Darkvater@5070: WC_BUILD_STATION, WC_BUILD_TOOLBAR, truelight@0: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, truelight@0: _build_dock_station_widgets, truelight@0: }; truelight@0: frosch@9338: static void ShowBuildDockStationPicker(Window *parent) truelight@0: { frosch@9338: new BuildDocksStationWindow(&_build_dock_station_desc, parent); truelight@0: } truelight@0: glx@9279: struct BuildDocksDepotWindow : public PickerWindowBase { glx@9279: private: glx@9279: enum BuildDockDepotWidgets { glx@9279: BDDW_CLOSE, glx@9279: BDDW_CAPTION, glx@9279: BDDW_BACKGROUND, glx@9279: BDDW_X, glx@9279: BDDW_Y, glx@9279: }; glx@9279: glx@9279: static void UpdateDocksDirection() glx@9279: { glx@9279: if (_ship_depot_direction != AXIS_X) { glx@9279: SetTileSelectSize(1, 2); glx@9279: } else { glx@9279: SetTileSelectSize(2, 1); glx@9279: } truelight@0: } truelight@0: glx@9279: public: frosch@9338: BuildDocksDepotWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) glx@9279: { glx@9279: this->LowerWidget(_ship_depot_direction + BDDW_X); glx@9279: UpdateDocksDirection(); glx@9279: this->FindWindowPlacementAndResize(desc); glx@9279: } belugas@4719: glx@9279: virtual void OnPaint() glx@9279: { glx@9279: this->DrawWidgets(); truelight@0: truelight@0: DrawShipDepotSprite(67, 35, 0); truelight@0: DrawShipDepotSprite(35, 51, 1); truelight@0: DrawShipDepotSprite(135, 35, 2); truelight@0: DrawShipDepotSprite(167, 51, 3); glx@9279: } truelight@0: glx@9279: virtual void OnClick(Point pt, int widget) glx@9279: { glx@9279: switch (widget) { glx@9279: case BDDW_X: glx@9279: case BDDW_Y: glx@9279: this->RaiseWidget(_ship_depot_direction + BDDW_X); glx@9279: _ship_depot_direction = (widget == BDDW_X ? AXIS_X : AXIS_Y); glx@9279: this->LowerWidget(_ship_depot_direction + BDDW_X); glx@9279: SndPlayFx(SND_15_BEEP); glx@9279: UpdateDocksDirection(); glx@9279: this->SetDirty(); glx@9279: break; truelight@0: } truelight@0: } glx@9279: }; truelight@0: truelight@0: static const Widget _build_docks_depot_widgets[] = { glx@9279: { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // BDDW_CLOSE glx@9279: { WWT_CAPTION, RESIZE_NONE, 7, 11, 203, 0, 13, STR_3800_SHIP_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // BDDW_CAPTION glx@9279: { WWT_PANEL, RESIZE_NONE, 7, 0, 203, 14, 85, 0x0, STR_NULL}, // BDDW_BACKGROUND glx@9279: { WWT_PANEL, RESIZE_NONE, 14, 3, 100, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION}, // BDDW_X glx@9279: { WWT_PANEL, RESIZE_NONE, 14, 103, 200, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION}, // BDDW_Y darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _build_docks_depot_desc = { rubidium@7341: WDP_AUTO, WDP_AUTO, 204, 86, 204, 86, Darkvater@5070: WC_BUILD_DEPOT, WC_BUILD_TOOLBAR, truelight@0: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, truelight@0: _build_docks_depot_widgets, truelight@0: }; truelight@0: truelight@0: frosch@9338: static void ShowBuildDocksDepotPicker(Window *parent) truelight@0: { frosch@9338: new BuildDocksDepotWindow(&_build_docks_depot_desc, parent); truelight@0: } truelight@0: truelight@0: rubidium@6247: void InitializeDockGui() truelight@0: { tron@3157: _ship_depot_direction = AXIS_X; truelight@0: }