Position of landscaping toolbar.
This commit is contained in:
574
src/airport_gui.cpp.orig
Normal file
574
src/airport_gui.cpp.orig
Normal file
@@ -0,0 +1,574 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 airport_gui.cpp The GUI for airports. */
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "window_gui.h"
|
||||||
|
#include "station_gui.h"
|
||||||
|
#include "terraform_gui.h"
|
||||||
|
#include "sound_func.h"
|
||||||
|
#include "window_func.h"
|
||||||
|
#include "strings_func.h"
|
||||||
|
#include "viewport_func.h"
|
||||||
|
#include "company_func.h"
|
||||||
|
#include "tilehighlight_func.h"
|
||||||
|
#include "company_base.h"
|
||||||
|
#include "station_type.h"
|
||||||
|
#include "newgrf_airport.h"
|
||||||
|
#include "newgrf_callbacks.h"
|
||||||
|
#include "widgets/dropdown_type.h"
|
||||||
|
#include "core/geometry_func.hpp"
|
||||||
|
#include "hotkeys.h"
|
||||||
|
#include "vehicle_func.h"
|
||||||
|
#include "gui.h"
|
||||||
|
|
||||||
|
#include "widgets/airport_widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
static AirportClassID _selected_airport_class; ///< the currently visible airport class
|
||||||
|
static int _selected_airport_index; ///< the index of the selected airport in the current class or -1
|
||||||
|
static byte _selected_airport_layout; ///< selected airport layout number.
|
||||||
|
|
||||||
|
static void ShowBuildAirportPicker(Window *parent);
|
||||||
|
|
||||||
|
SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout);
|
||||||
|
|
||||||
|
void CcBuildAirport(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
|
||||||
|
{
|
||||||
|
if (result.Failed()) return;
|
||||||
|
|
||||||
|
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT, tile);
|
||||||
|
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place an airport.
|
||||||
|
* @param tile Position to put the new airport.
|
||||||
|
*/
|
||||||
|
static void PlaceAirport(TileIndex tile)
|
||||||
|
{
|
||||||
|
if (_selected_airport_index == -1) return;
|
||||||
|
uint32 p2 = _ctrl_pressed;
|
||||||
|
SB(p2, 16, 16, INVALID_STATION); // no station to join
|
||||||
|
|
||||||
|
uint32 p1 = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex();
|
||||||
|
p1 |= _selected_airport_layout << 8;
|
||||||
|
CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_AIRPORT | CMD_MSG(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE), CcBuildAirport, "" };
|
||||||
|
ShowSelectStationIfNeeded(cmdcont, TileArea(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Airport build toolbar window handler. */
|
||||||
|
struct BuildAirToolbarWindow : Window {
|
||||||
|
int last_user_action; // Last started user action.
|
||||||
|
|
||||||
|
BuildAirToolbarWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
|
||||||
|
{
|
||||||
|
this->InitNested(window_number);
|
||||||
|
if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
|
||||||
|
this->last_user_action = WIDGET_LIST_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
~BuildAirToolbarWindow()
|
||||||
|
{
|
||||||
|
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnClick(Point pt, int widget, int click_count)
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_AT_AIRPORT:
|
||||||
|
if (HandlePlacePushButton(this, WID_AT_AIRPORT, SPR_CURSOR_AIRPORT, HT_RECT)) {
|
||||||
|
ShowBuildAirportPicker(this);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_AT_DEMOLISH:
|
||||||
|
HandlePlacePushButton(this, WID_AT_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT | HT_DIAGONAL);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void OnPlaceObject(Point pt, TileIndex tile)
|
||||||
|
{
|
||||||
|
switch (this->last_user_action) {
|
||||||
|
case WID_AT_AIRPORT:
|
||||||
|
PlaceAirport(tile);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_AT_DEMOLISH:
|
||||||
|
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 void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
|
||||||
|
{
|
||||||
|
if (pt.x != -1 && select_proc == DDSP_DEMOLISH_AREA) {
|
||||||
|
GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPlaceObjectAbort()
|
||||||
|
{
|
||||||
|
this->RaiseButtons();
|
||||||
|
|
||||||
|
DeleteWindowById(WC_BUILD_STATION, TRANSPORT_AIR);
|
||||||
|
DeleteWindowById(WC_SELECT_STATION, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HotkeyList hotkeys;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for global hotkeys of the BuildAirToolbarWindow.
|
||||||
|
* @param hotkey Hotkey
|
||||||
|
* @return ES_HANDLED if hotkey was accepted.
|
||||||
|
*/
|
||||||
|
static EventState AirportToolbarGlobalHotkeys(int hotkey)
|
||||||
|
{
|
||||||
|
if (_game_mode != GM_NORMAL || !CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) return ES_NOT_HANDLED;
|
||||||
|
Window *w = ShowBuildAirToolbar();
|
||||||
|
if (w == NULL) return ES_NOT_HANDLED;
|
||||||
|
return w->OnHotkey(hotkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Hotkey airtoolbar_hotkeys[] = {
|
||||||
|
Hotkey('1', "airport", WID_AT_AIRPORT),
|
||||||
|
Hotkey('2', "demolish", WID_AT_DEMOLISH),
|
||||||
|
HOTKEY_LIST_END
|
||||||
|
};
|
||||||
|
HotkeyList BuildAirToolbarWindow::hotkeys("airtoolbar", airtoolbar_hotkeys, AirportToolbarGlobalHotkeys);
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_air_toolbar_widgets[] = {
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_TOOLBAR_AIRCRAFT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||||
|
NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_AT_AIRPORT), SetFill(0, 1), SetMinimalSize(42, 22), SetDataTip(SPR_IMG_AIRPORT, STR_TOOLBAR_AIRCRAFT_BUILD_AIRPORT_TOOLTIP),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), SetFill(1, 1), EndContainer(),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_AT_DEMOLISH), SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
|
||||||
|
EndContainer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowDesc _air_toolbar_desc(
|
||||||
|
WDP_ALIGN_TOOLBAR, "toolbar_air", 0, 0,
|
||||||
|
WC_BUILD_TOOLBAR, WC_NONE,
|
||||||
|
WDF_CONSTRUCTION,
|
||||||
|
_nested_air_toolbar_widgets, lengthof(_nested_air_toolbar_widgets),
|
||||||
|
&BuildAirToolbarWindow::hotkeys
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the build airport toolbar window
|
||||||
|
*
|
||||||
|
* If the terraform toolbar is linked to the toolbar, that window is also opened.
|
||||||
|
*
|
||||||
|
* @return newly opened airport toolbar, or NULL if the toolbar could not be opened.
|
||||||
|
*/
|
||||||
|
Window *ShowBuildAirToolbar()
|
||||||
|
{
|
||||||
|
if (!Company::IsValidID(_local_company)) return NULL;
|
||||||
|
|
||||||
|
DeleteWindowByClass(WC_BUILD_TOOLBAR);
|
||||||
|
return AllocateWindowDescFront<BuildAirToolbarWindow>(&_air_toolbar_desc, TRANSPORT_AIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
class BuildAirportWindow : public PickerWindowBase {
|
||||||
|
SpriteID preview_sprite; ///< Cached airport preview sprite.
|
||||||
|
int line_height;
|
||||||
|
Scrollbar *vscroll;
|
||||||
|
|
||||||
|
/** Build a dropdown list of available airport classes */
|
||||||
|
static DropDownList *BuildAirportClassDropDown()
|
||||||
|
{
|
||||||
|
DropDownList *list = new DropDownList();
|
||||||
|
|
||||||
|
for (uint i = 0; i < AirportClass::GetClassCount(); i++) {
|
||||||
|
*list->Append() = new DropDownListStringItem(AirportClass::Get((AirportClassID)i)->name, i, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
BuildAirportWindow(WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent)
|
||||||
|
{
|
||||||
|
this->CreateNestedTree();
|
||||||
|
|
||||||
|
this->vscroll = this->GetScrollbar(WID_AP_SCROLLBAR);
|
||||||
|
this->vscroll->SetCapacity(5);
|
||||||
|
this->vscroll->SetPosition(0);
|
||||||
|
|
||||||
|
this->FinishInitNested(TRANSPORT_AIR);
|
||||||
|
|
||||||
|
this->SetWidgetLoweredState(WID_AP_BTN_DONTHILIGHT, !_settings_client.gui.station_show_coverage);
|
||||||
|
this->SetWidgetLoweredState(WID_AP_BTN_DOHILIGHT, _settings_client.gui.station_show_coverage);
|
||||||
|
this->OnInvalidateData();
|
||||||
|
|
||||||
|
this->vscroll->SetCount(AirportClass::Get(_selected_airport_class)->GetSpecCount());
|
||||||
|
this->SelectFirstAvailableAirport(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~BuildAirportWindow()
|
||||||
|
{
|
||||||
|
DeleteWindowById(WC_SELECT_STATION, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetStringParameters(int widget) const
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_AP_CLASS_DROPDOWN:
|
||||||
|
SetDParam(0, AirportClass::Get(_selected_airport_class)->name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_AP_LAYOUT_NUM:
|
||||||
|
SetDParam(0, STR_EMPTY);
|
||||||
|
if (_selected_airport_index != -1) {
|
||||||
|
const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index);
|
||||||
|
StringID string = GetAirportTextCallback(as, _selected_airport_layout, CBID_AIRPORT_LAYOUT_NAME);
|
||||||
|
if (string != STR_UNDEFINED) {
|
||||||
|
SetDParam(0, string);
|
||||||
|
} else if (as->num_table > 1) {
|
||||||
|
SetDParam(0, STR_STATION_BUILD_AIRPORT_LAYOUT_NAME);
|
||||||
|
SetDParam(1, _selected_airport_layout + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_AP_CLASS_DROPDOWN: {
|
||||||
|
Dimension d = {0, 0};
|
||||||
|
for (uint i = 0; i < AirportClass::GetClassCount(); i++) {
|
||||||
|
SetDParam(0, AirportClass::Get((AirportClassID)i)->name);
|
||||||
|
d = maxdim(d, GetStringBoundingBox(STR_BLACK_STRING));
|
||||||
|
}
|
||||||
|
d.width += padding.width;
|
||||||
|
d.height += padding.height;
|
||||||
|
*size = maxdim(*size, d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_AP_AIRPORT_LIST: {
|
||||||
|
for (int i = 0; i < NUM_AIRPORTS; i++) {
|
||||||
|
const AirportSpec *as = AirportSpec::Get(i);
|
||||||
|
if (!as->enabled) continue;
|
||||||
|
|
||||||
|
size->width = max(size->width, GetStringBoundingBox(as->name).width);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
|
||||||
|
size->height = 5 * this->line_height;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_AP_AIRPORT_SPRITE:
|
||||||
|
for (int i = 0; i < NUM_AIRPORTS; i++) {
|
||||||
|
const AirportSpec *as = AirportSpec::Get(i);
|
||||||
|
if (!as->enabled) continue;
|
||||||
|
for (byte layout = 0; layout < as->num_table; layout++) {
|
||||||
|
SpriteID sprite = GetCustomAirportSprite(as, layout);
|
||||||
|
if (sprite != 0) {
|
||||||
|
Dimension d = GetSpriteSize(sprite);
|
||||||
|
d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
|
||||||
|
d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
|
||||||
|
*size = maxdim(d, *size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_AP_EXTRA_TEXT:
|
||||||
|
for (int i = NEW_AIRPORT_OFFSET; i < NUM_AIRPORTS; i++) {
|
||||||
|
const AirportSpec *as = AirportSpec::Get(i);
|
||||||
|
if (!as->enabled) continue;
|
||||||
|
for (byte layout = 0; layout < as->num_table; layout++) {
|
||||||
|
StringID string = GetAirportTextCallback(as, layout, CBID_AIRPORT_ADDITIONAL_TEXT);
|
||||||
|
if (string == STR_UNDEFINED) continue;
|
||||||
|
|
||||||
|
/* STR_BLACK_STRING is used to start the string with {BLACK} */
|
||||||
|
SetDParam(0, string);
|
||||||
|
Dimension d = GetStringMultiLineBoundingBox(STR_BLACK_STRING, *size);
|
||||||
|
*size = maxdim(d, *size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DrawWidget(const Rect &r, int widget) const
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_AP_AIRPORT_LIST: {
|
||||||
|
int y = r.top;
|
||||||
|
AirportClass *apclass = AirportClass::Get(_selected_airport_class);
|
||||||
|
for (uint i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < apclass->GetSpecCount(); i++) {
|
||||||
|
const AirportSpec *as = apclass->GetSpec(i);
|
||||||
|
if (!as->IsAvailable()) {
|
||||||
|
GfxFillRect(r.left + 1, y + 1, r.right - 1, y + this->line_height - 2, PC_BLACK, FILLRECT_CHECKER);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, Center(y, this->line_height), as->name, ((int)i == _selected_airport_index) ? TC_WHITE : TC_BLACK);
|
||||||
|
|
||||||
|
y += this->line_height;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_AP_AIRPORT_SPRITE:
|
||||||
|
if (this->preview_sprite != 0) {
|
||||||
|
Dimension d = GetSpriteSize(this->preview_sprite);
|
||||||
|
DrawSprite(this->preview_sprite, COMPANY_SPRITE_COLOUR(_local_company), (r.left + r.right - d.width) / 2, (r.top + r.bottom - d.height) / 2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_AP_EXTRA_TEXT:
|
||||||
|
if (_selected_airport_index != -1) {
|
||||||
|
const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index);
|
||||||
|
StringID string = GetAirportTextCallback(as, _selected_airport_layout, CBID_AIRPORT_ADDITIONAL_TEXT);
|
||||||
|
if (string != STR_UNDEFINED) {
|
||||||
|
SetDParam(0, string);
|
||||||
|
DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_BLACK_STRING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPaint()
|
||||||
|
{
|
||||||
|
this->DrawWidgets();
|
||||||
|
|
||||||
|
uint16 top = this->GetWidget<NWidgetBase>(WID_AP_BTN_DOHILIGHT)->pos_y + this->GetWidget<NWidgetBase>(WID_AP_BTN_DOHILIGHT)->current_y + WD_PAR_VSEP_NORMAL;
|
||||||
|
NWidgetBase *panel_nwi = this->GetWidget<NWidgetBase>(WID_AP_BOTTOMPANEL);
|
||||||
|
|
||||||
|
int right = panel_nwi->pos_x + panel_nwi->current_x;
|
||||||
|
int bottom = panel_nwi->pos_y + panel_nwi->current_y;
|
||||||
|
|
||||||
|
if (_selected_airport_index != -1) {
|
||||||
|
const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index);
|
||||||
|
int rad = _settings_game.station.modified_catchment ? as->catchment : (uint)CA_UNMODIFIED;
|
||||||
|
|
||||||
|
/* only show the station (airport) noise, if the noise option is activated */
|
||||||
|
if (_settings_game.economy.station_noise_level) {
|
||||||
|
/* show the noise of the selected airport */
|
||||||
|
SetDParam(0, as->noise_level);
|
||||||
|
DrawString(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_STATION_BUILD_NOISE);
|
||||||
|
top += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* strings such as 'Size' and 'Coverage Area' */
|
||||||
|
top = DrawStationCoverageAreaText(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, SCT_ALL, rad, false) + WD_PAR_VSEP_NORMAL;
|
||||||
|
top = DrawStationCoverageAreaText(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, SCT_ALL, rad, true) + WD_PAR_VSEP_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resize background if the window is too small.
|
||||||
|
* Never make the window smaller to avoid oscillating if the size change affects the acceptance.
|
||||||
|
* (This is the case, if making the window bigger moves the mouse into the window.) */
|
||||||
|
if (top > bottom) {
|
||||||
|
ResizeWindow(this, 0, top - bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectOtherAirport(int airport_index)
|
||||||
|
{
|
||||||
|
_selected_airport_index = airport_index;
|
||||||
|
_selected_airport_layout = 0;
|
||||||
|
|
||||||
|
this->UpdateSelectSize();
|
||||||
|
this->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateSelectSize()
|
||||||
|
{
|
||||||
|
if (_selected_airport_index == -1) {
|
||||||
|
SetTileSelectSize(1, 1);
|
||||||
|
this->DisableWidget(WID_AP_LAYOUT_DECREASE);
|
||||||
|
this->DisableWidget(WID_AP_LAYOUT_INCREASE);
|
||||||
|
} else {
|
||||||
|
const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index);
|
||||||
|
int w = as->size_x;
|
||||||
|
int h = as->size_y;
|
||||||
|
Direction rotation = as->rotation[_selected_airport_layout];
|
||||||
|
if (rotation == DIR_E || rotation == DIR_W) Swap(w, h);
|
||||||
|
SetTileSelectSize(w, h);
|
||||||
|
|
||||||
|
this->preview_sprite = GetCustomAirportSprite(as, _selected_airport_layout);
|
||||||
|
|
||||||
|
this->SetWidgetDisabledState(WID_AP_LAYOUT_DECREASE, _selected_airport_layout == 0);
|
||||||
|
this->SetWidgetDisabledState(WID_AP_LAYOUT_INCREASE, _selected_airport_layout + 1 >= as->num_table);
|
||||||
|
|
||||||
|
int rad = _settings_game.station.modified_catchment ? as->catchment : (uint)CA_UNMODIFIED;
|
||||||
|
if (_settings_client.gui.station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnClick(Point pt, int widget, int click_count)
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_AP_CLASS_DROPDOWN:
|
||||||
|
ShowDropDownList(this, BuildAirportClassDropDown(), _selected_airport_class, WID_AP_CLASS_DROPDOWN);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_AP_AIRPORT_LIST: {
|
||||||
|
int num_clicked = this->vscroll->GetPosition() + (pt.y - this->nested_array[widget]->pos_y) / this->line_height;
|
||||||
|
if (num_clicked >= this->vscroll->GetCount()) break;
|
||||||
|
const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(num_clicked);
|
||||||
|
if (as->IsAvailable()) this->SelectOtherAirport(num_clicked);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_AP_BTN_DONTHILIGHT: case WID_AP_BTN_DOHILIGHT:
|
||||||
|
_settings_client.gui.station_show_coverage = (widget != WID_AP_BTN_DONTHILIGHT);
|
||||||
|
this->SetWidgetLoweredState(WID_AP_BTN_DONTHILIGHT, !_settings_client.gui.station_show_coverage);
|
||||||
|
this->SetWidgetLoweredState(WID_AP_BTN_DOHILIGHT, _settings_client.gui.station_show_coverage);
|
||||||
|
this->SetDirty();
|
||||||
|
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
|
||||||
|
this->UpdateSelectSize();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_AP_LAYOUT_DECREASE:
|
||||||
|
_selected_airport_layout--;
|
||||||
|
this->UpdateSelectSize();
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_AP_LAYOUT_INCREASE:
|
||||||
|
_selected_airport_layout++;
|
||||||
|
this->UpdateSelectSize();
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select the first available airport.
|
||||||
|
* @param change_class If true, change the class if no airport in the current
|
||||||
|
* class is available.
|
||||||
|
*/
|
||||||
|
void SelectFirstAvailableAirport(bool change_class)
|
||||||
|
{
|
||||||
|
/* First try to select an airport in the selected class. */
|
||||||
|
AirportClass *sel_apclass = AirportClass::Get(_selected_airport_class);
|
||||||
|
for (uint i = 0; i < sel_apclass->GetSpecCount(); i++) {
|
||||||
|
const AirportSpec *as = sel_apclass->GetSpec(i);
|
||||||
|
if (as->IsAvailable()) {
|
||||||
|
this->SelectOtherAirport(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (change_class) {
|
||||||
|
/* If that fails, select the first available airport
|
||||||
|
* from a random class. */
|
||||||
|
for (AirportClassID j = APC_BEGIN; j < APC_MAX; j++) {
|
||||||
|
AirportClass *apclass = AirportClass::Get(j);
|
||||||
|
for (uint i = 0; i < apclass->GetSpecCount(); i++) {
|
||||||
|
const AirportSpec *as = apclass->GetSpec(i);
|
||||||
|
if (as->IsAvailable()) {
|
||||||
|
_selected_airport_class = j;
|
||||||
|
this->SelectOtherAirport(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If all airports are unavailable, select nothing. */
|
||||||
|
this->SelectOtherAirport(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnDropdownSelect(int widget, int index)
|
||||||
|
{
|
||||||
|
assert(widget == WID_AP_CLASS_DROPDOWN);
|
||||||
|
_selected_airport_class = (AirportClassID)index;
|
||||||
|
this->vscroll->SetCount(AirportClass::Get(_selected_airport_class)->GetSpecCount());
|
||||||
|
this->SelectFirstAvailableAirport(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnTick()
|
||||||
|
{
|
||||||
|
CheckRedrawStationCoverage(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_build_airport_widgets[] = {
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_AIRPORT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetFill(1, 0), SetPIP(2, 0, 2),
|
||||||
|
NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_AIRPORT_CLASS_LABEL, STR_NULL), SetFill(1, 0),
|
||||||
|
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_AP_CLASS_DROPDOWN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_STATION_BUILD_AIRPORT_TOOLTIP),
|
||||||
|
NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, WID_AP_AIRPORT_SPRITE), SetFill(1, 0),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_MATRIX, COLOUR_GREY, WID_AP_AIRPORT_LIST), SetFill(1, 0), SetMatrixDataTip(1, 5, STR_STATION_BUILD_AIRPORT_TOOLTIP), SetScrollbar(WID_AP_SCROLLBAR),
|
||||||
|
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_AP_SCROLLBAR),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_AP_LAYOUT_DECREASE), SetMinimalSize(12, 0), SetDataTip(AWV_DECREASE, STR_NULL),
|
||||||
|
NWidget(WWT_LABEL, COLOUR_GREY, WID_AP_LAYOUT_NUM), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NULL),
|
||||||
|
NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_AP_LAYOUT_INCREASE), SetMinimalSize(12, 0), SetDataTip(AWV_INCREASE, STR_NULL),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, WID_AP_EXTRA_TEXT), SetFill(1, 0), SetMinimalSize(150, 0),
|
||||||
|
EndContainer(),
|
||||||
|
/* Bottom panel. */
|
||||||
|
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_AP_BOTTOMPANEL), SetPIP(2, 2, 2),
|
||||||
|
NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL), SetFill(1, 0),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(NWID_SPACER), SetMinimalSize(14, 0), SetFill(1, 0),
|
||||||
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||||
|
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_AP_BTN_DONTHILIGHT), SetMinimalSize(60, 12), SetFill(1, 0),
|
||||||
|
SetDataTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP),
|
||||||
|
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_AP_BTN_DOHILIGHT), SetMinimalSize(60, 12), SetFill(1, 0),
|
||||||
|
SetDataTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_SPACER), SetMinimalSize(14, 0), SetFill(1, 0),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetResize(0, 1), SetFill(1, 0),
|
||||||
|
EndContainer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowDesc _build_airport_desc(
|
||||||
|
WDP_AUTO, "build_station_air", 0, 0,
|
||||||
|
WC_BUILD_STATION, WC_BUILD_TOOLBAR,
|
||||||
|
WDF_CONSTRUCTION,
|
||||||
|
_nested_build_airport_widgets, lengthof(_nested_build_airport_widgets)
|
||||||
|
);
|
||||||
|
|
||||||
|
static void ShowBuildAirportPicker(Window *parent)
|
||||||
|
{
|
||||||
|
new BuildAirportWindow(&_build_airport_desc, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeAirportGui()
|
||||||
|
{
|
||||||
|
_selected_airport_class = APC_BEGIN;
|
||||||
|
_selected_airport_index = -1;
|
||||||
|
}
|
||||||
624
src/autoreplace_gui.cpp.orig
Normal file
624
src/autoreplace_gui.cpp.orig
Normal file
@@ -0,0 +1,624 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 autoreplace_gui.cpp GUI for autoreplace handling. */
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "command_func.h"
|
||||||
|
#include "vehicle_gui.h"
|
||||||
|
#include "newgrf_engine.h"
|
||||||
|
#include "rail.h"
|
||||||
|
#include "strings_func.h"
|
||||||
|
#include "window_func.h"
|
||||||
|
#include "autoreplace_func.h"
|
||||||
|
#include "company_func.h"
|
||||||
|
#include "engine_base.h"
|
||||||
|
#include "window_gui.h"
|
||||||
|
#include "engine_gui.h"
|
||||||
|
#include "settings_func.h"
|
||||||
|
#include "core/geometry_func.hpp"
|
||||||
|
#include "rail_gui.h"
|
||||||
|
#include "widgets/dropdown_func.h"
|
||||||
|
|
||||||
|
#include "widgets/autoreplace_widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
uint GetEngineListHeight(VehicleType type);
|
||||||
|
void DrawEngineList(VehicleType type, int x, int r, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group);
|
||||||
|
|
||||||
|
static int CDECL EngineNumberSorter(const EngineID *a, const EngineID *b)
|
||||||
|
{
|
||||||
|
int r = Engine::Get(*a)->list_position - Engine::Get(*b)->list_position;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebuild the left autoreplace list if an engine is removed or added
|
||||||
|
* @param e Engine to check if it is removed or added
|
||||||
|
* @param id_g The group the engine belongs to
|
||||||
|
* Note: this function only works if it is called either
|
||||||
|
* - when a new vehicle is build, but before it's counted in num_engines
|
||||||
|
* - when a vehicle is deleted and after it's subtracted from num_engines
|
||||||
|
* - when not changing the count (used when changing replace orders)
|
||||||
|
*/
|
||||||
|
void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
|
||||||
|
{
|
||||||
|
if (GetGroupNumEngines(_local_company, id_g, e) == 0 || GetGroupNumEngines(_local_company, ALL_GROUP, e) == 0) {
|
||||||
|
/* We don't have any of this engine type.
|
||||||
|
* Either we just sold the last one, we build a new one or we stopped replacing it.
|
||||||
|
* In all cases, we need to update the left list */
|
||||||
|
InvalidateWindowData(WC_REPLACE_VEHICLE, Engine::Get(e)->type, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an engine is made buildable or is removed from being buildable, add/remove it from the build/autoreplace lists
|
||||||
|
* @param type The type of engine
|
||||||
|
*/
|
||||||
|
void AddRemoveEngineFromAutoreplaceAndBuildWindows(VehicleType type)
|
||||||
|
{
|
||||||
|
InvalidateWindowData(WC_REPLACE_VEHICLE, type, 0); // Update the autoreplace window
|
||||||
|
InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well
|
||||||
|
}
|
||||||
|
|
||||||
|
static const StringID _start_replace_dropdown[] = {
|
||||||
|
STR_REPLACE_VEHICLES_NOW,
|
||||||
|
STR_REPLACE_VEHICLES_WHEN_OLD,
|
||||||
|
INVALID_STRING_ID
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Window for the autoreplacing of vehicles.
|
||||||
|
*/
|
||||||
|
class ReplaceVehicleWindow : public Window {
|
||||||
|
EngineID sel_engine[2]; ///< Selected engine left and right.
|
||||||
|
GUIEngineList engines[2]; ///< Left and right list of engines.
|
||||||
|
bool replace_engines; ///< If \c true, engines are replaced, if \c false, wagons are replaced (only for trains).
|
||||||
|
bool reset_sel_engine; ///< Also reset #sel_engine while updating left and/or right (#update_left and/or #update_right) and no valid engine selected.
|
||||||
|
GroupID sel_group; ///< Group selected to replace.
|
||||||
|
int details_height; ///< Minimal needed height of the details panels (found so far).
|
||||||
|
RailType sel_railtype; ///< Type of rail tracks selected.
|
||||||
|
Scrollbar *vscroll[2];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Figure out if an engine should be added to a list.
|
||||||
|
* @param e The EngineID.
|
||||||
|
* @param draw_left If \c true, the left list is drawn (the engines specific to the railtype you selected).
|
||||||
|
* @param show_engines If \c true, the locomotives are drawn, else the wagons are drawn (never both).
|
||||||
|
* @return \c true if the engine should be in the list (based on this check), else \c false.
|
||||||
|
*/
|
||||||
|
bool GenerateReplaceRailList(EngineID e, bool draw_left, bool show_engines)
|
||||||
|
{
|
||||||
|
const RailVehicleInfo *rvi = RailVehInfo(e);
|
||||||
|
|
||||||
|
/* Ensure that the wagon/engine selection fits the engine. */
|
||||||
|
if ((rvi->railveh_type == RAILVEH_WAGON) == show_engines) return false;
|
||||||
|
|
||||||
|
if (draw_left && show_engines) {
|
||||||
|
/* Ensure that the railtype is specific to the selected one */
|
||||||
|
if (rvi->railtype != this->sel_railtype) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate an engines list
|
||||||
|
* @param draw_left true if generating the left list, otherwise false
|
||||||
|
*/
|
||||||
|
void GenerateReplaceVehList(bool draw_left)
|
||||||
|
{
|
||||||
|
EngineID selected_engine = INVALID_ENGINE;
|
||||||
|
VehicleType type = (VehicleType)this->window_number;
|
||||||
|
byte side = draw_left ? 0 : 1;
|
||||||
|
|
||||||
|
GUIEngineList *list = &this->engines[side];
|
||||||
|
list->Clear();
|
||||||
|
|
||||||
|
const Engine *e;
|
||||||
|
FOR_ALL_ENGINES_OF_TYPE(e, type) {
|
||||||
|
EngineID eid = e->index;
|
||||||
|
if (type == VEH_TRAIN && !this->GenerateReplaceRailList(eid, draw_left, this->replace_engines)) continue; // special rules for trains
|
||||||
|
|
||||||
|
if (draw_left) {
|
||||||
|
const uint num_engines = GetGroupNumEngines(_local_company, this->sel_group, eid);
|
||||||
|
|
||||||
|
/* Skip drawing the engines we don't have any of and haven't set for replacement */
|
||||||
|
if (num_engines == 0 && EngineReplacementForCompany(Company::Get(_local_company), eid, this->sel_group) == INVALID_ENGINE) continue;
|
||||||
|
} else {
|
||||||
|
if (!CheckAutoreplaceValidity(this->sel_engine[0], eid, _local_company)) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*list->Append() = eid;
|
||||||
|
if (eid == this->sel_engine[side]) selected_engine = eid; // The selected engine is still in the list
|
||||||
|
}
|
||||||
|
this->sel_engine[side] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore)
|
||||||
|
EngList_Sort(list, &EngineNumberSorter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Generate the lists */
|
||||||
|
void GenerateLists()
|
||||||
|
{
|
||||||
|
EngineID e = this->sel_engine[0];
|
||||||
|
|
||||||
|
if (this->engines[0].NeedRebuild()) {
|
||||||
|
/* We need to rebuild the left engines list */
|
||||||
|
this->GenerateReplaceVehList(true);
|
||||||
|
this->vscroll[0]->SetCount(this->engines[0].Length());
|
||||||
|
if (this->reset_sel_engine && this->sel_engine[0] == INVALID_ENGINE && this->engines[0].Length() != 0) {
|
||||||
|
this->sel_engine[0] = this->engines[0][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->engines[1].NeedRebuild() || e != this->sel_engine[0]) {
|
||||||
|
/* Either we got a request to rebuild the right engines list, or the left engines list selected a different engine */
|
||||||
|
if (this->sel_engine[0] == INVALID_ENGINE) {
|
||||||
|
/* Always empty the right engines list when nothing is selected in the left engines list */
|
||||||
|
this->engines[1].Clear();
|
||||||
|
this->sel_engine[1] = INVALID_ENGINE;
|
||||||
|
} else {
|
||||||
|
if (this->reset_sel_engine && this->sel_engine[0] != INVALID_ENGINE) {
|
||||||
|
/* Select the current replacement for sel_engine[0]. */
|
||||||
|
const Company *c = Company::Get(_local_company);
|
||||||
|
this->sel_engine[1] = EngineReplacementForCompany(c, this->sel_engine[0], this->sel_group);
|
||||||
|
}
|
||||||
|
/* Regenerate the list on the right. Note: This resets sel_engine[1] to INVALID_ENGINE, if it is no longer available. */
|
||||||
|
this->GenerateReplaceVehList(false);
|
||||||
|
this->vscroll[1]->SetCount(this->engines[1].Length());
|
||||||
|
if (this->reset_sel_engine && this->sel_engine[1] != INVALID_ENGINE) {
|
||||||
|
int position = 0;
|
||||||
|
for (EngineID *it = this->engines[1].Begin(); it != this->engines[1].End(); ++it) {
|
||||||
|
if (*it == this->sel_engine[1]) break;
|
||||||
|
++position;
|
||||||
|
}
|
||||||
|
this->vscroll[1]->ScrollTowards(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Reset the flags about needed updates */
|
||||||
|
this->engines[0].RebuildDone();
|
||||||
|
this->engines[1].RebuildDone();
|
||||||
|
this->reset_sel_engine = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle click on the start replace button.
|
||||||
|
* @param replace_when_old Replace now or only when old?
|
||||||
|
*/
|
||||||
|
void ReplaceClick_StartReplace(bool replace_when_old)
|
||||||
|
{
|
||||||
|
EngineID veh_from = this->sel_engine[0];
|
||||||
|
EngineID veh_to = this->sel_engine[1];
|
||||||
|
DoCommandP(0, (replace_when_old ? 1 : 0) | (this->sel_group << 16), veh_from + (veh_to << 16), CMD_SET_AUTOREPLACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReplaceVehicleWindow(WindowDesc *desc, VehicleType vehicletype, GroupID id_g) : Window(desc)
|
||||||
|
{
|
||||||
|
if (vehicletype == VEH_TRAIN) {
|
||||||
|
/* For rail vehicles find the most used vehicle type, which is usually
|
||||||
|
* better than 'just' the first/previous vehicle type. */
|
||||||
|
uint type_count[RAILTYPE_END];
|
||||||
|
memset(type_count, 0, sizeof(type_count));
|
||||||
|
|
||||||
|
const Engine *e;
|
||||||
|
FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
|
||||||
|
if (e->u.rail.railveh_type == RAILVEH_WAGON) continue;
|
||||||
|
type_count[e->u.rail.railtype] += GetGroupNumEngines(_local_company, id_g, e->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->sel_railtype = RAILTYPE_BEGIN;
|
||||||
|
for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
|
||||||
|
if (type_count[this->sel_railtype] < type_count[rt]) this->sel_railtype = rt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->replace_engines = true; // start with locomotives (all other vehicles will not read this bool)
|
||||||
|
this->engines[0].ForceRebuild();
|
||||||
|
this->engines[1].ForceRebuild();
|
||||||
|
this->reset_sel_engine = true;
|
||||||
|
this->details_height = ((vehicletype == VEH_TRAIN) ? 10 : 9) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
|
||||||
|
this->sel_engine[0] = INVALID_ENGINE;
|
||||||
|
this->sel_engine[1] = INVALID_ENGINE;
|
||||||
|
|
||||||
|
this->CreateNestedTree();
|
||||||
|
this->vscroll[0] = this->GetScrollbar(WID_RV_LEFT_SCROLLBAR);
|
||||||
|
this->vscroll[1] = this->GetScrollbar(WID_RV_RIGHT_SCROLLBAR);
|
||||||
|
this->FinishInitNested(vehicletype);
|
||||||
|
|
||||||
|
this->owner = _local_company;
|
||||||
|
this->sel_group = id_g;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_RV_LEFT_MATRIX:
|
||||||
|
case WID_RV_RIGHT_MATRIX:
|
||||||
|
resize->height = GetEngineListHeight((VehicleType)this->window_number);
|
||||||
|
size->height = (this->window_number <= VEH_ROAD ? 8 : 4) * resize->height;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_RV_LEFT_DETAILS:
|
||||||
|
case WID_RV_RIGHT_DETAILS:
|
||||||
|
size->height = this->details_height;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_RV_TRAIN_WAGONREMOVE_TOGGLE: {
|
||||||
|
StringID str = this->GetWidget<NWidgetCore>(widget)->widget_data;
|
||||||
|
SetDParam(0, STR_CONFIG_SETTING_ON);
|
||||||
|
Dimension d = GetStringBoundingBox(str);
|
||||||
|
SetDParam(0, STR_CONFIG_SETTING_OFF);
|
||||||
|
d = maxdim(d, GetStringBoundingBox(str));
|
||||||
|
d.width += padding.width;
|
||||||
|
d.height += padding.height;
|
||||||
|
*size = maxdim(*size, d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_RV_TRAIN_ENGINEWAGON_TOGGLE: {
|
||||||
|
StringID str = this->GetWidget<NWidgetCore>(widget)->widget_data;
|
||||||
|
SetDParam(0, STR_REPLACE_ENGINES);
|
||||||
|
Dimension d = GetStringBoundingBox(str);
|
||||||
|
SetDParam(0, STR_REPLACE_WAGONS);
|
||||||
|
d = maxdim(d, GetStringBoundingBox(str));
|
||||||
|
d.width += padding.width;
|
||||||
|
d.height += padding.height;
|
||||||
|
*size = maxdim(*size, d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_RV_INFO_TAB: {
|
||||||
|
SetDParam(0, STR_REPLACE_NOT_REPLACING);
|
||||||
|
Dimension d = GetStringBoundingBox(STR_BLACK_STRING);
|
||||||
|
SetDParam(0, STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED);
|
||||||
|
d = maxdim(d, GetStringBoundingBox(STR_BLACK_STRING));
|
||||||
|
d.width += WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
|
||||||
|
d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
|
||||||
|
*size = maxdim(*size, d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_RV_TRAIN_RAILTYPE_DROPDOWN: {
|
||||||
|
Dimension d = {0, 0};
|
||||||
|
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
|
||||||
|
const RailtypeInfo *rti = GetRailTypeInfo(rt);
|
||||||
|
/* Skip rail type if it has no label */
|
||||||
|
if (rti->label == 0) continue;
|
||||||
|
d = maxdim(d, GetStringBoundingBox(rti->strings.replace_text));
|
||||||
|
}
|
||||||
|
d.width += padding.width;
|
||||||
|
d.height += padding.height;
|
||||||
|
*size = maxdim(*size, d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_RV_START_REPLACE: {
|
||||||
|
Dimension d = GetStringBoundingBox(STR_REPLACE_VEHICLES_START);
|
||||||
|
for (int i = 0; _start_replace_dropdown[i] != INVALID_STRING_ID; i++) {
|
||||||
|
d = maxdim(d, GetStringBoundingBox(_start_replace_dropdown[i]));
|
||||||
|
}
|
||||||
|
d.width += padding.width;
|
||||||
|
d.height += padding.height;
|
||||||
|
*size = maxdim(*size, d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetStringParameters(int widget) const
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_RV_CAPTION:
|
||||||
|
SetDParam(0, STR_REPLACE_VEHICLE_TRAIN + this->window_number);
|
||||||
|
switch (this->sel_group) {
|
||||||
|
case ALL_GROUP:
|
||||||
|
SetDParam(1, STR_GROUP_ALL_TRAINS + this->window_number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEFAULT_GROUP:
|
||||||
|
SetDParam(1, STR_GROUP_DEFAULT_TRAINS + this->window_number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
SetDParam(1, STR_GROUP_NAME);
|
||||||
|
SetDParam(2, sel_group);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_RV_TRAIN_WAGONREMOVE_TOGGLE: {
|
||||||
|
const Company *c = Company::Get(_local_company);
|
||||||
|
SetDParam(0, c->settings.renew_keep_length ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_RV_TRAIN_ENGINEWAGON_TOGGLE:
|
||||||
|
SetDParam(0, this->replace_engines ? STR_REPLACE_ENGINES : STR_REPLACE_WAGONS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DrawWidget(const Rect &r, int widget) const
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_RV_INFO_TAB: {
|
||||||
|
const Company *c = Company::Get(_local_company);
|
||||||
|
if (this->sel_engine[0] != INVALID_ENGINE) {
|
||||||
|
if (!EngineHasReplacementForCompany(c, this->sel_engine[0], this->sel_group)) {
|
||||||
|
SetDParam(0, STR_REPLACE_NOT_REPLACING);
|
||||||
|
} else {
|
||||||
|
bool when_old = false;
|
||||||
|
EngineID e = EngineReplacementForCompany(c, this->sel_engine[0], this->sel_group, &when_old);
|
||||||
|
SetDParam(0, when_old ? STR_REPLACE_REPLACING_WHEN_OLD : STR_ENGINE_NAME);
|
||||||
|
SetDParam(1, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SetDParam(0, STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_BLACK_STRING, TC_FROMSTRING, SA_HOR_CENTER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_RV_LEFT_MATRIX:
|
||||||
|
case WID_RV_RIGHT_MATRIX: {
|
||||||
|
int side = (widget == WID_RV_LEFT_MATRIX) ? 0 : 1;
|
||||||
|
EngineID start = this->vscroll[side]->GetPosition(); // what is the offset for the start (scrolling)
|
||||||
|
EngineID end = min(this->vscroll[side]->GetCapacity() + start, this->engines[side].Length());
|
||||||
|
|
||||||
|
/* Do the actual drawing */
|
||||||
|
DrawEngineList((VehicleType)this->window_number, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP,
|
||||||
|
&this->engines[side], start, end, this->sel_engine[side], side == 0, this->sel_group);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPaint()
|
||||||
|
{
|
||||||
|
if (this->engines[0].NeedRebuild() || this->engines[1].NeedRebuild()) this->GenerateLists();
|
||||||
|
|
||||||
|
Company *c = Company::Get(_local_company);
|
||||||
|
|
||||||
|
/* Disable the "Start Replacing" button if:
|
||||||
|
* Either engines list is empty
|
||||||
|
* or The selected replacement engine has a replacement (to prevent loops). */
|
||||||
|
this->SetWidgetDisabledState(WID_RV_START_REPLACE,
|
||||||
|
this->sel_engine[0] == INVALID_ENGINE ||
|
||||||
|
this->sel_engine[1] == INVALID_ENGINE ||
|
||||||
|
EngineReplacementForCompany(c, this->sel_engine[1], this->sel_group) != INVALID_ENGINE);
|
||||||
|
|
||||||
|
/* Disable the "Stop Replacing" button if:
|
||||||
|
* The left engines list (existing vehicle) is empty
|
||||||
|
* or The selected vehicle has no replacement set up */
|
||||||
|
this->SetWidgetDisabledState(WID_RV_STOP_REPLACE,
|
||||||
|
this->sel_engine[0] == INVALID_ENGINE ||
|
||||||
|
!EngineHasReplacementForCompany(c, this->sel_engine[0], this->sel_group));
|
||||||
|
|
||||||
|
if (this->window_number == VEH_TRAIN) {
|
||||||
|
/* sets the colour of that art thing */
|
||||||
|
this->GetWidget<NWidgetCore>(WID_RV_TRAIN_FLUFF_LEFT)->colour = _company_colours[_local_company];
|
||||||
|
this->GetWidget<NWidgetCore>(WID_RV_TRAIN_FLUFF_RIGHT)->colour = _company_colours[_local_company];
|
||||||
|
|
||||||
|
/* Show the selected railtype in the pulldown menu */
|
||||||
|
this->GetWidget<NWidgetCore>(WID_RV_TRAIN_RAILTYPE_DROPDOWN)->widget_data = GetRailTypeInfo(sel_railtype)->strings.replace_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->DrawWidgets();
|
||||||
|
|
||||||
|
if (!this->IsShaded()) {
|
||||||
|
int needed_height = this->details_height;
|
||||||
|
/* Draw details panels. */
|
||||||
|
for (int side = 0; side < 2; side++) {
|
||||||
|
if (this->sel_engine[side] != INVALID_ENGINE) {
|
||||||
|
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS);
|
||||||
|
int text_end = DrawVehiclePurchaseInfo(nwi->pos_x + WD_FRAMETEXT_LEFT, nwi->pos_x + nwi->current_x - WD_FRAMETEXT_RIGHT,
|
||||||
|
nwi->pos_y + WD_FRAMERECT_TOP, this->sel_engine[side]);
|
||||||
|
needed_height = max(needed_height, text_end - (int)nwi->pos_y + WD_FRAMERECT_BOTTOM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needed_height != this->details_height) { // Details window are not high enough, enlarge them.
|
||||||
|
this->details_height = needed_height;
|
||||||
|
this->ReInit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnClick(Point pt, int widget, int click_count)
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_RV_TRAIN_ENGINEWAGON_TOGGLE:
|
||||||
|
this->replace_engines = !(this->replace_engines);
|
||||||
|
this->engines[0].ForceRebuild();
|
||||||
|
this->reset_sel_engine = true;
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_RV_TRAIN_RAILTYPE_DROPDOWN: // Railtype selection dropdown menu
|
||||||
|
ShowDropDownList(this, GetRailTypeDropDownList(true), sel_railtype, WID_RV_TRAIN_RAILTYPE_DROPDOWN);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_RV_TRAIN_WAGONREMOVE_TOGGLE: // toggle renew_keep_length
|
||||||
|
DoCommandP(0, GetCompanySettingIndex("company.renew_keep_length"), Company::Get(_local_company)->settings.renew_keep_length ? 0 : 1, CMD_CHANGE_COMPANY_SETTING);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_RV_START_REPLACE: { // Start replacing
|
||||||
|
if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
|
||||||
|
this->HandleButtonClick(WID_RV_START_REPLACE);
|
||||||
|
ReplaceClick_StartReplace(false);
|
||||||
|
} else {
|
||||||
|
bool replacment_when_old = EngineHasReplacementWhenOldForCompany(Company::Get(_local_company), this->sel_engine[0], this->sel_group);
|
||||||
|
ShowDropDownMenu(this, _start_replace_dropdown, replacment_when_old ? 1 : 0, WID_RV_START_REPLACE, !this->replace_engines ? 1 << 1 : 0, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_RV_STOP_REPLACE: { // Stop replacing
|
||||||
|
EngineID veh_from = this->sel_engine[0];
|
||||||
|
DoCommandP(0, this->sel_group << 16, veh_from + (INVALID_ENGINE << 16), CMD_SET_AUTOREPLACE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_RV_LEFT_MATRIX:
|
||||||
|
case WID_RV_RIGHT_MATRIX: {
|
||||||
|
byte click_side;
|
||||||
|
if (widget == WID_RV_LEFT_MATRIX) {
|
||||||
|
click_side = 0;
|
||||||
|
} else {
|
||||||
|
click_side = 1;
|
||||||
|
}
|
||||||
|
uint i = this->vscroll[click_side]->GetScrolledRowFromWidget(pt.y, this, widget);
|
||||||
|
size_t engine_count = this->engines[click_side].Length();
|
||||||
|
|
||||||
|
EngineID e = engine_count > i ? this->engines[click_side][i] : INVALID_ENGINE;
|
||||||
|
if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected
|
||||||
|
this->sel_engine[click_side] = e;
|
||||||
|
if (click_side == 0) {
|
||||||
|
this->engines[1].ForceRebuild();
|
||||||
|
this->reset_sel_engine = true;
|
||||||
|
}
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnDropdownSelect(int widget, int index)
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_RV_TRAIN_RAILTYPE_DROPDOWN: {
|
||||||
|
RailType temp = (RailType)index;
|
||||||
|
if (temp == sel_railtype) return; // we didn't select a new one. No need to change anything
|
||||||
|
sel_railtype = temp;
|
||||||
|
/* Reset scrollbar positions */
|
||||||
|
this->vscroll[0]->SetPosition(0);
|
||||||
|
this->vscroll[1]->SetPosition(0);
|
||||||
|
/* Rebuild the lists */
|
||||||
|
this->engines[0].ForceRebuild();
|
||||||
|
this->engines[1].ForceRebuild();
|
||||||
|
this->reset_sel_engine = true;
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_RV_START_REPLACE:
|
||||||
|
this->ReplaceClick_StartReplace(index != 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnResize()
|
||||||
|
{
|
||||||
|
this->vscroll[0]->SetCapacityFromWidget(this, WID_RV_LEFT_MATRIX);
|
||||||
|
this->vscroll[1]->SetCapacityFromWidget(this, WID_RV_RIGHT_MATRIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some data on this window has become invalid.
|
||||||
|
* @param data Information about the changed data.
|
||||||
|
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
|
||||||
|
*/
|
||||||
|
virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
|
||||||
|
{
|
||||||
|
if (data != 0) {
|
||||||
|
/* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
|
||||||
|
this->engines[0].ForceRebuild();
|
||||||
|
} else {
|
||||||
|
this->engines[1].ForceRebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), SetDataTip(STR_REPLACE_VEHICLES_WHITE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||||
|
NWidget(WWT_SHADEBOX, COLOUR_GREY),
|
||||||
|
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
|
||||||
|
NWidget(WWT_STICKYBOX, COLOUR_GREY),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||||
|
NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR),
|
||||||
|
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_LEFT_SCROLLBAR),
|
||||||
|
NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR),
|
||||||
|
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_RIGHT_SCROLLBAR),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetDataTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_HELP_START_BUTTON),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetDataTip(0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB), SetResize(1, 0),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(150, 12), SetDataTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_HELP_STOP_BUTTON),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_ENGINEWAGON_TOGGLE), SetMinimalSize(139, 12), SetDataTip(STR_REPLACE_ENGINE_WAGON_SELECT, STR_REPLACE_ENGINE_WAGON_SELECT_HELP),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_TRAIN_FLUFF_LEFT), SetMinimalSize(15, 12), EndContainer(),
|
||||||
|
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_RAILTYPE_DROPDOWN), SetMinimalSize(136, 12), SetDataTip(0x0, STR_REPLACE_HELP_RAILTYPE), SetResize(1, 0),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_TRAIN_FLUFF_RIGHT), SetMinimalSize(16, 12), EndContainer(),
|
||||||
|
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_WAGONREMOVE_TOGGLE), SetMinimalSize(138, 12), SetDataTip(STR_REPLACE_REMOVE_WAGON, STR_REPLACE_REMOVE_WAGON_HELP),
|
||||||
|
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
|
||||||
|
EndContainer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowDesc _replace_rail_vehicle_desc(
|
||||||
|
WDP_AUTO, "replace_vehicle_train", 500, 140,
|
||||||
|
WC_REPLACE_VEHICLE, WC_NONE,
|
||||||
|
WDF_CONSTRUCTION,
|
||||||
|
_nested_replace_rail_vehicle_widgets, lengthof(_nested_replace_rail_vehicle_widgets)
|
||||||
|
);
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_replace_vehicle_widgets[] = {
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), SetMinimalSize(433, 14), SetDataTip(STR_REPLACE_VEHICLES_WHITE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||||
|
NWidget(WWT_SHADEBOX, COLOUR_GREY),
|
||||||
|
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
|
||||||
|
NWidget(WWT_STICKYBOX, COLOUR_GREY),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||||
|
NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR),
|
||||||
|
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_LEFT_SCROLLBAR),
|
||||||
|
NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR),
|
||||||
|
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_RIGHT_SCROLLBAR),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(228, 92), SetResize(1, 0), EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(228, 92), SetResize(1, 0), EndContainer(),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetDataTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_HELP_START_BUTTON),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetDataTip(0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB), SetResize(1, 0), EndContainer(),
|
||||||
|
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(138, 12), SetDataTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_HELP_STOP_BUTTON),
|
||||||
|
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
|
||||||
|
EndContainer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowDesc _replace_vehicle_desc(
|
||||||
|
WDP_AUTO, "replace_vehicle", 456, 118,
|
||||||
|
WC_REPLACE_VEHICLE, WC_NONE,
|
||||||
|
WDF_CONSTRUCTION,
|
||||||
|
_nested_replace_vehicle_widgets, lengthof(_nested_replace_vehicle_widgets)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the autoreplace configuration window for a particular group.
|
||||||
|
* @param id_g The group to replace the vehicles for.
|
||||||
|
* @param vehicletype The type of vehicles in the group.
|
||||||
|
*/
|
||||||
|
void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
|
||||||
|
{
|
||||||
|
DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
|
||||||
|
new ReplaceVehicleWindow(vehicletype == VEH_TRAIN ? &_replace_rail_vehicle_desc : &_replace_vehicle_desc, vehicletype, id_g);
|
||||||
|
}
|
||||||
1427
src/build_vehicle_gui.cpp.orig
Normal file
1427
src/build_vehicle_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
432
src/error_gui.cpp.orig
Normal file
432
src/error_gui.cpp.orig
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 error_gui.cpp GUI related to errors. */
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "landscape.h"
|
||||||
|
#include "newgrf_text.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "viewport_func.h"
|
||||||
|
#include "gfx_func.h"
|
||||||
|
#include "string_func.h"
|
||||||
|
#include "company_base.h"
|
||||||
|
#include "company_manager_face.h"
|
||||||
|
#include "strings_func.h"
|
||||||
|
#include "zoom_func.h"
|
||||||
|
#include "window_func.h"
|
||||||
|
#include "console_func.h"
|
||||||
|
#include "window_gui.h"
|
||||||
|
|
||||||
|
#include "widgets/error_widget.h"
|
||||||
|
|
||||||
|
#include "table/strings.h"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_errmsg_widgets[] = {
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_CLOSEBOX, COLOUR_RED),
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_RED, WID_EM_CAPTION), SetDataTip(STR_ERROR_MESSAGE_CAPTION, STR_NULL),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_RED),
|
||||||
|
NWidget(WWT_EMPTY, COLOUR_RED, WID_EM_MESSAGE), SetPadding(0, 2, 0, 2), SetMinimalSize(236, 32),
|
||||||
|
EndContainer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowDesc _errmsg_desc(
|
||||||
|
WDP_MANUAL, "error", 0, 0,
|
||||||
|
WC_ERRMSG, WC_NONE,
|
||||||
|
0,
|
||||||
|
_nested_errmsg_widgets, lengthof(_nested_errmsg_widgets)
|
||||||
|
);
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_errmsg_face_widgets[] = {
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_CLOSEBOX, COLOUR_RED),
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_RED, WID_EM_CAPTION), SetDataTip(STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY, STR_NULL),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_RED),
|
||||||
|
NWidget(NWID_HORIZONTAL), SetPIP(2, 1, 2),
|
||||||
|
NWidget(WWT_EMPTY, COLOUR_RED, WID_EM_FACE), SetMinimalSize(92, 119), SetFill(0, 1), SetPadding(2, 0, 1, 0),
|
||||||
|
NWidget(WWT_EMPTY, COLOUR_RED, WID_EM_MESSAGE), SetFill(0, 1), SetMinimalSize(238, 123),
|
||||||
|
EndContainer(),
|
||||||
|
EndContainer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowDesc _errmsg_face_desc(
|
||||||
|
WDP_MANUAL, "error_face", 0, 0,
|
||||||
|
WC_ERRMSG, WC_NONE,
|
||||||
|
0,
|
||||||
|
_nested_errmsg_face_widgets, lengthof(_nested_errmsg_face_widgets)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the given data into our instance.
|
||||||
|
* @param data The data to copy.
|
||||||
|
*/
|
||||||
|
ErrorMessageData::ErrorMessageData(const ErrorMessageData &data)
|
||||||
|
{
|
||||||
|
*this = data;
|
||||||
|
for (size_t i = 0; i < lengthof(this->strings); i++) {
|
||||||
|
if (this->strings[i] != NULL) {
|
||||||
|
this->strings[i] = strdup(this->strings[i]);
|
||||||
|
this->decode_params[i] = (size_t)this->strings[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Free all the strings. */
|
||||||
|
ErrorMessageData::~ErrorMessageData()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < lengthof(this->strings); i++) free(this->strings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display an error message in a window.
|
||||||
|
* @param summary_msg General error message showed in first line. Must be valid.
|
||||||
|
* @param detailed_msg Detailed error message showed in second line. Can be INVALID_STRING_ID.
|
||||||
|
* @param duration The amount of time to show this error message.
|
||||||
|
* @param x World X position (TileVirtX) of the error location. Set both x and y to 0 to just center the message when there is no related error tile.
|
||||||
|
* @param y World Y position (TileVirtY) of the error location. Set both x and y to 0 to just center the message when there is no related error tile.
|
||||||
|
* @param textref_stack_grffile NewGRF that provides the #TextRefStack for the error message.
|
||||||
|
* @param textref_stack_size Number of uint32 values to put on the #TextRefStack for the error message; 0 if the #TextRefStack shall not be used.
|
||||||
|
* @param textref_stack Values to put on the #TextRefStack.
|
||||||
|
*/
|
||||||
|
ErrorMessageData::ErrorMessageData(StringID summary_msg, StringID detailed_msg, uint duration, int x, int y, const GRFFile *textref_stack_grffile, uint textref_stack_size, const uint32 *textref_stack) :
|
||||||
|
duration(duration),
|
||||||
|
textref_stack_grffile(textref_stack_grffile),
|
||||||
|
textref_stack_size(textref_stack_size),
|
||||||
|
summary_msg(summary_msg),
|
||||||
|
detailed_msg(detailed_msg),
|
||||||
|
face(INVALID_COMPANY)
|
||||||
|
{
|
||||||
|
this->position.x = x;
|
||||||
|
this->position.y = y;
|
||||||
|
|
||||||
|
memset(this->decode_params, 0, sizeof(this->decode_params));
|
||||||
|
memset(this->strings, 0, sizeof(this->strings));
|
||||||
|
|
||||||
|
if (textref_stack_size > 0) MemCpyT(this->textref_stack, textref_stack, textref_stack_size);
|
||||||
|
|
||||||
|
assert(summary_msg != INVALID_STRING_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy error parameters from current DParams.
|
||||||
|
*/
|
||||||
|
void ErrorMessageData::CopyOutDParams()
|
||||||
|
{
|
||||||
|
/* Reset parameters */
|
||||||
|
for (size_t i = 0; i < lengthof(this->strings); i++) free(this->strings[i]);
|
||||||
|
memset(this->decode_params, 0, sizeof(this->decode_params));
|
||||||
|
memset(this->strings, 0, sizeof(this->strings));
|
||||||
|
|
||||||
|
/* Get parameters using type information */
|
||||||
|
if (this->textref_stack_size > 0) StartTextRefStackUsage(this->textref_stack_grffile, this->textref_stack_size, this->textref_stack);
|
||||||
|
CopyOutDParam(this->decode_params, this->strings, this->detailed_msg == INVALID_STRING_ID ? this->summary_msg : this->detailed_msg, lengthof(this->decode_params));
|
||||||
|
if (this->textref_stack_size > 0) StopTextRefStackUsage();
|
||||||
|
|
||||||
|
if (this->detailed_msg == STR_ERROR_OWNED_BY) {
|
||||||
|
CompanyID company = (CompanyID)GetDParamX(this->decode_params, 2);
|
||||||
|
if (company < MAX_COMPANIES) face = company;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a error string parameter.
|
||||||
|
* @param n Parameter index
|
||||||
|
* @param v Parameter value
|
||||||
|
*/
|
||||||
|
void ErrorMessageData::SetDParam(uint n, uint64 v)
|
||||||
|
{
|
||||||
|
this->decode_params[n] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a rawstring parameter.
|
||||||
|
* @param n Parameter index
|
||||||
|
* @param str Raw string
|
||||||
|
*/
|
||||||
|
void ErrorMessageData::SetDParamStr(uint n, const char *str)
|
||||||
|
{
|
||||||
|
free(this->strings[n]);
|
||||||
|
this->strings[n] = strdup(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Define a queue with errors. */
|
||||||
|
typedef std::list<ErrorMessageData> ErrorList;
|
||||||
|
/** The actual queue with errors. */
|
||||||
|
ErrorList _error_list;
|
||||||
|
/** Whether the window system is initialized or not. */
|
||||||
|
bool _window_system_initialized = false;
|
||||||
|
|
||||||
|
/** Window class for displaying an error message window. */
|
||||||
|
struct ErrmsgWindow : public Window, ErrorMessageData {
|
||||||
|
private:
|
||||||
|
uint height_summary; ///< Height of the #summary_msg string in pixels in the #WID_EM_MESSAGE widget.
|
||||||
|
uint height_detailed; ///< Height of the #detailed_msg string in pixels in the #WID_EM_MESSAGE widget.
|
||||||
|
|
||||||
|
public:
|
||||||
|
ErrmsgWindow(const ErrorMessageData &data) : Window(data.HasFace() ? &_errmsg_face_desc : &_errmsg_desc), ErrorMessageData(data)
|
||||||
|
{
|
||||||
|
this->InitNested();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
|
||||||
|
{
|
||||||
|
if (widget != WID_EM_MESSAGE) return;
|
||||||
|
|
||||||
|
CopyInDParam(0, this->decode_params, lengthof(this->decode_params));
|
||||||
|
if (this->textref_stack_size > 0) StartTextRefStackUsage(this->textref_stack_grffile, this->textref_stack_size, this->textref_stack);
|
||||||
|
|
||||||
|
int text_width = max(0, (int)size->width - WD_FRAMETEXT_LEFT - WD_FRAMETEXT_RIGHT);
|
||||||
|
this->height_summary = GetStringHeight(this->summary_msg, text_width);
|
||||||
|
this->height_detailed = (this->detailed_msg == INVALID_STRING_ID) ? 0 : GetStringHeight(this->detailed_msg, text_width);
|
||||||
|
|
||||||
|
if (this->textref_stack_size > 0) StopTextRefStackUsage();
|
||||||
|
|
||||||
|
uint panel_height = WD_FRAMERECT_TOP + this->height_summary + WD_FRAMERECT_BOTTOM;
|
||||||
|
if (this->detailed_msg != INVALID_STRING_ID) panel_height += this->height_detailed + WD_PAR_VSEP_WIDE;
|
||||||
|
|
||||||
|
size->height = max(size->height, panel_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number)
|
||||||
|
{
|
||||||
|
/* Position (0, 0) given, center the window. */
|
||||||
|
if (this->position.x == 0 && this->position.y == 0) {
|
||||||
|
Point pt = {(_screen.width - sm_width) >> 1, (_screen.height - sm_height) >> 1};
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the free screen space between the main toolbar at the top, and the statusbar at the bottom.
|
||||||
|
* Add a fixed distance 20 to make it less cluttered.
|
||||||
|
*/
|
||||||
|
int scr_top = GetMainViewTop() + 20;
|
||||||
|
int scr_bot = GetMainViewBottom() - 20;
|
||||||
|
|
||||||
|
Point pt = RemapCoords2(this->position.x, this->position.y);
|
||||||
|
const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
|
||||||
|
if (this->face == INVALID_COMPANY) {
|
||||||
|
/* move x pos to opposite corner */
|
||||||
|
pt.x = UnScaleByZoom(pt.x - vp->virtual_left, vp->zoom) + vp->left;
|
||||||
|
pt.x = (pt.x < (_screen.width >> 1)) ? _screen.width - sm_width - 20 : 20; // Stay 20 pixels away from the edge of the screen.
|
||||||
|
|
||||||
|
/* move y pos to opposite corner */
|
||||||
|
pt.y = UnScaleByZoom(pt.y - vp->virtual_top, vp->zoom) + vp->top;
|
||||||
|
pt.y = (pt.y < (_screen.height >> 1)) ? scr_bot - sm_height : scr_top;
|
||||||
|
} else {
|
||||||
|
pt.x = Clamp(UnScaleByZoom(pt.x - vp->virtual_left, vp->zoom) + vp->left - (sm_width / 2), 0, _screen.width - sm_width);
|
||||||
|
pt.y = Clamp(UnScaleByZoom(pt.y - vp->virtual_top, vp->zoom) + vp->top - (sm_height / 2), scr_top, scr_bot - sm_height);
|
||||||
|
}
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some data on this window has become invalid.
|
||||||
|
* @param data Information about the changed data.
|
||||||
|
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
|
||||||
|
*/
|
||||||
|
virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
|
||||||
|
{
|
||||||
|
/* If company gets shut down, while displaying an error about it, remove the error message. */
|
||||||
|
if (this->face != INVALID_COMPANY && !Company::IsValidID(this->face)) delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetStringParameters(int widget) const
|
||||||
|
{
|
||||||
|
if (widget == WID_EM_CAPTION) CopyInDParam(0, this->decode_params, lengthof(this->decode_params));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DrawWidget(const Rect &r, int widget) const
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_EM_FACE: {
|
||||||
|
const Company *c = Company::Get(this->face);
|
||||||
|
DrawCompanyManagerFace(c->face, c->colour, r.left, r.top);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_EM_MESSAGE:
|
||||||
|
CopyInDParam(0, this->decode_params, lengthof(this->decode_params));
|
||||||
|
if (this->textref_stack_size > 0) StartTextRefStackUsage(this->textref_stack_grffile, this->textref_stack_size, this->textref_stack);
|
||||||
|
|
||||||
|
if (this->detailed_msg == INVALID_STRING_ID) {
|
||||||
|
DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, r.top + WD_FRAMERECT_TOP, r.bottom - WD_FRAMERECT_BOTTOM,
|
||||||
|
this->summary_msg, TC_FROMSTRING, SA_CENTER);
|
||||||
|
} else {
|
||||||
|
int extra = (r.bottom - r.top + 1 - this->height_summary - this->height_detailed - WD_PAR_VSEP_WIDE) / 2;
|
||||||
|
|
||||||
|
/* Note: NewGRF supplied error message often do not start with a colour code, so default to white. */
|
||||||
|
int top = r.top + WD_FRAMERECT_TOP;
|
||||||
|
int bottom = top + this->height_summary + extra;
|
||||||
|
DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, top, bottom, this->summary_msg, TC_WHITE, SA_CENTER);
|
||||||
|
|
||||||
|
bottom = r.bottom - WD_FRAMERECT_BOTTOM;
|
||||||
|
top = bottom - this->height_detailed - extra;
|
||||||
|
DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, top, bottom, this->detailed_msg, TC_WHITE, SA_CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->textref_stack_size > 0) StopTextRefStackUsage();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnMouseLoop()
|
||||||
|
{
|
||||||
|
/* Disallow closing the window too easily, if timeout is disabled */
|
||||||
|
if (_right_button_down && this->duration != 0) delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnHundredthTick()
|
||||||
|
{
|
||||||
|
/* Timeout enabled? */
|
||||||
|
if (this->duration != 0) {
|
||||||
|
this->duration--;
|
||||||
|
if (this->duration == 0) delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~ErrmsgWindow()
|
||||||
|
{
|
||||||
|
SetRedErrorSquare(INVALID_TILE);
|
||||||
|
if (_window_system_initialized) ShowFirstError();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual EventState OnKeyPress(WChar key, uint16 keycode)
|
||||||
|
{
|
||||||
|
if (keycode != WKC_SPACE) return ES_NOT_HANDLED;
|
||||||
|
delete this;
|
||||||
|
return ES_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the currently shown error message was critical or not.
|
||||||
|
* @return True iff the message was critical.
|
||||||
|
*/
|
||||||
|
bool IsCritical()
|
||||||
|
{
|
||||||
|
return this->duration == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all errors from the queue.
|
||||||
|
*/
|
||||||
|
void ClearErrorMessages()
|
||||||
|
{
|
||||||
|
UnshowCriticalError();
|
||||||
|
_error_list.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Show the first error of the queue. */
|
||||||
|
void ShowFirstError()
|
||||||
|
{
|
||||||
|
_window_system_initialized = true;
|
||||||
|
if (!_error_list.empty()) {
|
||||||
|
new ErrmsgWindow(_error_list.front());
|
||||||
|
_error_list.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unshow the critical error. This has to happen when a critical
|
||||||
|
* error is shown and we uninitialise the window system, i.e.
|
||||||
|
* remove all the windows.
|
||||||
|
*/
|
||||||
|
void UnshowCriticalError()
|
||||||
|
{
|
||||||
|
ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0);
|
||||||
|
if (_window_system_initialized && w != NULL) {
|
||||||
|
if (w->IsCritical()) _error_list.push_front(*w);
|
||||||
|
_window_system_initialized = false;
|
||||||
|
delete w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display an error message in a window.
|
||||||
|
* @param summary_msg General error message showed in first line. Must be valid.
|
||||||
|
* @param detailed_msg Detailed error message showed in second line. Can be INVALID_STRING_ID.
|
||||||
|
* @param wl Message severity.
|
||||||
|
* @param x World X position (TileVirtX) of the error location. Set both x and y to 0 to just center the message when there is no related error tile.
|
||||||
|
* @param y World Y position (TileVirtY) of the error location. Set both x and y to 0 to just center the message when there is no related error tile.
|
||||||
|
* @param textref_stack_grffile NewGRF providing the #TextRefStack for the error message.
|
||||||
|
* @param textref_stack_size Number of uint32 values to put on the #TextRefStack for the error message; 0 if the #TextRefStack shall not be used.
|
||||||
|
* @param textref_stack Values to put on the #TextRefStack.
|
||||||
|
*/
|
||||||
|
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x, int y, const GRFFile *textref_stack_grffile, uint textref_stack_size, const uint32 *textref_stack)
|
||||||
|
{
|
||||||
|
assert(textref_stack_size == 0 || (textref_stack_grffile != NULL && textref_stack != NULL));
|
||||||
|
if (summary_msg == STR_NULL) summary_msg = STR_EMPTY;
|
||||||
|
|
||||||
|
if (wl != WL_INFO) {
|
||||||
|
/* Print message to console */
|
||||||
|
char buf[DRAW_STRING_BUFFER];
|
||||||
|
|
||||||
|
if (textref_stack_size > 0) StartTextRefStackUsage(textref_stack_grffile, textref_stack_size, textref_stack);
|
||||||
|
|
||||||
|
char *b = GetString(buf, summary_msg, lastof(buf));
|
||||||
|
if (detailed_msg != INVALID_STRING_ID) {
|
||||||
|
b += seprintf(b, lastof(buf), " ");
|
||||||
|
GetString(b, detailed_msg, lastof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textref_stack_size > 0) StopTextRefStackUsage();
|
||||||
|
|
||||||
|
switch (wl) {
|
||||||
|
case WL_WARNING: IConsolePrint(CC_WARNING, buf); break;
|
||||||
|
default: IConsoleError(buf); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool no_timeout = wl == WL_CRITICAL;
|
||||||
|
|
||||||
|
if (_settings_client.gui.errmsg_duration == 0 && !no_timeout) return;
|
||||||
|
|
||||||
|
ErrorMessageData data(summary_msg, detailed_msg, no_timeout ? 0 : _settings_client.gui.errmsg_duration, x, y, textref_stack_grffile, textref_stack_size, textref_stack);
|
||||||
|
data.CopyOutDParams();
|
||||||
|
|
||||||
|
ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0);
|
||||||
|
if (w != NULL && w->IsCritical()) {
|
||||||
|
/* A critical error is currently shown. */
|
||||||
|
if (wl == WL_CRITICAL) {
|
||||||
|
/* Push another critical error in the queue of errors,
|
||||||
|
* but do not put other errors in the queue. */
|
||||||
|
_error_list.push_back(data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Nothing or a non-critical error was shown. */
|
||||||
|
delete w;
|
||||||
|
new ErrmsgWindow(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a list of errors.
|
||||||
|
* Note: This does not try to display the error now. This is useful if the window system is not yet running.
|
||||||
|
* @param data Error message datas; cleared afterwards
|
||||||
|
*/
|
||||||
|
void ScheduleErrorMessage(ErrorList &datas)
|
||||||
|
{
|
||||||
|
_error_list.splice(_error_list.end(), datas);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule an error.
|
||||||
|
* Note: This does not try to display the error now. This is useful if the window system is not yet running.
|
||||||
|
* @param data Error message data; cleared afterwards
|
||||||
|
*/
|
||||||
|
void ScheduleErrorMessage(const ErrorMessageData &data)
|
||||||
|
{
|
||||||
|
_error_list.push_back(data);
|
||||||
|
}
|
||||||
1697
src/gfx.cpp.orig
Normal file
1697
src/gfx.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
226
src/gfx_func.h.orig
Normal file
226
src/gfx_func.h.orig
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 gfx_func.h Functions related to the gfx engine. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup dirty Dirty
|
||||||
|
*
|
||||||
|
* Handles the repaint of some part of the screen.
|
||||||
|
*
|
||||||
|
* Some places in the code are called functions which makes something "dirty".
|
||||||
|
* This has nothing to do with making a Tile or Window darker or less visible.
|
||||||
|
* This term comes from memory caching and is used to define an object must
|
||||||
|
* be repaint. If some data of an object (like a Tile, Window, Vehicle, whatever)
|
||||||
|
* are changed which are so extensive the object must be repaint its marked
|
||||||
|
* as "dirty". The video driver repaint this object instead of the whole screen
|
||||||
|
* (this is btw. also possible if needed). This is used to avoid a
|
||||||
|
* flickering of the screen by the video driver constantly repainting it.
|
||||||
|
*
|
||||||
|
* This whole mechanism is controlled by an rectangle defined in #_invalid_rect. This
|
||||||
|
* rectangle defines the area on the screen which must be repaint. If a new object
|
||||||
|
* needs to be repainted this rectangle is extended to 'catch' the object on the
|
||||||
|
* screen. At some point (which is normally uninteresting for patch writers) this
|
||||||
|
* rectangle is send to the video drivers method
|
||||||
|
* VideoDriver::MakeDirty and it is truncated back to an empty rectangle. At some
|
||||||
|
* later point (which is uninteresting, too) the video driver
|
||||||
|
* repaints all these saved rectangle instead of the whole screen and drop the
|
||||||
|
* rectangle informations. Then a new round begins by marking objects "dirty".
|
||||||
|
*
|
||||||
|
* @see VideoDriver::MakeDirty
|
||||||
|
* @see _invalid_rect
|
||||||
|
* @see _screen
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef GFX_FUNC_H
|
||||||
|
#define GFX_FUNC_H
|
||||||
|
|
||||||
|
#include "gfx_type.h"
|
||||||
|
#include "strings_type.h"
|
||||||
|
#include "string_type.h"
|
||||||
|
|
||||||
|
void GameLoop();
|
||||||
|
|
||||||
|
void CreateConsole();
|
||||||
|
|
||||||
|
extern byte _dirkeys; ///< 1 = left, 2 = up, 4 = right, 8 = down
|
||||||
|
extern bool _fullscreen;
|
||||||
|
extern CursorVars _cursor;
|
||||||
|
extern bool _ctrl_pressed; ///< Is Ctrl pressed?
|
||||||
|
extern bool _shift_pressed; ///< Is Shift pressed?
|
||||||
|
extern byte _fast_forward;
|
||||||
|
|
||||||
|
extern bool _left_button_down;
|
||||||
|
extern bool _left_button_clicked;
|
||||||
|
extern bool _right_button_down;
|
||||||
|
extern bool _right_button_clicked;
|
||||||
|
|
||||||
|
extern DrawPixelInfo _screen;
|
||||||
|
extern bool _screen_disable_anim; ///< Disable palette animation (important for 32bpp-anim blitter during giant screenshot)
|
||||||
|
|
||||||
|
extern int _num_resolutions;
|
||||||
|
extern Dimension _resolutions[32];
|
||||||
|
extern Dimension _cur_resolution;
|
||||||
|
extern Palette _cur_palette; ///< Current palette
|
||||||
|
|
||||||
|
void HandleKeypress(uint keycode, WChar key);
|
||||||
|
void HandleTextInput(const char *str, bool marked = false, const char *caret = NULL, const char *insert_location = NULL, const char *replacement_end = NULL);
|
||||||
|
void HandleCtrlChanged();
|
||||||
|
void HandleMouseEvents();
|
||||||
|
void CSleep(int milliseconds);
|
||||||
|
void UpdateWindows();
|
||||||
|
|
||||||
|
void DrawMouseCursor();
|
||||||
|
void ScreenSizeChanged();
|
||||||
|
void GameSizeChanged();
|
||||||
|
void UndrawMouseCursor();
|
||||||
|
|
||||||
|
/** Size of the buffer used for drawing strings. */
|
||||||
|
static const int DRAW_STRING_BUFFER = 2048;
|
||||||
|
|
||||||
|
void RedrawScreenRect(int left, int top, int right, int bottom);
|
||||||
|
void GfxScroll(int left, int top, int width, int height, int xo, int yo);
|
||||||
|
|
||||||
|
Dimension GetSpriteSize(SpriteID sprid, Point *offset = NULL, ZoomLevel zoom = ZOOM_LVL_GUI);
|
||||||
|
void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = NULL);
|
||||||
|
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = NULL, ZoomLevel zoom = ZOOM_LVL_GUI);
|
||||||
|
|
||||||
|
/** How to align the to-be drawn text. */
|
||||||
|
enum StringAlignment {
|
||||||
|
SA_LEFT = 0 << 0, ///< Left align the text.
|
||||||
|
SA_HOR_CENTER = 1 << 0, ///< Horizontally center the text.
|
||||||
|
SA_RIGHT = 2 << 0, ///< Right align the text (must be a single bit).
|
||||||
|
SA_HOR_MASK = 3 << 0, ///< Mask for horizontal alignment.
|
||||||
|
|
||||||
|
SA_TOP = 0 << 2, ///< Top align the text.
|
||||||
|
SA_VERT_CENTER = 1 << 2, ///< Vertically center the text.
|
||||||
|
SA_BOTTOM = 2 << 2, ///< Bottom align the text.
|
||||||
|
SA_VERT_MASK = 3 << 2, ///< Mask for vertical alignment.
|
||||||
|
|
||||||
|
SA_CENTER = SA_HOR_CENTER | SA_VERT_CENTER, ///< Center both horizontally and vertically.
|
||||||
|
|
||||||
|
SA_FORCE = 1 << 4, ///< Force the alignment, i.e. don't swap for RTL languages.
|
||||||
|
};
|
||||||
|
DECLARE_ENUM_AS_BIT_SET(StringAlignment)
|
||||||
|
|
||||||
|
int DrawString(int left, int right, int top, const char *str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false, FontSize fontsize = FS_NORMAL);
|
||||||
|
int DrawString(int left, int right, int top, StringID str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false, FontSize fontsize = FS_NORMAL);
|
||||||
|
int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL);
|
||||||
|
int DrawStringMultiLine(int left, int right, int top, int bottom, StringID str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL);
|
||||||
|
|
||||||
|
void DrawCharCentered(uint32 c, int x, int y, TextColour colour);
|
||||||
|
|
||||||
|
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode = FILLRECT_OPAQUE);
|
||||||
|
void GfxDrawLine(int left, int top, int right, int bottom, int colour, int width = 1, int dash = 0);
|
||||||
|
void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
|
||||||
|
|
||||||
|
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize = FS_NORMAL);
|
||||||
|
Dimension GetStringBoundingBox(StringID strid);
|
||||||
|
int GetStringHeight(const char *str, int maxw, FontSize fontsize = FS_NORMAL);
|
||||||
|
int GetStringHeight(StringID str, int maxw);
|
||||||
|
int GetStringLineCount(StringID str, int maxw);
|
||||||
|
Dimension GetStringMultiLineBoundingBox(StringID str, const Dimension &suggestion);
|
||||||
|
Dimension GetStringMultiLineBoundingBox(const char *str, const Dimension &suggestion);
|
||||||
|
void LoadStringWidthTable(bool monospace = false);
|
||||||
|
Point GetCharPosInString(const char *str, const char *ch, FontSize start_fontsize = FS_NORMAL);
|
||||||
|
const char *GetCharAtPosition(const char *str, int x, FontSize start_fontsize = FS_NORMAL);
|
||||||
|
|
||||||
|
void DrawDirtyBlocks();
|
||||||
|
void SetDirtyBlocks(int left, int top, int right, int bottom);
|
||||||
|
void MarkWholeScreenDirty();
|
||||||
|
|
||||||
|
void GfxInitPalettes();
|
||||||
|
void CheckBlitter();
|
||||||
|
|
||||||
|
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height);
|
||||||
|
|
||||||
|
/* window.cpp */
|
||||||
|
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom);
|
||||||
|
|
||||||
|
void SetMouseCursor(CursorID cursor, PaletteID pal);
|
||||||
|
void SetAnimatedMouseCursor(const AnimCursor *table);
|
||||||
|
void CursorTick();
|
||||||
|
void UpdateCursorSize();
|
||||||
|
bool ChangeResInGame(int w, int h);
|
||||||
|
void SortResolutions(int count);
|
||||||
|
bool ToggleFullScreen(bool fs);
|
||||||
|
|
||||||
|
/* gfx.cpp */
|
||||||
|
byte GetCharacterWidth(FontSize size, uint32 key);
|
||||||
|
byte GetDigitWidth(FontSize size = FS_NORMAL);
|
||||||
|
void GetBroadestDigit(uint *front, uint *next, FontSize size = FS_NORMAL);
|
||||||
|
|
||||||
|
int GetCharacterHeight(FontSize size);
|
||||||
|
|
||||||
|
/** Height of characters in the small (#FS_SMALL) font. */
|
||||||
|
#define FONT_HEIGHT_SMALL (GetCharacterHeight(FS_SMALL))
|
||||||
|
|
||||||
|
/** Height of characters in the normal (#FS_NORMAL) font. */
|
||||||
|
#define FONT_HEIGHT_NORMAL (GetCharacterHeight(FS_NORMAL))
|
||||||
|
|
||||||
|
/** Height of characters in the large (#FS_LARGE) font. */
|
||||||
|
#define FONT_HEIGHT_LARGE (GetCharacterHeight(FS_LARGE))
|
||||||
|
|
||||||
|
/** Height of characters in the large (#FS_MONO) font. */
|
||||||
|
#define FONT_HEIGHT_MONO (GetCharacterHeight(FS_MONO))
|
||||||
|
|
||||||
|
int InitTempMargin(int left, int right, bool to_end_line);
|
||||||
|
void AddSpace(int space, int &here, bool to_end_line);
|
||||||
|
|
||||||
|
void UpdateMarginEnd(int end, int &margin, bool to_end_line);
|
||||||
|
void UpdateMarginWidth(int adding, int &margin, bool to_end_line);
|
||||||
|
void UpdateMarginsEnd(int end, int &left, int &right, bool to_end_line);
|
||||||
|
void UpdateMarginsWidth(int width, int &left, int &right, bool to_end_line);
|
||||||
|
|
||||||
|
void DrawString2(int left, int right, int top, int &margin, StringID str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false);
|
||||||
|
void DrawSprite2(int width, int left, int right, int top, int &margin, SpriteID img, PaletteID pal, bool to_end_line = false, SubSprite *sub = NULL);
|
||||||
|
|
||||||
|
extern DrawPixelInfo *_cur_dpi;
|
||||||
|
|
||||||
|
TextColour GetContrastColour(uint8 background);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All 16 colour gradients
|
||||||
|
* 8 colours per gradient from darkest (0) to lightest (7)
|
||||||
|
*/
|
||||||
|
extern byte _colour_gradient[COLOUR_END][8];
|
||||||
|
|
||||||
|
extern bool _palette_remap_grf[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the colour for a particular greyscale level.
|
||||||
|
* @param level Intensity, 0 = black, 15 = white
|
||||||
|
* @return colour
|
||||||
|
*/
|
||||||
|
#define GREY_SCALE(level) (level)
|
||||||
|
|
||||||
|
static const uint8 PC_BLACK = GREY_SCALE(1); ///< Black palette colour.
|
||||||
|
static const uint8 PC_DARK_GREY = GREY_SCALE(6); ///< Dark grey palette colour.
|
||||||
|
static const uint8 PC_GREY = GREY_SCALE(10); ///< Grey palette colour.
|
||||||
|
static const uint8 PC_WHITE = GREY_SCALE(15); ///< White palette colour.
|
||||||
|
|
||||||
|
static const uint8 PC_VERY_DARK_RED = 0xB2; ///< Almost-black red palette colour.
|
||||||
|
static const uint8 PC_DARK_RED = 0xB4; ///< Dark red palette colour.
|
||||||
|
static const uint8 PC_RED = 0xB8; ///< Red palette colour.
|
||||||
|
|
||||||
|
static const uint8 PC_VERY_DARK_BROWN = 0x56; ///< Almost-black brown palette colour.
|
||||||
|
|
||||||
|
static const uint8 PC_ORANGE = 0xC2; ///< Orange palette colour.
|
||||||
|
|
||||||
|
static const uint8 PC_YELLOW = 0xBF; ///< Yellow palette colour.
|
||||||
|
static const uint8 PC_LIGHT_YELLOW = 0x44; ///< Light yellow palette colour.
|
||||||
|
static const uint8 PC_VERY_LIGHT_YELLOW = 0x45; ///< Almost-white yellow palette colour.
|
||||||
|
|
||||||
|
static const uint8 PC_GREEN = 0xD0; ///< Green palette colour.
|
||||||
|
|
||||||
|
static const uint8 PC_DARK_BLUE = 0x9D; ///< Dark blue palette colour.
|
||||||
|
static const uint8 PC_LIGHT_BLUE = 0x98; ///< Light blue palette colour.
|
||||||
|
|
||||||
|
#endif /* GFX_FUNC_H */
|
||||||
891
src/group_gui.cpp.orig
Normal file
891
src/group_gui.cpp.orig
Normal file
@@ -0,0 +1,891 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 group_gui.cpp GUI for the group window. */
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "textbuf_gui.h"
|
||||||
|
#include "command_func.h"
|
||||||
|
#include "vehicle_gui.h"
|
||||||
|
#include "vehicle_base.h"
|
||||||
|
#include "string_func.h"
|
||||||
|
#include "strings_func.h"
|
||||||
|
#include "window_func.h"
|
||||||
|
#include "vehicle_func.h"
|
||||||
|
#include "autoreplace_gui.h"
|
||||||
|
#include "company_func.h"
|
||||||
|
#include "widgets/dropdown_func.h"
|
||||||
|
#include "tilehighlight_func.h"
|
||||||
|
#include "vehicle_gui_base.h"
|
||||||
|
#include "core/geometry_func.hpp"
|
||||||
|
#include "company_base.h"
|
||||||
|
|
||||||
|
#include "widgets/group_widget.h"
|
||||||
|
|
||||||
|
#include "table/sprites.h"
|
||||||
|
|
||||||
|
typedef GUIList<const Group*> GUIGroupList;
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_group_widgets[] = {
|
||||||
|
NWidget(NWID_HORIZONTAL), // Window header
|
||||||
|
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_GREY, WID_GL_CAPTION),
|
||||||
|
NWidget(WWT_SHADEBOX, COLOUR_GREY),
|
||||||
|
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
|
||||||
|
NWidget(WWT_STICKYBOX, COLOUR_GREY),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
/* left part */
|
||||||
|
NWidget(NWID_VERTICAL),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalTextLines(1, WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM), SetFill(1, 0), EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY, WID_GL_ALL_VEHICLES), SetFill(1, 0), EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY, WID_GL_DEFAULT_VEHICLES), SetFill(1, 0), EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_MATRIX, COLOUR_GREY, WID_GL_LIST_GROUP), SetMatrixDataTip(1, 0, STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP),
|
||||||
|
SetFill(1, 0), SetResize(0, 1), SetScrollbar(WID_GL_LIST_GROUP_SCROLLBAR),
|
||||||
|
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_GL_LIST_GROUP_SCROLLBAR),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GL_CREATE_GROUP), SetFill(0, 1),
|
||||||
|
SetDataTip(SPR_GROUP_CREATE_TRAIN, STR_GROUP_CREATE_TOOLTIP),
|
||||||
|
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GL_DELETE_GROUP), SetFill(0, 1),
|
||||||
|
SetDataTip(SPR_GROUP_DELETE_TRAIN, STR_GROUP_DELETE_TOOLTIP),
|
||||||
|
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GL_RENAME_GROUP), SetFill(0, 1),
|
||||||
|
SetDataTip(SPR_GROUP_RENAME_TRAIN, STR_GROUP_RENAME_TOOLTIP),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), EndContainer(),
|
||||||
|
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GL_REPLACE_PROTECTION), SetFill(0, 1),
|
||||||
|
SetDataTip(SPR_GROUP_REPLACE_OFF_TRAIN, STR_GROUP_REPLACE_PROTECTION_TOOLTIP),
|
||||||
|
EndContainer(),
|
||||||
|
EndContainer(),
|
||||||
|
/* right part */
|
||||||
|
NWidget(NWID_VERTICAL),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GL_SORT_BY_ORDER), SetMinimalSize(81, 12), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
|
||||||
|
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_SORT_BY_DROPDOWN), SetMinimalSize(167, 12), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetResize(1, 0), EndContainer(),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_MATRIX, COLOUR_GREY, WID_GL_LIST_VEHICLE), SetMinimalSize(248, 0), SetMatrixDataTip(1, 0, STR_NULL), SetResize(1, 1), SetFill(1, 0), SetScrollbar(WID_GL_LIST_VEHICLE_SCROLLBAR),
|
||||||
|
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_GL_LIST_VEHICLE_SCROLLBAR),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(1, 0), SetFill(1, 1), SetResize(1, 0), EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GL_AVAILABLE_VEHICLES), SetMinimalSize(106, 12), SetFill(0, 1),
|
||||||
|
SetDataTip(STR_BLACK_STRING, STR_VEHICLE_LIST_AVAILABLE_ENGINES_TOOLTIP),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(),
|
||||||
|
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_MANAGE_VEHICLES_DROPDOWN), SetMinimalSize(118, 12), SetFill(0, 1),
|
||||||
|
SetDataTip(STR_VEHICLE_LIST_MANAGE_LIST, STR_VEHICLE_LIST_MANAGE_LIST_TOOLTIP),
|
||||||
|
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GL_STOP_ALL), SetMinimalSize(12, 12), SetFill(0, 1),
|
||||||
|
SetDataTip(SPR_FLAG_VEH_STOPPED, STR_VEHICLE_LIST_MASS_STOP_LIST_TOOLTIP),
|
||||||
|
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GL_START_ALL), SetMinimalSize(12, 12), SetFill(0, 1),
|
||||||
|
SetDataTip(SPR_FLAG_VEH_RUNNING, STR_VEHICLE_LIST_MASS_START_LIST_TOOLTIP),
|
||||||
|
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
|
||||||
|
EndContainer(),
|
||||||
|
EndContainer(),
|
||||||
|
EndContainer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
class VehicleGroupWindow : public BaseVehicleListWindow {
|
||||||
|
private:
|
||||||
|
/* Columns in the group list */
|
||||||
|
enum ListColumns {
|
||||||
|
VGC_NAME, ///< Group name.
|
||||||
|
VGC_PROTECT, ///< Autoreplace protect icon.
|
||||||
|
VGC_AUTOREPLACE, ///< Autoreplace active icon.
|
||||||
|
VGC_PROFIT, ///< Profit icon.
|
||||||
|
VGC_NUMBER, ///< Number of vehicles in the group.
|
||||||
|
|
||||||
|
VGC_END
|
||||||
|
};
|
||||||
|
|
||||||
|
VehicleID vehicle_sel; ///< Selected vehicle
|
||||||
|
GroupID group_rename; ///< Group being renamed, INVALID_GROUP if none
|
||||||
|
GroupID group_over; ///< Group over which a vehicle is dragged, INVALID_GROUP if none
|
||||||
|
GUIGroupList groups; ///< List of groups
|
||||||
|
uint tiny_step_height; ///< Step height for the group list
|
||||||
|
Scrollbar *group_sb;
|
||||||
|
|
||||||
|
Dimension column_size[VGC_END]; ///< Size of the columns in the group list.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re)Build the group list.
|
||||||
|
*
|
||||||
|
* @param owner The owner of the window
|
||||||
|
*/
|
||||||
|
void BuildGroupList(Owner owner)
|
||||||
|
{
|
||||||
|
if (!this->groups.NeedRebuild()) return;
|
||||||
|
|
||||||
|
this->groups.Clear();
|
||||||
|
|
||||||
|
const Group *g;
|
||||||
|
FOR_ALL_GROUPS(g) {
|
||||||
|
if (g->owner == owner && g->vehicle_type == this->vli.vtype) {
|
||||||
|
*this->groups.Append() = g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->groups.Compact();
|
||||||
|
this->groups.RebuildDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sort the groups by their name */
|
||||||
|
static int CDECL GroupNameSorter(const Group * const *a, const Group * const *b)
|
||||||
|
{
|
||||||
|
static const Group *last_group[2] = { NULL, NULL };
|
||||||
|
static char last_name[2][64] = { "", "" };
|
||||||
|
|
||||||
|
if (*a != last_group[0]) {
|
||||||
|
last_group[0] = *a;
|
||||||
|
SetDParam(0, (*a)->index);
|
||||||
|
GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*b != last_group[1]) {
|
||||||
|
last_group[1] = *b;
|
||||||
|
SetDParam(0, (*b)->index);
|
||||||
|
GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int r = strnatcmp(last_name[0], last_name[1]); // Sort by name (natural sorting).
|
||||||
|
if (r == 0) return (*a)->index - (*b)->index;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute tiny_step_height and column_size
|
||||||
|
* @return Total width required for the group list.
|
||||||
|
*/
|
||||||
|
uint ComputeGroupInfoSize()
|
||||||
|
{
|
||||||
|
this->column_size[VGC_NAME] = maxdim(GetStringBoundingBox(STR_GROUP_DEFAULT_TRAINS + this->vli.vtype), GetStringBoundingBox(STR_GROUP_ALL_TRAINS + this->vli.vtype));
|
||||||
|
/* We consider the max average length of characters to be the one of "a" */
|
||||||
|
this->column_size[VGC_NAME].width = max(GetCharacterWidth(FS_NORMAL, 97) * (MAX_LENGTH_GROUP_NAME_CHARS - 4), this->column_size[VGC_NAME].width);
|
||||||
|
this->tiny_step_height = this->column_size[VGC_NAME].height;
|
||||||
|
|
||||||
|
this->column_size[VGC_PROTECT] = GetSpriteSize(SPR_GROUP_REPLACE_PROTECT);
|
||||||
|
this->tiny_step_height = max(this->tiny_step_height, this->column_size[VGC_PROTECT].height);
|
||||||
|
|
||||||
|
this->column_size[VGC_AUTOREPLACE] = GetSpriteSize(SPR_GROUP_REPLACE_ACTIVE);
|
||||||
|
this->tiny_step_height = max(this->tiny_step_height, this->column_size[VGC_AUTOREPLACE].height);
|
||||||
|
|
||||||
|
this->column_size[VGC_PROFIT].width = 0;
|
||||||
|
this->column_size[VGC_PROFIT].height = 0;
|
||||||
|
static const SpriteID profit_sprites[] = {SPR_PROFIT_NA, SPR_PROFIT_NEGATIVE, SPR_PROFIT_SOME, SPR_PROFIT_LOT};
|
||||||
|
for (uint i = 0; i < lengthof(profit_sprites); i++) {
|
||||||
|
Dimension d = GetSpriteSize(profit_sprites[i]);
|
||||||
|
this->column_size[VGC_PROFIT] = maxdim(this->column_size[VGC_PROFIT], d);
|
||||||
|
}
|
||||||
|
this->tiny_step_height = max(this->tiny_step_height, this->column_size[VGC_PROFIT].height);
|
||||||
|
|
||||||
|
SetDParamMaxValue(0, GroupStatistics::Get(this->vli.company, ALL_GROUP, this->vli.vtype).num_vehicle, 3, FS_SMALL);
|
||||||
|
this->column_size[VGC_NUMBER] = GetStringBoundingBox(STR_TINY_COMMA);
|
||||||
|
this->tiny_step_height = max(this->tiny_step_height, this->column_size[VGC_NUMBER].height);
|
||||||
|
|
||||||
|
this->tiny_step_height += WD_MATRIX_TOP;
|
||||||
|
|
||||||
|
return WD_FRAMERECT_LEFT + 8 +
|
||||||
|
this->column_size[VGC_NAME].width + 2 +
|
||||||
|
this->column_size[VGC_PROTECT].width + 2 +
|
||||||
|
this->column_size[VGC_AUTOREPLACE].width + 2 +
|
||||||
|
this->column_size[VGC_PROFIT].width + 2 +
|
||||||
|
this->column_size[VGC_NUMBER].width + 2 +
|
||||||
|
WD_FRAMERECT_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a row in the group list.
|
||||||
|
* @param y Top of the row.
|
||||||
|
* @param left Left of the row.
|
||||||
|
* @param right Right of the row.
|
||||||
|
* @param g_id Group to list.
|
||||||
|
* @param protection Whether autoreplace protection is set.
|
||||||
|
*/
|
||||||
|
void DrawGroupInfo(int y, int left, int right, GroupID g_id, bool protection = false) const
|
||||||
|
{
|
||||||
|
/* Highlight the group if a vehicle is dragged over it */
|
||||||
|
if (g_id == this->group_over) {
|
||||||
|
GfxFillRect(left + WD_FRAMERECT_LEFT, y + WD_FRAMERECT_TOP + WD_MATRIX_TOP, right - WD_FRAMERECT_RIGHT, y + this->tiny_step_height - WD_FRAMERECT_BOTTOM - WD_MATRIX_TOP, _colour_gradient[COLOUR_GREY][7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_id == NEW_GROUP) return;
|
||||||
|
|
||||||
|
/* draw the selected group in white, else we draw it in black */
|
||||||
|
TextColour colour = g_id == this->vli.index ? TC_WHITE : TC_BLACK;
|
||||||
|
const GroupStatistics &stats = GroupStatistics::Get(this->vli.company, g_id, this->vli.vtype);
|
||||||
|
bool rtl = _current_text_dir == TD_RTL;
|
||||||
|
|
||||||
|
/* draw group name */
|
||||||
|
int longer_name = 0;
|
||||||
|
StringID str;
|
||||||
|
if (IsAllGroupID(g_id)) {
|
||||||
|
str = STR_GROUP_ALL_TRAINS + this->vli.vtype;
|
||||||
|
} else if (IsDefaultGroupID(g_id)) {
|
||||||
|
str = STR_GROUP_DEFAULT_TRAINS + this->vli.vtype;
|
||||||
|
} else {
|
||||||
|
SetDParam(0, g_id);
|
||||||
|
str = STR_GROUP_NAME;
|
||||||
|
if (!protection) {
|
||||||
|
longer_name += this->column_size[VGC_PROTECT].width + 2;
|
||||||
|
if (!stats.autoreplace_defined) longer_name += this->column_size[VGC_AUTOREPLACE].width + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int x = rtl ? right - WD_FRAMERECT_RIGHT - 8 - this->column_size[VGC_NAME].width - longer_name + 1 : left + WD_FRAMERECT_LEFT + 8;
|
||||||
|
DrawString(x, x + this->column_size[VGC_NAME].width + longer_name - 1, y + (this->tiny_step_height - this->column_size[VGC_NAME].height) / 2, str, colour);
|
||||||
|
|
||||||
|
/* draw autoreplace protection */
|
||||||
|
x = rtl ? x - 2 - this->column_size[VGC_PROTECT].width : x + 2 + this->column_size[VGC_NAME].width;
|
||||||
|
if (protection) DrawSprite(SPR_GROUP_REPLACE_PROTECT, PAL_NONE, x, y + (this->tiny_step_height - this->column_size[VGC_PROTECT].height) / 2);
|
||||||
|
|
||||||
|
/* draw autoreplace status */
|
||||||
|
x = rtl ? x - 2 - this->column_size[VGC_AUTOREPLACE].width : x + 2 + this->column_size[VGC_PROTECT].width;
|
||||||
|
if (stats.autoreplace_defined) DrawSprite(SPR_GROUP_REPLACE_ACTIVE, stats.autoreplace_finished ? PALETTE_CRASH : PAL_NONE, x, y + (this->tiny_step_height - this->column_size[VGC_AUTOREPLACE].height) / 2);
|
||||||
|
|
||||||
|
/* draw the profit icon */
|
||||||
|
x = rtl ? x - 2 - this->column_size[VGC_PROFIT].width : x + 2 + this->column_size[VGC_AUTOREPLACE].width;
|
||||||
|
SpriteID spr;
|
||||||
|
if (stats.num_profit_vehicle == 0) {
|
||||||
|
spr = SPR_PROFIT_NA;
|
||||||
|
} else if (stats.profit_last_year < 0) {
|
||||||
|
spr = SPR_PROFIT_NEGATIVE;
|
||||||
|
} else if (stats.profit_last_year < 10000 * stats.num_profit_vehicle) { // TODO magic number
|
||||||
|
spr = SPR_PROFIT_SOME;
|
||||||
|
} else {
|
||||||
|
spr = SPR_PROFIT_LOT;
|
||||||
|
}
|
||||||
|
DrawSprite(spr, PAL_NONE, x, y + (this->tiny_step_height - this->column_size[VGC_PROFIT].height) / 2);
|
||||||
|
|
||||||
|
/* draw the number of vehicles of the group */
|
||||||
|
x = rtl ? x - 2 - this->column_size[VGC_NUMBER].width : x + 2 + this->column_size[VGC_PROFIT].width;
|
||||||
|
SetDParam(0, stats.num_vehicle);
|
||||||
|
DrawString(x, x + this->column_size[VGC_NUMBER].width - 1, y + (this->tiny_step_height - this->column_size[VGC_NUMBER].height) / 2, STR_TINY_COMMA, colour, SA_RIGHT | SA_FORCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the widget containing the currently highlighted group as dirty.
|
||||||
|
*/
|
||||||
|
void DirtyHighlightedGroupWidget()
|
||||||
|
{
|
||||||
|
if (this->group_over == INVALID_GROUP) return;
|
||||||
|
|
||||||
|
if (IsAllGroupID(this->group_over)) {
|
||||||
|
this->SetWidgetDirty(WID_GL_ALL_VEHICLES);
|
||||||
|
} else if (IsDefaultGroupID(this->group_over)) {
|
||||||
|
this->SetWidgetDirty(WID_GL_DEFAULT_VEHICLES);
|
||||||
|
} else {
|
||||||
|
this->SetWidgetDirty(WID_GL_LIST_GROUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
VehicleGroupWindow(WindowDesc *desc, WindowNumber window_number) : BaseVehicleListWindow(desc, window_number)
|
||||||
|
{
|
||||||
|
this->CreateNestedTree();
|
||||||
|
|
||||||
|
this->vscroll = this->GetScrollbar(WID_GL_LIST_VEHICLE_SCROLLBAR);
|
||||||
|
this->group_sb = this->GetScrollbar(WID_GL_LIST_GROUP_SCROLLBAR);
|
||||||
|
|
||||||
|
switch (this->vli.vtype) {
|
||||||
|
default: NOT_REACHED();
|
||||||
|
case VEH_TRAIN: this->sorting = &_sorting.train; break;
|
||||||
|
case VEH_ROAD: this->sorting = &_sorting.roadveh; break;
|
||||||
|
case VEH_SHIP: this->sorting = &_sorting.ship; break;
|
||||||
|
case VEH_AIRCRAFT: this->sorting = &_sorting.aircraft; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->vli.index = ALL_GROUP;
|
||||||
|
this->vehicle_sel = INVALID_VEHICLE;
|
||||||
|
this->group_rename = INVALID_GROUP;
|
||||||
|
this->group_over = INVALID_GROUP;
|
||||||
|
|
||||||
|
this->vehicles.SetListing(*this->sorting);
|
||||||
|
this->vehicles.ForceRebuild();
|
||||||
|
this->vehicles.NeedResort();
|
||||||
|
|
||||||
|
this->BuildVehicleList();
|
||||||
|
this->SortVehicleList();
|
||||||
|
|
||||||
|
this->groups.ForceRebuild();
|
||||||
|
this->groups.NeedResort();
|
||||||
|
this->BuildGroupList(vli.company);
|
||||||
|
this->groups.Sort(&GroupNameSorter);
|
||||||
|
|
||||||
|
this->GetWidget<NWidgetCore>(WID_GL_CAPTION)->widget_data = STR_VEHICLE_LIST_TRAIN_CAPTION + this->vli.vtype;
|
||||||
|
this->GetWidget<NWidgetCore>(WID_GL_LIST_VEHICLE)->tool_tip = STR_VEHICLE_LIST_TRAIN_LIST_TOOLTIP + this->vli.vtype;
|
||||||
|
|
||||||
|
this->GetWidget<NWidgetCore>(WID_GL_CREATE_GROUP)->widget_data += this->vli.vtype;
|
||||||
|
this->GetWidget<NWidgetCore>(WID_GL_RENAME_GROUP)->widget_data += this->vli.vtype;
|
||||||
|
this->GetWidget<NWidgetCore>(WID_GL_DELETE_GROUP)->widget_data += this->vli.vtype;
|
||||||
|
this->GetWidget<NWidgetCore>(WID_GL_REPLACE_PROTECTION)->widget_data += this->vli.vtype;
|
||||||
|
|
||||||
|
this->FinishInitNested(window_number);
|
||||||
|
this->owner = vli.company;
|
||||||
|
}
|
||||||
|
|
||||||
|
~VehicleGroupWindow()
|
||||||
|
{
|
||||||
|
*this->sorting = this->vehicles.GetListing();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_GL_LIST_GROUP: {
|
||||||
|
size->width = this->ComputeGroupInfoSize();
|
||||||
|
resize->height = this->tiny_step_height;
|
||||||
|
|
||||||
|
/* Minimum height is the height of the list widget minus all and default vehicles... */
|
||||||
|
size->height = 4 * GetVehicleListHeight(this->vli.vtype, this->tiny_step_height) - 2 * this->tiny_step_height;
|
||||||
|
|
||||||
|
/* ... minus the buttons at the bottom ... */
|
||||||
|
uint max_icon_height = GetSpriteSize(this->GetWidget<NWidgetCore>(WID_GL_CREATE_GROUP)->widget_data).height;
|
||||||
|
max_icon_height = max(max_icon_height, GetSpriteSize(this->GetWidget<NWidgetCore>(WID_GL_RENAME_GROUP)->widget_data).height);
|
||||||
|
max_icon_height = max(max_icon_height, GetSpriteSize(this->GetWidget<NWidgetCore>(WID_GL_DELETE_GROUP)->widget_data).height);
|
||||||
|
max_icon_height = max(max_icon_height, GetSpriteSize(this->GetWidget<NWidgetCore>(WID_GL_REPLACE_PROTECTION)->widget_data).height);
|
||||||
|
|
||||||
|
/* Get a multiple of tiny_step_height of that amount */
|
||||||
|
size->height = Ceil(size->height - max_icon_height, tiny_step_height);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_GL_ALL_VEHICLES:
|
||||||
|
case WID_GL_DEFAULT_VEHICLES:
|
||||||
|
size->width = this->ComputeGroupInfoSize();
|
||||||
|
size->height = this->tiny_step_height;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_SORT_BY_ORDER: {
|
||||||
|
Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
|
||||||
|
d.width += padding.width + WD_SORTBUTTON_ARROW_WIDTH * 2; // Doubled since the string is centred and it also looks better.
|
||||||
|
d.height += padding.height;
|
||||||
|
*size = maxdim(*size, d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_GL_LIST_VEHICLE:
|
||||||
|
this->ComputeGroupInfoSize();
|
||||||
|
resize->height = GetVehicleListHeight(this->vli.vtype, this->tiny_step_height);
|
||||||
|
size->height = 4 * resize->height;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_MANAGE_VEHICLES_DROPDOWN: {
|
||||||
|
Dimension d = this->GetActionDropdownSize(true, true);
|
||||||
|
d.height += padding.height;
|
||||||
|
d.width += padding.width;
|
||||||
|
*size = maxdim(*size, d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some data on this window has become invalid.
|
||||||
|
* @param data Information about the changed data.
|
||||||
|
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
|
||||||
|
*/
|
||||||
|
virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
|
||||||
|
{
|
||||||
|
if (data == 0) {
|
||||||
|
/* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
|
||||||
|
this->vehicles.ForceRebuild();
|
||||||
|
this->groups.ForceRebuild();
|
||||||
|
} else {
|
||||||
|
this->vehicles.ForceResort();
|
||||||
|
this->groups.ForceResort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process ID-invalidation in command-scope as well */
|
||||||
|
if (this->group_rename != INVALID_GROUP && !Group::IsValidID(this->group_rename)) {
|
||||||
|
DeleteWindowByClass(WC_QUERY_STRING);
|
||||||
|
this->group_rename = INVALID_GROUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(IsAllGroupID(this->vli.index) || IsDefaultGroupID(this->vli.index) || Group::IsValidID(this->vli.index))) {
|
||||||
|
this->vli.index = ALL_GROUP;
|
||||||
|
HideDropDownMenu(this);
|
||||||
|
}
|
||||||
|
this->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetStringParameters(int widget) const
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_GL_AVAILABLE_VEHICLES:
|
||||||
|
SetDParam(0, STR_VEHICLE_LIST_AVAILABLE_TRAINS + this->vli.vtype);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_CAPTION:
|
||||||
|
/* If selected_group == DEFAULT_GROUP || ALL_GROUP, draw the standard caption
|
||||||
|
* We list all vehicles or ungrouped vehicles */
|
||||||
|
if (IsDefaultGroupID(this->vli.index) || IsAllGroupID(this->vli.index)) {
|
||||||
|
SetDParam(0, STR_COMPANY_NAME);
|
||||||
|
SetDParam(1, this->vli.company);
|
||||||
|
SetDParam(2, this->vehicles.Length());
|
||||||
|
SetDParam(3, this->vehicles.Length());
|
||||||
|
} else {
|
||||||
|
const Group *g = Group::Get(this->vli.index);
|
||||||
|
|
||||||
|
SetDParam(0, STR_GROUP_NAME);
|
||||||
|
SetDParam(1, g->index);
|
||||||
|
SetDParam(2, g->statistics.num_vehicle);
|
||||||
|
SetDParam(3, g->statistics.num_vehicle);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPaint()
|
||||||
|
{
|
||||||
|
/* If we select the all vehicles, this->list will contain all vehicles of the owner
|
||||||
|
* else this->list will contain all vehicles which belong to the selected group */
|
||||||
|
this->BuildVehicleList();
|
||||||
|
this->SortVehicleList();
|
||||||
|
|
||||||
|
this->BuildGroupList(this->owner);
|
||||||
|
this->groups.Sort(&GroupNameSorter);
|
||||||
|
|
||||||
|
this->group_sb->SetCount(this->groups.Length());
|
||||||
|
this->vscroll->SetCount(this->vehicles.Length());
|
||||||
|
|
||||||
|
/* The drop down menu is out, *but* it may not be used, retract it. */
|
||||||
|
if (this->vehicles.Length() == 0 && this->IsWidgetLowered(WID_GL_MANAGE_VEHICLES_DROPDOWN)) {
|
||||||
|
this->RaiseWidget(WID_GL_MANAGE_VEHICLES_DROPDOWN);
|
||||||
|
HideDropDownMenu(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable all lists management button when the list is empty */
|
||||||
|
this->SetWidgetsDisabledState(this->vehicles.Length() == 0 || _local_company != this->vli.company,
|
||||||
|
WID_GL_STOP_ALL,
|
||||||
|
WID_GL_START_ALL,
|
||||||
|
WID_GL_MANAGE_VEHICLES_DROPDOWN,
|
||||||
|
WIDGET_LIST_END);
|
||||||
|
|
||||||
|
/* Disable the group specific function when we select the default group or all vehicles */
|
||||||
|
this->SetWidgetsDisabledState(IsDefaultGroupID(this->vli.index) || IsAllGroupID(this->vli.index) || _local_company != this->vli.company,
|
||||||
|
WID_GL_DELETE_GROUP,
|
||||||
|
WID_GL_RENAME_GROUP,
|
||||||
|
WID_GL_REPLACE_PROTECTION,
|
||||||
|
WIDGET_LIST_END);
|
||||||
|
|
||||||
|
/* Disable remaining buttons for non-local companies
|
||||||
|
* Needed while changing _local_company, eg. by cheats
|
||||||
|
* All procedures (eg. move vehicle to another group)
|
||||||
|
* verify, whether you are the owner of the vehicle,
|
||||||
|
* so it doesn't have to be disabled
|
||||||
|
*/
|
||||||
|
this->SetWidgetsDisabledState(_local_company != this->vli.company,
|
||||||
|
WID_GL_CREATE_GROUP,
|
||||||
|
WID_GL_AVAILABLE_VEHICLES,
|
||||||
|
WIDGET_LIST_END);
|
||||||
|
|
||||||
|
/* If not a default group and the group has replace protection, show an enabled replace sprite. */
|
||||||
|
uint16 protect_sprite = SPR_GROUP_REPLACE_OFF_TRAIN;
|
||||||
|
if (!IsDefaultGroupID(this->vli.index) && !IsAllGroupID(this->vli.index) && Group::Get(this->vli.index)->replace_protection) protect_sprite = SPR_GROUP_REPLACE_ON_TRAIN;
|
||||||
|
this->GetWidget<NWidgetCore>(WID_GL_REPLACE_PROTECTION)->widget_data = protect_sprite + this->vli.vtype;
|
||||||
|
|
||||||
|
/* Set text of sort by dropdown */
|
||||||
|
this->GetWidget<NWidgetCore>(WID_GL_SORT_BY_DROPDOWN)->widget_data = this->vehicle_sorter_names[this->vehicles.SortType()];
|
||||||
|
|
||||||
|
this->DrawWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DrawWidget(const Rect &r, int widget) const
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_GL_ALL_VEHICLES:
|
||||||
|
DrawGroupInfo(r.top, r.left, r.right, ALL_GROUP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_DEFAULT_VEHICLES:
|
||||||
|
DrawGroupInfo(r.top, r.left, r.right, DEFAULT_GROUP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_LIST_GROUP: {
|
||||||
|
int y1 = r.top;
|
||||||
|
int max = min(this->group_sb->GetPosition() + this->group_sb->GetCapacity(), this->groups.Length());
|
||||||
|
for (int i = this->group_sb->GetPosition(); i < max; ++i) {
|
||||||
|
const Group *g = this->groups[i];
|
||||||
|
|
||||||
|
assert(g->owner == this->owner);
|
||||||
|
|
||||||
|
DrawGroupInfo(y1, r.left, r.right, g->index, g->replace_protection);
|
||||||
|
|
||||||
|
y1 += this->tiny_step_height;
|
||||||
|
}
|
||||||
|
if ((uint)this->group_sb->GetPosition() + this->group_sb->GetCapacity() > this->groups.Length()) {
|
||||||
|
DrawGroupInfo(y1, r.left, r.right, NEW_GROUP);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_GL_SORT_BY_ORDER:
|
||||||
|
this->DrawSortButtonState(WID_GL_SORT_BY_ORDER, this->vehicles.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_LIST_VEHICLE:
|
||||||
|
this->DrawVehicleListItems(this->vehicle_sel, this->resize.step_height, r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnClick(Point pt, int widget, int click_count)
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_GL_SORT_BY_ORDER: // Flip sorting method ascending/descending
|
||||||
|
this->vehicles.ToggleSortOrder();
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_SORT_BY_DROPDOWN: // Select sorting criteria dropdown menu
|
||||||
|
ShowDropDownMenu(this, this->vehicle_sorter_names, this->vehicles.SortType(), WID_GL_SORT_BY_DROPDOWN, 0, (this->vli.vtype == VEH_TRAIN || this->vli.vtype == VEH_ROAD) ? 0 : (1 << 10));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case WID_GL_ALL_VEHICLES: // All vehicles button
|
||||||
|
if (!IsAllGroupID(this->vli.index)) {
|
||||||
|
this->vli.index = ALL_GROUP;
|
||||||
|
this->vehicles.ForceRebuild();
|
||||||
|
this->SetDirty();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_DEFAULT_VEHICLES: // Ungrouped vehicles button
|
||||||
|
if (!IsDefaultGroupID(this->vli.index)) {
|
||||||
|
this->vli.index = DEFAULT_GROUP;
|
||||||
|
this->vehicles.ForceRebuild();
|
||||||
|
this->SetDirty();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_LIST_GROUP: { // Matrix Group
|
||||||
|
uint id_g = this->group_sb->GetScrolledRowFromWidget(pt.y, this, WID_GL_LIST_GROUP, 0, this->tiny_step_height);
|
||||||
|
if (id_g >= this->groups.Length()) return;
|
||||||
|
|
||||||
|
this->vli.index = this->groups[id_g]->index;
|
||||||
|
|
||||||
|
this->vehicles.ForceRebuild();
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_GL_LIST_VEHICLE: { // Matrix Vehicle
|
||||||
|
uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GL_LIST_VEHICLE);
|
||||||
|
if (id_v >= this->vehicles.Length()) return; // click out of list bound
|
||||||
|
|
||||||
|
const Vehicle *v = this->vehicles[id_v];
|
||||||
|
if (VehicleClicked(v)) break;
|
||||||
|
|
||||||
|
this->vehicle_sel = v->index;
|
||||||
|
|
||||||
|
int image = v->GetImage(_current_text_dir == TD_RTL ? DIR_E : DIR_W, EIT_IN_LIST);
|
||||||
|
SetObjectToPlaceWnd(image, GetVehiclePalette(v), HT_DRAG, this);
|
||||||
|
_cursor.vehchain = true;
|
||||||
|
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_GL_CREATE_GROUP: { // Create a new group
|
||||||
|
DoCommandP(0, this->vli.vtype, 0, CMD_CREATE_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_CREATE), CcCreateGroup);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_GL_DELETE_GROUP: { // Delete the selected group
|
||||||
|
GroupID group = this->vli.index;
|
||||||
|
this->vli.index = ALL_GROUP;
|
||||||
|
|
||||||
|
DoCommandP(0, group, 0, CMD_DELETE_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_DELETE));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_GL_RENAME_GROUP: // Rename the selected roup
|
||||||
|
this->ShowRenameGroupWindow(this->vli.index, false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_AVAILABLE_VEHICLES:
|
||||||
|
ShowBuildVehicleWindow(INVALID_TILE, this->vli.vtype);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_MANAGE_VEHICLES_DROPDOWN: {
|
||||||
|
DropDownList *list = this->BuildActionDropdownList(true, Group::IsValidID(this->vli.index));
|
||||||
|
ShowDropDownList(this, list, 0, WID_GL_MANAGE_VEHICLES_DROPDOWN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_GL_START_ALL:
|
||||||
|
case WID_GL_STOP_ALL: { // Start/stop all vehicles of the list
|
||||||
|
DoCommandP(0, (1 << 1) | (widget == WID_GL_START_ALL ? (1 << 0) : 0), this->vli.Pack(), CMD_MASS_START_STOP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_GL_REPLACE_PROTECTION: {
|
||||||
|
const Group *g = Group::GetIfValid(this->vli.index);
|
||||||
|
if (g != NULL) {
|
||||||
|
DoCommandP(0, this->vli.index, !g->replace_protection, CMD_SET_GROUP_REPLACE_PROTECTION);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnDragDrop(Point pt, int widget)
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_GL_DEFAULT_VEHICLES: // Ungrouped vehicles
|
||||||
|
DoCommandP(0, DEFAULT_GROUP, this->vehicle_sel | (_ctrl_pressed ? 1 << 31 : 0), CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_ADD_VEHICLE));
|
||||||
|
|
||||||
|
this->vehicle_sel = INVALID_VEHICLE;
|
||||||
|
this->group_over = INVALID_GROUP;
|
||||||
|
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_LIST_GROUP: { // Matrix group
|
||||||
|
const VehicleID vindex = this->vehicle_sel;
|
||||||
|
this->vehicle_sel = INVALID_VEHICLE;
|
||||||
|
this->group_over = INVALID_GROUP;
|
||||||
|
this->SetDirty();
|
||||||
|
|
||||||
|
uint id_g = this->group_sb->GetScrolledRowFromWidget(pt.y, this, WID_GL_LIST_GROUP, 0, this->tiny_step_height);
|
||||||
|
GroupID new_g = id_g >= this->groups.Length() ? NEW_GROUP : this->groups[id_g]->index;
|
||||||
|
|
||||||
|
DoCommandP(0, new_g, vindex | (_ctrl_pressed ? 1 << 31 : 0), CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_ADD_VEHICLE), new_g == NEW_GROUP ? CcAddVehicleNewGroup : NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_GL_LIST_VEHICLE: { // Matrix vehicle
|
||||||
|
const VehicleID vindex = this->vehicle_sel;
|
||||||
|
this->vehicle_sel = INVALID_VEHICLE;
|
||||||
|
this->group_over = INVALID_GROUP;
|
||||||
|
this->SetDirty();
|
||||||
|
|
||||||
|
uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GL_LIST_VEHICLE);
|
||||||
|
if (id_v >= this->vehicles.Length()) return; // click out of list bound
|
||||||
|
|
||||||
|
const Vehicle *v = this->vehicles[id_v];
|
||||||
|
if (!VehicleClicked(v) && vindex == v->index) {
|
||||||
|
ShowVehicleViewWindow(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_cursor.vehchain = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnQueryTextFinished(char *str)
|
||||||
|
{
|
||||||
|
if (str != NULL) DoCommandP(0, this->group_rename, 0, CMD_RENAME_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_RENAME), NULL, str);
|
||||||
|
this->group_rename = INVALID_GROUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnResize()
|
||||||
|
{
|
||||||
|
this->group_sb->SetCapacityFromWidget(this, WID_GL_LIST_GROUP);
|
||||||
|
this->vscroll->SetCapacityFromWidget(this, WID_GL_LIST_VEHICLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnDropdownSelect(int widget, int index)
|
||||||
|
{
|
||||||
|
switch (widget) {
|
||||||
|
case WID_GL_SORT_BY_DROPDOWN:
|
||||||
|
this->vehicles.SetSortType(index);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_MANAGE_VEHICLES_DROPDOWN:
|
||||||
|
assert(this->vehicles.Length() != 0);
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case ADI_REPLACE: // Replace window
|
||||||
|
ShowReplaceGroupVehicleWindow(this->vli.index, this->vli.vtype);
|
||||||
|
break;
|
||||||
|
case ADI_SERVICE: // Send for servicing
|
||||||
|
case ADI_DEPOT: { // Send to Depots
|
||||||
|
DoCommandP(0, DEPOT_MASS_SEND | (index == ADI_SERVICE ? DEPOT_SERVICE : 0U), this->vli.Pack(), GetCmdSendToDepot(this->vli.vtype));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ADI_ADD_SHARED: // Add shared Vehicles
|
||||||
|
assert(Group::IsValidID(this->vli.index));
|
||||||
|
|
||||||
|
DoCommandP(0, this->vli.index, this->vli.vtype, CMD_ADD_SHARED_VEHICLE_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE));
|
||||||
|
break;
|
||||||
|
case ADI_REMOVE_ALL: // Remove all Vehicles from the selected group
|
||||||
|
assert(Group::IsValidID(this->vli.index));
|
||||||
|
|
||||||
|
DoCommandP(0, this->vli.index, 0, CMD_REMOVE_ALL_VEHICLES_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES));
|
||||||
|
break;
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnTick()
|
||||||
|
{
|
||||||
|
if (_pause_mode != PM_UNPAUSED) return;
|
||||||
|
if (this->groups.NeedResort() || this->vehicles.NeedResort()) {
|
||||||
|
this->SetDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPlaceObjectAbort()
|
||||||
|
{
|
||||||
|
/* abort drag & drop */
|
||||||
|
this->vehicle_sel = INVALID_VEHICLE;
|
||||||
|
this->DirtyHighlightedGroupWidget();
|
||||||
|
this->group_over = INVALID_GROUP;
|
||||||
|
this->SetWidgetDirty(WID_GL_LIST_VEHICLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnMouseDrag(Point pt, int widget)
|
||||||
|
{
|
||||||
|
if (this->vehicle_sel == INVALID_VEHICLE) return;
|
||||||
|
|
||||||
|
/* A vehicle is dragged over... */
|
||||||
|
GroupID new_group_over = INVALID_GROUP;
|
||||||
|
switch (widget) {
|
||||||
|
case WID_GL_DEFAULT_VEHICLES: // ... the 'default' group.
|
||||||
|
new_group_over = DEFAULT_GROUP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_GL_LIST_GROUP: { // ... the list of custom groups.
|
||||||
|
uint id_g = this->group_sb->GetScrolledRowFromWidget(pt.y, this, WID_GL_LIST_GROUP, 0, this->tiny_step_height);
|
||||||
|
new_group_over = id_g >= this->groups.Length() ? NEW_GROUP : this->groups[id_g]->index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not highlight when dragging over the current group */
|
||||||
|
if (Vehicle::Get(vehicle_sel)->group_id == new_group_over) new_group_over = INVALID_GROUP;
|
||||||
|
|
||||||
|
/* Mark widgets as dirty if the group changed. */
|
||||||
|
if (new_group_over != this->group_over) {
|
||||||
|
this->DirtyHighlightedGroupWidget();
|
||||||
|
this->group_over = new_group_over;
|
||||||
|
this->DirtyHighlightedGroupWidget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowRenameGroupWindow(GroupID group, bool empty)
|
||||||
|
{
|
||||||
|
assert(Group::IsValidID(group));
|
||||||
|
this->group_rename = group;
|
||||||
|
/* Show empty query for new groups */
|
||||||
|
StringID str = STR_EMPTY;
|
||||||
|
if (!empty) {
|
||||||
|
SetDParam(0, group);
|
||||||
|
str = STR_GROUP_NAME;
|
||||||
|
}
|
||||||
|
ShowQueryString(str, STR_GROUP_RENAME_CAPTION, MAX_LENGTH_GROUP_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether a given vehicle is selected in the window, and unselects it if necessary.
|
||||||
|
* Called when the vehicle is deleted.
|
||||||
|
* @param vehicle Vehicle that is going to be deleted
|
||||||
|
*/
|
||||||
|
void UnselectVehicle(VehicleID vehicle)
|
||||||
|
{
|
||||||
|
if (this->vehicle_sel == vehicle) ResetObjectToPlace();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static WindowDesc _other_group_desc(
|
||||||
|
WDP_AUTO, "list_groups", 460, 246,
|
||||||
|
WC_INVALID, WC_NONE,
|
||||||
|
0,
|
||||||
|
_nested_group_widgets, lengthof(_nested_group_widgets)
|
||||||
|
);
|
||||||
|
|
||||||
|
static WindowDesc _train_group_desc(
|
||||||
|
WDP_AUTO, "list_groups_train", 525, 246,
|
||||||
|
WC_TRAINS_LIST, WC_NONE,
|
||||||
|
0,
|
||||||
|
_nested_group_widgets, lengthof(_nested_group_widgets)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the group window for the given company and vehicle type.
|
||||||
|
* @param company The company to show the window for.
|
||||||
|
* @param vehicle_type The type of vehicle to show it for.
|
||||||
|
*/
|
||||||
|
void ShowCompanyGroup(CompanyID company, VehicleType vehicle_type)
|
||||||
|
{
|
||||||
|
if (!Company::IsValidID(company)) return;
|
||||||
|
|
||||||
|
WindowNumber num = VehicleListIdentifier(VL_GROUP_LIST, vehicle_type, company).Pack();
|
||||||
|
if (vehicle_type == VEH_TRAIN) {
|
||||||
|
AllocateWindowDescFront<VehicleGroupWindow>(&_train_group_desc, num);
|
||||||
|
} else {
|
||||||
|
_other_group_desc.cls = GetWindowClassForVehicleType(vehicle_type);
|
||||||
|
AllocateWindowDescFront<VehicleGroupWindow>(&_other_group_desc, num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a group list window determined by vehicle type and owner
|
||||||
|
* @param vt vehicle type
|
||||||
|
* @param owner owner of groups
|
||||||
|
* @return pointer to VehicleGroupWindow, NULL if not found
|
||||||
|
*/
|
||||||
|
static inline VehicleGroupWindow *FindVehicleGroupWindow(VehicleType vt, Owner owner)
|
||||||
|
{
|
||||||
|
return (VehicleGroupWindow *)FindWindowById(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, owner).Pack());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a 'Rename group' window for newly created group
|
||||||
|
* @param success did command succeed?
|
||||||
|
* @param tile unused
|
||||||
|
* @param p1 vehicle type
|
||||||
|
* @param p2 unused
|
||||||
|
* @see CmdCreateGroup
|
||||||
|
*/
|
||||||
|
void CcCreateGroup(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
|
||||||
|
{
|
||||||
|
if (result.Failed()) return;
|
||||||
|
assert(p1 <= VEH_AIRCRAFT);
|
||||||
|
|
||||||
|
VehicleGroupWindow *w = FindVehicleGroupWindow((VehicleType)p1, _current_company);
|
||||||
|
if (w != NULL) w->ShowRenameGroupWindow(_new_group_id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open rename window after adding a vehicle to a new group via drag and drop.
|
||||||
|
* @param success Did command succeed?
|
||||||
|
* @param tile Unused.
|
||||||
|
* @param p1 Unused.
|
||||||
|
* @param p2 Bit 0-19: Vehicle ID.
|
||||||
|
*/
|
||||||
|
void CcAddVehicleNewGroup(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
|
||||||
|
{
|
||||||
|
if (result.Failed()) return;
|
||||||
|
assert(Vehicle::IsValidID(GB(p2, 0, 20)));
|
||||||
|
|
||||||
|
CcCreateGroup(result, 0, Vehicle::Get(GB(p2, 0, 20))->type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the highlight of a vehicle in a group window
|
||||||
|
* @param *v Vehicle to remove all highlights from
|
||||||
|
*/
|
||||||
|
void DeleteGroupHighlightOfVehicle(const Vehicle *v)
|
||||||
|
{
|
||||||
|
/* If we haven't got any vehicles on the mouse pointer, we haven't got any highlighted in any group windows either
|
||||||
|
* If that is the case, we can skip looping though the windows and save time
|
||||||
|
*/
|
||||||
|
if (_special_mouse_mode != WSM_DRAGDROP) return;
|
||||||
|
|
||||||
|
VehicleGroupWindow *w = FindVehicleGroupWindow(v->type, v->owner);
|
||||||
|
if (w != NULL) w->UnselectVehicle(v->index);
|
||||||
|
}
|
||||||
2718
src/industry_gui.cpp.orig
Normal file
2718
src/industry_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
4887
src/lang/english.txt.orig
Normal file
4887
src/lang/english.txt.orig
Normal file
File diff suppressed because it is too large
Load Diff
1213
src/misc_gui.cpp.orig
Normal file
1213
src/misc_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
460
src/osk_gui.cpp.orig
Normal file
460
src/osk_gui.cpp.orig
Normal file
@@ -0,0 +1,460 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 osk_gui.cpp The On Screen Keyboard GUI */
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "string_func.h"
|
||||||
|
#include "strings_func.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "window_func.h"
|
||||||
|
#include "gfx_func.h"
|
||||||
|
#include "querystring_gui.h"
|
||||||
|
#include "video/video_driver.hpp"
|
||||||
|
|
||||||
|
#include "widgets/osk_widget.h"
|
||||||
|
|
||||||
|
#include "table/sprites.h"
|
||||||
|
#include "table/strings.h"
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <SDL_screenkeyboard.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char _keyboard_opt[2][OSK_KEYBOARD_ENTRIES * 4 + 1];
|
||||||
|
static WChar _keyboard[2][OSK_KEYBOARD_ENTRIES];
|
||||||
|
|
||||||
|
enum KeyStateBits {
|
||||||
|
KEYS_NONE,
|
||||||
|
KEYS_SHIFT,
|
||||||
|
KEYS_CAPS
|
||||||
|
};
|
||||||
|
static byte _keystate = KEYS_NONE;
|
||||||
|
|
||||||
|
struct OskWindow : public Window {
|
||||||
|
StringID caption; ///< the caption for this window.
|
||||||
|
QueryString *qs; ///< text-input
|
||||||
|
int text_btn; ///< widget number of parent's text field
|
||||||
|
Textbuf *text; ///< pointer to parent's textbuffer (to update caret position)
|
||||||
|
char *orig_str_buf; ///< Original string.
|
||||||
|
bool shift; ///< Is the shift effectively pressed?
|
||||||
|
|
||||||
|
OskWindow(WindowDesc *desc, Window *parent, int button) : Window(desc)
|
||||||
|
{
|
||||||
|
this->parent = parent;
|
||||||
|
assert(parent != NULL);
|
||||||
|
|
||||||
|
NWidgetCore *par_wid = parent->GetWidget<NWidgetCore>(button);
|
||||||
|
assert(par_wid != NULL);
|
||||||
|
|
||||||
|
assert(parent->querystrings.Contains(button));
|
||||||
|
this->qs = parent->querystrings.Find(button)->second;
|
||||||
|
this->caption = (par_wid->widget_data != STR_NULL) ? par_wid->widget_data : this->qs->caption;
|
||||||
|
this->text_btn = button;
|
||||||
|
this->text = &this->qs->text;
|
||||||
|
this->querystrings[WID_OSK_TEXT] = this->qs;
|
||||||
|
|
||||||
|
/* make a copy in case we need to reset later */
|
||||||
|
this->orig_str_buf = strdup(this->qs->text.buf);
|
||||||
|
|
||||||
|
this->InitNested(0);
|
||||||
|
this->SetFocusedWidget(WID_OSK_TEXT);
|
||||||
|
|
||||||
|
/* Not needed by default. */
|
||||||
|
this->DisableWidget(WID_OSK_SPECIAL);
|
||||||
|
|
||||||
|
this->UpdateOskState();
|
||||||
|
}
|
||||||
|
|
||||||
|
~OskWindow()
|
||||||
|
{
|
||||||
|
free(this->orig_str_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only show valid characters; do not show characters that would
|
||||||
|
* only insert a space when we have a spacebar to do that or
|
||||||
|
* characters that are not allowed to be entered.
|
||||||
|
*/
|
||||||
|
void UpdateOskState()
|
||||||
|
{
|
||||||
|
this->shift = HasBit(_keystate, KEYS_CAPS) ^ HasBit(_keystate, KEYS_SHIFT);
|
||||||
|
|
||||||
|
for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
|
||||||
|
this->SetWidgetDisabledState(WID_OSK_LETTERS + i,
|
||||||
|
!IsValidChar(_keyboard[this->shift][i], this->qs->text.afilter) || _keyboard[this->shift][i] == ' ');
|
||||||
|
}
|
||||||
|
this->SetWidgetDisabledState(WID_OSK_SPACE, !IsValidChar(' ', this->qs->text.afilter));
|
||||||
|
|
||||||
|
this->SetWidgetLoweredState(WID_OSK_SHIFT, HasBit(_keystate, KEYS_SHIFT));
|
||||||
|
this->SetWidgetLoweredState(WID_OSK_CAPS, HasBit(_keystate, KEYS_CAPS));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetStringParameters(int widget) const
|
||||||
|
{
|
||||||
|
if (widget == WID_OSK_CAPTION) SetDParam(0, this->caption);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DrawWidget(const Rect &r, int widget) const
|
||||||
|
{
|
||||||
|
if (widget < WID_OSK_LETTERS) return;
|
||||||
|
|
||||||
|
widget -= WID_OSK_LETTERS;
|
||||||
|
DrawCharCentered(_keyboard[this->shift][widget],
|
||||||
|
r.left + 8,
|
||||||
|
r.top + 3,
|
||||||
|
TC_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnClick(Point pt, int widget, int click_count)
|
||||||
|
{
|
||||||
|
/* clicked a letter */
|
||||||
|
if (widget >= WID_OSK_LETTERS) {
|
||||||
|
WChar c = _keyboard[this->shift][widget - WID_OSK_LETTERS];
|
||||||
|
|
||||||
|
if (!IsValidChar(c, this->qs->text.afilter)) return;
|
||||||
|
|
||||||
|
if (this->qs->text.InsertChar(c)) this->OnEditboxChanged(WID_OSK_TEXT);
|
||||||
|
|
||||||
|
if (HasBit(_keystate, KEYS_SHIFT)) {
|
||||||
|
ToggleBit(_keystate, KEYS_SHIFT);
|
||||||
|
this->UpdateOskState();
|
||||||
|
this->SetDirty();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (widget) {
|
||||||
|
case WID_OSK_BACKSPACE:
|
||||||
|
if (this->qs->text.DeleteChar(WKC_BACKSPACE)) this->OnEditboxChanged(WID_OSK_TEXT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_OSK_SPECIAL:
|
||||||
|
/*
|
||||||
|
* Anything device specific can go here.
|
||||||
|
* The button itself is hidden by default, and when you need it you
|
||||||
|
* can not hide it in the create event.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_OSK_CAPS:
|
||||||
|
ToggleBit(_keystate, KEYS_CAPS);
|
||||||
|
this->UpdateOskState();
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_OSK_SHIFT:
|
||||||
|
ToggleBit(_keystate, KEYS_SHIFT);
|
||||||
|
this->UpdateOskState();
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_OSK_SPACE:
|
||||||
|
if (this->qs->text.InsertChar(' ')) this->OnEditboxChanged(WID_OSK_TEXT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_OSK_LEFT:
|
||||||
|
if (this->qs->text.MovePos(WKC_LEFT)) this->InvalidateData();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_OSK_RIGHT:
|
||||||
|
if (this->qs->text.MovePos(WKC_RIGHT)) this->InvalidateData();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_OSK_OK:
|
||||||
|
if (this->qs->orig == NULL || strcmp(this->qs->text.buf, this->qs->orig) != 0) {
|
||||||
|
/* pass information by simulating a button press on parent window */
|
||||||
|
if (this->qs->ok_button >= 0) {
|
||||||
|
this->parent->OnClick(pt, this->qs->ok_button, 1);
|
||||||
|
/* Window gets deleted when the parent window removes itself. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete this;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_OSK_CANCEL:
|
||||||
|
if (this->qs->cancel_button >= 0) { // pass a cancel event to the parent window
|
||||||
|
this->parent->OnClick(pt, this->qs->cancel_button, 1);
|
||||||
|
/* Window gets deleted when the parent window removes itself. */
|
||||||
|
return;
|
||||||
|
} else { // or reset to original string
|
||||||
|
qs->text.Assign(this->orig_str_buf);
|
||||||
|
qs->text.MovePos(WKC_END);
|
||||||
|
this->OnEditboxChanged(WID_OSK_TEXT);
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnEditboxChanged(int widget)
|
||||||
|
{
|
||||||
|
this->SetWidgetDirty(WID_OSK_TEXT);
|
||||||
|
this->parent->OnEditboxChanged(this->text_btn);
|
||||||
|
this->parent->SetWidgetDirty(this->text_btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
|
||||||
|
{
|
||||||
|
if (!gui_scope) return;
|
||||||
|
this->SetWidgetDirty(WID_OSK_TEXT);
|
||||||
|
this->parent->SetWidgetDirty(this->text_btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnFocusLost()
|
||||||
|
{
|
||||||
|
_video_driver->EditBoxLostFocus();
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int HALF_KEY_WIDTH = 7; // Width of 1/2 key in pixels.
|
||||||
|
static const int INTER_KEY_SPACE = 2; // Number of pixels between two keys.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a key widget to a row of the keyboard.
|
||||||
|
* @param hor Row container to add key widget to.
|
||||||
|
* @param height Height of the key (all keys in a row should have equal height).
|
||||||
|
* @param num_half Number of 1/2 key widths that this key has.
|
||||||
|
* @param widtype Widget type of the key. Must be either \c NWID_SPACER for an invisible key, or a \c WWT_* widget.
|
||||||
|
* @param widnum Widget number of the key.
|
||||||
|
* @param widdata Data value of the key widget.
|
||||||
|
* @param biggest_index Collected biggest widget index so far.
|
||||||
|
* @note Key width is measured in 1/2 keys to allow for 1/2 key shifting between rows.
|
||||||
|
*/
|
||||||
|
static void AddKey(NWidgetHorizontal *hor, int height, int num_half, WidgetType widtype, int widnum, uint16 widdata, int *biggest_index)
|
||||||
|
{
|
||||||
|
int min_half_key = max<int>(GetMinSizing(NWST_BUTTON) / 2, HALF_KEY_WIDTH);
|
||||||
|
int key_width = min_half_key + (INTER_KEY_SPACE + min_half_key) * (num_half - 1);
|
||||||
|
|
||||||
|
if (widtype == NWID_SPACER) {
|
||||||
|
if (!hor->IsEmpty()) key_width += INTER_KEY_SPACE;
|
||||||
|
NWidgetSpacer *spc = new NWidgetSpacer(key_width, height);
|
||||||
|
hor->Add(spc);
|
||||||
|
} else {
|
||||||
|
if (!hor->IsEmpty()) {
|
||||||
|
NWidgetSpacer *spc = new NWidgetSpacer(INTER_KEY_SPACE, height);
|
||||||
|
hor->Add(spc);
|
||||||
|
}
|
||||||
|
NWidgetLeaf *leaf = new NWidgetLeaf(widtype, COLOUR_GREY, widnum, widdata, STR_NULL);
|
||||||
|
leaf->SetMinimalSize(key_width, height);
|
||||||
|
hor->Add(leaf);
|
||||||
|
}
|
||||||
|
|
||||||
|
*biggest_index = max(*biggest_index, widnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct the top row keys (cancel, ok, backspace). */
|
||||||
|
static NWidgetBase *MakeTopKeys(int *biggest_index)
|
||||||
|
{
|
||||||
|
NWidgetHorizontal *hor = new NWidgetHorizontal();
|
||||||
|
int key_height = FONT_HEIGHT_NORMAL + 2;
|
||||||
|
|
||||||
|
AddKey(hor, key_height, 6 * 2, WWT_TEXTBTN, WID_OSK_CANCEL, STR_BUTTON_CANCEL, biggest_index);
|
||||||
|
AddKey(hor, key_height, 6 * 2, WWT_TEXTBTN, WID_OSK_OK, STR_BUTTON_OK, biggest_index);
|
||||||
|
AddKey(hor, key_height, 2 * 2, WWT_PUSHIMGBTN, WID_OSK_BACKSPACE, SPR_OSK_BACKSPACE, biggest_index);
|
||||||
|
return hor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct the row containing the digit keys. */
|
||||||
|
static NWidgetBase *MakeNumberKeys(int *biggest_index)
|
||||||
|
{
|
||||||
|
NWidgetHorizontal *hor = new NWidgetHorizontalLTR();
|
||||||
|
int key_height = FONT_HEIGHT_NORMAL + 6;
|
||||||
|
|
||||||
|
for (int widnum = WID_OSK_NUMBERS_FIRST; widnum <= WID_OSK_NUMBERS_LAST; widnum++) {
|
||||||
|
AddKey(hor, key_height, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index);
|
||||||
|
}
|
||||||
|
return hor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct the qwerty row keys. */
|
||||||
|
static NWidgetBase *MakeQwertyKeys(int *biggest_index)
|
||||||
|
{
|
||||||
|
NWidgetHorizontal *hor = new NWidgetHorizontalLTR();
|
||||||
|
int key_height = FONT_HEIGHT_NORMAL + 6;
|
||||||
|
|
||||||
|
AddKey(hor, key_height, 3, WWT_PUSHIMGBTN, WID_OSK_SPECIAL, SPR_OSK_SPECIAL, biggest_index);
|
||||||
|
for (int widnum = WID_OSK_QWERTY_FIRST; widnum <= WID_OSK_QWERTY_LAST; widnum++) {
|
||||||
|
AddKey(hor, key_height, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index);
|
||||||
|
}
|
||||||
|
AddKey(hor, key_height, 1, NWID_SPACER, 0, 0, biggest_index);
|
||||||
|
return hor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct the asdfg row keys. */
|
||||||
|
static NWidgetBase *MakeAsdfgKeys(int *biggest_index)
|
||||||
|
{
|
||||||
|
NWidgetHorizontal *hor = new NWidgetHorizontalLTR();
|
||||||
|
int key_height = FONT_HEIGHT_NORMAL + 6;
|
||||||
|
|
||||||
|
AddKey(hor, key_height, 4, WWT_IMGBTN, WID_OSK_CAPS, SPR_OSK_CAPS, biggest_index);
|
||||||
|
for (int widnum = WID_OSK_ASDFG_FIRST; widnum <= WID_OSK_ASDFG_LAST; widnum++) {
|
||||||
|
AddKey(hor, key_height, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index);
|
||||||
|
}
|
||||||
|
return hor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct the zxcvb row keys. */
|
||||||
|
static NWidgetBase *MakeZxcvbKeys(int *biggest_index)
|
||||||
|
{
|
||||||
|
NWidgetHorizontal *hor = new NWidgetHorizontalLTR();
|
||||||
|
int key_height = FONT_HEIGHT_NORMAL + 6;
|
||||||
|
|
||||||
|
AddKey(hor, key_height, 3, WWT_IMGBTN, WID_OSK_SHIFT, SPR_OSK_SHIFT, biggest_index);
|
||||||
|
for (int widnum = WID_OSK_ZXCVB_FIRST; widnum <= WID_OSK_ZXCVB_LAST; widnum++) {
|
||||||
|
AddKey(hor, key_height, 2, WWT_PUSHBTN, widnum, 0x0, biggest_index);
|
||||||
|
}
|
||||||
|
AddKey(hor, key_height, 1, NWID_SPACER, 0, 0, biggest_index);
|
||||||
|
return hor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct the spacebar row keys. */
|
||||||
|
static NWidgetBase *MakeSpacebarKeys(int *biggest_index)
|
||||||
|
{
|
||||||
|
NWidgetHorizontal *hor = new NWidgetHorizontal();
|
||||||
|
int key_height = FONT_HEIGHT_NORMAL + 6;
|
||||||
|
|
||||||
|
AddKey(hor, key_height, 8, NWID_SPACER, 0, 0, biggest_index);
|
||||||
|
AddKey(hor, key_height, 13, WWT_PUSHTXTBTN, WID_OSK_SPACE, STR_EMPTY, biggest_index);
|
||||||
|
AddKey(hor, key_height, 3, NWID_SPACER, 0, 0, biggest_index);
|
||||||
|
AddKey(hor, key_height, 2, WWT_PUSHIMGBTN, WID_OSK_LEFT, SPR_OSK_LEFT, biggest_index);
|
||||||
|
AddKey(hor, key_height, 2, WWT_PUSHIMGBTN, WID_OSK_RIGHT, SPR_OSK_RIGHT, biggest_index);
|
||||||
|
return hor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_osk_widgets[] = {
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_GREY, WID_OSK_CAPTION), SetSizingType(NWST_BUTTON), SetDataTip(STR_WHITE_STRING, STR_NULL),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY),
|
||||||
|
NWidget(WWT_EDITBOX, COLOUR_GREY, WID_OSK_TEXT), SetMinimalSize(252, 12), SetPadding(2, 2, 2, 2),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_GREY), SetPIP(5, 2, 3),
|
||||||
|
NWidgetFunction(MakeTopKeys), SetPadding(0, 3, 0, 3),
|
||||||
|
NWidgetFunction(MakeNumberKeys), SetPadding(0, 3, 0, 3),
|
||||||
|
NWidgetFunction(MakeQwertyKeys), SetPadding(0, 3, 0, 3),
|
||||||
|
NWidgetFunction(MakeAsdfgKeys), SetPadding(0, 3, 0, 3),
|
||||||
|
NWidgetFunction(MakeZxcvbKeys), SetPadding(0, 3, 0, 3),
|
||||||
|
NWidgetFunction(MakeSpacebarKeys), SetPadding(0, 3, 0, 3),
|
||||||
|
EndContainer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowDesc _osk_desc(
|
||||||
|
WDP_CENTER, "query_osk", 0, 0,
|
||||||
|
WC_OSK, WC_NONE,
|
||||||
|
0,
|
||||||
|
_nested_osk_widgets, lengthof(_nested_osk_widgets)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve keyboard layout from language string or (if set) config file.
|
||||||
|
* Also check for invalid characters.
|
||||||
|
*/
|
||||||
|
void GetKeyboardLayout()
|
||||||
|
{
|
||||||
|
char keyboard[2][OSK_KEYBOARD_ENTRIES * 4 + 1];
|
||||||
|
char errormark[2][OSK_KEYBOARD_ENTRIES + 1]; // used for marking invalid chars
|
||||||
|
bool has_error = false; // true when an invalid char is detected
|
||||||
|
|
||||||
|
if (StrEmpty(_keyboard_opt[0])) {
|
||||||
|
GetString(keyboard[0], STR_OSK_KEYBOARD_LAYOUT, lastof(keyboard[0]));
|
||||||
|
} else {
|
||||||
|
strecpy(keyboard[0], _keyboard_opt[0], lastof(keyboard[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrEmpty(_keyboard_opt[1])) {
|
||||||
|
GetString(keyboard[1], STR_OSK_KEYBOARD_LAYOUT_CAPS, lastof(keyboard[1]));
|
||||||
|
} else {
|
||||||
|
strecpy(keyboard[1], _keyboard_opt[1], lastof(keyboard[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint j = 0; j < 2; j++) {
|
||||||
|
const char *kbd = keyboard[j];
|
||||||
|
bool ended = false;
|
||||||
|
for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
|
||||||
|
_keyboard[j][i] = Utf8Consume(&kbd);
|
||||||
|
|
||||||
|
/* Be lenient when the last characters are missing (is quite normal) */
|
||||||
|
if (_keyboard[j][i] == '\0' || ended) {
|
||||||
|
ended = true;
|
||||||
|
_keyboard[j][i] = ' ';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsPrintable(_keyboard[j][i])) {
|
||||||
|
errormark[j][i] = ' ';
|
||||||
|
} else {
|
||||||
|
has_error = true;
|
||||||
|
errormark[j][i] = '^';
|
||||||
|
_keyboard[j][i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_error) {
|
||||||
|
ShowInfoF("The keyboard layout you selected contains invalid chars. Please check those chars marked with ^.");
|
||||||
|
ShowInfoF("Normal keyboard: %s", keyboard[0]);
|
||||||
|
ShowInfoF(" %s", errormark[0]);
|
||||||
|
ShowInfoF("Caps Lock: %s", keyboard[1]);
|
||||||
|
ShowInfoF(" %s", errormark[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the on-screen keyboard (osk) associated with a given textbox
|
||||||
|
* @param parent pointer to the Window where this keyboard originated from
|
||||||
|
* @param button widget number of parent's textbox
|
||||||
|
*/
|
||||||
|
void ShowOnScreenKeyboard(Window *parent, int button)
|
||||||
|
{
|
||||||
|
DeleteWindowById(WC_OSK, 0);
|
||||||
|
|
||||||
|
GetKeyboardLayout();
|
||||||
|
new OskWindow(&_osk_desc, parent, button);
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
char text[256];
|
||||||
|
SDL_ANDROID_GetScreenKeyboardTextInput(text, sizeof(text) - 1); /* Invoke Android built-in screen keyboard */
|
||||||
|
OskWindow *osk = dynamic_cast<OskWindow *>(FindWindowById(WC_OSK, 0));
|
||||||
|
osk->qs->text.Assign(text);
|
||||||
|
free(osk->orig_str_buf);
|
||||||
|
osk->orig_str_buf = strdup(osk->qs->text.buf);
|
||||||
|
|
||||||
|
osk->SetDirty();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the original text of the OSK so when the 'parent' changes the
|
||||||
|
* original and you press on cancel you won't get the 'old' original text
|
||||||
|
* but the updated one.
|
||||||
|
* @param parent window that just updated its orignal text
|
||||||
|
* @param button widget number of parent's textbox to update
|
||||||
|
*/
|
||||||
|
void UpdateOSKOriginalText(const Window *parent, int button)
|
||||||
|
{
|
||||||
|
OskWindow *osk = dynamic_cast<OskWindow *>(FindWindowById(WC_OSK, 0));
|
||||||
|
if (osk == NULL || osk->parent != parent || osk->text_btn != button) return;
|
||||||
|
|
||||||
|
free(osk->orig_str_buf);
|
||||||
|
osk->orig_str_buf = strdup(osk->qs->text.buf);
|
||||||
|
|
||||||
|
osk->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the OSK is opened for a specific editbox.
|
||||||
|
* @parent w Window to check for
|
||||||
|
* @param button Editbox of \a w to check for
|
||||||
|
* @return true if the OSK is oppened for \a button.
|
||||||
|
*/
|
||||||
|
bool IsOSKOpenedFor(const Window *w, int button)
|
||||||
|
{
|
||||||
|
OskWindow *osk = dynamic_cast<OskWindow *>(FindWindowById(WC_OSK, 0));
|
||||||
|
return osk != NULL && osk->parent == w && osk->text_btn == button;
|
||||||
|
}
|
||||||
1991
src/rail_gui.cpp.orig
Normal file
1991
src/rail_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
1092
src/road_gui.cpp.orig
Normal file
1092
src/road_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
1328
src/script/api/game/game_window.hpp.sq.orig
Normal file
1328
src/script/api/game/game_window.hpp.sq.orig
Normal file
File diff suppressed because it is too large
Load Diff
2579
src/script/api/script_window.hpp.orig
Normal file
2579
src/script/api/script_window.hpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
257
src/script/api/template/template_window.hpp.sq.orig
Normal file
257
src/script/api/template/template_window.hpp.sq.orig
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
|
||||||
|
|
||||||
|
#include "../script_window.hpp"
|
||||||
|
|
||||||
|
namespace SQConvert {
|
||||||
|
/* Allow enums to be used as Squirrel parameters */
|
||||||
|
template <> inline ScriptWindow::WindowNumberEnum GetParam(ForceType<ScriptWindow::WindowNumberEnum>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::WindowNumberEnum)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::WindowNumberEnum>(HSQUIRRELVM vm, ScriptWindow::WindowNumberEnum res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::WindowClass GetParam(ForceType<ScriptWindow::WindowClass>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::WindowClass)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::WindowClass>(HSQUIRRELVM vm, ScriptWindow::WindowClass res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::TextColour GetParam(ForceType<ScriptWindow::TextColour>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::TextColour)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::TextColour>(HSQUIRRELVM vm, ScriptWindow::TextColour res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NumberType GetParam(ForceType<ScriptWindow::NumberType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NumberType)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NumberType>(HSQUIRRELVM vm, ScriptWindow::NumberType res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::WidgetType GetParam(ForceType<ScriptWindow::WidgetType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::WidgetType)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::WidgetType>(HSQUIRRELVM vm, ScriptWindow::WidgetType res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::AIListWidgets GetParam(ForceType<ScriptWindow::AIListWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::AIListWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::AIListWidgets>(HSQUIRRELVM vm, ScriptWindow::AIListWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::AISettingsWidgets GetParam(ForceType<ScriptWindow::AISettingsWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::AISettingsWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::AISettingsWidgets>(HSQUIRRELVM vm, ScriptWindow::AISettingsWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::AIConfigWidgets GetParam(ForceType<ScriptWindow::AIConfigWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::AIConfigWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::AIConfigWidgets>(HSQUIRRELVM vm, ScriptWindow::AIConfigWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::AIDebugWidgets GetParam(ForceType<ScriptWindow::AIDebugWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::AIDebugWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::AIDebugWidgets>(HSQUIRRELVM vm, ScriptWindow::AIDebugWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::AirportToolbarWidgets GetParam(ForceType<ScriptWindow::AirportToolbarWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::AirportToolbarWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::AirportToolbarWidgets>(HSQUIRRELVM vm, ScriptWindow::AirportToolbarWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::AirportPickerWidgets GetParam(ForceType<ScriptWindow::AirportPickerWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::AirportPickerWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::AirportPickerWidgets>(HSQUIRRELVM vm, ScriptWindow::AirportPickerWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::ReplaceVehicleWidgets GetParam(ForceType<ScriptWindow::ReplaceVehicleWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ReplaceVehicleWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::ReplaceVehicleWidgets>(HSQUIRRELVM vm, ScriptWindow::ReplaceVehicleWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BootstrapBackgroundWidgets GetParam(ForceType<ScriptWindow::BootstrapBackgroundWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BootstrapBackgroundWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BootstrapBackgroundWidgets>(HSQUIRRELVM vm, ScriptWindow::BootstrapBackgroundWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BootstrapAskForDownloadWidgets GetParam(ForceType<ScriptWindow::BootstrapAskForDownloadWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BootstrapAskForDownloadWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BootstrapAskForDownloadWidgets>(HSQUIRRELVM vm, ScriptWindow::BootstrapAskForDownloadWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildBridgeSelectionWidgets GetParam(ForceType<ScriptWindow::BuildBridgeSelectionWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildBridgeSelectionWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildBridgeSelectionWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildBridgeSelectionWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildVehicleWidgets GetParam(ForceType<ScriptWindow::BuildVehicleWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildVehicleWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildVehicleWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildVehicleWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::CheatWidgets GetParam(ForceType<ScriptWindow::CheatWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::CheatWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::CheatWidgets>(HSQUIRRELVM vm, ScriptWindow::CheatWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::CompanyWidgets GetParam(ForceType<ScriptWindow::CompanyWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::CompanyWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::CompanyWidgets>(HSQUIRRELVM vm, ScriptWindow::CompanyWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::CompanyFinancesWidgets GetParam(ForceType<ScriptWindow::CompanyFinancesWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::CompanyFinancesWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::CompanyFinancesWidgets>(HSQUIRRELVM vm, ScriptWindow::CompanyFinancesWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::SelectCompanyLiveryWidgets GetParam(ForceType<ScriptWindow::SelectCompanyLiveryWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::SelectCompanyLiveryWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::SelectCompanyLiveryWidgets>(HSQUIRRELVM vm, ScriptWindow::SelectCompanyLiveryWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::SelectCompanyManagerFaceWidgets GetParam(ForceType<ScriptWindow::SelectCompanyManagerFaceWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::SelectCompanyManagerFaceWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::SelectCompanyManagerFaceWidgets>(HSQUIRRELVM vm, ScriptWindow::SelectCompanyManagerFaceWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::CompanyInfrastructureWidgets GetParam(ForceType<ScriptWindow::CompanyInfrastructureWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::CompanyInfrastructureWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::CompanyInfrastructureWidgets>(HSQUIRRELVM vm, ScriptWindow::CompanyInfrastructureWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuyCompanyWidgets GetParam(ForceType<ScriptWindow::BuyCompanyWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuyCompanyWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuyCompanyWidgets>(HSQUIRRELVM vm, ScriptWindow::BuyCompanyWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::ConsoleWidgets GetParam(ForceType<ScriptWindow::ConsoleWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ConsoleWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::ConsoleWidgets>(HSQUIRRELVM vm, ScriptWindow::ConsoleWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::SetDateWidgets GetParam(ForceType<ScriptWindow::SetDateWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::SetDateWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::SetDateWidgets>(HSQUIRRELVM vm, ScriptWindow::SetDateWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::DepotWidgets GetParam(ForceType<ScriptWindow::DepotWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::DepotWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::DepotWidgets>(HSQUIRRELVM vm, ScriptWindow::DepotWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildDockDepotWidgets GetParam(ForceType<ScriptWindow::BuildDockDepotWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildDockDepotWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildDockDepotWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildDockDepotWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::DockToolbarWidgets GetParam(ForceType<ScriptWindow::DockToolbarWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::DockToolbarWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::DockToolbarWidgets>(HSQUIRRELVM vm, ScriptWindow::DockToolbarWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::DropdownMenuWidgets GetParam(ForceType<ScriptWindow::DropdownMenuWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::DropdownMenuWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::DropdownMenuWidgets>(HSQUIRRELVM vm, ScriptWindow::DropdownMenuWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::EnginePreviewWidgets GetParam(ForceType<ScriptWindow::EnginePreviewWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::EnginePreviewWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::EnginePreviewWidgets>(HSQUIRRELVM vm, ScriptWindow::EnginePreviewWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::ErrorMessageWidgets GetParam(ForceType<ScriptWindow::ErrorMessageWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ErrorMessageWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::ErrorMessageWidgets>(HSQUIRRELVM vm, ScriptWindow::ErrorMessageWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::SaveLoadWidgets GetParam(ForceType<ScriptWindow::SaveLoadWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::SaveLoadWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::SaveLoadWidgets>(HSQUIRRELVM vm, ScriptWindow::SaveLoadWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::GenerateLandscapeWidgets GetParam(ForceType<ScriptWindow::GenerateLandscapeWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::GenerateLandscapeWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::GenerateLandscapeWidgets>(HSQUIRRELVM vm, ScriptWindow::GenerateLandscapeWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::CreateScenarioWidgets GetParam(ForceType<ScriptWindow::CreateScenarioWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::CreateScenarioWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::CreateScenarioWidgets>(HSQUIRRELVM vm, ScriptWindow::CreateScenarioWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::GenerationProgressWidgets GetParam(ForceType<ScriptWindow::GenerationProgressWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::GenerationProgressWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::GenerationProgressWidgets>(HSQUIRRELVM vm, ScriptWindow::GenerationProgressWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::GoalListWidgets GetParam(ForceType<ScriptWindow::GoalListWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::GoalListWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::GoalListWidgets>(HSQUIRRELVM vm, ScriptWindow::GoalListWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::GoalQuestionWidgets GetParam(ForceType<ScriptWindow::GoalQuestionWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::GoalQuestionWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::GoalQuestionWidgets>(HSQUIRRELVM vm, ScriptWindow::GoalQuestionWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::GraphLegendWidgets GetParam(ForceType<ScriptWindow::GraphLegendWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::GraphLegendWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::GraphLegendWidgets>(HSQUIRRELVM vm, ScriptWindow::GraphLegendWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::CompanyValueWidgets GetParam(ForceType<ScriptWindow::CompanyValueWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::CompanyValueWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::CompanyValueWidgets>(HSQUIRRELVM vm, ScriptWindow::CompanyValueWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::PerformanceHistoryGraphWidgets GetParam(ForceType<ScriptWindow::PerformanceHistoryGraphWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::PerformanceHistoryGraphWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::PerformanceHistoryGraphWidgets>(HSQUIRRELVM vm, ScriptWindow::PerformanceHistoryGraphWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::CargoPaymentRatesWidgets GetParam(ForceType<ScriptWindow::CargoPaymentRatesWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::CargoPaymentRatesWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::CargoPaymentRatesWidgets>(HSQUIRRELVM vm, ScriptWindow::CargoPaymentRatesWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::CompanyLeagueWidgets GetParam(ForceType<ScriptWindow::CompanyLeagueWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::CompanyLeagueWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::CompanyLeagueWidgets>(HSQUIRRELVM vm, ScriptWindow::CompanyLeagueWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::PerformanceRatingDetailsWidgets GetParam(ForceType<ScriptWindow::PerformanceRatingDetailsWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::PerformanceRatingDetailsWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::PerformanceRatingDetailsWidgets>(HSQUIRRELVM vm, ScriptWindow::PerformanceRatingDetailsWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::GroupListWidgets GetParam(ForceType<ScriptWindow::GroupListWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::GroupListWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::GroupListWidgets>(HSQUIRRELVM vm, ScriptWindow::GroupListWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::HighscoreWidgets GetParam(ForceType<ScriptWindow::HighscoreWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::HighscoreWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::HighscoreWidgets>(HSQUIRRELVM vm, ScriptWindow::HighscoreWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::DynamicPlaceIndustriesWidgets GetParam(ForceType<ScriptWindow::DynamicPlaceIndustriesWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::DynamicPlaceIndustriesWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::DynamicPlaceIndustriesWidgets>(HSQUIRRELVM vm, ScriptWindow::DynamicPlaceIndustriesWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::IndustryViewWidgets GetParam(ForceType<ScriptWindow::IndustryViewWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::IndustryViewWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::IndustryViewWidgets>(HSQUIRRELVM vm, ScriptWindow::IndustryViewWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::IndustryDirectoryWidgets GetParam(ForceType<ScriptWindow::IndustryDirectoryWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::IndustryDirectoryWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::IndustryDirectoryWidgets>(HSQUIRRELVM vm, ScriptWindow::IndustryDirectoryWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::IndustryCargoesWidgets GetParam(ForceType<ScriptWindow::IndustryCargoesWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::IndustryCargoesWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::IndustryCargoesWidgets>(HSQUIRRELVM vm, ScriptWindow::IndustryCargoesWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::SelectGameIntroWidgets GetParam(ForceType<ScriptWindow::SelectGameIntroWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::SelectGameIntroWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::SelectGameIntroWidgets>(HSQUIRRELVM vm, ScriptWindow::SelectGameIntroWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::LinkGraphLegendWidgets GetParam(ForceType<ScriptWindow::LinkGraphLegendWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::LinkGraphLegendWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::LinkGraphLegendWidgets>(HSQUIRRELVM vm, ScriptWindow::LinkGraphLegendWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::MainWidgets GetParam(ForceType<ScriptWindow::MainWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::MainWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::MainWidgets>(HSQUIRRELVM vm, ScriptWindow::MainWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::LandInfoWidgets GetParam(ForceType<ScriptWindow::LandInfoWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::LandInfoWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::LandInfoWidgets>(HSQUIRRELVM vm, ScriptWindow::LandInfoWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::ToolTipsWidgets GetParam(ForceType<ScriptWindow::ToolTipsWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ToolTipsWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::ToolTipsWidgets>(HSQUIRRELVM vm, ScriptWindow::ToolTipsWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::AboutWidgets GetParam(ForceType<ScriptWindow::AboutWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::AboutWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::AboutWidgets>(HSQUIRRELVM vm, ScriptWindow::AboutWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::QueryStringWidgets GetParam(ForceType<ScriptWindow::QueryStringWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::QueryStringWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::QueryStringWidgets>(HSQUIRRELVM vm, ScriptWindow::QueryStringWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::QueryWidgets GetParam(ForceType<ScriptWindow::QueryWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::QueryWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::QueryWidgets>(HSQUIRRELVM vm, ScriptWindow::QueryWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::TextfileWidgets GetParam(ForceType<ScriptWindow::TextfileWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::TextfileWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::TextfileWidgets>(HSQUIRRELVM vm, ScriptWindow::TextfileWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::MusicTrackSelectionWidgets GetParam(ForceType<ScriptWindow::MusicTrackSelectionWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::MusicTrackSelectionWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::MusicTrackSelectionWidgets>(HSQUIRRELVM vm, ScriptWindow::MusicTrackSelectionWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::MusicWidgets GetParam(ForceType<ScriptWindow::MusicWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::MusicWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::MusicWidgets>(HSQUIRRELVM vm, ScriptWindow::MusicWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NetWorkChatWidgets GetParam(ForceType<ScriptWindow::NetWorkChatWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NetWorkChatWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NetWorkChatWidgets>(HSQUIRRELVM vm, ScriptWindow::NetWorkChatWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NetworkContentDownloadStatusWidgets GetParam(ForceType<ScriptWindow::NetworkContentDownloadStatusWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NetworkContentDownloadStatusWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NetworkContentDownloadStatusWidgets>(HSQUIRRELVM vm, ScriptWindow::NetworkContentDownloadStatusWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NetworkContentListWidgets GetParam(ForceType<ScriptWindow::NetworkContentListWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NetworkContentListWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NetworkContentListWidgets>(HSQUIRRELVM vm, ScriptWindow::NetworkContentListWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NetworkGameWidgets GetParam(ForceType<ScriptWindow::NetworkGameWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NetworkGameWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NetworkGameWidgets>(HSQUIRRELVM vm, ScriptWindow::NetworkGameWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NetworkStartServerWidgets GetParam(ForceType<ScriptWindow::NetworkStartServerWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NetworkStartServerWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NetworkStartServerWidgets>(HSQUIRRELVM vm, ScriptWindow::NetworkStartServerWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NetworkLobbyWidgets GetParam(ForceType<ScriptWindow::NetworkLobbyWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NetworkLobbyWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NetworkLobbyWidgets>(HSQUIRRELVM vm, ScriptWindow::NetworkLobbyWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::ClientListWidgets GetParam(ForceType<ScriptWindow::ClientListWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ClientListWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::ClientListWidgets>(HSQUIRRELVM vm, ScriptWindow::ClientListWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::ClientListPopupWidgets GetParam(ForceType<ScriptWindow::ClientListPopupWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ClientListPopupWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::ClientListPopupWidgets>(HSQUIRRELVM vm, ScriptWindow::ClientListPopupWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NetworkJoinStatusWidgets GetParam(ForceType<ScriptWindow::NetworkJoinStatusWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NetworkJoinStatusWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NetworkJoinStatusWidgets>(HSQUIRRELVM vm, ScriptWindow::NetworkJoinStatusWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NetworkCompanyPasswordWidgets GetParam(ForceType<ScriptWindow::NetworkCompanyPasswordWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NetworkCompanyPasswordWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NetworkCompanyPasswordWidgets>(HSQUIRRELVM vm, ScriptWindow::NetworkCompanyPasswordWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NewGRFInspectWidgets GetParam(ForceType<ScriptWindow::NewGRFInspectWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NewGRFInspectWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NewGRFInspectWidgets>(HSQUIRRELVM vm, ScriptWindow::NewGRFInspectWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::SpriteAlignerWidgets GetParam(ForceType<ScriptWindow::SpriteAlignerWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::SpriteAlignerWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::SpriteAlignerWidgets>(HSQUIRRELVM vm, ScriptWindow::SpriteAlignerWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NewGRFParametersWidgets GetParam(ForceType<ScriptWindow::NewGRFParametersWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NewGRFParametersWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NewGRFParametersWidgets>(HSQUIRRELVM vm, ScriptWindow::NewGRFParametersWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NewGRFStateWidgets GetParam(ForceType<ScriptWindow::NewGRFStateWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NewGRFStateWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NewGRFStateWidgets>(HSQUIRRELVM vm, ScriptWindow::NewGRFStateWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::ScanProgressWidgets GetParam(ForceType<ScriptWindow::ScanProgressWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ScanProgressWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::ScanProgressWidgets>(HSQUIRRELVM vm, ScriptWindow::ScanProgressWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::NewsWidgets GetParam(ForceType<ScriptWindow::NewsWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NewsWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::NewsWidgets>(HSQUIRRELVM vm, ScriptWindow::NewsWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::MessageHistoryWidgets GetParam(ForceType<ScriptWindow::MessageHistoryWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::MessageHistoryWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::MessageHistoryWidgets>(HSQUIRRELVM vm, ScriptWindow::MessageHistoryWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildObjectWidgets GetParam(ForceType<ScriptWindow::BuildObjectWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildObjectWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildObjectWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildObjectWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::OrderWidgets GetParam(ForceType<ScriptWindow::OrderWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::OrderWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::OrderWidgets>(HSQUIRRELVM vm, ScriptWindow::OrderWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::OnScreenKeyboardWidgets GetParam(ForceType<ScriptWindow::OnScreenKeyboardWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::OnScreenKeyboardWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::OnScreenKeyboardWidgets>(HSQUIRRELVM vm, ScriptWindow::OnScreenKeyboardWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::RailToolbarWidgets GetParam(ForceType<ScriptWindow::RailToolbarWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::RailToolbarWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::RailToolbarWidgets>(HSQUIRRELVM vm, ScriptWindow::RailToolbarWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildRailStationWidgets GetParam(ForceType<ScriptWindow::BuildRailStationWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildRailStationWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildRailStationWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildRailStationWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildSignalWidgets GetParam(ForceType<ScriptWindow::BuildSignalWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildSignalWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildSignalWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildSignalWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildRailDepotWidgets GetParam(ForceType<ScriptWindow::BuildRailDepotWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildRailDepotWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildRailDepotWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildRailDepotWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildRailWaypointWidgets GetParam(ForceType<ScriptWindow::BuildRailWaypointWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildRailWaypointWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildRailWaypointWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildRailWaypointWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::RoadToolbarWidgets GetParam(ForceType<ScriptWindow::RoadToolbarWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::RoadToolbarWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::RoadToolbarWidgets>(HSQUIRRELVM vm, ScriptWindow::RoadToolbarWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildRoadDepotWidgets GetParam(ForceType<ScriptWindow::BuildRoadDepotWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildRoadDepotWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildRoadDepotWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildRoadDepotWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildRoadStationWidgets GetParam(ForceType<ScriptWindow::BuildRoadStationWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildRoadStationWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildRoadStationWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildRoadStationWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::GameOptionsWidgets GetParam(ForceType<ScriptWindow::GameOptionsWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::GameOptionsWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::GameOptionsWidgets>(HSQUIRRELVM vm, ScriptWindow::GameOptionsWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::GameSettingsWidgets GetParam(ForceType<ScriptWindow::GameSettingsWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::GameSettingsWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::GameSettingsWidgets>(HSQUIRRELVM vm, ScriptWindow::GameSettingsWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::CustomCurrencyWidgets GetParam(ForceType<ScriptWindow::CustomCurrencyWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::CustomCurrencyWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::CustomCurrencyWidgets>(HSQUIRRELVM vm, ScriptWindow::CustomCurrencyWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::SignListWidgets GetParam(ForceType<ScriptWindow::SignListWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::SignListWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::SignListWidgets>(HSQUIRRELVM vm, ScriptWindow::SignListWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::QueryEditSignWidgets GetParam(ForceType<ScriptWindow::QueryEditSignWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::QueryEditSignWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::QueryEditSignWidgets>(HSQUIRRELVM vm, ScriptWindow::QueryEditSignWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::SmallMapWidgets GetParam(ForceType<ScriptWindow::SmallMapWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::SmallMapWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::SmallMapWidgets>(HSQUIRRELVM vm, ScriptWindow::SmallMapWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::StationViewWidgets GetParam(ForceType<ScriptWindow::StationViewWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::StationViewWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::StationViewWidgets>(HSQUIRRELVM vm, ScriptWindow::StationViewWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::StationListWidgets GetParam(ForceType<ScriptWindow::StationListWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::StationListWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::StationListWidgets>(HSQUIRRELVM vm, ScriptWindow::StationListWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::JoinStationWidgets GetParam(ForceType<ScriptWindow::JoinStationWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::JoinStationWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::JoinStationWidgets>(HSQUIRRELVM vm, ScriptWindow::JoinStationWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::StatusbarWidgets GetParam(ForceType<ScriptWindow::StatusbarWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::StatusbarWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::StatusbarWidgets>(HSQUIRRELVM vm, ScriptWindow::StatusbarWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::StoryBookWidgets GetParam(ForceType<ScriptWindow::StoryBookWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::StoryBookWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::StoryBookWidgets>(HSQUIRRELVM vm, ScriptWindow::StoryBookWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::SubsidyListWidgets GetParam(ForceType<ScriptWindow::SubsidyListWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::SubsidyListWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::SubsidyListWidgets>(HSQUIRRELVM vm, ScriptWindow::SubsidyListWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::TerraformToolbarWidgets GetParam(ForceType<ScriptWindow::TerraformToolbarWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::TerraformToolbarWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::TerraformToolbarWidgets>(HSQUIRRELVM vm, ScriptWindow::TerraformToolbarWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::EditorTerraformToolbarWidgets GetParam(ForceType<ScriptWindow::EditorTerraformToolbarWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::EditorTerraformToolbarWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::EditorTerraformToolbarWidgets>(HSQUIRRELVM vm, ScriptWindow::EditorTerraformToolbarWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::VehicleTimetableWidgets GetParam(ForceType<ScriptWindow::VehicleTimetableWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::VehicleTimetableWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::VehicleTimetableWidgets>(HSQUIRRELVM vm, ScriptWindow::VehicleTimetableWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::ToolbarNormalWidgets GetParam(ForceType<ScriptWindow::ToolbarNormalWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ToolbarNormalWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::ToolbarNormalWidgets>(HSQUIRRELVM vm, ScriptWindow::ToolbarNormalWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::ToolbarEditorWidgets GetParam(ForceType<ScriptWindow::ToolbarEditorWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ToolbarEditorWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::ToolbarEditorWidgets>(HSQUIRRELVM vm, ScriptWindow::ToolbarEditorWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::TownDirectoryWidgets GetParam(ForceType<ScriptWindow::TownDirectoryWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::TownDirectoryWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::TownDirectoryWidgets>(HSQUIRRELVM vm, ScriptWindow::TownDirectoryWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::TownAuthorityWidgets GetParam(ForceType<ScriptWindow::TownAuthorityWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::TownAuthorityWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::TownAuthorityWidgets>(HSQUIRRELVM vm, ScriptWindow::TownAuthorityWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::TownViewWidgets GetParam(ForceType<ScriptWindow::TownViewWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::TownViewWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::TownViewWidgets>(HSQUIRRELVM vm, ScriptWindow::TownViewWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::TownFoundingWidgets GetParam(ForceType<ScriptWindow::TownFoundingWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::TownFoundingWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::TownFoundingWidgets>(HSQUIRRELVM vm, ScriptWindow::TownFoundingWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::TransparencyToolbarWidgets GetParam(ForceType<ScriptWindow::TransparencyToolbarWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::TransparencyToolbarWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::TransparencyToolbarWidgets>(HSQUIRRELVM vm, ScriptWindow::TransparencyToolbarWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::BuildTreesWidgets GetParam(ForceType<ScriptWindow::BuildTreesWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::BuildTreesWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::BuildTreesWidgets>(HSQUIRRELVM vm, ScriptWindow::BuildTreesWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::VehicleViewWidgets GetParam(ForceType<ScriptWindow::VehicleViewWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::VehicleViewWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::VehicleViewWidgets>(HSQUIRRELVM vm, ScriptWindow::VehicleViewWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::VehicleRefitWidgets GetParam(ForceType<ScriptWindow::VehicleRefitWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::VehicleRefitWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::VehicleRefitWidgets>(HSQUIRRELVM vm, ScriptWindow::VehicleRefitWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::VehicleDetailsWidgets GetParam(ForceType<ScriptWindow::VehicleDetailsWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::VehicleDetailsWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::VehicleDetailsWidgets>(HSQUIRRELVM vm, ScriptWindow::VehicleDetailsWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::VehicleListWidgets GetParam(ForceType<ScriptWindow::VehicleListWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::VehicleListWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::VehicleListWidgets>(HSQUIRRELVM vm, ScriptWindow::VehicleListWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::ExtraViewportWidgets GetParam(ForceType<ScriptWindow::ExtraViewportWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ExtraViewportWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::ExtraViewportWidgets>(HSQUIRRELVM vm, ScriptWindow::ExtraViewportWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
template <> inline ScriptWindow::WaypointWidgets GetParam(ForceType<ScriptWindow::WaypointWidgets>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::WaypointWidgets)tmp; }
|
||||||
|
template <> inline int Return<ScriptWindow::WaypointWidgets>(HSQUIRRELVM vm, ScriptWindow::WaypointWidgets res) { sq_pushinteger(vm, (int32)res); return 1; }
|
||||||
|
|
||||||
|
/* Allow ScriptWindow to be used as Squirrel parameter */
|
||||||
|
template <> inline ScriptWindow *GetParam(ForceType<ScriptWindow *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptWindow *)instance; }
|
||||||
|
template <> inline ScriptWindow &GetParam(ForceType<ScriptWindow &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptWindow *)instance; }
|
||||||
|
template <> inline const ScriptWindow *GetParam(ForceType<const ScriptWindow *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptWindow *)instance; }
|
||||||
|
template <> inline const ScriptWindow &GetParam(ForceType<const ScriptWindow &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptWindow *)instance; }
|
||||||
|
template <> inline int Return<ScriptWindow *>(HSQUIRRELVM vm, ScriptWindow *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "Window", res, NULL, DefSQDestructorCallback<ScriptWindow>, true); return 1; }
|
||||||
|
} // namespace SQConvert
|
||||||
2174
src/settings.cpp.orig
Normal file
2174
src/settings.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
11
src/settings.cpp.rej
Normal file
11
src/settings.cpp.rej
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
--- src/settings.cpp
|
||||||
|
+++ src/settings.cpp
|
||||||
|
@@ -1092,7 +1092,7 @@
|
||||||
|
|
||||||
|
static bool TouchscreenModeChanged(int32 p1)
|
||||||
|
{
|
||||||
|
- //ResetTabletWindow();
|
||||||
|
+ ResetTabletWindow();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
2651
src/settings_gui.cpp.orig
Normal file
2651
src/settings_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
1827
src/smallmap_gui.cpp.orig
Normal file
1827
src/smallmap_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
192
src/smallmap_gui.h.orig
Normal file
192
src/smallmap_gui.h.orig
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 smallmap_gui.h Smallmap GUI functions. */
|
||||||
|
|
||||||
|
#ifndef SMALLMAP_GUI_H
|
||||||
|
#define SMALLMAP_GUI_H
|
||||||
|
|
||||||
|
#include "industry_type.h"
|
||||||
|
#include "company_base.h"
|
||||||
|
#include "window_gui.h"
|
||||||
|
#include "strings_func.h"
|
||||||
|
#include "blitter/factory.hpp"
|
||||||
|
#include "linkgraph/linkgraph_gui.h"
|
||||||
|
#include "widgets/smallmap_widget.h"
|
||||||
|
|
||||||
|
/* set up the cargos to be displayed in the smallmap's route legend */
|
||||||
|
void BuildLinkStatsLegend();
|
||||||
|
|
||||||
|
void BuildIndustriesLegend();
|
||||||
|
void ShowSmallMap();
|
||||||
|
void BuildLandLegend();
|
||||||
|
void BuildOwnerLegend();
|
||||||
|
|
||||||
|
/** Structure for holding relevant data for legends in small map */
|
||||||
|
struct LegendAndColour {
|
||||||
|
uint8 colour; ///< Colour of the item on the map.
|
||||||
|
StringID legend; ///< String corresponding to the coloured item.
|
||||||
|
IndustryType type; ///< Type of industry. Only valid for industry entries.
|
||||||
|
uint8 height; ///< Height in tiles. Only valid for height legend entries.
|
||||||
|
CompanyID company; ///< Company to display. Only valid for company entries of the owner legend.
|
||||||
|
bool show_on_map; ///< For filtering industries, if \c true, industry is shown on the map in colour.
|
||||||
|
bool end; ///< This is the end of the list.
|
||||||
|
bool col_break; ///< Perform a column break and go further at the next column.
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Class managing the smallmap window. */
|
||||||
|
class SmallMapWindow : public Window {
|
||||||
|
protected:
|
||||||
|
/** Types of legends in the #WID_SM_LEGEND widget. */
|
||||||
|
enum SmallMapType {
|
||||||
|
SMT_CONTOUR,
|
||||||
|
SMT_VEHICLES,
|
||||||
|
SMT_INDUSTRY,
|
||||||
|
SMT_LINKSTATS,
|
||||||
|
SMT_ROUTES,
|
||||||
|
SMT_VEGETATION,
|
||||||
|
SMT_OWNER,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Available kinds of zoomlevel changes. */
|
||||||
|
enum ZoomLevelChange {
|
||||||
|
ZLC_INITIALIZE, ///< Initialize zoom level.
|
||||||
|
ZLC_ZOOM_OUT, ///< Zoom out.
|
||||||
|
ZLC_ZOOM_IN, ///< Zoom in.
|
||||||
|
};
|
||||||
|
|
||||||
|
static SmallMapType map_type; ///< Currently displayed legends.
|
||||||
|
static bool show_towns; ///< Display town names in the smallmap.
|
||||||
|
|
||||||
|
static const uint LEGEND_BLOB_WIDTH = 8; ///< Width of the coloured blob in front of a line text in the #WID_SM_LEGEND widget.
|
||||||
|
static const uint INDUSTRY_MIN_NUMBER_OF_COLUMNS = 2; ///< Minimal number of columns in the #WID_SM_LEGEND widget for the #SMT_INDUSTRY legend.
|
||||||
|
static const uint FORCE_REFRESH_PERIOD = 0x1F; ///< map is redrawn after that many ticks
|
||||||
|
static const uint BLINK_PERIOD = 0x0F; ///< highlight blinking interval
|
||||||
|
|
||||||
|
uint min_number_of_columns; ///< Minimal number of columns in legends.
|
||||||
|
uint min_number_of_fixed_rows; ///< Minimal number of rows in the legends for the fixed layouts only (all except #SMT_INDUSTRY).
|
||||||
|
uint column_width; ///< Width of a column in the #WID_SM_LEGEND widget.
|
||||||
|
|
||||||
|
int32 scroll_x; ///< Horizontal world coordinate of the base tile left of the top-left corner of the smallmap display.
|
||||||
|
int32 scroll_y; ///< Vertical world coordinate of the base tile left of the top-left corner of the smallmap display.
|
||||||
|
int32 subscroll; ///< Number of pixels (0..3) between the right end of the base tile and the pixel at the top-left corner of the smallmap display.
|
||||||
|
int zoom; ///< Zoom level. Bigger number means more zoom-out (further away).
|
||||||
|
|
||||||
|
uint8 refresh; ///< Refresh counter, zeroed every FORCE_REFRESH_PERIOD ticks.
|
||||||
|
LinkGraphOverlay *overlay;
|
||||||
|
|
||||||
|
Point SmallmapRemapCoords(int x, int y) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws vertical part of map indicator
|
||||||
|
* @param x X coord of left/right border of main viewport
|
||||||
|
* @param y Y coord of top border of main viewport
|
||||||
|
* @param y2 Y coord of bottom border of main viewport
|
||||||
|
*/
|
||||||
|
static inline void DrawVertMapIndicator(int x, int y, int y2)
|
||||||
|
{
|
||||||
|
GfxFillRect(x, y, x, y + 3, PC_VERY_LIGHT_YELLOW);
|
||||||
|
GfxFillRect(x, y2 - 3, x, y2, PC_VERY_LIGHT_YELLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws horizontal part of map indicator
|
||||||
|
* @param x X coord of left border of main viewport
|
||||||
|
* @param x2 X coord of right border of main viewport
|
||||||
|
* @param y Y coord of top/bottom border of main viewport
|
||||||
|
*/
|
||||||
|
static inline void DrawHorizMapIndicator(int x, int x2, int y)
|
||||||
|
{
|
||||||
|
GfxFillRect(x, y, x + 3, y, PC_VERY_LIGHT_YELLOW);
|
||||||
|
GfxFillRect(x2 - 3, y, x2, y, PC_VERY_LIGHT_YELLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute minimal required width of the legends.
|
||||||
|
* @return Minimally needed width for displaying the smallmap legends in pixels.
|
||||||
|
*/
|
||||||
|
inline uint GetMinLegendWidth() const
|
||||||
|
{
|
||||||
|
return WD_FRAMERECT_LEFT + this->min_number_of_columns * this->column_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return number of columns that can be displayed in \a width pixels.
|
||||||
|
* @return Number of columns to display.
|
||||||
|
*/
|
||||||
|
inline uint GetNumberColumnsLegend(uint width) const
|
||||||
|
{
|
||||||
|
return width / this->column_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute height given a number of columns.
|
||||||
|
* @param num_columns Number of columns.
|
||||||
|
* @return Needed height for displaying the smallmap legends in pixels.
|
||||||
|
*/
|
||||||
|
inline uint GetLegendHeight(uint num_columns) const
|
||||||
|
{
|
||||||
|
return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM +
|
||||||
|
this->GetNumberRowsLegend(num_columns) * FONT_HEIGHT_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a bitmask for company links to be displayed. Usually this will be
|
||||||
|
* the _local_company. Spectators get to see all companies' links.
|
||||||
|
* @return Company mask.
|
||||||
|
*/
|
||||||
|
inline uint32 GetOverlayCompanyMask() const
|
||||||
|
{
|
||||||
|
return Company::IsValidID(_local_company) ? 1U << _local_company : 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint GetNumberRowsLegend(uint columns) const;
|
||||||
|
void SelectLegendItem(int click_pos, LegendAndColour *legend, int end_legend_item, int begin_legend_item = 0);
|
||||||
|
void SwitchMapType(SmallMapType map_type);
|
||||||
|
void SetNewScroll(int sx, int sy, int sub);
|
||||||
|
|
||||||
|
void DrawMapIndicators() const;
|
||||||
|
void DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const;
|
||||||
|
void DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const;
|
||||||
|
void DrawTowns(const DrawPixelInfo *dpi) const;
|
||||||
|
void DrawSmallMap(DrawPixelInfo *dpi) const;
|
||||||
|
|
||||||
|
Point RemapTile(int tile_x, int tile_y) const;
|
||||||
|
Point PixelToTile(int px, int py, int *sub, bool add_sub = true) const;
|
||||||
|
Point ComputeScroll(int tx, int ty, int x, int y, int *sub);
|
||||||
|
void SetZoomLevel(ZoomLevelChange change, const Point *zoom_pt);
|
||||||
|
void SetOverlayCargoMask();
|
||||||
|
void SetupWidgetData();
|
||||||
|
uint32 GetTileColours(const TileArea &ta) const;
|
||||||
|
|
||||||
|
int GetPositionOnLegend(Point pt);
|
||||||
|
|
||||||
|
public:
|
||||||
|
friend class NWidgetSmallmapDisplay;
|
||||||
|
|
||||||
|
SmallMapWindow(WindowDesc *desc, int window_number);
|
||||||
|
virtual ~SmallMapWindow() { delete this->overlay; }
|
||||||
|
|
||||||
|
void SmallMapCenterOnCurrentPos();
|
||||||
|
Point GetStationMiddle(const Station *st) const;
|
||||||
|
|
||||||
|
virtual void SetStringParameters(int widget) const;
|
||||||
|
virtual void OnInit();
|
||||||
|
virtual void OnPaint();
|
||||||
|
virtual void DrawWidget(const Rect &r, int widget) const;
|
||||||
|
virtual void OnClick(Point pt, int widget, int click_count);
|
||||||
|
virtual void OnInvalidateData(int data = 0, bool gui_scope = true);
|
||||||
|
virtual bool OnRightClick(Point pt, int widget);
|
||||||
|
virtual void OnMouseWheel(int wheel);
|
||||||
|
virtual void OnTick();
|
||||||
|
virtual void OnScroll(Point delta);
|
||||||
|
virtual void OnMouseOver(Point pt, int widget);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SMALLMAP_GUI_H */
|
||||||
534
src/station_base.h.orig
Normal file
534
src/station_base.h.orig
Normal file
@@ -0,0 +1,534 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 station_base.h Base classes/functions for stations. */
|
||||||
|
|
||||||
|
#ifndef STATION_BASE_H
|
||||||
|
#define STATION_BASE_H
|
||||||
|
|
||||||
|
#include "core/random_func.hpp"
|
||||||
|
#include "base_station_base.h"
|
||||||
|
#include "newgrf_airport.h"
|
||||||
|
#include "cargopacket.h"
|
||||||
|
#include "industry_type.h"
|
||||||
|
#include "linkgraph/linkgraph_type.h"
|
||||||
|
#include "newgrf_storage.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
|
||||||
|
extern StationPool _station_pool;
|
||||||
|
|
||||||
|
static const byte INITIAL_STATION_RATING = 175;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flow statistics telling how much flow should be sent along a link. This is
|
||||||
|
* done by creating "flow shares" and using std::map's upper_bound() method to
|
||||||
|
* look them up with a random number. A flow share is the difference between a
|
||||||
|
* key in a map and the previous key. So one key in the map doesn't actually
|
||||||
|
* mean anything by itself.
|
||||||
|
*/
|
||||||
|
class FlowStat {
|
||||||
|
public:
|
||||||
|
typedef std::map<uint32, StationID> SharesMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid constructor. This can't be called as a FlowStat must not be
|
||||||
|
* empty. However, the constructor must be defined and reachable for
|
||||||
|
* FlwoStat to be used in a std::map.
|
||||||
|
*/
|
||||||
|
inline FlowStat() {NOT_REACHED();}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a FlowStat with an initial entry.
|
||||||
|
* @param st Station the initial entry refers to.
|
||||||
|
* @param flow Amount of flow for the initial entry.
|
||||||
|
*/
|
||||||
|
inline FlowStat(StationID st, uint flow)
|
||||||
|
{
|
||||||
|
assert(flow > 0);
|
||||||
|
this->shares[flow] = st;
|
||||||
|
this->unrestricted = flow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add some flow to the end of the shares map. Only do that if you know
|
||||||
|
* that the station isn't in the map yet. Anything else may lead to
|
||||||
|
* inconsistencies.
|
||||||
|
* @param st Remote station.
|
||||||
|
* @param flow Amount of flow to be added.
|
||||||
|
* @param restricted If the flow to be added is restricted.
|
||||||
|
*/
|
||||||
|
inline void AppendShare(StationID st, uint flow, bool restricted = false)
|
||||||
|
{
|
||||||
|
assert(flow > 0);
|
||||||
|
this->shares[(--this->shares.end())->first + flow] = st;
|
||||||
|
if (!restricted) this->unrestricted += flow;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint GetShare(StationID st) const;
|
||||||
|
|
||||||
|
void ChangeShare(StationID st, int flow);
|
||||||
|
|
||||||
|
void RestrictShare(StationID st);
|
||||||
|
|
||||||
|
void ReleaseShare(StationID st);
|
||||||
|
|
||||||
|
void ScaleToMonthly(uint runtime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the actual shares as a const pointer so that they can be iterated
|
||||||
|
* over.
|
||||||
|
* @return Actual shares.
|
||||||
|
*/
|
||||||
|
inline const SharesMap *GetShares() const { return &this->shares; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return total amount of unrestricted shares.
|
||||||
|
* @return Amount of unrestricted shares.
|
||||||
|
*/
|
||||||
|
inline uint GetUnrestricted() const { return this->unrestricted; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap the shares maps, and thus the content of this FlowStat with the
|
||||||
|
* other one.
|
||||||
|
* @param other FlowStat to swap with.
|
||||||
|
*/
|
||||||
|
inline void SwapShares(FlowStat &other)
|
||||||
|
{
|
||||||
|
this->shares.swap(other.shares);
|
||||||
|
Swap(this->unrestricted, other.unrestricted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a station a package can be routed to. This done by drawing a
|
||||||
|
* random number between 0 and sum_shares and then looking that up in
|
||||||
|
* the map with lower_bound. So each share gets selected with a
|
||||||
|
* probability dependent on its flow. Do include restricted flows here.
|
||||||
|
* @param is_restricted Output if a restricted flow was chosen.
|
||||||
|
* @return A station ID from the shares map.
|
||||||
|
*/
|
||||||
|
inline StationID GetViaWithRestricted(bool &is_restricted) const
|
||||||
|
{
|
||||||
|
assert(!this->shares.empty());
|
||||||
|
uint rand = RandomRange((--this->shares.end())->first);
|
||||||
|
is_restricted = rand >= this->unrestricted;
|
||||||
|
return this->shares.upper_bound(rand)->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a station a package can be routed to. This done by drawing a
|
||||||
|
* random number between 0 and sum_shares and then looking that up in
|
||||||
|
* the map with lower_bound. So each share gets selected with a
|
||||||
|
* probability dependent on its flow. Don't include restricted flows.
|
||||||
|
* @return A station ID from the shares map.
|
||||||
|
*/
|
||||||
|
inline StationID GetVia() const
|
||||||
|
{
|
||||||
|
assert(!this->shares.empty());
|
||||||
|
return this->unrestricted > 0 ?
|
||||||
|
this->shares.upper_bound(RandomRange(this->unrestricted))->second :
|
||||||
|
INVALID_STATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
|
||||||
|
|
||||||
|
void Invalidate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SharesMap shares; ///< Shares of flow to be sent via specified station (or consumed locally).
|
||||||
|
uint unrestricted; ///< Limit for unrestricted shares.
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Flow descriptions by origin stations. */
|
||||||
|
class FlowStatMap : public std::map<StationID, FlowStat> {
|
||||||
|
public:
|
||||||
|
void AddFlow(StationID origin, StationID via, uint amount);
|
||||||
|
void PassOnFlow(StationID origin, StationID via, uint amount);
|
||||||
|
StationIDStack DeleteFlows(StationID via);
|
||||||
|
void RestrictFlows(StationID via);
|
||||||
|
void ReleaseFlows(StationID via);
|
||||||
|
void FinalizeLocalConsumption(StationID self);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores station stats for a single cargo.
|
||||||
|
*/
|
||||||
|
struct GoodsEntry {
|
||||||
|
/** Status of this cargo for the station. */
|
||||||
|
enum GoodsEntryStatus {
|
||||||
|
/**
|
||||||
|
* Set when the station accepts the cargo currently for final deliveries.
|
||||||
|
* It is updated every STATION_ACCEPTANCE_TICKS ticks by checking surrounding tiles for acceptance >= 8/8.
|
||||||
|
*/
|
||||||
|
GES_ACCEPTANCE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set when the cargo was ever waiting at the station.
|
||||||
|
* It is set when cargo supplied by surrounding tiles is moved to the station, or when
|
||||||
|
* arriving vehicles unload/transfer cargo without it being a final delivery.
|
||||||
|
* This also indicates, whether a cargo has a rating at the station.
|
||||||
|
* This flag is never cleared.
|
||||||
|
*/
|
||||||
|
GES_PICKUP,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set when a vehicle ever delivered cargo to the station for final delivery.
|
||||||
|
* This flag is never cleared.
|
||||||
|
*/
|
||||||
|
GES_EVER_ACCEPTED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set when cargo was delivered for final delivery last month.
|
||||||
|
* This flag is set to the value of GES_CURRENT_MONTH at the start of each month.
|
||||||
|
*/
|
||||||
|
GES_LAST_MONTH,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set when cargo was delivered for final delivery this month.
|
||||||
|
* This flag is reset on the beginning of every month.
|
||||||
|
*/
|
||||||
|
GES_CURRENT_MONTH,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set when cargo was delivered for final delivery during the current STATION_ACCEPTANCE_TICKS interval.
|
||||||
|
* This flag is reset every STATION_ACCEPTANCE_TICKS ticks.
|
||||||
|
*/
|
||||||
|
GES_ACCEPTED_BIGTICK,
|
||||||
|
};
|
||||||
|
|
||||||
|
GoodsEntry() :
|
||||||
|
acceptance_pickup(0),
|
||||||
|
time_since_pickup(255),
|
||||||
|
rating(INITIAL_STATION_RATING),
|
||||||
|
last_speed(0),
|
||||||
|
last_age(255),
|
||||||
|
amount_fract(0),
|
||||||
|
link_graph(INVALID_LINK_GRAPH),
|
||||||
|
node(INVALID_NODE),
|
||||||
|
max_waiting_cargo(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
byte acceptance_pickup; ///< Status of this cargo, see #GoodsEntryStatus.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of rating-intervals (up to 255) since the last vehicle tried to load this cargo.
|
||||||
|
* The unit used is STATION_RATING_TICKS.
|
||||||
|
* This does not imply there was any cargo to load.
|
||||||
|
*/
|
||||||
|
byte time_since_pickup;
|
||||||
|
|
||||||
|
byte rating; ///< %Station rating for this cargo.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum speed (up to 255) of the last vehicle that tried to load this cargo.
|
||||||
|
* This does not imply there was any cargo to load.
|
||||||
|
* The unit used is a special vehicle-specific speed unit for station ratings.
|
||||||
|
* - Trains: km-ish/h
|
||||||
|
* - RV: km-ish/h
|
||||||
|
* - Ships: 0.5 * km-ish/h
|
||||||
|
* - Aircraft: 8 * mph
|
||||||
|
*/
|
||||||
|
byte last_speed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Age in years (up to 255) of the last vehicle that tried to load this cargo.
|
||||||
|
* This does not imply there was any cargo to load.
|
||||||
|
*/
|
||||||
|
byte last_age;
|
||||||
|
|
||||||
|
byte amount_fract; ///< Fractional part of the amount in the cargo list
|
||||||
|
StationCargoList cargo; ///< The cargo packets of cargo waiting in this station
|
||||||
|
|
||||||
|
LinkGraphID link_graph; ///< Link graph this station belongs to.
|
||||||
|
NodeID node; ///< ID of node in link graph referring to this goods entry.
|
||||||
|
FlowStatMap flows; ///< Planned flows through this station.
|
||||||
|
uint max_waiting_cargo; ///< Max cargo from this station waiting at any station.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reports whether a vehicle has ever tried to load the cargo at this station.
|
||||||
|
* This does not imply that there was cargo available for loading. Refer to GES_PICKUP for that.
|
||||||
|
* @return true if vehicle tried to load.
|
||||||
|
*/
|
||||||
|
bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this cargo have a rating at this station?
|
||||||
|
* @return true if the cargo has a rating, i.e. pickup has been attempted.
|
||||||
|
*/
|
||||||
|
inline bool HasRating() const
|
||||||
|
{
|
||||||
|
return HasBit(this->acceptance_pickup, GES_PICKUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint GetSumFlowVia(StationID via) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the best next hop for a cargo packet from station source.
|
||||||
|
* @param source Source of the packet.
|
||||||
|
* @return The chosen next hop or INVALID_STATION if none was found.
|
||||||
|
*/
|
||||||
|
inline StationID GetVia(StationID source) const
|
||||||
|
{
|
||||||
|
FlowStatMap::const_iterator flow_it(this->flows.find(source));
|
||||||
|
return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the best next hop for a cargo packet from station source, optionally
|
||||||
|
* excluding one or two stations.
|
||||||
|
* @param source Source of the packet.
|
||||||
|
* @param excluded If this station would be chosen choose the second best one instead.
|
||||||
|
* @param excluded2 Second station to be excluded, if != INVALID_STATION.
|
||||||
|
* @return The chosen next hop or INVALID_STATION if none was found.
|
||||||
|
*/
|
||||||
|
inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
|
||||||
|
{
|
||||||
|
FlowStatMap::const_iterator flow_it(this->flows.find(source));
|
||||||
|
return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** All airport-related information. Only valid if tile != INVALID_TILE. */
|
||||||
|
struct Airport : public TileArea {
|
||||||
|
Airport() : TileArea(INVALID_TILE, 0, 0) {}
|
||||||
|
|
||||||
|
uint64 flags; ///< stores which blocks on the airport are taken. was 16 bit earlier on, then 32
|
||||||
|
byte type; ///< Type of this airport, @see AirportTypes
|
||||||
|
byte layout; ///< Airport layout number.
|
||||||
|
Direction rotation; ///< How this airport is rotated.
|
||||||
|
|
||||||
|
PersistentStorage *psa; ///< Persistent storage for NewGRF airports.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the AirportSpec that from the airport type of this airport. If there
|
||||||
|
* is no airport (\c tile == INVALID_TILE) then return the dummy AirportSpec.
|
||||||
|
* @return The AirportSpec for this airport.
|
||||||
|
*/
|
||||||
|
const AirportSpec *GetSpec() const
|
||||||
|
{
|
||||||
|
if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
|
||||||
|
return AirportSpec::Get(this->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the finite-state machine for this airport or the finite-state machine
|
||||||
|
* for the dummy airport in case this isn't an airport.
|
||||||
|
* @pre this->type < NEW_AIRPORT_OFFSET.
|
||||||
|
* @return The state machine for this airport.
|
||||||
|
*/
|
||||||
|
const AirportFTAClass *GetFTA() const
|
||||||
|
{
|
||||||
|
return this->GetSpec()->fsm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if this airport has at least one hangar. */
|
||||||
|
inline bool HasHangar() const
|
||||||
|
{
|
||||||
|
return this->GetSpec()->nof_depots > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the tileoffset to the base tile of this airport but rotate it first.
|
||||||
|
* The base tile is the northernmost tile of this airport. This function
|
||||||
|
* helps to make sure that getting the tile of a hangar works even for
|
||||||
|
* rotated airport layouts without requiring a rotated array of hangar tiles.
|
||||||
|
* @param tidc The tilediff to add to the airport tile.
|
||||||
|
* @return The tile of this airport plus the rotated offset.
|
||||||
|
*/
|
||||||
|
inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
|
||||||
|
{
|
||||||
|
const AirportSpec *as = this->GetSpec();
|
||||||
|
switch (this->rotation) {
|
||||||
|
case DIR_N: return this->tile + ToTileIndexDiff(tidc);
|
||||||
|
|
||||||
|
case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
|
||||||
|
|
||||||
|
case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
|
||||||
|
|
||||||
|
case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
|
||||||
|
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the first tile of the given hangar.
|
||||||
|
* @param hangar_num The hangar to get the location of.
|
||||||
|
* @pre hangar_num < GetNumHangars().
|
||||||
|
* @return A tile with the given hangar.
|
||||||
|
*/
|
||||||
|
inline TileIndex GetHangarTile(uint hangar_num) const
|
||||||
|
{
|
||||||
|
const AirportSpec *as = this->GetSpec();
|
||||||
|
for (uint i = 0; i < as->nof_depots; i++) {
|
||||||
|
if (as->depot_table[i].hangar_num == hangar_num) {
|
||||||
|
return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the exit direction of the hangar at a specific tile.
|
||||||
|
* @param tile The tile to query.
|
||||||
|
* @pre IsHangarTile(tile).
|
||||||
|
* @return The exit direction of the hangar, taking airport rotation into account.
|
||||||
|
*/
|
||||||
|
inline Direction GetHangarExitDirection(TileIndex tile) const
|
||||||
|
{
|
||||||
|
const AirportSpec *as = this->GetSpec();
|
||||||
|
const HangarTileTable *htt = GetHangarDataByTile(tile);
|
||||||
|
return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the hangar number of the hangar at a specific tile.
|
||||||
|
* @param tile The tile to query.
|
||||||
|
* @pre IsHangarTile(tile).
|
||||||
|
* @return The hangar number of the hangar at the given tile.
|
||||||
|
*/
|
||||||
|
inline uint GetHangarNum(TileIndex tile) const
|
||||||
|
{
|
||||||
|
const HangarTileTable *htt = GetHangarDataByTile(tile);
|
||||||
|
return htt->hangar_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the number of hangars on this airport. */
|
||||||
|
inline uint GetNumHangars() const
|
||||||
|
{
|
||||||
|
uint num = 0;
|
||||||
|
uint counted = 0;
|
||||||
|
const AirportSpec *as = this->GetSpec();
|
||||||
|
for (uint i = 0; i < as->nof_depots; i++) {
|
||||||
|
if (!HasBit(counted, as->depot_table[i].hangar_num)) {
|
||||||
|
num++;
|
||||||
|
SetBit(counted, as->depot_table[i].hangar_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Retrieve hangar information of a hangar at a given tile.
|
||||||
|
* @param tile %Tile containing the hangar.
|
||||||
|
* @return The requested hangar information.
|
||||||
|
* @pre The \a tile must be at a hangar tile at an airport.
|
||||||
|
*/
|
||||||
|
inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
|
||||||
|
{
|
||||||
|
const AirportSpec *as = this->GetSpec();
|
||||||
|
for (uint i = 0; i < as->nof_depots; i++) {
|
||||||
|
if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
|
||||||
|
return as->depot_table + i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NOT_REACHED();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef SmallVector<Industry *, 2> IndustryVector;
|
||||||
|
|
||||||
|
/** Station data structure */
|
||||||
|
struct Station FINAL : SpecializedStation<Station, false> {
|
||||||
|
public:
|
||||||
|
RoadStop *GetPrimaryRoadStop(RoadStopType type) const
|
||||||
|
{
|
||||||
|
return type == ROADSTOP_BUS ? bus_stops : truck_stops;
|
||||||
|
}
|
||||||
|
|
||||||
|
RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
|
||||||
|
|
||||||
|
RoadStop *bus_stops; ///< All the road stops
|
||||||
|
TileArea bus_station; ///< Tile area the bus 'station' part covers
|
||||||
|
RoadStop *truck_stops; ///< All the truck stops
|
||||||
|
TileArea truck_station; ///< Tile area the truck 'station' part covers
|
||||||
|
|
||||||
|
Airport airport; ///< Tile area the airport covers
|
||||||
|
TileIndex dock_tile; ///< The location of the dock
|
||||||
|
|
||||||
|
IndustryType indtype; ///< Industry type to get the name from
|
||||||
|
|
||||||
|
StationHadVehicleOfTypeByte had_vehicle_of_type;
|
||||||
|
|
||||||
|
byte time_since_load;
|
||||||
|
byte time_since_unload;
|
||||||
|
|
||||||
|
byte last_vehicle_type;
|
||||||
|
std::list<Vehicle *> loading_vehicles;
|
||||||
|
GoodsEntry goods[NUM_CARGO]; ///< Goods at this station
|
||||||
|
uint32 always_accepted; ///< Bitmask of always accepted cargo types (by houses, HQs, industry tiles when industry doesn't accept cargo)
|
||||||
|
|
||||||
|
IndustryVector industries_near; ///< Cached list of industries near the station that can accept cargo, @see DeliverGoodsToIndustry()
|
||||||
|
|
||||||
|
Station(TileIndex tile = INVALID_TILE);
|
||||||
|
~Station();
|
||||||
|
|
||||||
|
void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
|
||||||
|
|
||||||
|
void MarkTilesDirty(bool cargo_change) const;
|
||||||
|
|
||||||
|
void UpdateVirtCoord();
|
||||||
|
|
||||||
|
/* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
|
||||||
|
/* virtual */ uint GetPlatformLength(TileIndex tile) const;
|
||||||
|
void RecomputeIndustriesNear();
|
||||||
|
static void RecomputeIndustriesNearForAll();
|
||||||
|
|
||||||
|
uint GetCatchmentRadius() const;
|
||||||
|
Rect GetCatchmentRect() const;
|
||||||
|
|
||||||
|
/* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
|
||||||
|
{
|
||||||
|
return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool TileBelongsToAirport(TileIndex tile) const
|
||||||
|
{
|
||||||
|
return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* virtual */ uint32 GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const;
|
||||||
|
|
||||||
|
/* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
|
||||||
|
|
||||||
|
/** Iterator to iterate over all tiles belonging to an airport. */
|
||||||
|
class AirportTileIterator : public OrthogonalTileIterator {
|
||||||
|
private:
|
||||||
|
const Station *st; ///< The station the airport is a part of.
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Construct the iterator.
|
||||||
|
* @param ta Area, i.e. begin point and width/height of to-be-iterated area.
|
||||||
|
*/
|
||||||
|
AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
|
||||||
|
{
|
||||||
|
if (!st->TileBelongsToAirport(this->tile)) ++(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TileIterator& operator ++()
|
||||||
|
{
|
||||||
|
(*this).OrthogonalTileIterator::operator++();
|
||||||
|
while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
|
||||||
|
(*this).OrthogonalTileIterator::operator++();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual TileIterator *Clone() const
|
||||||
|
{
|
||||||
|
return new AirportTileIterator(*this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* STATION_BASE_H */
|
||||||
2450
src/station_gui.cpp.orig
Normal file
2450
src/station_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -259,13 +259,6 @@ struct TerraformToolbarWindow : Window {
|
|||||||
VpSelectTilesWithMethod(pt.x, pt.y, select_method);
|
VpSelectTilesWithMethod(pt.x, pt.y, select_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Point OnInitialPosition(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)
|
virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
|
||||||
{
|
{
|
||||||
if (pt.x != -1) {
|
if (pt.x != -1) {
|
||||||
@@ -348,7 +341,7 @@ static const NWidgetPart _nested_terraform_widgets[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static WindowDesc _terraform_desc(
|
static WindowDesc _terraform_desc(
|
||||||
WDP_MANUAL, "toolbar_landscape", 0, 0,
|
WDP_ALIGN_TOOLBAR, "toolbar_landscape", 0, 0,
|
||||||
WC_SCEN_LAND_GEN, WC_NONE,
|
WC_SCEN_LAND_GEN, WC_NONE,
|
||||||
WDF_CONSTRUCTION,
|
WDF_CONSTRUCTION,
|
||||||
_nested_terraform_widgets, lengthof(_nested_terraform_widgets),
|
_nested_terraform_widgets, lengthof(_nested_terraform_widgets),
|
||||||
@@ -374,7 +367,6 @@ Window *ShowTerraformToolbar(Window *link)
|
|||||||
DeleteWindowById(WC_SCEN_LAND_GEN, 0, true);
|
DeleteWindowById(WC_SCEN_LAND_GEN, 0, true);
|
||||||
w = AllocateWindowDescFront<TerraformToolbarWindow>(&_terraform_desc, 0);
|
w = AllocateWindowDescFront<TerraformToolbarWindow>(&_terraform_desc, 0);
|
||||||
/* Align the terraform toolbar under the main toolbar. */
|
/* Align the terraform toolbar under the main toolbar. */
|
||||||
w->top -= w->height;
|
|
||||||
w->SetDirty();
|
w->SetDirty();
|
||||||
/* Put the linked toolbar to the left / right of it. */
|
/* Put the linked toolbar to the left / right of it. */
|
||||||
link->left = w->left + (_current_text_dir == TD_RTL ? w->width : -link->width);
|
link->left = w->left + (_current_text_dir == TD_RTL ? w->width : -link->width);
|
||||||
|
|||||||
760
src/terraform_gui.cpp.orig
Normal file
760
src/terraform_gui.cpp.orig
Normal file
@@ -0,0 +1,760 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 "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 "object.h"
|
||||||
|
#include "hotkeys.h"
|
||||||
|
#include "engine_base.h"
|
||||||
|
#include "terraform_gui.h"
|
||||||
|
|
||||||
|
#include "widgets/terraform_widget.h"
|
||||||
|
|
||||||
|
#include "table/strings.h"
|
||||||
|
|
||||||
|
void CcTerraform(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
|
||||||
|
{
|
||||||
|
if (result.Succeeded()) {
|
||||||
|
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT, tile);
|
||||||
|
} else {
|
||||||
|
extern TileIndex _terraform_err_tile;
|
||||||
|
SetRedErrorSquare(_terraform_err_tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Scenario editor command that generates desert areas */
|
||||||
|
static void GenerateDesertArea(TileIndex end, TileIndex start)
|
||||||
|
{
|
||||||
|
if (_game_mode != GM_EDITOR) return;
|
||||||
|
|
||||||
|
_generating_world = true;
|
||||||
|
|
||||||
|
TileArea ta(start, end);
|
||||||
|
TILE_AREA_LOOP(tile, ta) {
|
||||||
|
SetTropicZone(tile, (_ctrl_pressed) ? TROPICZONE_NORMAL : TROPICZONE_DESERT);
|
||||||
|
DoCommandP(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
|
||||||
|
MarkTileDirtyByTile(tile);
|
||||||
|
}
|
||||||
|
_generating_world = false;
|
||||||
|
InvalidateWindowClassesData(WC_TOWN_VIEW, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Scenario editor command that generates rocky areas */
|
||||||
|
static void GenerateRockyArea(TileIndex end, TileIndex start)
|
||||||
|
{
|
||||||
|
if (_game_mode != GM_EDITOR) return;
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
TileArea ta(start, end);
|
||||||
|
|
||||||
|
TILE_AREA_LOOP(tile, ta) {
|
||||||
|
switch (GetTileType(tile)) {
|
||||||
|
case MP_TREES:
|
||||||
|
if (GetTreeGround(tile) == TREE_GROUND_SHORE) continue;
|
||||||
|
/* FALL THROUGH */
|
||||||
|
case MP_CLEAR:
|
||||||
|
MakeClear(tile, CLEAR_ROCKS, 3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: continue;
|
||||||
|
}
|
||||||
|
MarkTileDirtyByTile(tile);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success && _settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A central place to handle all X_AND_Y dragged GUI functions.
|
||||||
|
* @param proc Procedure related to the dragging
|
||||||
|
* @param start_tile Begin of the dragging
|
||||||
|
* @param end_tile End of the dragging
|
||||||
|
* @return Returns true if the action was found and handled, and false otherwise. This
|
||||||
|
* allows for additional implements that are more local. For example X_Y drag
|
||||||
|
* of convertrail which belongs in rail_gui.cpp and not terraform_gui.cpp
|
||||||
|
*/
|
||||||
|
bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_tile, TileIndex end_tile)
|
||||||
|
{
|
||||||
|
if (!_settings_game.construction.freeform_edges) {
|
||||||
|
/* When end_tile is MP_VOID, the error tile will not be visible to the
|
||||||
|
* user. This happens when terraforming at the southern border. */
|
||||||
|
if (TileX(end_tile) == MapMaxX()) end_tile += TileDiffXY(-1, 0);
|
||||||
|
if (TileY(end_tile) == MapMaxY()) end_tile += TileDiffXY(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (proc) {
|
||||||
|
case DDSP_DEMOLISH_AREA:
|
||||||
|
DoCommandP(end_tile, start_tile, _ctrl_pressed ? 1 : 0, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA), CcPlaySound10);
|
||||||
|
break;
|
||||||
|
case DDSP_RAISE_AND_LEVEL_AREA:
|
||||||
|
DoCommandP(end_tile, start_tile, LM_RAISE << 1 | (_ctrl_pressed ? 1 : 0), CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_RAISE_LAND_HERE), CcTerraform);
|
||||||
|
break;
|
||||||
|
case DDSP_LOWER_AND_LEVEL_AREA:
|
||||||
|
DoCommandP(end_tile, start_tile, LM_LOWER << 1 | (_ctrl_pressed ? 1 : 0), CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_LOWER_LAND_HERE), CcTerraform);
|
||||||
|
break;
|
||||||
|
case DDSP_LEVEL_AREA:
|
||||||
|
DoCommandP(end_tile, start_tile, LM_LEVEL << 1 | (_ctrl_pressed ? 1 : 0), CMD_LEVEL_LAND | CMD_MSG(STR_ERROR_CAN_T_LEVEL_LAND_HERE), CcTerraform);
|
||||||
|
break;
|
||||||
|
case DDSP_CREATE_ROCKS:
|
||||||
|
GenerateRockyArea(end_tile, start_tile);
|
||||||
|
break;
|
||||||
|
case DDSP_CREATE_DESERT:
|
||||||
|
GenerateDesertArea(end_tile, start_tile);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a drag for demolishing an area.
|
||||||
|
* @param tile Position of one corner.
|
||||||
|
*/
|
||||||
|
void PlaceProc_DemolishArea(TileIndex tile)
|
||||||
|
{
|
||||||
|
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_DEMOLISH_AREA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Terra form toolbar managing class. */
|
||||||
|
struct TerraformToolbarWindow : Window {
|
||||||
|
int last_user_action; ///< Last started user action.
|
||||||
|
|
||||||
|
TerraformToolbarWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
|
||||||
|
{
|
||||||
|
/* This is needed as we like to have the tree available on OnInit. */
|
||||||
|
this->CreateNestedTree();
|
||||||
|
this->FinishInitNested(window_number);
|
||||||
|
this->last_user_action = WIDGET_LIST_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TerraformToolbarWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnInit()
|
||||||
|
{
|
||||||
|
/* Don't show the place object button when there are no objects to place. */
|
||||||
|
NWidgetStacked *show_object = this->GetWidget<NWidgetStacked>(WID_TT_SHOW_PLACE_OBJECT);
|
||||||
|
show_object->SetDisplayedPlane(ObjectClass::GetUIClassCount() != 0 ? 0 : SZSP_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnClick(Point pt, int widget, int click_count)
|
||||||
|
{
|
||||||
|
if (widget < WID_TT_BUTTONS_START) return;
|
||||||
|
|
||||||
|
switch (widget) {
|
||||||
|
case WID_TT_LOWER_LAND: // Lower land button
|
||||||
|
HandlePlacePushButton(this, WID_TT_LOWER_LAND, ANIMCURSOR_LOWERLAND, HT_POINT | HT_DIAGONAL);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_RAISE_LAND: // Raise land button
|
||||||
|
HandlePlacePushButton(this, WID_TT_RAISE_LAND, ANIMCURSOR_RAISELAND, HT_POINT | HT_DIAGONAL);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_LEVEL_LAND: // Level land button
|
||||||
|
HandlePlacePushButton(this, WID_TT_LEVEL_LAND, SPR_CURSOR_LEVEL_LAND, HT_POINT | HT_DIAGONAL);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_DEMOLISH: // Demolish aka dynamite button
|
||||||
|
HandlePlacePushButton(this, WID_TT_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT | HT_DIAGONAL);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_BUY_LAND: // Buy land button
|
||||||
|
HandlePlacePushButton(this, WID_TT_BUY_LAND, SPR_CURSOR_BUY_LAND, HT_RECT);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_PLANT_TREES: // Plant trees button
|
||||||
|
ShowBuildTreesToolbar();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_PLACE_SIGN: // Place sign button
|
||||||
|
HandlePlacePushButton(this, WID_TT_PLACE_SIGN, SPR_CURSOR_SIGN, HT_RECT);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_PLACE_OBJECT: // Place object button
|
||||||
|
/* Don't show the place object button when there are no objects to place. */
|
||||||
|
if (ObjectClass::GetUIClassCount() == 0) return;
|
||||||
|
if (HandlePlacePushButton(this, WID_TT_PLACE_OBJECT, SPR_CURSOR_TRANSMITTER, HT_RECT)) {
|
||||||
|
ShowBuildObjectPicker(this);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPlaceObject(Point pt, TileIndex tile)
|
||||||
|
{
|
||||||
|
switch (this->last_user_action) {
|
||||||
|
case WID_TT_LOWER_LAND: // Lower land button
|
||||||
|
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LOWER_AND_LEVEL_AREA);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_RAISE_LAND: // Raise land button
|
||||||
|
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_RAISE_AND_LEVEL_AREA);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_LEVEL_LAND: // Level land button
|
||||||
|
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LEVEL_AREA);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_DEMOLISH: // Demolish aka dynamite button
|
||||||
|
PlaceProc_DemolishArea(tile);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_BUY_LAND: // Buy land button
|
||||||
|
DoCommandP(tile, OBJECT_OWNED_LAND, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_PURCHASE_THIS_LAND), CcPlaySound1E);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_PLACE_SIGN: // Place sign button
|
||||||
|
PlaceProc_Sign(tile);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TT_PLACE_OBJECT: // Place object button
|
||||||
|
PlaceProc_Object(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(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:
|
||||||
|
case DDSP_RAISE_AND_LEVEL_AREA:
|
||||||
|
case DDSP_LOWER_AND_LEVEL_AREA:
|
||||||
|
case DDSP_LEVEL_AREA:
|
||||||
|
GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPlaceObjectAbort()
|
||||||
|
{
|
||||||
|
DeleteWindowById(WC_BUILD_OBJECT, 0);
|
||||||
|
this->RaiseButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
static HotkeyList hotkeys;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for global hotkeys of the TerraformToolbarWindow.
|
||||||
|
* @param hotkey Hotkey
|
||||||
|
* @return ES_HANDLED if hotkey was accepted.
|
||||||
|
*/
|
||||||
|
static EventState TerraformToolbarGlobalHotkeys(int hotkey)
|
||||||
|
{
|
||||||
|
if (_game_mode != GM_NORMAL) return ES_NOT_HANDLED;
|
||||||
|
Window *w = ShowTerraformToolbar(NULL);
|
||||||
|
if (w == NULL) return ES_NOT_HANDLED;
|
||||||
|
return w->OnHotkey(hotkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Hotkey terraform_hotkeys[] = {
|
||||||
|
Hotkey('Q' | WKC_GLOBAL_HOTKEY, "lower", WID_TT_LOWER_LAND),
|
||||||
|
Hotkey('W' | WKC_GLOBAL_HOTKEY, "raise", WID_TT_RAISE_LAND),
|
||||||
|
Hotkey('E' | WKC_GLOBAL_HOTKEY, "level", WID_TT_LEVEL_LAND),
|
||||||
|
Hotkey('D' | WKC_GLOBAL_HOTKEY, "dynamite", WID_TT_DEMOLISH),
|
||||||
|
Hotkey('U', "buyland", WID_TT_BUY_LAND),
|
||||||
|
Hotkey('I', "trees", WID_TT_PLANT_TREES),
|
||||||
|
Hotkey('O', "placesign", WID_TT_PLACE_SIGN),
|
||||||
|
Hotkey('P', "placeobject", WID_TT_PLACE_OBJECT),
|
||||||
|
HOTKEY_LIST_END
|
||||||
|
};
|
||||||
|
HotkeyList TerraformToolbarWindow::hotkeys("terraform", terraform_hotkeys, TerraformToolbarGlobalHotkeys);
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_terraform_widgets[] = {
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_LANDSCAPING_TOOLBAR, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||||
|
NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_LOWER_LAND), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_DOWN, STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_RAISE_LAND), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_UP, STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_LEVEL_LAND), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_LEVEL_LAND, STR_LANDSCAPING_LEVEL_LAND_TOOLTIP),
|
||||||
|
|
||||||
|
NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),
|
||||||
|
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_DEMOLISH), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_BUY_LAND), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_BUY_LAND, STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND),
|
||||||
|
NWidget(WWT_PUSHIMGBTN, COLOUR_DARK_GREEN, WID_TT_PLANT_TREES), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_PLACE_SIGN), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
|
||||||
|
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_TT_SHOW_PLACE_OBJECT),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_TT_PLACE_OBJECT), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER, STR_SCENEDIT_TOOLBAR_PLACE_OBJECT),
|
||||||
|
EndContainer(),
|
||||||
|
EndContainer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowDesc _terraform_desc(
|
||||||
|
WDP_MANUAL, "toolbar_landscape", 0, 0,
|
||||||
|
WC_SCEN_LAND_GEN, WC_NONE,
|
||||||
|
WDF_CONSTRUCTION,
|
||||||
|
_nested_terraform_widgets, lengthof(_nested_terraform_widgets),
|
||||||
|
&TerraformToolbarWindow::hotkeys
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the toolbar for terraforming in the game.
|
||||||
|
* @param link The toolbar we might want to link to.
|
||||||
|
* @return The allocated toolbar.
|
||||||
|
*/
|
||||||
|
Window *ShowTerraformToolbar(Window *link)
|
||||||
|
{
|
||||||
|
if (!Company::IsValidID(_local_company)) return NULL;
|
||||||
|
|
||||||
|
Window *w;
|
||||||
|
if (link == NULL) {
|
||||||
|
w = AllocateWindowDescFront<TerraformToolbarWindow>(&_terraform_desc, 0);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete the terraform toolbar to place it again. */
|
||||||
|
DeleteWindowById(WC_SCEN_LAND_GEN, 0, true);
|
||||||
|
w = AllocateWindowDescFront<TerraformToolbarWindow>(&_terraform_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte _terraform_size = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raise/Lower a bigger chunk of land at the same time in the editor. When
|
||||||
|
* raising get the lowest point, when lowering the highest point, and set all
|
||||||
|
* tiles in the selection to that height.
|
||||||
|
* @todo : Incorporate into game itself to allow for ingame raising/lowering of
|
||||||
|
* larger chunks at the same time OR remove altogether, as we have 'level land' ?
|
||||||
|
* @param tile The top-left tile where the terraforming will start
|
||||||
|
* @param mode 1 for raising, 0 for lowering land
|
||||||
|
*/
|
||||||
|
static void CommonRaiseLowerBigLand(TileIndex tile, int mode)
|
||||||
|
{
|
||||||
|
if (_terraform_size == 1) {
|
||||||
|
StringID msg =
|
||||||
|
mode ? STR_ERROR_CAN_T_RAISE_LAND_HERE : STR_ERROR_CAN_T_LOWER_LAND_HERE;
|
||||||
|
|
||||||
|
DoCommandP(tile, SLOPE_N, (uint32)mode, CMD_TERRAFORM_LAND | CMD_MSG(msg), CcTerraform);
|
||||||
|
} else {
|
||||||
|
assert(_terraform_size != 0);
|
||||||
|
TileArea ta(tile, _terraform_size, _terraform_size);
|
||||||
|
ta.ClampToMap();
|
||||||
|
|
||||||
|
if (ta.w == 0 || ta.h == 0) return;
|
||||||
|
|
||||||
|
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT, tile);
|
||||||
|
|
||||||
|
uint h;
|
||||||
|
if (mode != 0) {
|
||||||
|
/* Raise land */
|
||||||
|
h = MAX_TILE_HEIGHT;
|
||||||
|
TILE_AREA_LOOP(tile2, ta) {
|
||||||
|
h = min(h, TileHeight(tile2));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Lower land */
|
||||||
|
h = 0;
|
||||||
|
TILE_AREA_LOOP(tile2, ta) {
|
||||||
|
h = max(h, TileHeight(tile2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TILE_AREA_LOOP(tile2, ta) {
|
||||||
|
if (TileHeight(tile2) == h) {
|
||||||
|
DoCommandP(tile2, SLOPE_N, (uint32)mode, CMD_TERRAFORM_LAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int8 _multi_terraform_coords[][2] = {
|
||||||
|
{ 0, -2},
|
||||||
|
{ 4, 0}, { -4, 0}, { 0, 2},
|
||||||
|
{ -8, 2}, { -4, 4}, { 0, 6}, { 4, 4}, { 8, 2},
|
||||||
|
{-12, 0}, { -8, -2}, { -4, -4}, { 0, -6}, { 4, -4}, { 8, -2}, { 12, 0},
|
||||||
|
{-16, 2}, {-12, 4}, { -8, 6}, { -4, 8}, { 0, 10}, { 4, 8}, { 8, 6}, { 12, 4}, { 16, 2},
|
||||||
|
{-20, 0}, {-16, -2}, {-12, -4}, { -8, -6}, { -4, -8}, { 0,-10}, { 4, -8}, { 8, -6}, { 12, -4}, { 16, -2}, { 20, 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}, {-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},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_scen_edit_land_gen_widgets[] = {
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||||
|
NWidget(WWT_SHADEBOX, COLOUR_DARK_GREEN),
|
||||||
|
NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
|
||||||
|
NWidget(NWID_HORIZONTAL), SetPadding(2, 2, 7, 2),
|
||||||
|
NWidget(NWID_SPACER), SetFill(1, 0),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_ETT_DEMOLISH), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_ETT_LOWER_LAND), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_DOWN, STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_ETT_RAISE_LAND), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_TERRAFORM_UP, STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_ETT_LEVEL_LAND), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_LEVEL_LAND, STR_LANDSCAPING_LEVEL_LAND_TOOLTIP),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_ETT_PLACE_ROCKS), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_ROCKS, STR_TERRAFORM_TOOLTIP_PLACE_ROCKY_AREAS_ON_LANDSCAPE),
|
||||||
|
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_ETT_SHOW_PLACE_DESERT),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_ETT_PLACE_DESERT), SetMinimalSize(22, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_DESERT, STR_TERRAFORM_TOOLTIP_DEFINE_DESERT_AREA),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_ETT_PLACE_OBJECT), SetMinimalSize(23, 22),
|
||||||
|
SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER, STR_SCENEDIT_TOOLBAR_PLACE_OBJECT),
|
||||||
|
NWidget(NWID_SPACER), SetFill(1, 0),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(NWID_SPACER), SetFill(1, 0),
|
||||||
|
NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, WID_ETT_DOTS), SetMinimalSize(59, 31), SetDataTip(STR_EMPTY, STR_NULL),
|
||||||
|
NWidget(NWID_SPACER), SetFill(1, 0),
|
||||||
|
NWidget(NWID_VERTICAL),
|
||||||
|
NWidget(NWID_SPACER), SetFill(0, 1),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_ETT_INCREASE_SIZE), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_UP, STR_TERRAFORM_TOOLTIP_INCREASE_SIZE_OF_LAND_AREA),
|
||||||
|
NWidget(NWID_SPACER), SetMinimalSize(0, 1),
|
||||||
|
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_ETT_DECREASE_SIZE), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_DOWN, STR_TERRAFORM_TOOLTIP_DECREASE_SIZE_OF_LAND_AREA),
|
||||||
|
NWidget(NWID_SPACER), SetFill(0, 1),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_SPACER), SetMinimalSize(2, 0),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_SPACER), SetMinimalSize(0, 6),
|
||||||
|
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_ETT_NEW_SCENARIO), SetMinimalSize(160, 12),
|
||||||
|
SetFill(1, 0), SetDataTip(STR_TERRAFORM_SE_NEW_WORLD, STR_TERRAFORM_TOOLTIP_GENERATE_RANDOM_LAND), SetPadding(0, 2, 0, 2),
|
||||||
|
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_ETT_RESET_LANDSCAPE), SetMinimalSize(160, 12),
|
||||||
|
SetFill(1, 0), SetDataTip(STR_TERRAFORM_RESET_LANDSCAPE, STR_TERRAFORM_RESET_LANDSCAPE_TOOLTIP), SetPadding(1, 2, 2, 2),
|
||||||
|
EndContainer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function for the scenario editor 'reset landscape' confirmation window
|
||||||
|
* @param w Window unused
|
||||||
|
* @param confirmed boolean value, true when yes was clicked, false otherwise
|
||||||
|
*/
|
||||||
|
static void ResetLandscapeConfirmationCallback(Window *w, bool confirmed)
|
||||||
|
{
|
||||||
|
if (confirmed) {
|
||||||
|
/* Set generating_world to true to get instant-green grass after removing
|
||||||
|
* company property. */
|
||||||
|
_generating_world = true;
|
||||||
|
|
||||||
|
/* Delete all companies */
|
||||||
|
Company *c;
|
||||||
|
FOR_ALL_COMPANIES(c) {
|
||||||
|
ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
|
||||||
|
delete c;
|
||||||
|
}
|
||||||
|
|
||||||
|
_generating_world = false;
|
||||||
|
|
||||||
|
/* Delete all station signs */
|
||||||
|
BaseStation *st;
|
||||||
|
FOR_ALL_BASE_STATIONS(st) {
|
||||||
|
/* There can be buoys, remove them */
|
||||||
|
if (IsBuoyTile(st->xy)) DoCommand(st->xy, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
|
||||||
|
if (!st->IsInUse()) delete st;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now that all vehicles are gone, we can reset the engine pool. Maybe it reduces some NewGRF changing-mess */
|
||||||
|
EngineOverrideManager::ResetToCurrentNewGRFConfig();
|
||||||
|
|
||||||
|
MarkWholeScreenDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Landscape generation window handler in the scenario editor. */
|
||||||
|
struct ScenarioEditorLandscapeGenerationWindow : Window {
|
||||||
|
int last_user_action; ///< Last started user action.
|
||||||
|
|
||||||
|
ScenarioEditorLandscapeGenerationWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
|
||||||
|
{
|
||||||
|
this->CreateNestedTree();
|
||||||
|
NWidgetStacked *show_desert = this->GetWidget<NWidgetStacked>(WID_ETT_SHOW_PLACE_DESERT);
|
||||||
|
show_desert->SetDisplayedPlane(_settings_game.game_creation.landscape == LT_TROPIC ? 0 : SZSP_NONE);
|
||||||
|
this->FinishInitNested(window_number);
|
||||||
|
this->last_user_action = WIDGET_LIST_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPaint()
|
||||||
|
{
|
||||||
|
this->DrawWidgets();
|
||||||
|
|
||||||
|
if (this->IsWidgetLowered(WID_ETT_LOWER_LAND) || this->IsWidgetLowered(WID_ETT_RAISE_LAND)) { // change area-size if raise/lower corner is selected
|
||||||
|
SetTileSelectSize(_terraform_size, _terraform_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DrawWidget(const Rect &r, int widget) const
|
||||||
|
{
|
||||||
|
if (widget != WID_ETT_DOTS) return;
|
||||||
|
|
||||||
|
int center_x = RoundDivSU(r.left + r.right, 2);
|
||||||
|
int center_y = RoundDivSU(r.top + r.bottom, 2);
|
||||||
|
|
||||||
|
int n = _terraform_size * _terraform_size;
|
||||||
|
const int8 *coords = &_multi_terraform_coords[0][0];
|
||||||
|
|
||||||
|
assert(n != 0);
|
||||||
|
do {
|
||||||
|
DrawSprite(SPR_WHITE_POINT, PAL_NONE, center_x + coords[0], center_y + coords[1]);
|
||||||
|
coords += 2;
|
||||||
|
} while (--n);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnClick(Point pt, int widget, int click_count)
|
||||||
|
{
|
||||||
|
if (widget < WID_ETT_BUTTONS_START) return;
|
||||||
|
|
||||||
|
switch (widget) {
|
||||||
|
case WID_ETT_DEMOLISH: // Demolish aka dynamite button
|
||||||
|
HandlePlacePushButton(this, WID_ETT_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT | HT_DIAGONAL);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_LOWER_LAND: // Lower land button
|
||||||
|
HandlePlacePushButton(this, WID_ETT_LOWER_LAND, ANIMCURSOR_LOWERLAND, HT_POINT);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_RAISE_LAND: // Raise land button
|
||||||
|
HandlePlacePushButton(this, WID_ETT_RAISE_LAND, ANIMCURSOR_RAISELAND, HT_POINT);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_LEVEL_LAND: // Level land button
|
||||||
|
HandlePlacePushButton(this, WID_ETT_LEVEL_LAND, SPR_CURSOR_LEVEL_LAND, HT_POINT | HT_DIAGONAL);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_PLACE_ROCKS: // Place rocks button
|
||||||
|
HandlePlacePushButton(this, WID_ETT_PLACE_ROCKS, SPR_CURSOR_ROCKY_AREA, HT_RECT);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_PLACE_DESERT: // Place desert button (in tropical climate)
|
||||||
|
HandlePlacePushButton(this, WID_ETT_PLACE_DESERT, SPR_CURSOR_DESERT, HT_RECT);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_PLACE_OBJECT: // Place transmitter button
|
||||||
|
if (HandlePlacePushButton(this, WID_ETT_PLACE_OBJECT, SPR_CURSOR_TRANSMITTER, HT_RECT)) {
|
||||||
|
ShowBuildObjectPicker(this);
|
||||||
|
this->last_user_action = widget;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_INCREASE_SIZE:
|
||||||
|
case WID_ETT_DECREASE_SIZE: { // Increase/Decrease terraform size
|
||||||
|
int size = (widget == WID_ETT_INCREASE_SIZE) ? 1 : -1;
|
||||||
|
this->HandleButtonClick(widget);
|
||||||
|
size += _terraform_size;
|
||||||
|
|
||||||
|
if (!IsInsideMM(size, 1, 8 + 1)) return;
|
||||||
|
_terraform_size = size;
|
||||||
|
|
||||||
|
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_ETT_NEW_SCENARIO: // gen random land
|
||||||
|
this->HandleButtonClick(widget);
|
||||||
|
ShowCreateScenario();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_RESET_LANDSCAPE: // Reset landscape
|
||||||
|
ShowQuery(STR_QUERY_RESET_LANDSCAPE_CAPTION, STR_RESET_LANDSCAPE_CONFIRMATION_TEXT, NULL, ResetLandscapeConfirmationCallback);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnTimeout()
|
||||||
|
{
|
||||||
|
for (uint i = WID_ETT_START; i < this->nested_array_size; i++) {
|
||||||
|
if (i == WID_ETT_BUTTONS_START) i = WID_ETT_BUTTONS_END; // skip the buttons
|
||||||
|
if (this->IsWidgetLowered(i)) {
|
||||||
|
this->RaiseWidget(i);
|
||||||
|
this->SetWidgetDirty(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPlaceObject(Point pt, TileIndex tile)
|
||||||
|
{
|
||||||
|
switch (this->last_user_action) {
|
||||||
|
case WID_ETT_DEMOLISH: // Demolish aka dynamite button
|
||||||
|
PlaceProc_DemolishArea(tile);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_LOWER_LAND: // Lower land button
|
||||||
|
CommonRaiseLowerBigLand(tile, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_RAISE_LAND: // Raise land button
|
||||||
|
CommonRaiseLowerBigLand(tile, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_LEVEL_LAND: // Level land button
|
||||||
|
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LEVEL_AREA);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_PLACE_ROCKS: // Place rocks button
|
||||||
|
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CREATE_ROCKS);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_PLACE_DESERT: // Place desert button (in tropical climate)
|
||||||
|
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CREATE_DESERT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_ETT_PLACE_OBJECT: // Place transmitter button
|
||||||
|
PlaceProc_Object(tile);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
|
||||||
|
{
|
||||||
|
VpSelectTilesWithMethod(pt.x, pt.y, select_method);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_CREATE_ROCKS:
|
||||||
|
case DDSP_CREATE_DESERT:
|
||||||
|
case DDSP_RAISE_AND_LEVEL_AREA:
|
||||||
|
case DDSP_LOWER_AND_LEVEL_AREA:
|
||||||
|
case DDSP_LEVEL_AREA:
|
||||||
|
case DDSP_DEMOLISH_AREA:
|
||||||
|
GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnPlaceObjectAbort()
|
||||||
|
{
|
||||||
|
this->RaiseButtons();
|
||||||
|
this->SetDirty();
|
||||||
|
DeleteWindowById(WC_BUILD_OBJECT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HotkeyList hotkeys;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for global hotkeys of the ScenarioEditorLandscapeGenerationWindow.
|
||||||
|
* @param hotkey Hotkey
|
||||||
|
* @return ES_HANDLED if hotkey was accepted.
|
||||||
|
*/
|
||||||
|
static EventState TerraformToolbarEditorGlobalHotkeys(int hotkey)
|
||||||
|
{
|
||||||
|
if (_game_mode != GM_EDITOR) return ES_NOT_HANDLED;
|
||||||
|
Window *w = ShowEditorTerraformToolbar();
|
||||||
|
if (w == NULL) return ES_NOT_HANDLED;
|
||||||
|
return w->OnHotkey(hotkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Hotkey terraform_editor_hotkeys[] = {
|
||||||
|
Hotkey('D' | WKC_GLOBAL_HOTKEY, "dynamite", WID_ETT_DEMOLISH),
|
||||||
|
Hotkey('Q' | WKC_GLOBAL_HOTKEY, "lower", WID_ETT_LOWER_LAND),
|
||||||
|
Hotkey('W' | WKC_GLOBAL_HOTKEY, "raise", WID_ETT_RAISE_LAND),
|
||||||
|
Hotkey('E' | WKC_GLOBAL_HOTKEY, "level", WID_ETT_LEVEL_LAND),
|
||||||
|
Hotkey('R', "rocky", WID_ETT_PLACE_ROCKS),
|
||||||
|
Hotkey('T', "desert", WID_ETT_PLACE_DESERT),
|
||||||
|
Hotkey('O', "object", WID_ETT_PLACE_OBJECT),
|
||||||
|
HOTKEY_LIST_END
|
||||||
|
};
|
||||||
|
|
||||||
|
HotkeyList ScenarioEditorLandscapeGenerationWindow::hotkeys("terraform_editor", terraform_editor_hotkeys, TerraformToolbarEditorGlobalHotkeys);
|
||||||
|
|
||||||
|
static WindowDesc _scen_edit_land_gen_desc(
|
||||||
|
WDP_AUTO, "toolbar_landscape_scen", 0, 0,
|
||||||
|
WC_SCEN_LAND_GEN, WC_NONE,
|
||||||
|
WDF_CONSTRUCTION,
|
||||||
|
_nested_scen_edit_land_gen_widgets, lengthof(_nested_scen_edit_land_gen_widgets),
|
||||||
|
&ScenarioEditorLandscapeGenerationWindow::hotkeys
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the toolbar for terraforming in the scenario editor.
|
||||||
|
* @return The allocated toolbar.
|
||||||
|
*/
|
||||||
|
Window *ShowEditorTerraformToolbar()
|
||||||
|
{
|
||||||
|
return AllocateWindowDescFront<ScenarioEditorLandscapeGenerationWindow>(&_scen_edit_land_gen_desc, 0);
|
||||||
|
}
|
||||||
2228
src/toolbar_gui.cpp.orig
Normal file
2228
src/toolbar_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
23
src/toolbar_type.h
Normal file
23
src/toolbar_type.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 toolbar_type.h Types related to toolbars. */
|
||||||
|
|
||||||
|
#ifndef TOOLBAR_TYPE_H
|
||||||
|
#define TOOLBAR_TYPE_H
|
||||||
|
|
||||||
|
/** Types of touchscreen modes. */
|
||||||
|
enum TouchscreenMode {
|
||||||
|
TSC_NONE = 0,
|
||||||
|
TSC_SIMPLE,
|
||||||
|
};
|
||||||
|
DECLARE_CYCLE(TouchscreenMode, TSC_NONE, TSC_SIMPLE)
|
||||||
|
typedef SimpleTinyEnumT<TouchscreenMode, byte> TouchscreenModeByte;
|
||||||
|
|
||||||
|
#endif /* TOOLBAR_TYPE_H */
|
||||||
1199
src/town_gui.cpp.orig
Normal file
1199
src/town_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
2841
src/vehicle_gui.cpp.orig
Normal file
2841
src/vehicle_gui.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
104
src/vehicle_gui.h.orig
Normal file
104
src/vehicle_gui.h.orig
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 vehicle_gui.h Functions related to the vehicle's GUIs. */
|
||||||
|
|
||||||
|
#ifndef VEHICLE_GUI_H
|
||||||
|
#define VEHICLE_GUI_H
|
||||||
|
|
||||||
|
#include "window_type.h"
|
||||||
|
#include "vehicle_type.h"
|
||||||
|
#include "order_type.h"
|
||||||
|
#include "station_type.h"
|
||||||
|
#include "engine_type.h"
|
||||||
|
#include "company_type.h"
|
||||||
|
|
||||||
|
void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit = false);
|
||||||
|
|
||||||
|
/** The tabs in the train details window */
|
||||||
|
enum TrainDetailsWindowTabs {
|
||||||
|
TDW_TAB_CARGO = 0, ///< Tab with cargo carried by the vehicles
|
||||||
|
TDW_TAB_INFO, ///< Tab with name and value of the vehicles
|
||||||
|
TDW_TAB_CAPACITY, ///< Tab with cargo capacity of the vehicles
|
||||||
|
TDW_TAB_TOTALS, ///< Tab with sum of total cargo transported
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Special values for vehicle-related windows for the data parameter of #InvalidateWindowData. */
|
||||||
|
enum VehicleInvalidateWindowData {
|
||||||
|
VIWD_REMOVE_ALL_ORDERS = -1, ///< Removed / replaced all orders (after deleting / sharing).
|
||||||
|
VIWD_MODIFY_ORDERS = -2, ///< Other order modifications.
|
||||||
|
VIWD_CONSIST_CHANGED = -3, ///< Vehicle composition was changed.
|
||||||
|
VIWD_AUTOREPLACE = -4, ///< Autoreplace replaced the vehicle.
|
||||||
|
};
|
||||||
|
|
||||||
|
int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number);
|
||||||
|
|
||||||
|
void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip, VehicleID drag_dest = INVALID_VEHICLE);
|
||||||
|
void DrawRoadVehImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip = 0);
|
||||||
|
void DrawShipImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type);
|
||||||
|
void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type);
|
||||||
|
|
||||||
|
void ShowBuildVehicleWindow(TileIndex tile, VehicleType type);
|
||||||
|
|
||||||
|
uint ShowRefitOptionsList(int left, int right, int y, EngineID engine);
|
||||||
|
StringID GetCargoSubtypeText(const Vehicle *v);
|
||||||
|
|
||||||
|
void ShowVehicleListWindow(const Vehicle *v);
|
||||||
|
void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type);
|
||||||
|
void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, StationID station);
|
||||||
|
void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, TileIndex depot_tile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the height of a single vehicle in the GUIs.
|
||||||
|
* @param type the vehicle type to look at
|
||||||
|
* @return the height
|
||||||
|
*/
|
||||||
|
static inline uint GetVehicleHeight(VehicleType type)
|
||||||
|
{
|
||||||
|
return (type == VEH_TRAIN || type == VEH_ROAD) ? 14 : 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetVehicleWidth(Vehicle *v, EngineImageType image_type);
|
||||||
|
|
||||||
|
/** Dimensions of a cell in the purchase/depot windows. */
|
||||||
|
struct VehicleCellSize {
|
||||||
|
uint height; ///< Vehicle cell height.
|
||||||
|
uint extend_left; ///< Extend of the cell to the left.
|
||||||
|
uint extend_right; ///< Extend of the cell to the right.
|
||||||
|
};
|
||||||
|
|
||||||
|
VehicleCellSize GetVehicleImageCellSize(VehicleType type, EngineImageType image_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get WindowClass for vehicle list of given vehicle type
|
||||||
|
* @param vt vehicle type to check
|
||||||
|
* @return corresponding window class
|
||||||
|
* @note works only for company buildable vehicle types
|
||||||
|
*/
|
||||||
|
static inline WindowClass GetWindowClassForVehicleType(VehicleType vt)
|
||||||
|
{
|
||||||
|
switch (vt) {
|
||||||
|
default: NOT_REACHED();
|
||||||
|
case VEH_TRAIN: return WC_TRAINS_LIST;
|
||||||
|
case VEH_ROAD: return WC_ROADVEH_LIST;
|
||||||
|
case VEH_SHIP: return WC_SHIPS_LIST;
|
||||||
|
case VEH_AIRCRAFT: return WC_AIRCRAFT_LIST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unified window procedure */
|
||||||
|
void ShowVehicleViewWindow(const Vehicle *v);
|
||||||
|
bool VehicleClicked(const Vehicle *v);
|
||||||
|
void StartStopVehicle(const Vehicle *v, bool texteffect);
|
||||||
|
|
||||||
|
Vehicle *CheckClickOnVehicle(const struct ViewPort *vp, int x, int y);
|
||||||
|
|
||||||
|
void DrawVehicleImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip);
|
||||||
|
|
||||||
|
#endif /* VEHICLE_GUI_H */
|
||||||
868
src/video/sdl_v.cpp.orig
Normal file
868
src/video/sdl_v.cpp.orig
Normal file
@@ -0,0 +1,868 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 sdl_v.cpp Implementation of the SDL video driver. */
|
||||||
|
|
||||||
|
#ifdef WITH_SDL
|
||||||
|
|
||||||
|
#include "../stdafx.h"
|
||||||
|
#include "../openttd.h"
|
||||||
|
#include "../gfx_func.h"
|
||||||
|
#include "../sdl.h"
|
||||||
|
#include "../rev.h"
|
||||||
|
#include "../blitter/factory.hpp"
|
||||||
|
#include "../network/network.h"
|
||||||
|
#include "../thread/thread.h"
|
||||||
|
#include "../progress.h"
|
||||||
|
#include "../core/random_func.hpp"
|
||||||
|
#include "../core/math_func.hpp"
|
||||||
|
#include "../fileio_func.h"
|
||||||
|
#include "sdl_v.h"
|
||||||
|
#include <SDL.h>
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <SDL_screenkeyboard.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static FVideoDriver_SDL iFVideoDriver_SDL;
|
||||||
|
|
||||||
|
static SDL_Surface *_sdl_screen;
|
||||||
|
static SDL_Surface *_sdl_realscreen;
|
||||||
|
static bool _all_modes;
|
||||||
|
|
||||||
|
/** Whether the drawing is/may be done in a separate thread. */
|
||||||
|
static bool _draw_threaded;
|
||||||
|
/** Thread used to 'draw' to the screen, i.e. push data to the screen. */
|
||||||
|
static ThreadObject *_draw_thread = NULL;
|
||||||
|
/** Mutex to keep the access to the shared memory controlled. */
|
||||||
|
static ThreadMutex *_draw_mutex = NULL;
|
||||||
|
/** Should we keep continue drawing? */
|
||||||
|
static volatile bool _draw_continue;
|
||||||
|
static Palette _local_palette;
|
||||||
|
|
||||||
|
#define MAX_DIRTY_RECTS 100
|
||||||
|
static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS];
|
||||||
|
static int _num_dirty_rects;
|
||||||
|
static int _use_hwpalette;
|
||||||
|
static int _requested_hwpalette; /* Did we request a HWPALETTE for the current video mode? */
|
||||||
|
|
||||||
|
void VideoDriver_SDL::MakeDirty(int left, int top, int width, int height)
|
||||||
|
{
|
||||||
|
if (_num_dirty_rects < MAX_DIRTY_RECTS) {
|
||||||
|
_dirty_rects[_num_dirty_rects].x = left;
|
||||||
|
_dirty_rects[_num_dirty_rects].y = top;
|
||||||
|
_dirty_rects[_num_dirty_rects].w = width;
|
||||||
|
_dirty_rects[_num_dirty_rects].h = height;
|
||||||
|
}
|
||||||
|
_num_dirty_rects++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UpdatePalette(bool init = false)
|
||||||
|
{
|
||||||
|
SDL_Color pal[256];
|
||||||
|
|
||||||
|
for (int i = 0; i != _local_palette.count_dirty; i++) {
|
||||||
|
pal[i].r = _local_palette.palette[_local_palette.first_dirty + i].r;
|
||||||
|
pal[i].g = _local_palette.palette[_local_palette.first_dirty + i].g;
|
||||||
|
pal[i].b = _local_palette.palette[_local_palette.first_dirty + i].b;
|
||||||
|
pal[i].unused = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_CALL SDL_SetColors(_sdl_screen, pal, _local_palette.first_dirty, _local_palette.count_dirty);
|
||||||
|
|
||||||
|
if (_sdl_screen != _sdl_realscreen && init) {
|
||||||
|
/* When using a shadow surface, also set our palette on the real screen. This lets SDL
|
||||||
|
* allocate as much colors (or approximations) as
|
||||||
|
* possible, instead of using only the default SDL
|
||||||
|
* palette. This allows us to get more colors exactly
|
||||||
|
* right and might allow using better approximations for
|
||||||
|
* other colors.
|
||||||
|
*
|
||||||
|
* Note that colors allocations are tried in-order, so
|
||||||
|
* this favors colors further up into the palette. Also
|
||||||
|
* note that if two colors from the same animation
|
||||||
|
* sequence are approximated using the same color, that
|
||||||
|
* animation will stop working.
|
||||||
|
*
|
||||||
|
* Since changing the system palette causes the colours
|
||||||
|
* to change right away, and allocations might
|
||||||
|
* drastically change, we can't use this for animation,
|
||||||
|
* since that could cause weird coloring between the
|
||||||
|
* palette change and the blitting below, so we only set
|
||||||
|
* the real palette during initialisation.
|
||||||
|
*/
|
||||||
|
SDL_CALL SDL_SetColors(_sdl_realscreen, pal, _local_palette.first_dirty, _local_palette.count_dirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sdl_screen != _sdl_realscreen && !init) {
|
||||||
|
/* We're not using real hardware palette, but are letting SDL
|
||||||
|
* approximate the palette during shadow -> screen copy. To
|
||||||
|
* change the palette, we need to recopy the entire screen.
|
||||||
|
*
|
||||||
|
* Note that this operation can slow down the rendering
|
||||||
|
* considerably, especially since changing the shadow
|
||||||
|
* palette will need the next blit to re-detect the
|
||||||
|
* best mapping of shadow palette colors to real palette
|
||||||
|
* colors from scratch.
|
||||||
|
*/
|
||||||
|
SDL_CALL SDL_BlitSurface(_sdl_screen, NULL, _sdl_realscreen, NULL);
|
||||||
|
SDL_CALL SDL_UpdateRect(_sdl_realscreen, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InitPalette()
|
||||||
|
{
|
||||||
|
_local_palette = _cur_palette;
|
||||||
|
_local_palette.first_dirty = 0;
|
||||||
|
_local_palette.count_dirty = 256;
|
||||||
|
UpdatePalette(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CheckPaletteAnim()
|
||||||
|
{
|
||||||
|
if (_cur_palette.count_dirty != 0) {
|
||||||
|
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
|
||||||
|
|
||||||
|
switch (blitter->UsePaletteAnimation()) {
|
||||||
|
case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
|
||||||
|
UpdatePalette();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Blitter::PALETTE_ANIMATION_BLITTER:
|
||||||
|
blitter->PaletteAnimate(_local_palette);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Blitter::PALETTE_ANIMATION_NONE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NOT_REACHED();
|
||||||
|
}
|
||||||
|
_cur_palette.count_dirty = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawSurfaceToScreen()
|
||||||
|
{
|
||||||
|
int n = _num_dirty_rects;
|
||||||
|
if (n == 0) return;
|
||||||
|
|
||||||
|
_num_dirty_rects = 0;
|
||||||
|
if (n > MAX_DIRTY_RECTS) {
|
||||||
|
if (_sdl_screen != _sdl_realscreen) {
|
||||||
|
SDL_CALL SDL_BlitSurface(_sdl_screen, NULL, _sdl_realscreen, NULL);
|
||||||
|
}
|
||||||
|
SDL_CALL SDL_UpdateRect(_sdl_realscreen, 0, 0, 0, 0);
|
||||||
|
} else {
|
||||||
|
if (_sdl_screen != _sdl_realscreen) {
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
SDL_CALL SDL_BlitSurface(_sdl_screen, &_dirty_rects[i], _sdl_realscreen, &_dirty_rects[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_CALL SDL_UpdateRects(_sdl_realscreen, n, _dirty_rects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawSurfaceToScreenThread(void *)
|
||||||
|
{
|
||||||
|
/* First tell the main thread we're started */
|
||||||
|
_draw_mutex->BeginCritical();
|
||||||
|
_draw_mutex->SendSignal();
|
||||||
|
|
||||||
|
/* Now wait for the first thing to draw! */
|
||||||
|
_draw_mutex->WaitForSignal();
|
||||||
|
|
||||||
|
while (_draw_continue) {
|
||||||
|
CheckPaletteAnim();
|
||||||
|
/* Then just draw and wait till we stop */
|
||||||
|
DrawSurfaceToScreen();
|
||||||
|
_draw_mutex->WaitForSignal();
|
||||||
|
}
|
||||||
|
|
||||||
|
_draw_mutex->EndCritical();
|
||||||
|
_draw_thread->Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Dimension _default_resolutions[] = {
|
||||||
|
{ 640, 480},
|
||||||
|
{ 800, 600},
|
||||||
|
{1024, 768},
|
||||||
|
{1152, 864},
|
||||||
|
{1280, 800},
|
||||||
|
{1280, 960},
|
||||||
|
{1280, 1024},
|
||||||
|
{1400, 1050},
|
||||||
|
{1600, 1200},
|
||||||
|
{1680, 1050},
|
||||||
|
{1920, 1200}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void GetVideoModes()
|
||||||
|
{
|
||||||
|
SDL_Rect **modes = SDL_CALL SDL_ListModes(NULL, SDL_SWSURFACE | SDL_FULLSCREEN);
|
||||||
|
if (modes == NULL) usererror("sdl: no modes available");
|
||||||
|
|
||||||
|
_all_modes = (SDL_CALL SDL_ListModes(NULL, SDL_SWSURFACE | (_fullscreen ? SDL_FULLSCREEN : 0)) == (void*)-1);
|
||||||
|
if (modes == (void*)-1) {
|
||||||
|
int n = 0;
|
||||||
|
for (uint i = 0; i < lengthof(_default_resolutions); i++) {
|
||||||
|
if (SDL_CALL SDL_VideoModeOK(_default_resolutions[i].width, _default_resolutions[i].height, 8, SDL_FULLSCREEN) != 0) {
|
||||||
|
_resolutions[n] = _default_resolutions[i];
|
||||||
|
if (++n == lengthof(_resolutions)) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_num_resolutions = n;
|
||||||
|
} else {
|
||||||
|
int n = 0;
|
||||||
|
for (int i = 0; modes[i]; i++) {
|
||||||
|
uint w = modes[i]->w;
|
||||||
|
uint h = modes[i]->h;
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < n; j++) {
|
||||||
|
if (_resolutions[j].width == w && _resolutions[j].height == h) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == n) {
|
||||||
|
_resolutions[j].width = w;
|
||||||
|
_resolutions[j].height = h;
|
||||||
|
if (++n == lengthof(_resolutions)) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_num_resolutions = n;
|
||||||
|
SortResolutions(_num_resolutions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetAvailableVideoMode(uint *w, uint *h)
|
||||||
|
{
|
||||||
|
/* All modes available? */
|
||||||
|
if (_all_modes || _num_resolutions == 0) return;
|
||||||
|
|
||||||
|
/* Is the wanted mode among the available modes? */
|
||||||
|
for (int i = 0; i != _num_resolutions; i++) {
|
||||||
|
if (*w == _resolutions[i].width && *h == _resolutions[i].height) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use the closest possible resolution */
|
||||||
|
int best = 0;
|
||||||
|
uint delta = Delta(_resolutions[0].width, *w) * Delta(_resolutions[0].height, *h);
|
||||||
|
for (int i = 1; i != _num_resolutions; ++i) {
|
||||||
|
uint newdelta = Delta(_resolutions[i].width, *w) * Delta(_resolutions[i].height, *h);
|
||||||
|
if (newdelta < delta) {
|
||||||
|
best = i;
|
||||||
|
delta = newdelta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*w = _resolutions[best].width;
|
||||||
|
*h = _resolutions[best].height;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/* Let's redefine the LoadBMP macro with because we are dynamically
|
||||||
|
* loading SDL and need to 'SDL_CALL' all functions */
|
||||||
|
#undef SDL_LoadBMP
|
||||||
|
#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_CALL SDL_RWFromFile(file, "rb"), 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool VideoDriver_SDL::CreateMainSurface(uint w, uint h)
|
||||||
|
{
|
||||||
|
SDL_Surface *newscreen, *icon;
|
||||||
|
char caption[50];
|
||||||
|
int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth();
|
||||||
|
bool want_hwpalette;
|
||||||
|
|
||||||
|
GetAvailableVideoMode(&w, &h);
|
||||||
|
|
||||||
|
DEBUG(driver, 1, "SDL: using mode %ux%ux%d", w, h, bpp);
|
||||||
|
|
||||||
|
if (bpp == 0) usererror("Can't use a blitter that blits 0 bpp for normal visuals");
|
||||||
|
|
||||||
|
char icon_path[MAX_PATH];
|
||||||
|
if (FioFindFullPath(icon_path, lengthof(icon_path), BASESET_DIR, "openttd.32.bmp") != NULL) {
|
||||||
|
/* Give the application an icon */
|
||||||
|
icon = SDL_CALL SDL_LoadBMP(icon_path);
|
||||||
|
if (icon != NULL) {
|
||||||
|
/* Get the colourkey, which will be magenta */
|
||||||
|
uint32 rgbmap = SDL_CALL SDL_MapRGB(icon->format, 255, 0, 255);
|
||||||
|
|
||||||
|
SDL_CALL SDL_SetColorKey(icon, SDL_SRCCOLORKEY, rgbmap);
|
||||||
|
SDL_CALL SDL_WM_SetIcon(icon, NULL);
|
||||||
|
SDL_CALL SDL_FreeSurface(icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_use_hwpalette == 2) {
|
||||||
|
/* Default is to autodetect when to use SDL_HWPALETTE.
|
||||||
|
* In this case, SDL_HWPALETTE is only used for 8bpp
|
||||||
|
* blitters in fullscreen.
|
||||||
|
*
|
||||||
|
* When using an 8bpp blitter on a 8bpp system in
|
||||||
|
* windowed mode with SDL_HWPALETTE, OpenTTD will claim
|
||||||
|
* the system palette, making all other applications
|
||||||
|
* get the wrong colours. In this case, we're better of
|
||||||
|
* trying to approximate the colors we need using system
|
||||||
|
* colors, using a shadow surface (see below).
|
||||||
|
*
|
||||||
|
* On a 32bpp system, SDL_HWPALETTE is ignored, so it
|
||||||
|
* doesn't matter what we do.
|
||||||
|
*
|
||||||
|
* When using a 32bpp blitter on a 8bpp system, setting
|
||||||
|
* SDL_HWPALETTE messes up rendering (at least on X11),
|
||||||
|
* so we don't do that. In this case, SDL takes care of
|
||||||
|
* color approximation using its own shadow surface
|
||||||
|
* (which we can't force in 8bpp on 8bpp mode,
|
||||||
|
* unfortunately).
|
||||||
|
*/
|
||||||
|
want_hwpalette = (bpp == 8 && _fullscreen);
|
||||||
|
} else {
|
||||||
|
/* User specified a value manually */
|
||||||
|
want_hwpalette = _use_hwpalette;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (want_hwpalette) DEBUG(driver, 1, "SDL: requesting hardware palete");
|
||||||
|
|
||||||
|
/* Free any previously allocated shadow surface */
|
||||||
|
if (_sdl_screen != NULL && _sdl_screen != _sdl_realscreen) SDL_CALL SDL_FreeSurface(_sdl_screen);
|
||||||
|
|
||||||
|
if (_sdl_realscreen != NULL) {
|
||||||
|
if (_requested_hwpalette != want_hwpalette) {
|
||||||
|
/* SDL (at least the X11 driver), reuses the
|
||||||
|
* same window and palette settings when the bpp
|
||||||
|
* (and a few flags) are the same. Since we need
|
||||||
|
* to hwpalette value to change (in particular
|
||||||
|
* when switching between fullscreen and
|
||||||
|
* windowed), we restart the entire video
|
||||||
|
* subsystem to force creating a new window.
|
||||||
|
*/
|
||||||
|
DEBUG(driver, 0, "SDL: Restarting SDL video subsystem, to force hwpalette change");
|
||||||
|
SDL_CALL SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||||
|
SDL_CALL SDL_InitSubSystem(SDL_INIT_VIDEO);
|
||||||
|
ClaimMousePointer();
|
||||||
|
SetupKeyboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Remember if we wanted a hwpalette. We can't reliably query
|
||||||
|
* SDL for the SDL_HWPALETTE flag, since it might get set even
|
||||||
|
* though we didn't ask for it (when SDL creates a shadow
|
||||||
|
* surface, for example). */
|
||||||
|
_requested_hwpalette = want_hwpalette;
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
SDL_Rect r;
|
||||||
|
r.h = SDL_ListModes(NULL, 0)[0]->h / 10;
|
||||||
|
r.w = r.h;
|
||||||
|
r.x = SDL_ListModes(NULL, 0)[0]->w - r.w;
|
||||||
|
r.y = SDL_ListModes(NULL, 0)[0]->h - r.h;
|
||||||
|
SDL_ANDROID_SetScreenKeyboardButtonPos(SDL_ANDROID_SCREENKEYBOARD_BUTTON_TEXT, &r);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DO NOT CHANGE TO HWSURFACE, IT DOES NOT WORK */
|
||||||
|
newscreen = SDL_CALL SDL_SetVideoMode(w, h, bpp, SDL_SWSURFACE | (want_hwpalette ? SDL_HWPALETTE : 0) | (_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE));
|
||||||
|
if (newscreen == NULL) {
|
||||||
|
DEBUG(driver, 0, "SDL: Couldn't allocate a window to draw on");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_sdl_realscreen = newscreen;
|
||||||
|
|
||||||
|
if (bpp == 8 && (_sdl_realscreen->flags & SDL_HWPALETTE) != SDL_HWPALETTE) {
|
||||||
|
/* Using an 8bpp blitter, if we didn't get a hardware
|
||||||
|
* palette (most likely because we didn't request one,
|
||||||
|
* see above), we'll have to set up a shadow surface to
|
||||||
|
* render on.
|
||||||
|
*
|
||||||
|
* Our palette will be applied to this shadow surface,
|
||||||
|
* while the real screen surface will use the shared
|
||||||
|
* system palette (which will partly contain our colors,
|
||||||
|
* but most likely will not have enough free color cells
|
||||||
|
* for all of our colors). SDL can use these two
|
||||||
|
* palettes at blit time to approximate colors used in
|
||||||
|
* the shadow surface using system colors automatically.
|
||||||
|
*
|
||||||
|
* Note that when using an 8bpp blitter on a 32bpp
|
||||||
|
* system, SDL will create an internal shadow surface.
|
||||||
|
* This shadow surface will have SDL_HWPALLETE set, so
|
||||||
|
* we won't create a second shadow surface in this case.
|
||||||
|
*/
|
||||||
|
DEBUG(driver, 1, "SDL: using shadow surface");
|
||||||
|
newscreen = SDL_CALL SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp, 0, 0, 0, 0);
|
||||||
|
if (newscreen == NULL) {
|
||||||
|
DEBUG(driver, 0, "SDL: Couldn't allocate a shadow surface to draw on");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delay drawing for this cycle; the next cycle will redraw the whole screen */
|
||||||
|
_num_dirty_rects = 0;
|
||||||
|
|
||||||
|
_screen.width = newscreen->w;
|
||||||
|
_screen.height = newscreen->h;
|
||||||
|
_screen.pitch = newscreen->pitch / (bpp / 8);
|
||||||
|
_screen.dst_ptr = newscreen->pixels;
|
||||||
|
_sdl_screen = newscreen;
|
||||||
|
|
||||||
|
/* When in full screen, we will always have the mouse cursor
|
||||||
|
* within the window, even though SDL does not give us the
|
||||||
|
* appropriate event to know this. */
|
||||||
|
if (_fullscreen) _cursor.in_window = true;
|
||||||
|
|
||||||
|
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
|
||||||
|
blitter->PostResize();
|
||||||
|
|
||||||
|
InitPalette();
|
||||||
|
switch (blitter->UsePaletteAnimation()) {
|
||||||
|
case Blitter::PALETTE_ANIMATION_NONE:
|
||||||
|
case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
|
||||||
|
UpdatePalette();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Blitter::PALETTE_ANIMATION_BLITTER:
|
||||||
|
if (_video_driver != NULL) blitter->PaletteAnimate(_local_palette);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision);
|
||||||
|
SDL_CALL SDL_WM_SetCaption(caption, caption);
|
||||||
|
|
||||||
|
GameSizeChanged();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoDriver_SDL::ClaimMousePointer()
|
||||||
|
{
|
||||||
|
SDL_CALL SDL_ShowCursor(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VkMapping {
|
||||||
|
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||||
|
SDL_Keycode vk_from;
|
||||||
|
#else
|
||||||
|
uint16 vk_from;
|
||||||
|
#endif
|
||||||
|
byte vk_count;
|
||||||
|
byte map_to;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AS(x, z) {x, 0, z}
|
||||||
|
#define AM(x, y, z, w) {x, (byte)(y - x), z}
|
||||||
|
|
||||||
|
static const VkMapping _vk_mapping[] = {
|
||||||
|
/* Pageup stuff + up/down */
|
||||||
|
AM(SDLK_PAGEUP, SDLK_PAGEDOWN, WKC_PAGEUP, WKC_PAGEDOWN),
|
||||||
|
AS(SDLK_UP, WKC_UP),
|
||||||
|
AS(SDLK_DOWN, WKC_DOWN),
|
||||||
|
AS(SDLK_LEFT, WKC_LEFT),
|
||||||
|
AS(SDLK_RIGHT, WKC_RIGHT),
|
||||||
|
|
||||||
|
AS(SDLK_HOME, WKC_HOME),
|
||||||
|
AS(SDLK_END, WKC_END),
|
||||||
|
|
||||||
|
AS(SDLK_INSERT, WKC_INSERT),
|
||||||
|
AS(SDLK_DELETE, WKC_DELETE),
|
||||||
|
|
||||||
|
/* Map letters & digits */
|
||||||
|
AM(SDLK_a, SDLK_z, 'A', 'Z'),
|
||||||
|
AM(SDLK_0, SDLK_9, '0', '9'),
|
||||||
|
|
||||||
|
AS(SDLK_ESCAPE, WKC_ESC),
|
||||||
|
AS(SDLK_PAUSE, WKC_PAUSE),
|
||||||
|
AS(SDLK_BACKSPACE, WKC_BACKSPACE),
|
||||||
|
|
||||||
|
AS(SDLK_SPACE, WKC_SPACE),
|
||||||
|
AS(SDLK_RETURN, WKC_RETURN),
|
||||||
|
AS(SDLK_TAB, WKC_TAB),
|
||||||
|
|
||||||
|
/* Function keys */
|
||||||
|
AM(SDLK_F1, SDLK_F12, WKC_F1, WKC_F12),
|
||||||
|
|
||||||
|
/* Numeric part. */
|
||||||
|
AM(SDLK_KP0, SDLK_KP9, '0', '9'),
|
||||||
|
AS(SDLK_KP_DIVIDE, WKC_NUM_DIV),
|
||||||
|
AS(SDLK_KP_MULTIPLY, WKC_NUM_MUL),
|
||||||
|
AS(SDLK_KP_MINUS, WKC_NUM_MINUS),
|
||||||
|
AS(SDLK_KP_PLUS, WKC_NUM_PLUS),
|
||||||
|
AS(SDLK_KP_ENTER, WKC_NUM_ENTER),
|
||||||
|
AS(SDLK_KP_PERIOD, WKC_NUM_DECIMAL),
|
||||||
|
|
||||||
|
/* Other non-letter keys */
|
||||||
|
AS(SDLK_SLASH, WKC_SLASH),
|
||||||
|
AS(SDLK_SEMICOLON, WKC_SEMICOLON),
|
||||||
|
AS(SDLK_EQUALS, WKC_EQUALS),
|
||||||
|
AS(SDLK_LEFTBRACKET, WKC_L_BRACKET),
|
||||||
|
AS(SDLK_BACKSLASH, WKC_BACKSLASH),
|
||||||
|
AS(SDLK_RIGHTBRACKET, WKC_R_BRACKET),
|
||||||
|
|
||||||
|
AS(SDLK_QUOTE, WKC_SINGLEQUOTE),
|
||||||
|
AS(SDLK_COMMA, WKC_COMMA),
|
||||||
|
AS(SDLK_MINUS, WKC_MINUS),
|
||||||
|
AS(SDLK_PERIOD, WKC_PERIOD)
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint ConvertSdlKeyIntoMy(SDL_keysym *sym, WChar *character)
|
||||||
|
{
|
||||||
|
const VkMapping *map;
|
||||||
|
uint key = 0;
|
||||||
|
|
||||||
|
for (map = _vk_mapping; map != endof(_vk_mapping); ++map) {
|
||||||
|
if ((uint)(sym->sym - map->vk_from) <= map->vk_count) {
|
||||||
|
key = sym->sym - map->vk_from + map->map_to;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check scancode for BACKQUOTE key, because we want the key left of "1", not anything else (on non-US keyboards) */
|
||||||
|
#if defined(WIN32) || defined(__OS2__)
|
||||||
|
if (sym->scancode == 41) key = WKC_BACKQUOTE;
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
if (sym->scancode == 10) key = WKC_BACKQUOTE;
|
||||||
|
#elif defined(__MORPHOS__)
|
||||||
|
if (sym->scancode == 0) key = WKC_BACKQUOTE; // yes, that key is code '0' under MorphOS :)
|
||||||
|
#elif defined(__BEOS__)
|
||||||
|
if (sym->scancode == 17) key = WKC_BACKQUOTE;
|
||||||
|
#elif defined(__SVR4) && defined(__sun)
|
||||||
|
if (sym->scancode == 60) key = WKC_BACKQUOTE;
|
||||||
|
if (sym->scancode == 49) key = WKC_BACKSPACE;
|
||||||
|
#elif defined(__sgi__)
|
||||||
|
if (sym->scancode == 22) key = WKC_BACKQUOTE;
|
||||||
|
#elif defined(__ANDROID__)
|
||||||
|
if (sym->scancode == SDLK_BACKQUOTE) key = WKC_BACKQUOTE;
|
||||||
|
#else
|
||||||
|
if (sym->scancode == 49) key = WKC_BACKQUOTE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* META are the command keys on mac */
|
||||||
|
if (sym->mod & KMOD_META) key |= WKC_META;
|
||||||
|
if (sym->mod & KMOD_SHIFT) key |= WKC_SHIFT;
|
||||||
|
if (sym->mod & KMOD_CTRL) key |= WKC_CTRL;
|
||||||
|
if (sym->mod & KMOD_ALT) key |= WKC_ALT;
|
||||||
|
|
||||||
|
*character = sym->unicode;
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
int VideoDriver_SDL::PollEvent()
|
||||||
|
{
|
||||||
|
SDL_Event ev;
|
||||||
|
|
||||||
|
if (!SDL_CALL SDL_PollEvent(&ev)) return -2;
|
||||||
|
|
||||||
|
switch (ev.type) {
|
||||||
|
case SDL_MOUSEMOTION:
|
||||||
|
if (_cursor.fix_at) {
|
||||||
|
int dx = ev.motion.x - _cursor.pos.x;
|
||||||
|
int dy = ev.motion.y - _cursor.pos.y;
|
||||||
|
if (dx != 0 || dy != 0) {
|
||||||
|
_cursor.delta.x = dx;
|
||||||
|
_cursor.delta.y = dy;
|
||||||
|
SDL_CALL SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_cursor.delta.x = ev.motion.x - _cursor.pos.x;
|
||||||
|
_cursor.delta.y = ev.motion.y - _cursor.pos.y;
|
||||||
|
_cursor.pos.x = ev.motion.x;
|
||||||
|
_cursor.pos.y = ev.motion.y;
|
||||||
|
_cursor.dirty = true;
|
||||||
|
}
|
||||||
|
HandleMouseEvents();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
if (_rightclick_emulate && SDL_CALL SDL_GetModState() & KMOD_CTRL) {
|
||||||
|
ev.button.button = SDL_BUTTON_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ev.button.button) {
|
||||||
|
case SDL_BUTTON_LEFT:
|
||||||
|
_left_button_down = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_BUTTON_RIGHT:
|
||||||
|
_right_button_down = true;
|
||||||
|
_right_button_clicked = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_BUTTON_WHEELUP: _cursor.wheel--; break;
|
||||||
|
case SDL_BUTTON_WHEELDOWN: _cursor.wheel++; break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
HandleMouseEvents();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_MOUSEBUTTONUP:
|
||||||
|
if (_rightclick_emulate) {
|
||||||
|
_right_button_down = false;
|
||||||
|
_left_button_down = false;
|
||||||
|
_left_button_clicked = false;
|
||||||
|
} else if (ev.button.button == SDL_BUTTON_LEFT) {
|
||||||
|
_left_button_down = false;
|
||||||
|
_left_button_clicked = false;
|
||||||
|
} else if (ev.button.button == SDL_BUTTON_RIGHT) {
|
||||||
|
_right_button_down = false;
|
||||||
|
}
|
||||||
|
HandleMouseEvents();
|
||||||
|
break;
|
||||||
|
#ifndef __ANDROID__
|
||||||
|
case SDL_ACTIVEEVENT:
|
||||||
|
if (!(ev.active.state & SDL_APPMOUSEFOCUS)) break;
|
||||||
|
|
||||||
|
if (ev.active.gain) { // mouse entered the window, enable cursor
|
||||||
|
_cursor.in_window = true;
|
||||||
|
} else {
|
||||||
|
UndrawMouseCursor(); // mouse left the window, undraw cursor
|
||||||
|
_cursor.in_window = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* not __ANDROID__ */
|
||||||
|
case SDL_QUIT:
|
||||||
|
HandleExitGameRequest();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_KEYDOWN: // Toggle full-screen on ALT + ENTER/F
|
||||||
|
if ((ev.key.keysym.mod & (KMOD_ALT | KMOD_META)) &&
|
||||||
|
(ev.key.keysym.sym == SDLK_RETURN || ev.key.keysym.sym == SDLK_f)) {
|
||||||
|
ToggleFullScreen(!_fullscreen);
|
||||||
|
} else {
|
||||||
|
WChar character;
|
||||||
|
uint keycode = ConvertSdlKeyIntoMy(&ev.key.keysym, &character);
|
||||||
|
HandleKeypress(keycode, character);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#ifndef __ANDROID__
|
||||||
|
case SDL_VIDEORESIZE: {
|
||||||
|
int w = max(ev.resize.w, 64);
|
||||||
|
int h = max(ev.resize.h, 64);
|
||||||
|
CreateMainSurface(w, h);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* not __ANDROID__ */
|
||||||
|
case SDL_VIDEOEXPOSE: {
|
||||||
|
/* Force a redraw of the entire screen. Note
|
||||||
|
* that SDL 1.2 seems to do this automatically
|
||||||
|
* in most cases, but 1.3 / 2.0 does not. */
|
||||||
|
_num_dirty_rects = MAX_DIRTY_RECTS + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *VideoDriver_SDL::Start(const char * const *parm)
|
||||||
|
{
|
||||||
|
char buf[30];
|
||||||
|
_use_hwpalette = GetDriverParamInt(parm, "hw_palette", 2);
|
||||||
|
|
||||||
|
const char *s = SdlOpen(SDL_INIT_VIDEO);
|
||||||
|
if (s != NULL) return s;
|
||||||
|
|
||||||
|
GetVideoModes();
|
||||||
|
if (!CreateMainSurface(_cur_resolution.width, _cur_resolution.height)) {
|
||||||
|
return SDL_CALL SDL_GetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_CALL SDL_VideoDriverName(buf, sizeof buf);
|
||||||
|
DEBUG(driver, 1, "SDL: using driver '%s'", buf);
|
||||||
|
|
||||||
|
MarkWholeScreenDirty();
|
||||||
|
SetupKeyboard();
|
||||||
|
|
||||||
|
_draw_threaded = GetDriverParam(parm, "no_threads") == NULL && GetDriverParam(parm, "no_thread") == NULL;
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
_draw_threaded = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoDriver_SDL::SetupKeyboard()
|
||||||
|
{
|
||||||
|
SDL_CALL SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
|
||||||
|
SDL_CALL SDL_EnableUNICODE(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoDriver_SDL::Stop()
|
||||||
|
{
|
||||||
|
SdlClose(SDL_INIT_VIDEO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoDriver_SDL::MainLoop()
|
||||||
|
{
|
||||||
|
uint32 cur_ticks = SDL_CALL SDL_GetTicks();
|
||||||
|
uint32 last_cur_ticks = cur_ticks;
|
||||||
|
uint32 next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
||||||
|
uint32 mod;
|
||||||
|
int numkeys;
|
||||||
|
Uint8 *keys;
|
||||||
|
|
||||||
|
CheckPaletteAnim();
|
||||||
|
|
||||||
|
if (_draw_threaded) {
|
||||||
|
/* Initialise the mutex first, because that's the thing we *need*
|
||||||
|
* directly in the newly created thread. */
|
||||||
|
_draw_mutex = ThreadMutex::New();
|
||||||
|
if (_draw_mutex == NULL) {
|
||||||
|
_draw_threaded = false;
|
||||||
|
} else {
|
||||||
|
_draw_mutex->BeginCritical();
|
||||||
|
_draw_continue = true;
|
||||||
|
|
||||||
|
_draw_threaded = ThreadObject::New(&DrawSurfaceToScreenThread, NULL, &_draw_thread);
|
||||||
|
|
||||||
|
/* Free the mutex if we won't be able to use it. */
|
||||||
|
if (!_draw_threaded) {
|
||||||
|
_draw_mutex->EndCritical();
|
||||||
|
delete _draw_mutex;
|
||||||
|
_draw_mutex = NULL;
|
||||||
|
} else {
|
||||||
|
/* Wait till the draw mutex has started itself. */
|
||||||
|
_draw_mutex->WaitForSignal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(driver, 1, "SDL: using %sthreads", _draw_threaded ? "" : "no ");
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
|
||||||
|
InteractiveRandom(); // randomness
|
||||||
|
|
||||||
|
while (PollEvent() == -1) {}
|
||||||
|
if (_exit_game) break;
|
||||||
|
|
||||||
|
mod = SDL_CALL SDL_GetModState();
|
||||||
|
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||||
|
keys = SDL_CALL SDL_GetKeyboardState(&numkeys);
|
||||||
|
#else
|
||||||
|
keys = SDL_CALL SDL_GetKeyState(&numkeys);
|
||||||
|
#endif
|
||||||
|
#if defined(_DEBUG)
|
||||||
|
if (_shift_pressed)
|
||||||
|
#else
|
||||||
|
/* Speedup when pressing tab, except when using ALT+TAB
|
||||||
|
* to switch to another application */
|
||||||
|
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||||
|
if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0)
|
||||||
|
#else
|
||||||
|
if (keys[SDLK_TAB] && (mod & KMOD_ALT) == 0)
|
||||||
|
#endif /* SDL_VERSION_ATLEAST(1, 3, 0) */
|
||||||
|
#endif /* defined(_DEBUG) */
|
||||||
|
{
|
||||||
|
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
|
||||||
|
} else if (_fast_forward & 2) {
|
||||||
|
_fast_forward = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_ticks = SDL_CALL SDL_GetTicks();
|
||||||
|
if (cur_ticks >= next_tick || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) {
|
||||||
|
_realtime_tick += cur_ticks - last_cur_ticks;
|
||||||
|
last_cur_ticks = cur_ticks;
|
||||||
|
next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
||||||
|
|
||||||
|
bool old_ctrl_pressed = _ctrl_pressed;
|
||||||
|
|
||||||
|
_ctrl_pressed = !!(mod & KMOD_CTRL);
|
||||||
|
_shift_pressed = !!(mod & KMOD_SHIFT);
|
||||||
|
|
||||||
|
/* determine which directional keys are down */
|
||||||
|
_dirkeys =
|
||||||
|
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||||
|
(keys[SDL_SCANCODE_LEFT] ? 1 : 0) |
|
||||||
|
(keys[SDL_SCANCODE_UP] ? 2 : 0) |
|
||||||
|
(keys[SDL_SCANCODE_RIGHT] ? 4 : 0) |
|
||||||
|
(keys[SDL_SCANCODE_DOWN] ? 8 : 0);
|
||||||
|
#else
|
||||||
|
(keys[SDLK_LEFT] ? 1 : 0) |
|
||||||
|
(keys[SDLK_UP] ? 2 : 0) |
|
||||||
|
(keys[SDLK_RIGHT] ? 4 : 0) |
|
||||||
|
(keys[SDLK_DOWN] ? 8 : 0);
|
||||||
|
#endif
|
||||||
|
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
|
||||||
|
|
||||||
|
/* The gameloop is the part that can run asynchronously. The rest
|
||||||
|
* except sleeping can't. */
|
||||||
|
if (_draw_mutex != NULL) _draw_mutex->EndCritical();
|
||||||
|
|
||||||
|
GameLoop();
|
||||||
|
|
||||||
|
if (_draw_mutex != NULL) _draw_mutex->BeginCritical();
|
||||||
|
|
||||||
|
UpdateWindows();
|
||||||
|
_local_palette = _cur_palette;
|
||||||
|
} else {
|
||||||
|
/* Release the thread while sleeping */
|
||||||
|
if (_draw_mutex != NULL) _draw_mutex->EndCritical();
|
||||||
|
CSleep(1);
|
||||||
|
if (_draw_mutex != NULL) _draw_mutex->BeginCritical();
|
||||||
|
|
||||||
|
NetworkDrawChatMessage();
|
||||||
|
DrawMouseCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End of the critical part. */
|
||||||
|
if (_draw_mutex != NULL && !HasModalProgress()) {
|
||||||
|
_draw_mutex->SendSignal();
|
||||||
|
} else {
|
||||||
|
/* Oh, we didn't have threads, then just draw unthreaded */
|
||||||
|
CheckPaletteAnim();
|
||||||
|
DrawSurfaceToScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_draw_mutex != NULL) {
|
||||||
|
_draw_continue = false;
|
||||||
|
/* Sending signal if there is no thread blocked
|
||||||
|
* is very valid and results in noop */
|
||||||
|
_draw_mutex->SendSignal();
|
||||||
|
_draw_mutex->EndCritical();
|
||||||
|
_draw_thread->Join();
|
||||||
|
|
||||||
|
delete _draw_mutex;
|
||||||
|
delete _draw_thread;
|
||||||
|
|
||||||
|
_draw_mutex = NULL;
|
||||||
|
_draw_thread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoDriver_SDL::ChangeResolution(int w, int h)
|
||||||
|
{
|
||||||
|
if (_draw_mutex != NULL) _draw_mutex->BeginCritical(true);
|
||||||
|
bool ret = CreateMainSurface(w, h);
|
||||||
|
if (_draw_mutex != NULL) _draw_mutex->EndCritical(true);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoDriver_SDL::ToggleFullscreen(bool fullscreen)
|
||||||
|
{
|
||||||
|
if (_draw_mutex != NULL) _draw_mutex->BeginCritical(true);
|
||||||
|
_fullscreen = fullscreen;
|
||||||
|
GetVideoModes(); // get the list of available video modes
|
||||||
|
bool ret = _num_resolutions != 0 && CreateMainSurface(_cur_resolution.width, _cur_resolution.height);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
/* switching resolution failed, put back full_screen to original status */
|
||||||
|
_fullscreen ^= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_draw_mutex != NULL) _draw_mutex->EndCritical(true);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoDriver_SDL::AfterBlitterChange()
|
||||||
|
{
|
||||||
|
if (_draw_mutex != NULL) _draw_mutex->BeginCritical(true);
|
||||||
|
bool ret = CreateMainSurface(_screen.width, _screen.height);
|
||||||
|
if (_draw_mutex != NULL) _draw_mutex->EndCritical(true);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_SDL */
|
||||||
3012
src/viewport.cpp.orig
Normal file
3012
src/viewport.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
2938
src/widget.cpp.orig
Normal file
2938
src/widget.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
3515
src/window.cpp.orig
Normal file
3515
src/window.cpp.orig
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user