Removing leftovers of my sloppy merging
This commit is contained in:
@@ -1,574 +0,0 @@
|
||||
/* $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;
|
||||
}
|
||||
@@ -1,624 +0,0 @@
|
||||
/* $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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,432 +0,0 @@
|
||||
/* $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
1697
src/gfx.cpp.orig
File diff suppressed because it is too large
Load Diff
@@ -1,226 +0,0 @@
|
||||
/* $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 */
|
||||
@@ -1,891 +0,0 @@
|
||||
/* $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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,459 +0,0 @@
|
||||
/* $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 key_width = HALF_KEY_WIDTH + (INTER_KEY_SPACE + HALF_KEY_WIDTH) * (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), 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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,257 +0,0 @@
|
||||
/* $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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
||||
--- src/settings.cpp
|
||||
+++ src/settings.cpp
|
||||
@@ -1092,7 +1092,7 @@
|
||||
|
||||
static bool TouchscreenModeChanged(int32 p1)
|
||||
{
|
||||
- //ResetTabletWindow();
|
||||
+ ResetTabletWindow();
|
||||
return true;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,192 +0,0 @@
|
||||
/* $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 */
|
||||
@@ -1,534 +0,0 @@
|
||||
/* $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 */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,760 +0,0 @@
|
||||
/* $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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,104 +0,0 @@
|
||||
/* $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 */
|
||||
@@ -1,868 +0,0 @@
|
||||
/* $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 */
|
||||
File diff suppressed because it is too large
Load Diff
2932
src/widget.cpp.orig
2932
src/widget.cpp.orig
File diff suppressed because it is too large
Load Diff
3515
src/window.cpp.orig
3515
src/window.cpp.orig
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user