diff --git a/.ottdrev b/.ottdrev
new file mode 100644
index 0000000000..38c021e62b
--- /dev/null
+++ b/.ottdrev
@@ -0,0 +1 @@
+1.4.2 26740 0 1.4.2
diff --git a/config.lib b/config.lib
index 72c8fb0dca..20d94b67d5 100644
--- a/config.lib
+++ b/config.lib
@@ -1035,7 +1035,7 @@ check_params() {
# of the tags folder, the folder of the tag does not have a .svn folder
# anymore and this fails to detect the subversion repository checkout.
log 1 "checking revision... svn detection (tag)"
- elif [ -d "$ROOT_DIR/.git" ] && [ -n "`git help 2>/dev/null`" ]; then
+ elif [ -e "$ROOT_DIR/.git" ] && [ -n "`git help 2>/dev/null`" ]; then
log 1 "checking revision... git detection"
elif [ -d "$ROOT_DIR/.hg" ] && [ -n "`HGPLAIN= hg help 2>/dev/null`" ]; then
log 1 "checking revision... hg detection"
diff --git a/findversion.sh b/findversion.sh
index 6be52b696f..1755388c5b 100755
--- a/findversion.sh
+++ b/findversion.sh
@@ -67,6 +67,12 @@ fi
cd `dirname "$0"`
ROOT_DIR=`pwd`
+# Override version number, to allow OpenTTD with Android modifications to connect to official servers
+if [ -e $ROOT_DIR/version-override ]; then
+ cat $ROOT_DIR/version-override
+ exit
+fi
+
# Determine if we are using a modified version
# Assume the dir is not modified
MODIFIED="0"
@@ -84,7 +90,7 @@ if [ -d "$ROOT_DIR/.svn" ] || [ -d "$ROOT_DIR/../.svn" ]; then
else
REV="r$REV_NR"
fi
-elif [ -d "$ROOT_DIR/.git" ]; then
+elif [ -e "$ROOT_DIR/.git" ]; then
# We are a git checkout
# Refresh the index to make sure file stat info is in sync, then look for modifications
git update-index --refresh >/dev/null
@@ -134,6 +140,7 @@ else
REV_NR=""
fi
+MODIFIED="0" # This prevents Andorid build from connecting to a public servers
if [ "$MODIFIED" -eq "2" ]; then
REV="${REV}M"
fi
diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj
index cfff536145..868fe6fd00 100644
--- a/projects/openttd_vs100.vcxproj
+++ b/projects/openttd_vs100.vcxproj
@@ -626,6 +626,7 @@
+
diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters
index b5dcdfc5a5..5b58d29719 100644
--- a/projects/openttd_vs100.vcxproj.filters
+++ b/projects/openttd_vs100.vcxproj.filters
@@ -1107,6 +1107,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj
index 17c2d8d4f1..377064da1e 100644
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -1778,6 +1778,10 @@
RelativePath=".\..\src\timetable.h"
>
+
+
diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj
index 666760ce78..d77cc0fc28 100644
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -1775,6 +1775,10 @@
RelativePath=".\..\src\timetable.h"
>
+
+
diff --git a/source.list b/source.list
index 3b66ab9fca..6ed9b881d5 100644
--- a/source.list
+++ b/source.list
@@ -93,6 +93,7 @@ tgp.cpp
tile_map.cpp
tilearea.cpp
townname.cpp
+tutorial_gui.cpp
#if WIN32
#else
#if WINCE
@@ -365,6 +366,7 @@ tilehighlight_func.h
tilehighlight_type.h
tilematrix_type.hpp
timetable.h
+toolbar_type.h
toolbar_gui.h
town.h
town_type.h
@@ -905,6 +907,12 @@ script/api/script_window.cpp
# Blitters
#if DEDICATED
#else
+blitter/16bpp_base.cpp
+blitter/16bpp_base.hpp
+blitter/16bpp_anim.cpp
+blitter/16bpp_anim.hpp
+blitter/16bpp_simple.cpp
+blitter/16bpp_simple.hpp
blitter/32bpp_anim.cpp
blitter/32bpp_anim.hpp
#if SSE
diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp
index 0c557d790b..6652ebe159 100644
--- a/src/ai/ai_gui.cpp
+++ b/src/ai/ai_gui.cpp
@@ -108,7 +108,7 @@ struct AIListWindow : public Window {
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
{
if (widget == WID_AIL_LIST) {
- this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
+ this->line_height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM);
resize->width = 1;
resize->height = this->line_height;
@@ -121,16 +121,16 @@ struct AIListWindow : public Window {
switch (widget) {
case WID_AIL_LIST: {
/* Draw a list of all available AIs. */
- int y = this->GetWidget(WID_AIL_LIST)->pos_y;
+ int y = Center(r.top, this->line_height);
/* First AI in the list is hardcoded to random */
if (this->vscroll->IsVisible(0)) {
- DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_LEFT, y + WD_MATRIX_TOP, this->slot == OWNER_DEITY ? STR_AI_CONFIG_NONE : STR_AI_CONFIG_RANDOM_AI, this->selected == -1 ? TC_WHITE : TC_ORANGE);
+ DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_LEFT, y, this->slot == OWNER_DEITY ? STR_AI_CONFIG_NONE : STR_AI_CONFIG_RANDOM_AI, this->selected == -1 ? TC_WHITE : TC_ORANGE);
y += this->line_height;
}
ScriptInfoList::const_iterator it = this->info_list->begin();
for (int i = 1; it != this->info_list->end(); i++, it++) {
if (this->vscroll->IsVisible(i)) {
- DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, y + WD_MATRIX_TOP, (*it).second->GetName(), (this->selected == i - 1) ? TC_WHITE : TC_ORANGE);
+ DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, y, (*it).second->GetName(), (this->selected == i - 1) ? TC_WHITE : TC_ORANGE);
y += this->line_height;
}
}
@@ -368,7 +368,6 @@ struct AISettingsWindow : public Window {
uint text_left = r.left + (rtl ? WD_FRAMERECT_LEFT : SETTING_BUTTON_WIDTH + 8);
uint text_right = r.right - (rtl ? SETTING_BUTTON_WIDTH + 8 : WD_FRAMERECT_RIGHT);
-
int y = r.top;
int button_y_offset = (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
int text_y_offset = (this->line_height - FONT_HEIGHT_NORMAL) / 2;
@@ -661,39 +660,41 @@ static const NWidgetPart _nested_ai_config_widgets[] = {
NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_MAUVE, WID_AIC_BACKGROUND),
- NWidget(NWID_VERTICAL), SetPIP(4, 4, 4),
- NWidget(NWID_HORIZONTAL), SetPIP(7, 0, 7),
- NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_DECREASE), SetFill(0, 1), SetDataTip(AWV_DECREASE, STR_NULL),
- NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_INCREASE), SetFill(0, 1), SetDataTip(AWV_INCREASE, STR_NULL),
- NWidget(NWID_SPACER), SetMinimalSize(6, 0),
- NWidget(WWT_TEXT, COLOUR_MAUVE, WID_AIC_NUMBER), SetDataTip(STR_DIFFICULTY_LEVEL_SETTING_MAXIMUM_NO_COMPETITORS, STR_NULL), SetFill(1, 0), SetPadding(1, 0, 0, 0),
+ NWidget(NWID_HORIZONTAL), SetPIP(7, 7, 7),
+ NWidget(WWT_FRAME, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_AI, STR_NULL), SetPadding(0, 5, 0, 5),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_AIC_LIST), SetMinimalSize(288, 112), SetFill(1, 0), SetMatrixDataTip(1, 8, STR_AI_CONFIG_AILIST_TOOLTIP), SetScrollbar(WID_AIC_SCROLLBAR),
+ NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_AIC_SCROLLBAR),
+ EndContainer(),
EndContainer(),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_MOVE_UP), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_AI_CONFIG_MOVE_UP, STR_AI_CONFIG_MOVE_UP_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_MOVE_DOWN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_AI_CONFIG_MOVE_DOWN, STR_AI_CONFIG_MOVE_DOWN_TOOLTIP),
+ NWidget(NWID_VERTICAL), SetPIP(4, 4, 4),
+ NWidget(NWID_HORIZONTAL), SetPIP(7, 0, 7),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_DECREASE), SetFill(0, 1), SetDataTip(AWV_DECREASE, STR_NULL),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_AIC_INCREASE), SetFill(0, 1), SetDataTip(AWV_INCREASE, STR_NULL),
+ NWidget(NWID_SPACER), SetMinimalSize(6, 0),
+ NWidget(WWT_TEXT, COLOUR_MAUVE, WID_AIC_NUMBER), SetDataTip(STR_DIFFICULTY_LEVEL_SETTING_MAXIMUM_NO_COMPETITORS, STR_NULL), SetFill(1, 0), SetPadding(1, 0, 0, 0),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_MOVE_UP), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_AI_CONFIG_MOVE_UP, STR_AI_CONFIG_MOVE_UP_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_MOVE_DOWN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_AI_CONFIG_MOVE_DOWN, STR_AI_CONFIG_MOVE_DOWN_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 9),
+ NWidget(WWT_FRAME, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_GAMESCRIPT, STR_NULL), SetPadding(0, 5, 4, 5),
+ NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_AIC_GAMELIST), SetSizingType(NWST_STEP), SetMinimalSize(288, 14), SetFill(1, 0), SetMatrixDataTip(1, 1, STR_AI_CONFIG_GAMELIST_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CHANGE), SetFill(1, 0), SetMinimalSize(93, 12), SetDataTip(STR_AI_CONFIG_CHANGE, STR_AI_CONFIG_CHANGE_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CONFIGURE), SetFill(1, 0), SetMinimalSize(93, 12), SetDataTip(STR_AI_CONFIG_CONFIGURE, STR_AI_CONFIG_CONFIGURE_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CLOSE), SetFill(1, 0), SetMinimalSize(93, 12), SetDataTip(STR_AI_SETTINGS_CLOSE, STR_NULL),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
+ EndContainer(),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CONTENT_DOWNLOAD), SetFill(1, 0), SetMinimalSize(279, 12), SetPadding(0, 7, 9, 7), SetDataTip(STR_INTRO_ONLINE_CONTENT, STR_INTRO_TOOLTIP_ONLINE_CONTENT),
EndContainer(),
EndContainer(),
- NWidget(WWT_FRAME, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_AI, STR_NULL), SetPadding(0, 5, 0, 5),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_AIC_LIST), SetMinimalSize(288, 112), SetFill(1, 0), SetMatrixDataTip(1, 8, STR_AI_CONFIG_AILIST_TOOLTIP), SetScrollbar(WID_AIC_SCROLLBAR),
- NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_AIC_SCROLLBAR),
- EndContainer(),
- EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 9),
- NWidget(WWT_FRAME, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_GAMESCRIPT, STR_NULL), SetPadding(0, 5, 4, 5),
- NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_AIC_GAMELIST), SetMinimalSize(288, 14), SetFill(1, 0), SetMatrixDataTip(1, 1, STR_AI_CONFIG_GAMELIST_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CHANGE), SetFill(1, 0), SetMinimalSize(93, 12), SetDataTip(STR_AI_CONFIG_CHANGE, STR_AI_CONFIG_CHANGE_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CONFIGURE), SetFill(1, 0), SetMinimalSize(93, 12), SetDataTip(STR_AI_CONFIG_CONFIGURE, STR_AI_CONFIG_CONFIGURE_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CLOSE), SetFill(1, 0), SetMinimalSize(93, 12), SetDataTip(STR_AI_SETTINGS_CLOSE, STR_NULL),
- EndContainer(),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
- EndContainer(),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_AIC_CONTENT_DOWNLOAD), SetFill(1, 0), SetMinimalSize(279, 12), SetPadding(0, 7, 9, 7), SetDataTip(STR_INTRO_ONLINE_CONTENT, STR_INTRO_TOOLTIP_ONLINE_CONTENT),
EndContainer(),
};
@@ -758,12 +759,12 @@ struct AIConfigWindow : public Window {
{
switch (widget) {
case WID_AIC_GAMELIST:
- this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
- size->height = 1 * this->line_height;
+ this->line_height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM);
+ size->height = this->line_height;
break;
case WID_AIC_LIST:
- this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
+ this->line_height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM);
size->height = 8 * this->line_height;
break;
}
@@ -801,14 +802,14 @@ struct AIConfigWindow : public Window {
text = STR_JUST_RAW_STRING;
}
- DrawString(r.left + 10, r.right - 10, r.top + WD_MATRIX_TOP, text,
+ DrawString(r.left + 10, r.right - 10, Center(r.top, this->line_height), text,
(this->selected_slot == OWNER_DEITY) ? TC_WHITE : (IsEditable(OWNER_DEITY) ? TC_ORANGE : TC_SILVER));
break;
}
case WID_AIC_LIST: {
- int y = r.top;
+ int y = Center(r.top, this->line_height);
for (int i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < MAX_COMPANIES; i++) {
StringID text;
@@ -820,7 +821,7 @@ struct AIConfigWindow : public Window {
} else {
text = STR_AI_CONFIG_RANDOM_AI;
}
- DrawString(r.left + 10, r.right - 10, y + WD_MATRIX_TOP, text,
+ DrawString(r.left + 10, r.right - 10, y, text,
(this->selected_slot == i) ? TC_WHITE : (IsEditable((CompanyID)i) ? TC_ORANGE : TC_SILVER));
y += this->line_height;
}
@@ -1074,7 +1075,7 @@ struct AIDebugWindow : public Window {
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
{
if (widget == WID_AID_LOG_PANEL) {
- resize->height = FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
+ resize->height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL);
size->height = 14 * resize->height + this->top_offset + this->bottom_offset;
}
}
@@ -1090,6 +1091,8 @@ struct AIDebugWindow : public Window {
bool dirty = false;
+ Dimension d = GetSpriteSize(SPR_COMPANY_ICON);
+ uint offset_y = Center(0, GetMinSizing(NWST_STEP, d.height + WD_MATRIX_TOP + WD_MATRIX_BOTTOM + 1), d.height);
/* Paint the company icons */
for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
NWidgetCore *button = this->GetWidget(i + WID_AID_COMPANY_BUTTON_START);
@@ -1110,7 +1113,7 @@ struct AIDebugWindow : public Window {
if (!valid) continue;
byte offset = (i == ai_debug_company) ? 1 : 0;
- DrawCompanyIcon(i, button->pos_x + button->current_x / 2 - 7 + offset, this->GetWidget(WID_AID_COMPANY_BUTTON_START + i)->pos_y + 2 + offset);
+ DrawCompanyIcon(i, Center(button->pos_x + offset, button->current_x, d.width), button->pos_y + offset + offset_y);
}
/* Set button colour for Game Script. */
@@ -1189,7 +1192,7 @@ struct AIDebugWindow : public Window {
ScriptLog::LogData *log = this->GetLogPointer();
if (log == NULL) return;
- int y = this->top_offset;
+ int y = Center(this->top_offset, this->resize.step_height);
for (int i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < log->used; i++) {
int pos = (i + log->pos + 1 - log->used + log->count) % log->count;
if (log->lines[pos] == NULL) break;
diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp
index 6437f236cd..08726a4cb1 100644
--- a/src/airport_gui.cpp
+++ b/src/airport_gui.cpp
@@ -28,6 +28,7 @@
#include "hotkeys.h"
#include "vehicle_func.h"
#include "gui.h"
+#include "command_func.h"
#include "widgets/airport_widget.h"
@@ -79,6 +80,7 @@ struct BuildAirToolbarWindow : Window {
~BuildAirToolbarWindow()
{
+ if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort();
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
}
@@ -113,13 +115,14 @@ struct BuildAirToolbarWindow : Window {
}
}
-
virtual void OnPlaceObject(Point pt, TileIndex tile)
{
switch (this->last_user_action) {
- case WID_AT_AIRPORT:
- PlaceAirport(tile);
+ case WID_AT_AIRPORT: {
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_BUILD_STATION);
+ MoveAllWindowsOffScreen();
break;
+ }
case WID_AT_DEMOLISH:
PlaceProc_DemolishArea(tile);
@@ -136,8 +139,17 @@ struct BuildAirToolbarWindow : Window {
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);
+ if (pt.x == -1) return;
+ switch (select_proc) {
+ case DDSP_BUILD_STATION:
+ assert(start_tile == end_tile);
+ MoveAllHiddenWindowsBackToScreen();
+ PlaceAirport(end_tile);
+ break;
+ case DDSP_DEMOLISH_AREA:
+ GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
+ break;
+ default: NOT_REACHED();
}
}
@@ -147,6 +159,7 @@ struct BuildAirToolbarWindow : Window {
DeleteWindowById(WC_BUILD_STATION, TRANSPORT_AIR);
DeleteWindowById(WC_SELECT_STATION, 0);
+ ResetObjectToPlace();
}
static HotkeyList hotkeys;
@@ -204,7 +217,7 @@ Window *ShowBuildAirToolbar()
{
if (!Company::IsValidID(_local_company)) return NULL;
- DeleteWindowByClass(WC_BUILD_TOOLBAR);
+ DeleteToolbarLinkedWindows();
return AllocateWindowDescFront(&_air_toolbar_desc, TRANSPORT_AIR);
}
@@ -305,6 +318,7 @@ public:
d.width += padding.width;
d.height += padding.height;
*size = maxdim(*size, d);
+ size->height = GetMinSizing(NWST_STEP, size->height);
break;
}
@@ -316,7 +330,7 @@ public:
size->width = max(size->width, GetStringBoundingBox(as->name).width);
}
- this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
+ this->line_height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM);
size->height = 5 * this->line_height;
break;
}
@@ -368,7 +382,9 @@ public:
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, y + WD_MATRIX_TOP, as->name, ((int)i == _selected_airport_index) ? TC_WHITE : TC_BLACK);
+
+ 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;
@@ -554,35 +570,41 @@ static const NWidgetPart _nested_build_airport_widgets[] = {
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),
+ NWidget(NWID_HORIZONTAL),
+ /* Airport dropdown selector and picture. */
+ NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetFill(1, 0), SetPIP(2, 0, 2),
+ NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetSizingType(NWST_STEP), 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),
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),
+ /* Airport parameters and info. */
+ NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetFill(1, 0), SetPIP(2, 0, 2),
+ 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_SPACER), SetMinimalSize(14, 0), SetFill(1, 0),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_AP_LAYOUT_DECREASE), SetSizingType(NWST_STEP), 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), SetSizingType(NWST_STEP), 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(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetResize(0, 1), SetFill(1, 0),
EndContainer(),
};
diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp
index 691042a1d5..7949027e5a 100644
--- a/src/autoreplace_gui.cpp
+++ b/src/autoreplace_gui.cpp
@@ -268,7 +268,7 @@ public:
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;
+ size->height = 4 * resize->height;
break;
case WID_RV_LEFT_DETAILS:
@@ -396,7 +396,7 @@ public:
str = STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED;
}
- DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_BLACK, SA_HOR_CENTER);
+ DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, Center(r.top + WD_FRAMERECT_TOP, r.bottom - r.top - WD_FRAMERECT_TOP), STR_BLACK_STRING, TC_FROMSTRING, SA_HOR_CENTER);
break;
}
diff --git a/src/blitter/16bpp_anim.cpp b/src/blitter/16bpp_anim.cpp
new file mode 100644
index 0000000000..115ffe9df5
--- /dev/null
+++ b/src/blitter/16bpp_anim.cpp
@@ -0,0 +1,386 @@
+/* $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 .
+ */
+
+/** @file 16bpp_anim.cpp Implementation of the optimized 32 bpp blitter with animation support. */
+
+#include "../stdafx.h"
+#include "../video/video_driver.hpp"
+#include "../zoom_func.h"
+#include "16bpp_anim.hpp"
+
+#include "../table/sprites.h"
+
+/** Instantiation of the 16bpp with animation blitter factory. */
+static FBlitter_16bppAnim iFBlitter_16bppAnim;
+
+template
+void Blitter_16bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
+{
+ const Pixel *src, *src_line;
+ Colour16 *dst, *dst_line;
+ Anim *anim, *anim_line;
+
+ /* Find where to start reading in the source sprite */
+ src_line = (const Pixel *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
+ dst_line = (Colour16 *)bp->dst + bp->top * bp->pitch + bp->left;
+ anim_line = this->anim_buf + ((Colour16 *)bp->dst - (Colour16 *)_screen.dst_ptr) + bp->top * this->anim_buf_width + bp->left;
+
+ for (int y = 0; y < bp->height; y++) {
+ dst = dst_line;
+ dst_line += bp->pitch;
+
+ src = src_line;
+ src_line += bp->sprite_width * ScaleByZoom(1, zoom);
+
+ anim = anim_line;
+ anim_line += this->anim_buf_width;
+
+ for (int x = 0; x < bp->width; x++) {
+ switch (mode) {
+ case BM_COLOUR_REMAP:
+ /* In case the m-channel is zero, do not remap this pixel in any way */
+ anim->m = 0;
+ anim->v = 0;
+ if (src->m == 0) {
+ if (src->a != 0) *dst = ComposeColourPA(src->c, src->a, *dst);
+ } else {
+ uint8 r = bp->remap[src->m];
+ if (r != 0) {
+ *dst = ComposeColourPA(AdjustBrightness(LookupColourInPalette(r), src->v), src->a, *dst);
+ if (src->a == 15 && r >= PALETTE_ANIM_START) {
+ anim->m = r - PALETTE_ANIM_START + 1;
+ anim->v = src->v >> 1;
+ }
+ }
+ }
+ break;
+
+ case BM_TRANSPARENT:
+ /* TODO -- We make an assumption here that the remap in fact is transparency, not some colour.
+ * This is never a problem with the code we produce, but newgrfs can make it fail... or at least:
+ * we produce a result the newgrf maker didn't expect ;) */
+
+ /* Make the current colour a bit more black, so it looks like this image is transparent */
+ if (src->a != 0) *dst = MakeTransparent(*dst, 192);
+ anim->m = 0;
+ anim->v = 0;
+ break;
+
+ default:
+ if (src->a == 15 && src->m >= PALETTE_ANIM_START) {
+ *dst = AdjustBrightness(LookupColourInPalette(src->m), src->v);
+ anim->m = src->m - PALETTE_ANIM_START + 1;
+ anim->v = src->v >> 1;
+ } else {
+ if (src->a != 0) {
+ if (src->m >= PALETTE_ANIM_START) {
+ *dst = ComposeColourPANoCheck(AdjustBrightness(LookupColourInPalette(src->m), src->v), src->a, *dst);
+ } else {
+ *dst = ComposeColourPA(src->c, src->a, *dst);
+ }
+ }
+ anim->m = 0;
+ anim->v = 0;
+ }
+ break;
+ }
+ dst++;
+ src += ScaleByZoom(1, zoom);
+ }
+ }
+}
+
+void Blitter_16bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
+{
+ if (_screen_disable_anim) {
+ /* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent Draw() */
+ Blitter_16bppOptimized::Draw(bp, mode, zoom);
+ return;
+ }
+
+ switch (mode) {
+ default: NOT_REACHED();
+ case BM_NORMAL: Draw (bp, zoom); return;
+ case BM_COLOUR_REMAP: Draw(bp, zoom); return;
+ case BM_TRANSPARENT: Draw (bp, zoom); return;
+ }
+}
+
+void Blitter_16bppAnim::DrawColourMappingRect(void *dst, int width, int height, PaletteID pal)
+{
+ if (_screen_disable_anim) {
+ /* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawColourMappingRect() */
+ Blitter_16bppOptimized::DrawColourMappingRect(dst, width, height, pal);
+ return;
+ }
+
+ Colour16 *udst = (Colour16 *)dst;
+ Anim *anim;
+
+ anim = this->anim_buf + ((Colour16 *)dst - (Colour16 *)_screen.dst_ptr);
+
+ if (pal == PALETTE_TO_TRANSPARENT) {
+ do {
+ for (int i = 0; i != width; i++) {
+ *udst = MakeTransparent(*udst, 154);
+ anim->m = 0;
+ anim->v = 0;
+ udst++;
+ anim++;
+ }
+ udst = udst - width + _screen.pitch;
+ anim = anim - width + this->anim_buf_width;
+ } while (--height);
+ return;
+ }
+ if (pal == PALETTE_NEWSPAPER) {
+ do {
+ for (int i = 0; i != width; i++) {
+ *udst = MakeGrey(*udst);
+ anim->m = 0;
+ anim->v = 0;
+ udst++;
+ anim++;
+ }
+ udst = udst - width + _screen.pitch;
+ anim = anim - width + this->anim_buf_width;
+ } while (--height);
+ return;
+ }
+
+ DEBUG(misc, 0, "16bpp blitter doesn't know how to draw this colour table ('%d')", pal);
+}
+
+void Blitter_16bppAnim::SetPixel(void *video, int x, int y, uint8 colour)
+{
+ *((Colour16 *)video + x + y * _screen.pitch) = LookupColourInPalette(colour);
+
+ /* Set the colour in the anim-buffer too, if we are rendering to the screen */
+ if (_screen_disable_anim) return;
+ Anim *anim = this->anim_buf + ((Colour16 *)video - (Colour16 *)_screen.dst_ptr) + x + y * this->anim_buf_width;
+ if (colour >= PALETTE_ANIM_START) {
+ anim->m = colour - PALETTE_ANIM_START + 1;
+ anim->v = DEFAULT_BRIGHTNESS >> 1;
+ } else {
+ anim->m = 0;
+ anim->v = 0;
+ }
+}
+
+void Blitter_16bppAnim::DrawRect(void *video, int width, int height, uint8 colour)
+{
+ if (_screen_disable_anim) {
+ /* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */
+ Blitter_16bppOptimized::DrawRect(video, width, height, colour);
+ return;
+ }
+
+ Colour16 colour16 = LookupColourInPalette(colour);
+ Anim *anim_line = this->anim_buf + ((Colour16 *)video - (Colour16 *)_screen.dst_ptr);
+
+ do {
+ Colour16 *dst = (Colour16 *)video;
+ Anim *anim = anim_line;
+
+ for (int i = width; i > 0; i--) {
+ *dst = colour16;
+ /* Set the colour in the anim-buffer too */
+ if (colour >= PALETTE_ANIM_START) {
+ anim->m = colour - PALETTE_ANIM_START + 1;
+ anim->v = DEFAULT_BRIGHTNESS >> 1;
+ } else {
+ anim->m = 0;
+ anim->v = 0;
+ }
+ dst++;
+ anim++;
+ }
+ video = (Colour16 *)video + _screen.pitch;
+ anim_line += this->anim_buf_width;
+ } while (--height);
+}
+
+void Blitter_16bppAnim::CopyFromBuffer(void *video, const void *src, int width, int height)
+{
+ assert(!_screen_disable_anim);
+ assert(video >= _screen.dst_ptr && video <= (Colour16 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
+ Colour16 *dst = (Colour16 *)video;
+ const uint8 *usrc = (const uint8 *)src;
+ Anim *anim_line = this->anim_buf + ((Colour16 *)video - (Colour16 *)_screen.dst_ptr);
+
+ for (; height > 0; height--) {
+ /* We need to keep those for palette animation. */
+ Colour16 *dst_pal = dst;
+ Anim *anim_pal = anim_line;
+
+ memcpy(dst, usrc, width * sizeof(Colour16));
+ usrc += width * sizeof(Colour16);
+ dst += _screen.pitch;
+ /* Copy back the anim-buffer */
+ memcpy(anim_line, usrc, width * sizeof(Anim));
+ usrc += width * sizeof(Anim);
+ anim_line += this->anim_buf_width;
+
+ /* Okay, it is *very* likely that the image we stored is using
+ * the wrong palette animated colours. There are two things we
+ * can do to fix this. The first is simply reviewing the whole
+ * screen after we copied the buffer, i.e. run PaletteAnimate,
+ * however that forces a full screen redraw which is expensive
+ * for just the cursor. This just copies the implementation of
+ * palette animation, much cheaper though slightly nastier. */
+ for (int i = 0; i < width; i++) {
+ uint8 colour = anim_pal->m;
+ if (colour) {
+ /* Update this pixel */
+ *dst_pal = AdjustBrightness(LookupColourInPalette(colour + PALETTE_ANIM_START - 1), anim_pal->v << 1);
+ }
+ dst_pal++;
+ anim_pal++;
+ }
+ }
+}
+
+void Blitter_16bppAnim::CopyToBuffer(const void *video, void *dst, int width, int height)
+{
+ assert(!_screen_disable_anim);
+ assert(video >= _screen.dst_ptr && video <= (Colour16 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
+ uint8 *udst = (uint8 *)dst;
+ const Colour16 *src = (const Colour16 *)video;
+ const Anim *anim_line = this->anim_buf + ((const Colour16 *)video - (Colour16 *)_screen.dst_ptr);
+
+ for (; height > 0; height--) {
+ memcpy(udst, src, width * sizeof(Colour16));
+ src += _screen.pitch;
+ udst += width * sizeof(Colour16);
+ /* Copy the anim-buffer */
+ memcpy(udst, anim_line, width * sizeof(Anim));
+ udst += width * sizeof(Anim);
+ anim_line += this->anim_buf_width;
+ }
+}
+
+void Blitter_16bppAnim::ScrollBuffer(void *video, int &left_ref, int &top_ref, int &width_ref, int &height_ref, int scroll_x, int scroll_y)
+{
+ assert(!_screen_disable_anim);
+ assert(video >= _screen.dst_ptr && video <= (Colour16 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
+ const Anim *src;
+ Anim *dst;
+ int left = left_ref, top = top_ref, width = width_ref, height = height_ref;
+
+ /* We need to scroll the anim-buffer too */
+ if (scroll_y > 0) {
+ /* Calculate pointers */
+ dst = this->anim_buf + left + (top + height - 1) * this->anim_buf_width;
+ src = dst - scroll_y * this->anim_buf_width;
+
+ /* Decrease height and increase top */
+ top += scroll_y;
+ height -= scroll_y;
+ assert(height > 0);
+
+ /* Adjust left & width */
+ if (scroll_x >= 0) {
+ dst += scroll_x;
+ left += scroll_x;
+ width -= scroll_x;
+ } else {
+ src -= scroll_x;
+ width += scroll_x;
+ }
+
+ for (int h = height; h > 0; h--) {
+ memcpy(dst, src, width * sizeof(Anim));
+ src -= this->anim_buf_width;
+ dst -= this->anim_buf_width;
+ }
+ } else {
+ /* Calculate pointers */
+ dst = this->anim_buf + left + top * this->anim_buf_width;
+ src = dst - scroll_y * this->anim_buf_width;
+
+ /* Decrease height. (scroll_y is <=0). */
+ height += scroll_y;
+ assert(height > 0);
+
+ /* Adjust left & width */
+ if (scroll_x >= 0) {
+ dst += scroll_x;
+ left += scroll_x;
+ width -= scroll_x;
+ } else {
+ src -= scroll_x;
+ width += scroll_x;
+ }
+
+ /* the y-displacement may be 0 therefore we have to use memmove,
+ * because source and destination may overlap */
+ for (int h = height; h > 0; h--) {
+ memmove(dst, src, width * sizeof(Anim));
+ src += _screen.pitch;
+ dst += _screen.pitch;
+ }
+ }
+
+ Blitter_16bppOptimized::ScrollBuffer(video, left_ref, top_ref, width_ref, height_ref, scroll_x, scroll_y);
+}
+
+int Blitter_16bppAnim::BufferSize(int width, int height)
+{
+ return width * height * (sizeof(Anim) + sizeof(Colour16));
+}
+
+void Blitter_16bppAnim::PaletteAnimate(const Palette &palette)
+{
+ assert(!_screen_disable_anim);
+
+ /* If first_dirty is 0, it is for 8bpp indication to send the new
+ * palette. However, only the animation colours might possibly change.
+ * Especially when going between toyland and non-toyland. */
+ assert(palette.first_dirty == PALETTE_ANIM_START || palette.first_dirty == 0);
+
+ for (int i = 0; i < 256; i++) {
+ this->palette[i] = To16(palette.palette[i]);
+ }
+
+ const Anim *anim = this->anim_buf;
+ Colour16 *dst = (Colour16 *)_screen.dst_ptr;
+
+ /* Let's walk the anim buffer and try to find the pixels */
+ for (int y = this->anim_buf_height; y != 0 ; y--) {
+ for (int x = this->anim_buf_width; x != 0 ; x--) {
+ uint8 colour = anim->m;
+ if (colour) {
+ /* Update this pixel */
+ *dst = AdjustBrightness(LookupColourInPalette(colour + PALETTE_ANIM_START - 1), anim->v << 1);
+ }
+ dst++;
+ anim++;
+ }
+ dst += _screen.pitch - this->anim_buf_width;
+ }
+
+ /* Make sure the backend redraws the whole screen */
+ VideoDriver::GetInstance()->MakeDirty(0, 0, _screen.width, _screen.height);
+}
+
+Blitter::PaletteAnimation Blitter_16bppAnim::UsePaletteAnimation()
+{
+ return Blitter::PALETTE_ANIMATION_BLITTER;
+}
+
+void Blitter_16bppAnim::PostResize()
+{
+ if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height) {
+ /* The size of the screen changed; we can assume we can wipe all data from our buffer */
+ free(this->anim_buf);
+ this->anim_buf = CallocT(_screen.width * _screen.height);
+ this->anim_buf_width = _screen.width;
+ this->anim_buf_height = _screen.height;
+ }
+}
diff --git a/src/blitter/16bpp_anim.hpp b/src/blitter/16bpp_anim.hpp
new file mode 100644
index 0000000000..80bf6e5df5
--- /dev/null
+++ b/src/blitter/16bpp_anim.hpp
@@ -0,0 +1,75 @@
+/* $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 .
+ */
+
+/** @file 16bpp_anim.hpp A 16 bpp blitter with animation support. */
+
+#ifndef BLITTER_16BPP_ANIM_HPP
+#define BLITTER_16BPP_ANIM_HPP
+
+#include "16bpp_simple.hpp"
+
+class Blitter_16bppOptimized: public Blitter_16bppSimple {
+ // TODO: implement that
+};
+
+/** The optimised 16 bpp blitter with palette animation. */
+class Blitter_16bppAnim : public Blitter_16bppOptimized {
+protected:
+ // PALETTE_ANIM_SIZE is less than 32, so we'll use 5 bits for color index, and 3 bits for brightness, losing 1 bit compared to struct Pixel
+ struct Anim {
+ unsigned m : 5 __attribute__((packed)); ///< Color index channel, packed 5 bits, 0 = no animation, 1 = PALETTE_ANIM_START
+ unsigned v : 3 __attribute__((packed)); ///< Brightness-channel, packed 3 bits
+ };
+
+ Anim *anim_buf; ///< In this buffer we keep track of the 8bpp indexes so we can do palette animation
+ int anim_buf_width; ///< The width of the animation buffer.
+ int anim_buf_height; ///< The height of the animation buffer.
+ Colour16 palette[256]; ///< The current palette.
+
+public:
+ Blitter_16bppAnim() :
+ anim_buf(NULL),
+ anim_buf_width(0),
+ anim_buf_height(0)
+ {}
+
+ /* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
+ /* virtual */ void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal);
+ /* virtual */ void SetPixel(void *video, int x, int y, uint8 colour);
+ /* virtual */ void DrawRect(void *video, int width, int height, uint8 colour);
+ /* virtual */ void CopyFromBuffer(void *video, const void *src, int width, int height);
+ /* virtual */ void CopyToBuffer(const void *video, void *dst, int width, int height);
+ /* virtual */ void ScrollBuffer(void *video, int &left_ref, int &top_ref, int &width_ref, int &height_ref, int scroll_x, int scroll_y);
+ /* virtual */ int BufferSize(int width, int height);
+ /* virtual */ void PaletteAnimate(const Palette &palette);
+ /* virtual */ Blitter::PaletteAnimation UsePaletteAnimation();
+ /* virtual */ int GetBytesPerPixel() { return 3; }
+
+ /* virtual */ const char *GetName() { return "16bpp-anim"; }
+ /* virtual */ void PostResize();
+
+ /**
+ * Look up the colour in the current palette.
+ */
+ inline Colour16 LookupColourInPalette(uint8 index)
+ {
+ return this->palette[index];
+ }
+
+ template void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
+};
+
+/** Factory for the 16bpp blitter with animation. */
+class FBlitter_16bppAnim : public BlitterFactory {
+public:
+ FBlitter_16bppAnim() : BlitterFactory("16bpp-anim-broken", "16bpp Animation Blitter, currently broken (palette animation)") {}
+ /* virtual */ Blitter *CreateInstance() { return new Blitter_16bppAnim(); }
+};
+
+#endif /* BLITTER_16BPP_ANIM_HPP */
diff --git a/src/blitter/16bpp_base.cpp b/src/blitter/16bpp_base.cpp
new file mode 100644
index 0000000000..9161ce92c4
--- /dev/null
+++ b/src/blitter/16bpp_base.cpp
@@ -0,0 +1,147 @@
+/* $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 .
+ */
+
+/** @file 16bpp_base.cpp Implementation of base for 32 bpp blitters. */
+
+#include "../stdafx.h"
+#include "16bpp_base.hpp"
+
+void *Blitter_16bppBase::MoveTo(void *video, int x, int y)
+{
+ return (uint16 *)video + x + y * _screen.pitch;
+}
+
+void Blitter_16bppBase::SetPixel(void *video, int x, int y, uint8 colour)
+{
+ *((Colour16 *)video + x + y * _screen.pitch) = LookupColourInPalette(colour);
+}
+
+void Blitter_16bppBase::DrawRect(void *video, int width, int height, uint8 colour)
+{
+ Colour16 target = LookupColourInPalette(colour);
+
+ do {
+ Colour16 *dst = (Colour16 *)video;
+ for (int i = width; i > 0; i--) {
+ *dst = target;
+ dst++;
+ }
+ video = (uint16 *)video + _screen.pitch;
+ } while (--height);
+}
+
+void Blitter_16bppBase::CopyFromBuffer(void *video, const void *src, int width, int height)
+{
+ uint16 *dst = (uint16 *)video;
+ const uint16 *usrc = (const uint16 *)src;
+
+ for (; height > 0; height--) {
+ memcpy(dst, usrc, width * sizeof(uint16));
+ usrc += width;
+ dst += _screen.pitch;
+ }
+}
+
+void Blitter_16bppBase::CopyToBuffer(const void *video, void *dst, int width, int height)
+{
+ uint16 *udst = (uint16 *)dst;
+ const uint16 *src = (const uint16 *)video;
+
+ for (; height > 0; height--) {
+ memcpy(udst, src, width * sizeof(uint16));
+ src += _screen.pitch;
+ udst += width;
+ }
+}
+
+void Blitter_16bppBase::CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch)
+{
+ uint16 *udst = (uint16 *)dst;
+ const uint16 *src = (const uint16 *)video;
+
+ for (; height > 0; height--) {
+ memcpy(udst, src, width * sizeof(uint16));
+ src += _screen.pitch;
+ udst += dst_pitch;
+ }
+}
+
+void Blitter_16bppBase::ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y)
+{
+ const Colour16 *src;
+ Colour16 *dst;
+
+ if (scroll_y > 0) {
+ /* Calculate pointers */
+ dst = (Colour16 *)video + left + (top + height - 1) * _screen.pitch;
+ src = dst - scroll_y * _screen.pitch;
+
+ /* Decrease height and increase top */
+ top += scroll_y;
+ height -= scroll_y;
+ assert(height > 0);
+
+ /* Adjust left & width */
+ if (scroll_x >= 0) {
+ dst += scroll_x;
+ left += scroll_x;
+ width -= scroll_x;
+ } else {
+ src -= scroll_x;
+ width += scroll_x;
+ }
+
+ for (int h = height; h > 0; h--) {
+ memcpy(dst, src, width * sizeof(Colour16));
+ src -= _screen.pitch;
+ dst -= _screen.pitch;
+ }
+ } else {
+ /* Calculate pointers */
+ dst = (Colour16 *)video + left + top * _screen.pitch;
+ src = dst - scroll_y * _screen.pitch;
+
+ /* Decrease height. (scroll_y is <=0). */
+ height += scroll_y;
+ assert(height > 0);
+
+ /* Adjust left & width */
+ if (scroll_x >= 0) {
+ dst += scroll_x;
+ left += scroll_x;
+ width -= scroll_x;
+ } else {
+ src -= scroll_x;
+ width += scroll_x;
+ }
+
+ /* the y-displacement may be 0 therefore we have to use memmove,
+ * because source and destination may overlap */
+ for (int h = height; h > 0; h--) {
+ memmove(dst, src, width * sizeof(Colour16));
+ src += _screen.pitch;
+ dst += _screen.pitch;
+ }
+ }
+}
+
+int Blitter_16bppBase::BufferSize(int width, int height)
+{
+ return width * height * sizeof(Colour16);
+}
+
+void Blitter_16bppBase::PaletteAnimate(const Palette &palette)
+{
+ /* By default, 16bpp doesn't have palette animation */
+}
+
+Blitter::PaletteAnimation Blitter_16bppBase::UsePaletteAnimation()
+{
+ return Blitter::PALETTE_ANIMATION_NONE;
+}
diff --git a/src/blitter/16bpp_base.hpp b/src/blitter/16bpp_base.hpp
new file mode 100644
index 0000000000..c4d63b0bd4
--- /dev/null
+++ b/src/blitter/16bpp_base.hpp
@@ -0,0 +1,225 @@
+/* $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 .
+ */
+
+/** @file 16bpp_base.hpp Base for all 16 bits blitters. */
+
+#ifndef BLITTER_16BPP_BASE_HPP
+#define BLITTER_16BPP_BASE_HPP
+
+#include "base.hpp"
+#include "../core/bitmath_func.hpp"
+#include "../core/math_func.hpp"
+#include "../gfx_func.h"
+
+/** Base for all 16bpp blitters. */
+class Blitter_16bppBase : public Blitter {
+public:
+
+ // TODO: GCC-specific attributes
+ struct Colour16 {
+ unsigned b : 5 __attribute__((packed)); ///< Blue-channel, packed 5 bits
+ unsigned g : 6 __attribute__((packed)); ///< Green-channel, packed 6 bits
+ unsigned r : 5 __attribute__((packed)); ///< Red-channel, packed 5 bits
+ Colour16(uint8 r = 0, uint8 g = 0, uint8 b = 0):
+ b(b), g(g), r(r)
+ {
+ }
+ };
+
+ struct Pixel {
+ Colour16 c;
+ unsigned a : 4 __attribute__((packed)); ///< Alpha-channel, packed 4 bits
+ unsigned v : 4 __attribute__((packed)); ///< Brightness-channel, packed 4 bits
+ unsigned m : 8 __attribute__((packed)); ///< Remap-channel, cannot pack it, because it's palette lookup index, so it must be in range 0-255
+ };
+
+ /* virtual */ uint8 GetScreenDepth() { return 16; }
+ /* virtual */ void *MoveTo(void *video, int x, int y);
+ /* virtual */ void SetPixel(void *video, int x, int y, uint8 colour);
+ /* virtual */ void DrawRect(void *video, int width, int height, uint8 colour);
+ /* virtual */ void CopyFromBuffer(void *video, const void *src, int width, int height);
+ /* virtual */ void CopyToBuffer(const void *video, void *dst, int width, int height);
+ /* virtual */ void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch);
+ /* virtual */ void ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y);
+ /* virtual */ int BufferSize(int width, int height);
+ /* virtual */ void PaletteAnimate(const Palette &palette);
+ /* virtual */ Blitter::PaletteAnimation UsePaletteAnimation();
+ /* virtual */ int GetBytesPerPixel() { return 2; }
+
+
+ /**
+ * Convert from rgb values to screen native 16bpp colour
+ */
+ static inline Colour16 To16(uint8 r, uint8 g, uint8 b)
+ {
+ return Colour16(r >> 3, g >> 2, b >> 3);
+ }
+
+ /**
+ * Convert from 32bpp colour to screen native 16bpp colour
+ */
+ static inline Colour16 To16(Colour c)
+ {
+ return To16(c.r, c.g, c.b);
+ }
+
+ /**
+ * Look up the colour in the current palette.
+ */
+ static inline Colour LookupColourInPalette32(uint index)
+ {
+ return _cur_palette.palette[index];
+ }
+
+ /**
+ * Look up the colour in the current palette.
+ */
+ static inline Colour16 LookupColourInPalette(uint index)
+ {
+ return To16(LookupColourInPalette32(index));
+ }
+
+ /**
+ * Compose a colour based on RGBA values and the current pixel value.
+ * @param r range is from 0 to 31.
+ * @param g range is from 0 to 63.
+ * @param b range is from 0 to 31.
+ * @param a range is from 0 to 15.
+ */
+ static inline Colour16 ComposeColourRGBANoCheck(uint8 r, uint8 g, uint8 b, uint8 a, Colour16 current)
+ {
+ /* The 16 is wrong, it should be 15, but 16 is much faster... */
+ return Colour16 ( ((int)(r - current.r) * a) / 16 + current.r,
+ ((int)(g - current.g) * a) / 16 + current.g,
+ ((int)(b - current.b) * a) / 16 + current.b );
+ }
+
+ /**
+ * Compose a colour based on RGBA values and the current pixel value.
+ * Handles fully transparent and solid pixels in a special (faster) way.
+ * @param r range is from 0 to 31.
+ * @param g range is from 0 to 63.
+ * @param b range is from 0 to 31.
+ * @param a range is from 0 to 15.
+ */
+ static inline Colour16 ComposeColourRGBA(uint8 r, uint8 g, uint8 b, uint8 a, Colour16 current)
+ {
+ if (a == 0) return current;
+ if (a >= 15) return Colour16(r, g, b);
+
+ return ComposeColourRGBANoCheck(r, g, b, a, current);
+ }
+
+ /**
+ * Compose a colour based on Pixel value, alpha value, and the current pixel value.
+ * @param a range is from 0 to 16.
+ */
+ static inline Colour16 ComposeColourPANoCheck(Colour16 colour, uint8 a, Colour16 current)
+ {
+ return ComposeColourRGBANoCheck(colour.r, colour.g, colour.b, a, current);
+ }
+
+ /**
+ * Compose a colour based on Pixel value, alpha value, and the current pixel value.
+ * Handles fully transparent and solid pixels in a special (faster) way.
+ * @param a range is from 0 to 15.
+ */
+ static inline Colour16 ComposeColourPA(Colour16 colour, uint8 a, Colour16 current)
+ {
+ if (a == 0) return current;
+ if (a >= 15) return colour;
+
+ return ComposeColourPANoCheck(colour, a, current);
+ }
+
+ /**
+ * Make a pixel looks like it is transparent.
+ * @param colour the colour already on the screen.
+ * @param nom the amount of transparency, nominator, makes colour lighter.
+ * @param denom denominator, makes colour darker.
+ * @return the new colour for the screen.
+ */
+ static inline Colour16 MakeTransparent(Colour16 colour, uint nom, uint denom = 256)
+ {
+ uint r = colour.r;
+ uint g = colour.g;
+ uint b = colour.b;
+
+ return Colour16( r * nom / denom,
+ g * nom / denom,
+ b * nom / denom );
+ }
+
+ /**
+ * Make a colour grey - based.
+ * @param colour the colour to make grey.
+ * @return the new colour, now grey.
+ */
+ static inline Colour16 MakeGrey(Colour16 colour)
+ {
+ uint8 r = colour.r;
+ uint8 g = colour.g;
+ uint8 b = colour.b;
+
+ /* To avoid doubles and stuff, multiple it with a total of 65536 (16bits), then
+ * divide by it to normalize the value to a byte again. See heightmap.cpp for
+ * information about the formula. */
+ uint grey = (((r << 3) * 19595) + ((g << 2) * 38470) + ((b << 3) * 7471)) / 65536;
+
+ return To16(grey, grey, grey);
+ }
+
+ /**
+ * Make a colour dark grey, for specialized 32bpp remapping.
+ * @param r red component
+ * @param g green component
+ * @param b blue component
+ * @return the brightness value of the new colour, now dark grey.
+ */
+ static inline uint8 MakeDark(Colour16 colour)
+ {
+ uint8 r = colour.r;
+ uint8 g = colour.g;
+ uint8 b = colour.b;
+
+ /* Magic-numbers are ~66% of those used in MakeGrey() */
+ return (((r << 3) * 13063) + ((g << 2) * 25647) + ((b << 3) * 4981)) / 65536;
+ }
+
+ enum { DEFAULT_BRIGHTNESS = 8 };
+
+ /**
+ * @param brightness range is from 0 to 15.
+ */
+ static inline Colour16 AdjustBrightness(Colour16 colour, uint8 brightness)
+ {
+ /* Shortcut for normal brightness */
+ if (brightness == DEFAULT_BRIGHTNESS) return colour;
+
+ uint16 ob = 0;
+ uint16 r = colour.r * brightness / DEFAULT_BRIGHTNESS;
+ uint16 g = colour.g * brightness / DEFAULT_BRIGHTNESS;
+ uint16 b = colour.b * brightness / DEFAULT_BRIGHTNESS;
+
+ /* Sum overbright */
+ if (r > 31) ob += r - 31;
+ if (g > 63) ob += g - 63;
+ if (b > 31) ob += b - 31;
+
+ if (ob == 0) return Colour16(r, g, b);
+
+ /* Reduce overbright strength */
+ ob /= 2;
+ return Colour16( r >= 31 ? 31 : min(r + ob * (31 - r) / 32, 31),
+ g >= 63 ? 63 : min(g + ob * (63 - g) / 64, 63),
+ b >= 31 ? 31 : min(b + ob * (31 - b) / 32, 31) );
+ }
+};
+
+#endif /* BLITTER_16BPP_BASE_HPP */
diff --git a/src/blitter/16bpp_simple.cpp b/src/blitter/16bpp_simple.cpp
new file mode 100644
index 0000000000..675b58b87d
--- /dev/null
+++ b/src/blitter/16bpp_simple.cpp
@@ -0,0 +1,166 @@
+/* $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 .
+ */
+
+/** @file 32bpp_simple.cpp Implementation of the simple 32 bpp blitter. */
+
+#include "../stdafx.h"
+#include "../zoom_func.h"
+#include "16bpp_simple.hpp"
+
+#include "../table/sprites.h"
+
+/** Instantiation of the simple 16bpp blitter factory. */
+static FBlitter_16bppSimple iFBlitter_16bppSimple;
+
+template
+void Blitter_16bppSimple::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
+{
+ const Pixel *src, *src_line;
+ Colour16 *dst, *dst_line;
+
+ /* Find where to start reading in the source sprite */
+ src_line = (const Pixel *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
+ dst_line = (Colour16 *)bp->dst + bp->top * bp->pitch + bp->left;
+
+ for (int y = 0; y < bp->height; y++) {
+ dst = dst_line;
+ dst_line += bp->pitch;
+
+ src = src_line;
+ src_line += bp->sprite_width * ScaleByZoom(1, zoom);
+
+ for (int x = 0; x < bp->width; x++) {
+ switch (mode) {
+ case BM_COLOUR_REMAP:
+ /* In case the m-channel is zero, do not remap this pixel in any way */
+ if (src->m == 0) {
+ if (src->a != 0) *dst = ComposeColourPA(src->c, src->a, *dst);
+ } else {
+ if (bp->remap[src->m] != 0) *dst = ComposeColourPA(AdjustBrightness(LookupColourInPalette(bp->remap[src->m]), src->v), src->a, *dst);
+ }
+ break;
+
+ case BM_CRASH_REMAP:
+ if (src->m == 0) {
+ if (src->a != 0) {
+ uint8 g = MakeDark(src->c);
+ *dst = ComposeColourRGBA(g, g, g, src->a, *dst);
+ }
+ } else {
+ if (bp->remap[src->m] != 0) *dst = ComposeColourPA(AdjustBrightness(LookupColourInPalette(bp->remap[src->m]), src->v), src->a, *dst);
+ }
+ break;
+
+ case BM_TRANSPARENT:
+ /* TODO -- We make an assumption here that the remap in fact is transparency, not some colour.
+ * This is never a problem with the code we produce, but newgrfs can make it fail... or at least:
+ * we produce a result the newgrf maker didn't expect ;) */
+
+ /* Make the current colour a bit more black, so it looks like this image is transparent */
+ if (src->a != 0) *dst = MakeTransparent(*dst, 192);
+ break;
+
+ default:
+ if (src->a != 0) *dst = ComposeColourPA(src->c, src->a, *dst);
+ break;
+ }
+ dst++;
+ src += ScaleByZoom(1, zoom);
+ }
+ }
+}
+
+void Blitter_16bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
+{
+ switch (mode) {
+ default: NOT_REACHED();
+ case BM_NORMAL: Draw (bp, zoom); return;
+ case BM_COLOUR_REMAP: Draw(bp, zoom); return;
+ case BM_TRANSPARENT: Draw (bp, zoom); return;
+ case BM_CRASH_REMAP: Draw (bp, zoom); return;
+ }
+}
+
+void Blitter_16bppSimple::DrawColourMappingRect(void *dst, int width, int height, PaletteID pal)
+{
+ Colour16 *udst = (Colour16 *)dst;
+
+ if (pal == PALETTE_TO_TRANSPARENT) {
+ do {
+ for (int i = 0; i != width; i++) {
+ *udst = MakeTransparent(*udst, 154);
+ udst++;
+ }
+ udst = udst - width + _screen.pitch;
+ } while (--height);
+ return;
+ }
+ if (pal == PALETTE_NEWSPAPER) {
+ do {
+ for (int i = 0; i != width; i++) {
+ *udst = MakeGrey(*udst);
+ udst++;
+ }
+ udst = udst - width + _screen.pitch;
+ } while (--height);
+ return;
+ }
+
+ DEBUG(misc, 0, "16bpp blitter doesn't know how to draw this colour table ('%d')", pal);
+}
+
+Sprite *Blitter_16bppSimple::Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator)
+{
+ Pixel *dst;
+ Sprite *dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + (size_t)sprite->height * (size_t)sprite->width * sizeof(Pixel));
+
+ dest_sprite->height = sprite->height;
+ dest_sprite->width = sprite->width;
+ dest_sprite->x_offs = sprite->x_offs;
+ dest_sprite->y_offs = sprite->y_offs;
+
+ dst = (Pixel *)dest_sprite->data;
+ SpriteLoader::CommonPixel *src = (SpriteLoader::CommonPixel *)sprite->data;
+
+ for (int i = 0; i < sprite->height * sprite->width; i++) {
+ if (src->m == 0) {
+ dst[i].c = To16(src->r, src->g, src->b);
+ dst[i].a = src->a / 16;
+ dst[i].m = 0;
+ dst[i].v = 0;
+ } else {
+ /* Get brightest value */
+ uint8 rgb_max = max(src->r, max(src->g, src->b));
+#if 0
+ /* Pre-convert the mapping channel to a RGB value,
+ use 32bpp AdjustBrightness() variant for better colors,
+ because this function is not called each frame */
+ if (rgb_max == 0) rgb_max = Blitter_32bppBase::DEFAULT_BRIGHTNESS;
+ dst[i].c = To16(Blitter_32bppBase::AdjustBrightness(LookupColourInPalette32(src->m), rgb_max));
+ dst[i].v = rgb_max / 16;
+#endif
+ rgb_max /= 16;
+
+ /* Black pixel (8bpp or old 32bpp image), so use default value */
+ if (rgb_max == 0) rgb_max = DEFAULT_BRIGHTNESS;
+
+ /* Pre-convert the mapping channel to a RGB value,
+ use 32bpp AdjustBrightness() variant for better colors,
+ because this function is not called each frame */
+ dst[i].c = AdjustBrightness(LookupColourInPalette(src->m), rgb_max);
+ dst[i].v = rgb_max;
+
+ dst[i].a = src->a / 16;
+ dst[i].m = src->m;
+ }
+ src++;
+ }
+
+ return dest_sprite;
+}
diff --git a/src/blitter/16bpp_simple.hpp b/src/blitter/16bpp_simple.hpp
new file mode 100644
index 0000000000..9feb934062
--- /dev/null
+++ b/src/blitter/16bpp_simple.hpp
@@ -0,0 +1,36 @@
+/* $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 .
+ */
+
+/** @file 16bpp_simple.hpp Simple 16 bpp blitter. */
+
+#ifndef BLITTER_16BPP_SIMPLE_HPP
+#define BLITTER_16BPP_SIMPLE_HPP
+
+#include "16bpp_base.hpp"
+#include "factory.hpp"
+
+/** The most trivial 32 bpp blitter (without palette animation). */
+class Blitter_16bppSimple : public Blitter_16bppBase {
+public:
+ /* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
+ /* virtual */ void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal);
+ /* virtual */ Sprite *Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator);
+ template void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
+
+ /* virtual */ const char *GetName() { return "16bpp-simple"; }
+};
+
+/** Factory for the simple 16 bpp blitter. */
+class FBlitter_16bppSimple : public BlitterFactory {
+public:
+ FBlitter_16bppSimple() : BlitterFactory("16bpp-simple", "16bpp Simple Blitter (no palette animation)") {}
+ /* virtual */ Blitter *CreateInstance() { return new Blitter_16bppSimple(); }
+};
+
+#endif /* BLITTER_16BPP_SIMPLE_HPP */
diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp
index 797ead1f51..3c6ad22016 100644
--- a/src/bridge_gui.cpp
+++ b/src/bridge_gui.cpp
@@ -24,6 +24,7 @@
#include "cmd_helper.h"
#include "tunnelbridge_map.h"
#include "road_gui.h"
+#include "tilehighlight_func.h"
#include "widgets/bridge_widget.h"
@@ -233,7 +234,8 @@ public:
SetDParam(1, b->speed);
SetDParam(0, b->material);
- DrawSprite(b->sprite, b->pal, r.left + WD_MATRIX_LEFT, y + this->resize.step_height - 1 - GetSpriteSize(b->sprite).height);
+ uint y_sprite = Center(y, this->resize.step_height, GetSpriteSize(b->sprite).height);
+ DrawSprite(b->sprite, b->pal, r.left + WD_MATRIX_LEFT, y_sprite);
DrawStringMultiLine(r.left + this->bridgetext_offset, r.right, y + 2, y + this->resize.step_height,
_game_mode == GM_EDITOR ? STR_SELECT_BRIDGE_SCENEDIT_INFO : STR_SELECT_BRIDGE_INFO);
y += this->resize.step_height;
@@ -430,6 +432,8 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
new BuildBridgeWindow(&_build_bridge_desc, start, end, type, bl);
} else {
delete bl;
+ SetSelectionTilesDirty();
+ _thd.Reset();
ShowErrorMessage(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, errmsg, WL_INFO, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
}
}
diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp
index bd4bf3b59b..2435a02b0f 100644
--- a/src/build_vehicle_gui.cpp
+++ b/src/build_vehicle_gui.cpp
@@ -46,7 +46,8 @@
*/
uint GetEngineListHeight(VehicleType type)
{
- return max(FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM, GetVehicleImageCellSize(type, EIT_PURCHASE).height);
+ uint size = max(FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM, GetVehicleImageCellSize(type, EIT_PURCHASE).height);
+ return GetMinSizing(NWST_STEP, size);
}
static const NWidgetPart _nested_build_vehicle_widgets[] = {
@@ -60,13 +61,14 @@ static const NWidgetPart _nested_build_vehicle_widgets[] = {
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(NWID_VERTICAL),
NWidget(NWID_HORIZONTAL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
- NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_BV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), SetSizingType(NWST_STEP),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_BV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA), SetSizingType(NWST_STEP),
EndContainer(),
NWidget(NWID_HORIZONTAL),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BV_SHOW_HIDDEN_ENGINES),
- NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_BV_CARGO_FILTER_DROPDOWN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BV_SHOW_HIDDEN_ENGINES), SetSizingType(NWST_STEP),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_BV_CARGO_FILTER_DROPDOWN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA), SetSizingType(NWST_STEP),
EndContainer(),
+ NWidget(NWID_SPACER), SetFill(1, 1),
EndContainer(),
EndContainer(),
/* Vehicle list. */
@@ -891,7 +893,6 @@ void DrawEngineList(VehicleType type, int l, int r, int y, const GUIEngineList *
int sprite_width = sprite_left + sprite_right;
int sprite_x = rtl ? r - sprite_right - 1 : l + sprite_left + 1;
- int sprite_y_offset = sprite_y_offsets[type] + step_size / 2;
Dimension replace_icon = {0, 0};
int count_width = 0;
@@ -907,10 +908,6 @@ void DrawEngineList(VehicleType type, int l, int r, int y, const GUIEngineList *
int count_left = l;
int count_right = rtl ? text_left : r - WD_FRAMERECT_RIGHT - replace_icon.width - 8;
- int normal_text_y_offset = (step_size - FONT_HEIGHT_NORMAL) / 2;
- int small_text_y_offset = step_size - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 1;
- int replace_icon_y_offset = (step_size - replace_icon.height) / 2 - 1;
-
for (; min < max; min++, y += step_size) {
const EngineID engine = (*eng_list)[min];
/* Note: num_engines is only used in the autoreplace GUI, so it is correct to use _local_company here. */
@@ -926,8 +923,8 @@ void DrawEngineList(VehicleType type, int l, int r, int y, const GUIEngineList *
DrawVehicleEngine(l, r, sprite_x, y + sprite_y_offset, engine, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_company), EIT_PURCHASE);
if (show_count) {
SetDParam(0, num_engines);
- DrawString(count_left, count_right, y + small_text_y_offset, STR_TINY_BLACK_COMA, TC_FROMSTRING, SA_RIGHT | SA_FORCE);
- if (EngineHasReplacementForCompany(Company::Get(_local_company), engine, selected_group)) DrawSprite(SPR_GROUP_REPLACE_ACTIVE, num_engines == 0 ? PALETTE_CRASH : PAL_NONE, replace_icon_left, y + replace_icon_y_offset);
+ DrawString(count_left, count_right, Center(y, step_size, FONT_HEIGHT_SMALL), STR_TINY_BLACK_COMA, TC_FROMSTRING, SA_RIGHT | SA_FORCE);
+ if (EngineHasReplacementForCompany(Company::Get(_local_company), engine, selected_group)) DrawSprite(SPR_GROUP_REPLACE_ACTIVE, num_engines == 0 ? PALETTE_CRASH : PAL_NONE, replace_icon_left, Center(y, step_size, replace_icon.height));
}
}
}
@@ -1381,7 +1378,7 @@ struct BuildVehicleWindow : Window {
switch (widget) {
case WID_BV_LIST:
resize->height = GetEngineListHeight(this->vehicle_type);
- size->height = 3 * resize->height;
+ size->height = 4 * resize->height;
size->width = max(size->width, GetVehicleImageCellSize(this->vehicle_type, EIT_PURCHASE).extend_left + GetVehicleImageCellSize(this->vehicle_type, EIT_PURCHASE).extend_right + 165);
break;
@@ -1393,6 +1390,7 @@ struct BuildVehicleWindow : Window {
Dimension d = GetStringBoundingBox(this->GetWidget(widget)->widget_data);
d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
d.height += padding.height;
+ d.height = GetMinSizing(NWST_STEP, d.height);
*size = maxdim(*size, d);
break;
}
diff --git a/src/command.cpp b/src/command.cpp
index 959610cd28..769478ffa4 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -26,6 +26,8 @@
#include "signal_func.h"
#include "core/backup_type.hpp"
#include "object_base.h"
+#include "string_func.h"
+#include "tilehighlight_func.h"
#include "table/strings.h"
diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp
index 577ea884d8..5d5156dc78 100644
--- a/src/company_cmd.cpp
+++ b/src/company_cmd.cpp
@@ -904,7 +904,10 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
Game::NewEvent(new ScriptEventCompanyBankrupt(c_index));
CompanyAdminRemove(c_index, (CompanyRemoveReason)reason);
- if (StoryPage::GetNumItems() == 0 || Goal::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
+ if (StoryPage::GetNumItems() == 0 || Goal::GetNumItems() == 0) {
+ InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
+ InvalidateWindowData(WC_MAIN_TOOLBAR_RIGHT, 0);
+ }
break;
}
diff --git a/src/company_gui.cpp b/src/company_gui.cpp
index 1343acb91b..d48760e832 100644
--- a/src/company_gui.cpp
+++ b/src/company_gui.cpp
@@ -36,6 +36,7 @@
#include "water.h"
#include "station_func.h"
#include "zoom_func.h"
+#include "widget_type.h"
#include "widgets/company_widget.h"
@@ -930,102 +931,112 @@ static const NWidgetPart _nested_select_company_manager_face_widgets[] = {
EndContainer(),
EndContainer(),
EndContainer(),
- NWidget(NWID_VERTICAL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON), SetFill(1, 0), SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP),
- NWidget(NWID_SPACER), SetMinimalSize(0, 2),
- NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_MALEFEMALE), // Simple male/female face setting.
- NWidget(NWID_VERTICAL),
- NWidget(NWID_SPACER), SetFill(0, 1),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
- NWidget(NWID_SPACER), SetFill(0, 1),
+
+ NWidget(NWID_HORIZONTAL),
+ NWidget(NWID_SPACER), SetFill(1, 0),
+ NWidget(NWID_VERTICAL),
+ NWidget(NWID_SPACER), SetFill(0, 1),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON), SetFill(1, 0), SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 2),
+ NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_MALEFEMALE), // Simple male/female face setting.
+ NWidget(NWID_VERTICAL),
+ NWidget(NWID_SPACER), SetFill(0, 1),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
+ NWidget(NWID_SPACER), SetFill(0, 1),
+ EndContainer(),
EndContainer(),
- EndContainer(),
- NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_PARTS), // Advanced face parts setting.
- NWidget(NWID_VERTICAL),
- NWidget(NWID_SPACER), SetMinimalSize(0, 2),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE2), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE2), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
- EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 2),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_EUR), SetFill(1, 0), SetDataTip(STR_FACE_EUROPEAN, STR_FACE_SELECT_EUROPEAN),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_AFR), SetFill(1, 0), SetDataTip(STR_FACE_AFRICAN, STR_FACE_SELECT_AFRICAN),
- EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 4),
+ NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_PARTS), // Advanced face parts setting.
NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_MOUSTACHE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_MOUSTACHE_EARRING_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAS_GLASSES_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP),
- EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetFill(1, 0),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAIR_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_L), SetDataTip(AWV_DECREASE, STR_FACE_HAIR_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAIR), SetDataTip(STR_EMPTY, STR_FACE_HAIR_TOOLTIP),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_R), SetDataTip(AWV_INCREASE, STR_FACE_HAIR_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYEBROWS_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_L), SetDataTip(AWV_DECREASE, STR_FACE_EYEBROWS_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYEBROWS), SetDataTip(STR_EMPTY, STR_FACE_EYEBROWS_TOOLTIP),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_R), SetDataTip(AWV_INCREASE, STR_FACE_EYEBROWS_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYECOLOUR_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_L), SetDataTip(AWV_DECREASE, STR_FACE_EYECOLOUR_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR), SetDataTip(STR_EMPTY, STR_FACE_EYECOLOUR_TOOLTIP),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_R), SetDataTip(AWV_INCREASE, STR_FACE_EYECOLOUR_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_GLASSES_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_L), SetDataTip(AWV_DECREASE, STR_FACE_GLASSES_TOOLTIP_2),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP_2),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_R), SetDataTip(AWV_INCREASE, STR_FACE_GLASSES_TOOLTIP_2),
- EndContainer(),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_NOSE_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_L), SetDataTip(AWV_DECREASE, STR_FACE_NOSE_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_NOSE), SetDataTip(STR_EMPTY, STR_FACE_NOSE_TOOLTIP),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_R), SetDataTip(AWV_INCREASE, STR_FACE_NOSE_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_LIPS_MOUSTACHE_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_L), SetDataTip(AWV_DECREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE), SetDataTip(STR_EMPTY, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_R), SetDataTip(AWV_INCREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_CHIN_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_L), SetDataTip(AWV_DECREASE, STR_FACE_CHIN_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CHIN), SetDataTip(STR_EMPTY, STR_FACE_CHIN_TOOLTIP),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_R), SetDataTip(AWV_INCREASE, STR_FACE_CHIN_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_JACKET_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_L), SetDataTip(AWV_DECREASE, STR_FACE_JACKET_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_JACKET), SetDataTip(STR_EMPTY, STR_FACE_JACKET_TOOLTIP),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_R), SetDataTip(AWV_INCREASE, STR_FACE_JACKET_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_COLLAR_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_L), SetDataTip(AWV_DECREASE, STR_FACE_COLLAR_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_COLLAR), SetDataTip(STR_EMPTY, STR_FACE_COLLAR_TOOLTIP),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_R), SetDataTip(AWV_INCREASE, STR_FACE_COLLAR_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_TIE_EARRING_TEXT), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_L), SetDataTip(AWV_DECREASE, STR_FACE_TIE_EARRING_TOOLTIP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_TIE_EARRING_TOOLTIP),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_R), SetDataTip(AWV_INCREASE, STR_FACE_TIE_EARRING_TOOLTIP),
+ NWidget(NWID_VERTICAL),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 2),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE2), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE2), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 2),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_EUR), SetFill(1, 0), SetDataTip(STR_FACE_EUROPEAN, STR_FACE_SELECT_EUROPEAN),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_AFR), SetFill(1, 0), SetDataTip(STR_FACE_AFRICAN, STR_FACE_SELECT_AFRICAN),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 4),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_MOUSTACHE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_MOUSTACHE_EARRING_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAS_GLASSES_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetFill(1, 0),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAIR_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_L), SetSizingType(NWST_STEP), SetDataTip(AWV_DECREASE, STR_FACE_HAIR_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAIR), SetSizingType(NWST_STEP), SetDataTip(STR_EMPTY, STR_FACE_HAIR_TOOLTIP),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_R), SetSizingType(NWST_STEP), SetDataTip(AWV_INCREASE, STR_FACE_HAIR_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYEBROWS_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_L), SetSizingType(NWST_STEP), SetDataTip(AWV_DECREASE, STR_FACE_EYEBROWS_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYEBROWS), SetSizingType(NWST_STEP), SetDataTip(STR_EMPTY, STR_FACE_EYEBROWS_TOOLTIP),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_R), SetSizingType(NWST_STEP), SetDataTip(AWV_INCREASE, STR_FACE_EYEBROWS_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYECOLOUR_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_L), SetSizingType(NWST_STEP), SetDataTip(AWV_DECREASE, STR_FACE_EYECOLOUR_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR), SetSizingType(NWST_STEP), SetDataTip(STR_EMPTY, STR_FACE_EYECOLOUR_TOOLTIP),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_R), SetSizingType(NWST_STEP), SetDataTip(AWV_INCREASE, STR_FACE_EYECOLOUR_TOOLTIP),
+ EndContainer(),
+ EndContainer(),
+ NWidget(NWID_VERTICAL),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_GLASSES_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_L), SetSizingType(NWST_STEP), SetDataTip(AWV_DECREASE, STR_FACE_GLASSES_TOOLTIP_2),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_GLASSES), SetSizingType(NWST_STEP), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP_2),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_R), SetSizingType(NWST_STEP), SetDataTip(AWV_INCREASE, STR_FACE_GLASSES_TOOLTIP_2),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_NOSE_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_L), SetSizingType(NWST_STEP), SetDataTip(AWV_DECREASE, STR_FACE_NOSE_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_NOSE), SetSizingType(NWST_STEP), SetDataTip(STR_EMPTY, STR_FACE_NOSE_TOOLTIP),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_R), SetSizingType(NWST_STEP), SetDataTip(AWV_INCREASE, STR_FACE_NOSE_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_LIPS_MOUSTACHE_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_L), SetSizingType(NWST_STEP), SetDataTip(AWV_DECREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE), SetSizingType(NWST_STEP), SetDataTip(STR_EMPTY, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_R), SetSizingType(NWST_STEP), SetDataTip(AWV_INCREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_CHIN_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_L), SetSizingType(NWST_STEP), SetDataTip(AWV_DECREASE, STR_FACE_CHIN_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CHIN), SetSizingType(NWST_STEP), SetDataTip(STR_EMPTY, STR_FACE_CHIN_TOOLTIP),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_R), SetSizingType(NWST_STEP), SetDataTip(AWV_INCREASE, STR_FACE_CHIN_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_JACKET_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_L), SetSizingType(NWST_STEP), SetDataTip(AWV_DECREASE, STR_FACE_JACKET_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_JACKET), SetSizingType(NWST_STEP), SetDataTip(STR_EMPTY, STR_FACE_JACKET_TOOLTIP),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_R), SetSizingType(NWST_STEP), SetDataTip(AWV_INCREASE, STR_FACE_JACKET_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_COLLAR_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_L), SetSizingType(NWST_STEP), SetDataTip(AWV_DECREASE, STR_FACE_COLLAR_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_COLLAR), SetSizingType(NWST_STEP), SetDataTip(STR_EMPTY, STR_FACE_COLLAR_TOOLTIP),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_R), SetSizingType(NWST_STEP), SetDataTip(AWV_INCREASE, STR_FACE_COLLAR_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_TIE_EARRING_TEXT), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_L), SetSizingType(NWST_STEP), SetDataTip(AWV_DECREASE, STR_FACE_TIE_EARRING_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING), SetSizingType(NWST_STEP), SetDataTip(STR_EMPTY, STR_FACE_TIE_EARRING_TOOLTIP),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_R), SetSizingType(NWST_STEP), SetDataTip(AWV_INCREASE, STR_FACE_TIE_EARRING_TOOLTIP),
+ EndContainer(),
+ EndContainer(),
EndContainer(),
NWidget(NWID_SPACER), SetFill(0, 1),
EndContainer(),
EndContainer(),
+ NWidget(NWID_SPACER), SetFill(1, 0),
EndContainer(),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
@@ -1075,7 +1086,7 @@ class SelectCompanyManagerFaceWindow : public Window
/* Draw the value/bool in white (0xC). If the button clicked adds 1px to x and y text coordinates (IsWindowWidgetLowered()). */
DrawString(nwi_widget->pos_x + nwi_widget->IsLowered(), nwi_widget->pos_x + nwi_widget->current_x - 1 - nwi_widget->IsLowered(),
- nwi_widget->pos_y + 1 + nwi_widget->IsLowered(), str, TC_WHITE, SA_HOR_CENTER);
+ Center(nwi_widget->pos_y + nwi_widget->IsLowered(), nwi_widget->current_y), str, TC_WHITE, SA_HOR_CENTER);
}
}
@@ -1125,6 +1136,10 @@ public:
Dimension yesno_dim = maxdim(GetStringBoundingBox(STR_FACE_YES), GetStringBoundingBox(STR_FACE_NO));
yesno_dim.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
yesno_dim.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
+
+ yesno_dim.width = GetMinSizing(NWST_STEP, yesno_dim.width);
+ yesno_dim.height = GetMinSizing(NWST_STEP, yesno_dim.height);
+
/* Size of the number button + arrows. */
Dimension number_dim = {0, 0};
for (int val = 1; val <= 12; val++) {
@@ -1268,12 +1283,12 @@ public:
case WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT:
case WID_SCMF_TIE_EARRING_TEXT: {
StringID str = PART_TEXTS_IS_FEMALE[(widget - WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT) * 2 + this->is_female];
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_GOLD, SA_RIGHT);
+ DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(r.top, r.bottom - r.top), str, TC_GOLD, SA_RIGHT);
break;
}
case WID_SCMF_LIPS_MOUSTACHE_TEXT:
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, (this->is_moust_male) ? STR_FACE_MOUSTACHE : STR_FACE_LIPS, TC_GOLD, SA_RIGHT);
+ DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(r.top, r.bottom - r.top), (this->is_moust_male) ? STR_FACE_MOUSTACHE : STR_FACE_LIPS, TC_GOLD, SA_RIGHT);
break;
case WID_SCMF_HAS_GLASSES_TEXT:
@@ -1285,7 +1300,7 @@ public:
case WID_SCMF_CHIN_TEXT:
case WID_SCMF_JACKET_TEXT:
case WID_SCMF_COLLAR_TEXT:
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, PART_TEXTS[widget - WID_SCMF_HAS_GLASSES_TEXT], TC_GOLD, SA_RIGHT);
+ DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(r.top, r.bottom - r.top), PART_TEXTS[widget - WID_SCMF_HAS_GLASSES_TEXT], TC_GOLD, SA_RIGHT);
break;
diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp
index 8d9e04113d..80352031d5 100644
--- a/src/console_cmds.cpp
+++ b/src/console_cmds.cpp
@@ -425,6 +425,20 @@ DEF_CONSOLE_CMD(ConListFiles)
return true;
}
+/* Open the cheat window. */
+DEF_CONSOLE_CMD(ConOpenCheats)
+{
+ if (argc == 0) {
+ IConsoleHelp("Open the cheat window. Usage: 'open_cheats'");
+ return true;
+ }
+
+ extern void ShowCheatWindow();
+ ShowCheatWindow();
+
+ return true;
+}
+
/* Change the dir via console */
DEF_CONSOLE_CMD(ConChangeDirectory)
{
@@ -1928,6 +1942,8 @@ void IConsoleStdLibRegister()
IConsoleCmdRegister("save", ConSave);
IConsoleCmdRegister("saveconfig", ConSaveConfig);
IConsoleCmdRegister("ls", ConListFiles);
+ IConsoleCmdRegister("open_cheats", ConOpenCheats);
+ IConsoleCmdRegister("cheats", ConOpenCheats);
IConsoleCmdRegister("cd", ConChangeDirectory);
IConsoleCmdRegister("pwd", ConPrintWorkingDirectory);
IConsoleCmdRegister("clear", ConClearBuffer);
diff --git a/src/console_gui.cpp b/src/console_gui.cpp
index ed46938cd5..ed84f6fe09 100644
--- a/src/console_gui.cpp
+++ b/src/console_gui.cpp
@@ -22,6 +22,7 @@
#include "console_func.h"
#include "rev.h"
#include "video/video_driver.hpp"
+#include "textbuf_gui.h"
#include "widgets/console_widget.h"
@@ -29,6 +30,10 @@
#include "safeguards.h"
+#ifdef __ANDROID__
+#include
+#endif
+
static const uint ICON_HISTORY_SIZE = 20;
static const uint ICON_LINE_SPACING = 2;
static const uint ICON_RIGHT_BORDERWIDTH = 10;
@@ -229,6 +234,16 @@ struct IConsoleWindow : Window
}
}
+ virtual void OnQueryTextFinished(char *str)
+ {
+ _focused_window = this;
+
+ if (str == NULL) return;
+
+ _iconsole_cmdline.Assign(str);
+ this->OnKeyPress(0, WKC_RETURN);
+ }
+
virtual void OnHundredthTick()
{
if (IConsoleLine::Truncate() &&
@@ -430,9 +445,25 @@ void IConsoleSwitch()
{
switch (_iconsole_mode) {
case ICONSOLE_CLOSED:
- new IConsoleWindow();
+#ifdef __ANDROID__
+ {
+ char buf[1024] = "";
+ for (const IConsoleLine *print = IConsoleLine::Get(0); print != NULL; print = print->previous) {
+ if (print->buffer && print->buffer[0]) {
+ strecat(buf, print->buffer, lastof(buf));
+ strecat(buf, "\n", lastof(buf));
+ }
+ }
+ strecat(buf, "\n\n\n\n\n\n\n\n", lastof(buf)); // Move all text to top
+ SDL_ANDROID_SetScreenKeyboardHintMesage(buf);
+ char text[512] = "";
+ SDL_ANDROID_GetScreenKeyboardTextInput(text, sizeof(text) - 1); /* Invoke Android built-in screen keyboard */
+ IConsoleCmdExec(text);
+ }
+#else
+ new IConsoleWindow();
+#endif
break;
-
case ICONSOLE_OPENED: case ICONSOLE_FULL:
DeleteWindowById(WC_CONSOLE, 0);
break;
diff --git a/src/core/enum_type.hpp b/src/core/enum_type.hpp
index 35a0cb2926..b5a12c4836 100644
--- a/src/core/enum_type.hpp
+++ b/src/core/enum_type.hpp
@@ -28,6 +28,19 @@
}
+/** Some enums need to have cycling through values */
+#define DECLARE_CYCLE(type, min_val, max_val) \
+ inline type CycleUp(type e) \
+ { \
+ assert(!((int)e < min_val || (int)e > max_val)); \
+ return e == max_val ? (type)min_val : (type)((int)e + 1); \
+ } \
+ inline type CycleDown(type e) \
+ { \
+ assert(!((int)e < min_val || (int)e > max_val)); \
+ return e == min_val ? (type)max_val : (type)((int)e - 1); \
+ }
+
/** Operators to allow to work with enum as with type safe bit set in C++ */
# define DECLARE_ENUM_AS_BIT_SET(mask_t) \
diff --git a/src/debug.cpp b/src/debug.cpp
index 16eecadad0..f03e9490bd 100644
--- a/src/debug.cpp
+++ b/src/debug.cpp
@@ -16,6 +16,9 @@
#include "string_func.h"
#include "fileio_func.h"
#include "settings_type.h"
+#ifdef __ANDROID__
+#include
+#endif
#include
@@ -109,6 +112,9 @@ char *DumpDebugFacilityNames(char *buf, char *last)
*/
static void debug_print(const char *dbg, const char *buf)
{
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_INFO, "OpenTTD", "[%s] %s", dbg, buf);
+#endif
#if defined(ENABLE_NETWORK)
if (_debug_socket != INVALID_SOCKET) {
char buf2[1024 + 32];
diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp
index fe75708ddf..54d56087f8 100644
--- a/src/depot_gui.cpp
+++ b/src/depot_gui.cpp
@@ -62,8 +62,8 @@ static const NWidgetPart _nested_train_depot_widgets[] = {
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_D_SHOW_SELL_CHAIN),
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_D_SELL_CHAIN), SetDataTip(SPR_SELL_CHAIN_TRAIN, STR_DEPOT_DRAG_WHOLE_TRAIN_TO_SELL_TOOLTIP), SetResize(0, 1), SetFill(0, 1),
EndContainer(),
- NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_SELL_ALL), SetDataTip(0x0, STR_NULL),
- NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_AUTOREPLACE), SetDataTip(0x0, STR_NULL),
+ NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_SELL_ALL), SetResize(0, 1), SetFill(0, 1), SetDataTip(0x0, STR_NULL),
+ NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_AUTOREPLACE), SetResize(0, 1), SetFill(0, 1), SetDataTip(0x0, STR_NULL),
EndContainer(),
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_D_V_SCROLL),
EndContainer(),
@@ -297,7 +297,7 @@ struct DepotWindow : Window {
/* Length of consist in tiles with 1 fractional digit (rounded up) */
SetDParam(0, CeilDiv(u->gcache.cached_total_length * 10, TILE_SIZE));
SetDParam(1, 1);
- DrawString(rtl ? left + WD_FRAMERECT_LEFT : right - this->count_width, rtl ? left + this->count_width : right - WD_FRAMERECT_RIGHT, y + (this->resize.step_height - FONT_HEIGHT_SMALL) / 2, STR_TINY_BLACK_DECIMAL, TC_FROMSTRING, SA_RIGHT); // Draw the counter
+ DrawString(rtl ? left + WD_FRAMERECT_LEFT : right - this->count_width, rtl ? left + this->count_width : right - WD_FRAMERECT_RIGHT, Center(y, this->resize.step_height, FONT_HEIGHT_SMALL), STR_TINY_BLACK_DECIMAL, TC_FROMSTRING, SA_RIGHT); // Draw the counter
break;
}
@@ -307,26 +307,28 @@ struct DepotWindow : Window {
default: NOT_REACHED();
}
- uint diff_x, diff_y;
+ uint diff_x, y_sprite, y_num;
if (v->IsGroundVehicle()) {
/* Arrange unitnumber and flag horizontally */
diff_x = this->flag_width + WD_FRAMERECT_LEFT;
- diff_y = (this->resize.step_height - this->flag_height) / 2 - 2;
+ y_sprite = Center(y, this->resize.step_height, this->flag_height);
+ y_num = Center(y, this->resize.step_height);
} else {
/* Arrange unitnumber and flag vertically */
diff_x = WD_FRAMERECT_LEFT;
- diff_y = FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
+ y_num = Center(y, this->resize.step_height, FONT_HEIGHT_NORMAL + this->flag_height + 2);
+ y_sprite = y_num + FONT_HEIGHT_NORMAL;
}
int text_left = rtl ? right - this->header_width - 1 : left + diff_x;
int text_right = rtl ? right - diff_x : left + this->header_width - 1;
if (free_wagon) {
- DrawString(text_left, text_right, y + 2, STR_DEPOT_NO_ENGINE);
+ DrawString(text_left, text_right, Center(y, this->resize.step_height), STR_DEPOT_NO_ENGINE);
} else {
- DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, rtl ? right - this->flag_width : left + WD_FRAMERECT_LEFT, y + diff_y);
+ DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, rtl ? right - this->flag_width : left + WD_FRAMERECT_LEFT, y_sprite);
SetDParam(0, v->unitnumber);
- DrawString(text_left, text_right, y + 2, (uint16)(v->max_age - DAYS_IN_LEAP_YEAR) >= v->age ? STR_BLACK_COMMA : STR_RED_COMMA);
+ DrawString(text_left, text_right, y_num, (uint16)(v->max_age - DAYS_IN_LEAP_YEAR) >= v->age ? STR_BLACK_COMMA : STR_RED_COMMA);
}
}
@@ -343,7 +345,7 @@ struct DepotWindow : Window {
uint16 num = this->vscroll->GetPosition() * this->num_columns;
int maxval = min(this->vehicle_list.Length(), num + (rows_in_display * this->num_columns));
int y;
- for (y = r.top + 1; num < maxval; y += this->resize.step_height) { // Draw the rows
+ for (y = r.top; num < maxval; y += this->resize.step_height) { // Draw the rows
for (byte i = 0; i < this->num_columns && num < maxval; i++, num++) {
/* Draw all vehicles in the current row */
const Vehicle *v = this->vehicle_list[num];
@@ -625,6 +627,7 @@ struct DepotWindow : Window {
int base_width = this->count_width + this->header_width;
resize->height = max(GetVehicleImageCellSize(this->type, EIT_IN_DEPOT).height, min_height);
+ resize->height = GetMinSizing(NWST_STEP, resize->height);
if (this->type == VEH_TRAIN) {
resize->width = 1;
size->width = base_width + 2 * ScaleGUITrad(29); // about 2 parts
diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp
index f6699daeff..486982b96d 100644
--- a/src/dock_gui.cpp
+++ b/src/dock_gui.cpp
@@ -27,6 +27,7 @@
#include "hotkeys.h"
#include "gui.h"
#include "zoom_func.h"
+#include "bridge_map.h"
#include "widgets/dock_widget.h"
@@ -105,6 +106,7 @@ struct BuildDocksToolbarWindow : Window {
~BuildDocksToolbarWindow()
{
+ if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort();
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
}
@@ -146,7 +148,7 @@ struct BuildDocksToolbarWindow : Window {
case WID_DT_DEPOT: // Build depot button
if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return;
- if (HandlePlacePushButton(this, WID_DT_DEPOT, SPR_CURSOR_SHIP_DEPOT, HT_RECT)) ShowBuildDocksDepotPicker(this);
+ if (HandlePlacePushButton(this, WID_DT_DEPOT, SPR_CURSOR_SHIP_DEPOT, HT_RECT | HT_SCROLL_VIEWPORT)) ShowBuildDocksDepotPicker(this);
break;
case WID_DT_STATION: // Build station button
@@ -156,7 +158,7 @@ struct BuildDocksToolbarWindow : Window {
case WID_DT_BUOY: // Build buoy button
if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return;
- HandlePlacePushButton(this, WID_DT_BUOY, SPR_CURSOR_BUOY, HT_RECT);
+ HandlePlacePushButton(this, WID_DT_BUOY, SPR_CURSOR_BUOY, HT_RECT | HT_SCROLL_VIEWPORT);
break;
case WID_DT_RIVER: // Build river button (in scenario editor)
@@ -181,33 +183,21 @@ struct BuildDocksToolbarWindow : Window {
break;
case WID_DT_LOCK: // Build lock button
- DoCommandP(tile, 0, 0, CMD_BUILD_LOCK | CMD_MSG(STR_ERROR_CAN_T_BUILD_LOCKS), CcBuildDocks);
+ /* Reuse DDSP_REMOVE_TRUCKSTOP. */
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_REMOVE_TRUCKSTOP);
break;
case WID_DT_DEMOLISH: // Demolish aka dynamite button
PlaceProc_DemolishArea(tile);
break;
+ case WID_DT_STATION: // Build station button
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_BUILD_STATION);
+ break;
+
case WID_DT_DEPOT: // Build depot button
- DoCommandP(tile, _ship_depot_direction, 0, CMD_BUILD_SHIP_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_SHIP_DEPOT), CcBuildDocks);
- break;
-
- case WID_DT_STATION: { // Build station button
- uint32 p2 = (uint32)INVALID_STATION << 16; // no station to join
-
- /* tile is always the land tile, so need to evaluate _thd.pos */
- CommandContainer cmdcont = { tile, _ctrl_pressed, p2, CMD_BUILD_DOCK | CMD_MSG(STR_ERROR_CAN_T_BUILD_DOCK_HERE), CcBuildDocks, "" };
-
- /* Determine the watery part of the dock. */
- DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile));
- TileIndex tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile, ReverseDiagDir(dir)) : tile);
-
- ShowSelectStationIfNeeded(cmdcont, TileArea(tile, tile_to));
- break;
- }
-
case WID_DT_BUOY: // Build buoy button
- DoCommandP(tile, 0, 0, CMD_BUILD_BUOY | CMD_MSG(STR_ERROR_CAN_T_POSITION_BUOY_HERE), CcBuildDocks);
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_SINGLE_TILE);
break;
case WID_DT_RIVER: // Build river button (in scenario editor)
@@ -215,7 +205,7 @@ struct BuildDocksToolbarWindow : Window {
break;
case WID_DT_BUILD_AQUEDUCT: // Build aqueduct button
- DoCommandP(tile, GetOtherAqueductEnd(tile), TRANSPORT_WATER << 15, CMD_BUILD_BRIDGE | CMD_MSG(STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE), CcBuildBridge);
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_BUILD_BRIDGE);
break;
default: NOT_REACHED();
@@ -224,7 +214,16 @@ struct BuildDocksToolbarWindow : Window {
virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
{
- VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+ switch (last_clicked_widget) {
+ case WID_DT_BUILD_AQUEDUCT:
+ case WID_DT_LOCK:
+ case WID_DT_STATION:
+ this->OnPlacePresize(pt, TileVirtXY(pt.x, pt.y));
+ break;
+ default:
+ VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+ break;
+ }
}
virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
@@ -240,6 +239,42 @@ struct BuildDocksToolbarWindow : Window {
case DDSP_CREATE_RIVER:
DoCommandP(end_tile, start_tile, WATER_CLASS_RIVER, CMD_BUILD_CANAL | CMD_MSG(STR_ERROR_CAN_T_PLACE_RIVERS), CcBuildCanal);
break;
+ case DDSP_BUILD_STATION: {
+ uint32 p2 = (uint32)INVALID_STATION << 16; // no station to join
+
+ /* Tile is always the land tile, so need to evaluate _thd.pos. */
+ CommandContainer cmdcont = { start_tile, _ctrl_pressed, p2, CMD_BUILD_DOCK | CMD_MSG(STR_ERROR_CAN_T_BUILD_DOCK_HERE), CcBuildDocks, "" };
+
+ //SetObjectToPlace(SPR_CURSOR_DOCK, PAL_NONE, HT_SPECIAL, this->window_class, this->window_number);
+ ShowSelectStationIfNeeded(cmdcont, TileArea(start_tile, end_tile));
+ VpStartPreSizing();
+ break;
+ }
+
+ case DDSP_BUILD_BRIDGE:
+ DoCommandP(start_tile, GetOtherAqueductEnd(start_tile), TRANSPORT_WATER << 15, CMD_BUILD_BRIDGE | CMD_MSG(STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE), CcBuildBridge);
+ VpStartPreSizing();
+ break;
+
+ case DDSP_REMOVE_TRUCKSTOP: { // Reusing for locks.
+ TileIndex middle_tile = start_tile;
+ if (start_tile != end_tile) middle_tile = TileAddByDiagDir(start_tile, DiagdirBetweenTiles(start_tile, end_tile));
+ DoCommandP(middle_tile, 0, 0, CMD_BUILD_LOCK | CMD_MSG(STR_ERROR_CAN_T_BUILD_LOCKS), CcBuildDocks);
+ VpStartPreSizing();
+ break;
+ }
+
+ case DDSP_SINGLE_TILE:
+ assert(start_tile == end_tile);
+ switch (last_clicked_widget) {
+ case WID_DT_BUOY:
+ DoCommandP(end_tile, 0, 0, CMD_BUILD_BUOY | CMD_MSG(STR_ERROR_CAN_T_POSITION_BUOY_HERE), CcBuildDocks);
+ break;
+ case WID_DT_DEPOT: // Build depot button
+ DoCommandP(end_tile, _ship_depot_direction, 0, CMD_BUILD_SHIP_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_SHIP_DEPOT), CcBuildDocks);
+ break;
+ default: NOT_REACHED();
+ }
default: break;
}
@@ -256,8 +291,19 @@ struct BuildDocksToolbarWindow : Window {
DeleteWindowByClass(WC_BUILD_BRIDGE);
}
+ virtual void SelectLastTool()
+ {
+ // User misplaced something - activate last selected tool again
+ if (this->last_clicked_widget == WIDGET_LIST_END)
+ return;
+ Point dummy = {0, 0};
+ this->RaiseWidget(this->last_clicked_widget);
+ this->OnClick(dummy, this->last_clicked_widget, 0);
+ }
+
virtual void OnPlacePresize(Point pt, TileIndex tile_from)
{
+ if (!IsValidTile(tile_from)) return;
TileIndex tile_to = tile_from;
if (this->last_clicked_widget == WID_DT_BUILD_AQUEDUCT) {
@@ -347,7 +393,7 @@ Window *ShowBuildDocksToolbar()
{
if (!Company::IsValidID(_local_company)) return NULL;
- DeleteWindowByClass(WC_BUILD_TOOLBAR);
+ DeleteToolbarLinkedWindows();
return AllocateWindowDescFront(&_build_docks_toolbar_desc, TRANSPORT_WATER);
}
@@ -373,7 +419,7 @@ static const NWidgetPart _nested_build_docks_scen_toolbar_widgets[] = {
/** Window definition for the build docks in scenario editor window. */
static WindowDesc _build_docks_scen_toolbar_desc(
- WDP_AUTO, "toolbar_water_scen", 0, 0,
+ WDP_ALIGN_TOOLBAR, "toolbar_water_scen", 0, 0,
WC_SCEN_BUILD_TOOLBAR, WC_NONE,
WDF_CONSTRUCTION,
_nested_build_docks_scen_toolbar_widgets, lengthof(_nested_build_docks_scen_toolbar_widgets)
@@ -386,6 +432,7 @@ static WindowDesc _build_docks_scen_toolbar_desc(
*/
Window *ShowBuildDocksScenToolbar()
{
+ DeleteToolbarLinkedWindows();
return AllocateWindowDescFront(&_build_docks_scen_toolbar_desc, TRANSPORT_WATER);
}
@@ -556,10 +603,10 @@ static const NWidgetPart _nested_build_docks_depot_widgets[] = {
NWidget(NWID_SPACER), SetMinimalSize(0, 3),
NWidget(NWID_HORIZONTAL_LTR),
NWidget(NWID_SPACER), SetMinimalSize(3, 0),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BDD_X), SetMinimalSize(98, 66), SetDataTip(0x0, STR_DEPOT_BUILD_SHIP_ORIENTATION_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BDD_X), SetSizingType(NWST_BUTTON), SetMinimalSize(98, 66), SetDataTip(0x0, STR_DEPOT_BUILD_SHIP_ORIENTATION_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(2, 0),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BDD_Y), SetMinimalSize(98, 66), SetDataTip(0x0, STR_DEPOT_BUILD_SHIP_ORIENTATION_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BDD_Y), SetSizingType(NWST_BUTTON), SetMinimalSize(98, 66), SetDataTip(0x0, STR_DEPOT_BUILD_SHIP_ORIENTATION_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(3, 0),
EndContainer(),
diff --git a/src/error_gui.cpp b/src/error_gui.cpp
index 98988de5a0..8d40ebbbbe 100644
--- a/src/error_gui.cpp
+++ b/src/error_gui.cpp
@@ -187,6 +187,7 @@ public:
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);
+ size->width = GetMinSizing(NWST_WINDOW_LENGTH, size->width);
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);
diff --git a/src/fileio.cpp b/src/fileio.cpp
index a72950bc73..467ea0fb92 100644
--- a/src/fileio.cpp
+++ b/src/fileio.cpp
@@ -292,7 +292,11 @@ static const char * const _subdirs[] = {
"ai" PATHSEP "library" PATHSEP,
"game" PATHSEP,
"game" PATHSEP "library" PATHSEP,
+#ifdef __ANDROID__
"screenshot" PATHSEP,
+#else
+ "screenshot" PATHSEP,
+#endif
};
assert_compile(lengthof(_subdirs) == NUM_SUBDIRS);
@@ -1315,6 +1319,21 @@ void DeterminePaths(const char *exe)
_searchpaths[SP_AUTODOWNLOAD_DIR] = NULL;
}
#endif /* ENABLE_NETWORK */
+
+#ifdef __ANDROID__
+ // Copy savegames from "full" OpenTTD to "lite" save directory
+ char curdir[PATH_MAX];
+ if (getcwd(curdir, sizeof(curdir)) && strstr(curdir, "org.openttd.sdl.lowmem")) {
+ // No, I won't implement file copying in C, shell script is just fine for this job
+ DEBUG(misc, 1, "Copying savegames from ../../org.openttd.sdl/files/.openttd/save to %s", curdir);
+ system("cd ../../org.openttd.sdl/files/.openttd/save && "
+ "for F in *.sav ; do "
+ "ls \"../../../../org.openttd.sdl.lowmem/files/.openttd/save/$F\" || "
+ "cat \"$F\" > \"../../../../org.openttd.sdl.lowmem/files/.openttd/save/$F\" ; "
+ "done");
+ chdir(curdir);
+ }
+#endif
}
/**
diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp
index 9316deb658..1af2d14e41 100644
--- a/src/fios_gui.cpp
+++ b/src/fios_gui.cpp
@@ -35,12 +35,16 @@
#include "table/strings.h"
#include "safeguards.h"
+#ifdef __ANDROID__
+#include
+#endif
SaveLoadDialogMode _saveload_mode;
LoadCheckData _load_check_data; ///< Data loaded from save during SL_LOAD_CHECK.
static bool _fios_path_changed;
static bool _savegame_sort_dirty;
+static const char *NETWORK_SAVE_FILENAME = "network-save.sav";
/**
@@ -107,6 +111,9 @@ static const NWidgetPart _nested_load_dialog_widgets[] = {
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SL_NEWGRF_INFO), SetDataTip(STR_INTRO_NEWGRF_SETTINGS, STR_NULL), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SL_LOAD_BUTTON), SetDataTip(STR_SAVELOAD_LOAD_BUTTON, STR_SAVELOAD_LOAD_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
EndContainer(),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SL_LOAD_NETWORK_BUTTON), SetDataTip(STR_SAVELOAD_LOAD_NETWORK_BUTTON, STR_SAVELOAD_LOAD_NETWORK_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
EndContainer(),
EndContainer(),
@@ -180,7 +187,7 @@ static const NWidgetPart _nested_save_dialog_widgets[] = {
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SL_DETAILS), SetResize(1, 1), SetFill(1, 1),
NWidget(NWID_HORIZONTAL),
- NWidget(NWID_SPACER), SetResize(1, 0), SetFill(1, 1),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SL_SAVE_NETWORK_BUTTON), SetDataTip(STR_SAVELOAD_SAVE_NETWORK_BUTTON, STR_SAVELOAD_SAVE_NETWORK_TOOLTIP), SetFill(1, 1), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
EndContainer(),
EndContainer(),
@@ -282,6 +289,7 @@ public:
this->FinishInitNested(0);
this->LowerWidget(WID_SL_DRIVES_DIRECTORIES_LIST);
+ if (mode == SLD_SAVE_GAME) this->SetWidgetLoweredState(WID_SL_SAVE_NETWORK_BUTTON, _settings_client.gui.save_to_network);
/* pause is only used in single-player, non-editor mode, non-menu mode. It
* will be unpaused in the WE_DESTROY event handler. */
@@ -366,7 +374,7 @@ public:
if (item == this->selected) {
GfxFillRect(r.left + 1, y, r.right, y + this->resize.step_height, PC_DARK_BLUE);
}
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, item->title, _fios_colours[item->type]);
+ DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(y, this->resize.step_height), item->title, _fios_colours[item->type]);
y += this->resize.step_height;
if (y >= this->vscroll->GetCapacity() * this->resize.step_height + r.top + WD_FRAMERECT_TOP) break;
}
@@ -477,8 +485,8 @@ public:
break;
case WID_SL_DRIVES_DIRECTORIES_LIST:
- resize->height = FONT_HEIGHT_NORMAL;
- size->height = resize->height * 10 + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
+ resize->height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL);
+ size->height = resize->height * 5 + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
break;
case WID_SL_SORT_BYNAME:
case WID_SL_SORT_BYDATE: {
@@ -624,6 +632,32 @@ public:
/* Note, this is also called via the OSK; and we need to lower the button. */
this->HandleButtonClick(WID_SL_SAVE_GAME);
break;
+
+ case WID_SL_SAVE_NETWORK_BUTTON:
+ _settings_client.gui.save_to_network = !_settings_client.gui.save_to_network;
+ this->SetWidgetLoweredState(WID_SL_SAVE_NETWORK_BUTTON, _settings_client.gui.save_to_network);
+ this->SetDirty();
+ break;
+
+ case WID_SL_LOAD_NETWORK_BUTTON: {
+ char savePath[PATH_MAX];
+ FiosMakeSavegameName(savePath, NETWORK_SAVE_FILENAME, sizeof(savePath));
+#ifdef __ANDROID__
+ if (!SDL_ANDROID_CloudLoad(savePath, NULL, "OpenTTD")) {
+ break;
+ }
+#endif
+ _load_check_data.Clear();
+ SaveOrLoadResult res = SaveOrLoad(savePath, SL_LOAD_CHECK, SAVE_DIR, false);
+ if (res == SL_OK && !_load_check_data.HasErrors()) {
+ strecpy(_file_to_saveload.name, savePath, lastof(_file_to_saveload.name));
+ strecpy(_file_to_saveload.title, "", lastof(_file_to_saveload.title));
+ if (!_load_check_data.HasNewGrfs() || _load_check_data.grf_compatibility != GLC_NOT_FOUND || _settings_client.gui.UserIsAllowedToChangeNewGRFs()) {
+ _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD_GAME;
+ }
+ }
+ break;
+ }
}
}
diff --git a/src/fontcache.cpp b/src/fontcache.cpp
index 6bea59c103..a37ea0b6ec 100644
--- a/src/fontcache.cpp
+++ b/src/fontcache.cpp
@@ -383,7 +383,7 @@ static void LoadFreeTypeFont(FontSize fs)
return;
found_face:
- new FreeTypeFontCache(fs, face, settings->size);
+ new FreeTypeFontCache(fs, face, RescaleFrom854x480(settings->size));
}
@@ -460,7 +460,7 @@ static void *AllocateFont(size_t size)
static bool GetFontAAState(FontSize size)
{
/* AA is only supported for 32 bpp */
- if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 32) return false;
+ if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 32 && BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 16) return false;
switch (size) {
default: NOT_REACHED();
diff --git a/src/fontdetection.cpp b/src/fontdetection.cpp
index 6df45cf6a1..d1d9a36f96 100644
--- a/src/fontdetection.cpp
+++ b/src/fontdetection.cpp
@@ -645,6 +645,7 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i
if (fs != NULL) {
int best_weight = -1;
const char *best_font = NULL;
+ int best_missing_glypths = 65536;
for (int i = 0; i < fs->nfont; i++) {
FcPattern *font = fs->fonts[i];
@@ -670,12 +671,13 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i
callback->SetFontNames(settings, (const char*)file);
- bool missing = callback->FindMissingGlyphs(NULL);
- DEBUG(freetype, 1, "Font \"%s\" misses%s glyphs", file, missing ? "" : " no");
+ int missing = callback->FindMissingGlyphs(NULL);
+ DEBUG(freetype, 1, "Font \"%s\" misses %d glyphs for lang %s", file, missing, lang);
- if (!missing) {
+ if (missing < best_missing_glypths) {
best_weight = value;
best_font = (const char *)file;
+ best_missing_glypths = missing;
}
}
@@ -683,6 +685,7 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i
ret = true;
callback->SetFontNames(settings, best_font);
InitFreeType(callback->Monospace());
+ DEBUG(freetype, 1, "Selected font %s for lang %s", best_font, lang);
}
/* Clean up the list of filenames. */
diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp
index 1e9485b5f6..2eb3155cf7 100644
--- a/src/genworld_gui.cpp
+++ b/src/genworld_gui.cpp
@@ -62,20 +62,20 @@ static const NWidgetPart _nested_generate_landscape_widgets[] = {
EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN),
NWidget(NWID_SPACER), SetMinimalSize(0, 10),
- /* Landscape selection. */
- NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 10),
- NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_GL_TEMPERATE), SetDataTip(SPR_SELECT_TEMPERATE, STR_INTRO_TOOLTIP_TEMPERATE),
- NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_GL_ARCTIC), SetDataTip(SPR_SELECT_SUB_ARCTIC, STR_INTRO_TOOLTIP_SUB_ARCTIC_LANDSCAPE),
- NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_GL_TROPICAL), SetDataTip(SPR_SELECT_SUB_TROPICAL, STR_INTRO_TOOLTIP_SUB_TROPICAL_LANDSCAPE),
- NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_GL_TOYLAND), SetDataTip(SPR_SELECT_TOYLAND, STR_INTRO_TOOLTIP_TOYLAND_LANDSCAPE),
- NWidget(NWID_SPACER), SetFill(1, 0),
- EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 11),
NWidget(NWID_HORIZONTAL), SetPIP(10, 5, 10),
+ /* Landscape selection. */
+ NWidget(NWID_VERTICAL), SetPIP(10, 0, 10),
+ NWidget(NWID_SPACER), SetFill(1, 1),
+ NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_GL_TEMPERATE), SetDataTip(SPR_SELECT_TEMPERATE, STR_INTRO_TOOLTIP_TEMPERATE),
+ NWidget(NWID_SPACER), SetFill(1, 1),
+ NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_GL_ARCTIC), SetDataTip(SPR_SELECT_SUB_ARCTIC, STR_INTRO_TOOLTIP_SUB_ARCTIC_LANDSCAPE),
+ NWidget(NWID_SPACER), SetFill(1, 1),
+ NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_GL_TROPICAL), SetDataTip(SPR_SELECT_SUB_TROPICAL, STR_INTRO_TOOLTIP_SUB_TROPICAL_LANDSCAPE),
+ NWidget(NWID_SPACER), SetFill(1, 1),
+ NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_GL_TOYLAND), SetDataTip(SPR_SELECT_TOYLAND, STR_INTRO_TOOLTIP_TOYLAND_LANDSCAPE),
+ NWidget(NWID_SPACER), SetFill(1, 1),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(20, 0),
NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0),
/* Left column with labels. */
NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 4, 0),
@@ -168,7 +168,7 @@ static const NWidgetPart _nested_generate_landscape_widgets[] = {
NWidget(NWID_SPACER), SetFill(1, 1),
EndContainer(),
EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 9), SetFill(1, 1),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 10),
EndContainer(),
};
@@ -457,6 +457,7 @@ struct GenerateLandscapeWindow : public Window {
case WID_GL_MAPSIZE_Y_PULLDOWN:
SetDParamMaxValue(0, MAX_MAP_SIZE);
*size = maxdim(*size, GetStringBoundingBox(STR_JUST_INT));
+ size->width = size->width + GetMinSizing(NWST_BUTTON);
break;
case WID_GL_SNOW_LEVEL_TEXT:
@@ -946,7 +947,9 @@ struct CreateScenarioWindow : public Window
}
*size = maxdim(*size, GetStringBoundingBox(str));
size->width += padding.width;
+ size->width = GetMinSizing(NWST_BUTTON, size->width);
size->height += padding.height;
+ size->height = GetMinSizing(NWST_BUTTON, size->height);
}
virtual void OnClick(Point pt, int widget, int click_count)
@@ -1065,11 +1068,16 @@ static const NWidgetPart _nested_create_scenario_widgets[] = {
NWidget(NWID_SPACER), SetMinimalSize(0, 10),
/* Landscape style selection. */
NWidget(NWID_HORIZONTAL), SetPIP(10, 3, 10),
+ NWidget(NWID_SPACER), SetFill(1, 1),
NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_CS_TEMPERATE), SetDataTip(SPR_SELECT_TEMPERATE, STR_INTRO_TOOLTIP_TEMPERATE),
+ NWidget(NWID_SPACER), SetFill(1, 1),
NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_CS_ARCTIC), SetDataTip(SPR_SELECT_SUB_ARCTIC, STR_INTRO_TOOLTIP_SUB_ARCTIC_LANDSCAPE),
+ NWidget(NWID_SPACER), SetFill(1, 1),
NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_CS_TROPICAL), SetDataTip(SPR_SELECT_SUB_TROPICAL, STR_INTRO_TOOLTIP_SUB_TROPICAL_LANDSCAPE),
+ NWidget(NWID_SPACER), SetFill(1, 1),
NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_CS_TOYLAND), SetDataTip(SPR_SELECT_TOYLAND, STR_INTRO_TOOLTIP_TOYLAND_LANDSCAPE),
- EndContainer(),
+ NWidget(NWID_SPACER), SetFill(1, 1),
+ EndContainer(),
NWidget(NWID_HORIZONTAL), SetPIP(10, 8, 10),
/* Green generation type buttons: 'Flat land' and 'Random land'. */
NWidget(NWID_VERTICAL), SetPIP(10, 6, 10),
diff --git a/src/gfx.cpp b/src/gfx.cpp
index 410a2ee961..80964ed218 100644
--- a/src/gfx.cpp
+++ b/src/gfx.cpp
@@ -34,11 +34,15 @@ byte _support8bpp;
CursorVars _cursor;
bool _ctrl_pressed; ///< Is Ctrl pressed?
bool _shift_pressed; ///< Is Shift pressed?
+bool _move_pressed;
+
byte _fast_forward;
bool _left_button_down; ///< Is left mouse button pressed?
bool _left_button_clicked; ///< Is left mouse button clicked?
bool _right_button_down; ///< Is right mouse button pressed?
bool _right_button_clicked; ///< Is right mouse button clicked?
+Point _right_button_down_pos; ///< Pos of right mouse button click, for drag and drop
+
DrawPixelInfo _screen;
bool _screen_disable_anim = false; ///< Disable palette animation (important for 32bpp-anim blitter during giant screenshot)
bool _exit_game;
@@ -1201,6 +1205,8 @@ void ScreenSizeChanged()
/* screen size changed and the old bitmap is invalid now, so we don't want to undraw it */
_cursor.visible = false;
+
+ NWidgetScrollbar::ResetAllWidgetMinSizes();
}
void UndrawMouseCursor()
@@ -1218,11 +1224,6 @@ void UndrawMouseCursor()
void DrawMouseCursor()
{
-#if defined(WINCE)
- /* Don't ever draw the mouse for WinCE, as we work with a stylus */
- return;
-#endif
-
/* Don't draw the mouse cursor if the screen is not ready */
if (_screen.dst_ptr == NULL) return;
@@ -1678,3 +1679,104 @@ void SortResolutions(int count)
{
QSortT(_resolutions, count, &compare_res);
}
+
+
+/**
+ * Returns the initial value for a margin, after telling where are the left and right margins and where we want to draw/write (begining/end of line)
+ * @param left is the left margin of the horizontal space we want to draw to
+ * @param right: right margin
+ * @param to_end_line: 0 if working at the begining of the line, 1 if working at the end
+ * @return the margin we asked
+ */
+int InitTempMargin(int left, int right, bool to_end_line)
+{
+ return to_end_line ^ (_current_text_dir == TD_RTL) ? right :left;
+}
+
+/**
+ * Consumes a space in an horizontal margin
+ * @param space: amount of space used
+ * @param here: the margin where to add the space
+ * @param to_end_line: 0 if working at the begining of the line, 1 if working at the end
+ */
+void AddSpace(int space, int &here, bool to_end_line)
+{
+ here += to_end_line ^ (_current_text_dir == TD_RTL) ? -space : space;
+}
+
+/**
+ * After drawing something, update a margin
+ * @param end is where we ended drawing (usually the return value of a DrawString function)
+ * @param margin is the margin we want to update
+ * @param to_end_line: 0 if working at the begining of the line, 1 if working at the end
+ */
+void UpdateMarginEnd(int end, int &margin, bool to_end_line)
+{
+ margin = to_end_line ^ (_current_text_dir == TD_RTL) ? min(end, margin) : max(end, margin);
+}
+
+/**
+ * After drawing something, horizontal margins are updated
+ * @param end: last position drawn
+ * @param left is the left margin of the horizontal space drawn
+ * @param right: right margin
+ * @param to_end_line: 0 if working at the begining of the line, 1 if working at the end
+ */
+void UpdateMarginsEnd(int end, int &left, int &right, bool to_end_line)
+{
+ if (to_end_line ^ (_current_text_dir == TD_RTL)) {
+ right = end;
+ } else {
+ left = end;
+ }
+}
+
+/**
+ * After drawing something of a certain width, update margins
+ * @param width: used space
+ * @param initial left margin
+ * @param initial right margin
+ * @param to_end_line: 0 if working at the begining of the line, 1 if working at the end
+ */
+void UpdateMarginsWidth(int width, int &left, int &right, bool to_end_line)
+{
+ if (to_end_line ^ (_current_text_dir == TD_RTL)) {
+ right -= width;
+ } else {
+ left += width;
+ }
+}
+
+/**
+ * Draws a string in a delimited space; temporal margin gets updated
+ * @param left is the left margin of the horizontal space we want to draw to
+ * @param right: right margin of the horizontal space we want to draw to
+ * @param top: vertical position
+ * @param margin keeps the most extreme limit used of the line (this should be previously initialized with InitTempLimit)
+ * @param string to draw
+ * @param colour for the string
+ * @param alignment of the string (only left or right alignment)
+ * @param underline
+ */
+void DrawString2(int left, int right, int top, int &margin, StringID str, TextColour colour, StringAlignment align, bool underline)
+{
+ int end = DrawString(left, right, top, str, colour, align, underline);
+ UpdateMarginEnd(end, margin, align == SA_RIGHT);
+}
+
+/**
+ * Draws a sprite in a delimited space; temporal margin gets updated
+ * @param width of the sprite
+ * @param left is the left margin of the horizontal space we want to draw to
+ * @param right: right margin of the horizontal space
+ * @param top: vertical position
+ * @param margin keeps the most extreme limit used of the line (this should be previously initialized with InitTempLimit)
+ * @param sprite
+ * @param palette
+ * @param to_end_line: 0 if working at the begining of the line, 1 if working at the end
+ */
+void DrawSprite2(int width, int left, int right, int top, int &margin, SpriteID img, PaletteID pal, bool to_end_line, SubSprite *sub)
+{
+ DrawSprite(img, pal, to_end_line ^ (_current_text_dir == TD_RTL) ? right - width : left, top, sub);
+ margin = to_end_line ^ (_current_text_dir == TD_RTL) ? min(right - width, margin): max(margin, left + width);
+}
diff --git a/src/gfx_func.h b/src/gfx_func.h
index 6576dee4fb..f48e3610b3 100644
--- a/src/gfx_func.h
+++ b/src/gfx_func.h
@@ -45,6 +45,7 @@
#include "gfx_type.h"
#include "strings_type.h"
#include "string_type.h"
+#include "core/math_func.hpp"
void GameLoop();
@@ -56,12 +57,15 @@ extern byte _support8bpp;
extern CursorVars _cursor;
extern bool _ctrl_pressed; ///< Is Ctrl pressed?
extern bool _shift_pressed; ///< Is Shift pressed?
+extern bool _move_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 Point _right_button_down_pos;
extern DrawPixelInfo _screen;
extern bool _screen_disable_anim; ///< Disable palette animation (important for 32bpp-anim blitter during giant screenshot)
@@ -172,6 +176,39 @@ int GetCharacterHeight(FontSize size);
/** 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);
+
+/**
+ * Return where to start drawing a centered object inside a widget.
+ * @param top The top coordinate (or the left coordinate) of the widget.
+ * @param height The height (or width) of the widget.
+ * @param size The height (or width) of the object to draw.
+ * @return The coordinate where to start drawing the centered object.
+ */
+static inline int Center(int top, int height, uint size = FONT_HEIGHT_NORMAL)
+{
+ return top + (height - size) / 2;
+}
+
+/**
+ * Returns fint/button size, rescaled to current screen resolution from the base Android resolution, which is 854x480
+ * @param value The value to rescale
+ * @return Rescaled value, using lesser of the curret screen coordinates
+ */
+static inline int RescaleFrom854x480(int value)
+{
+ return min(value * _cur_resolution.width / 854, value * _cur_resolution.height / 480);
+}
+
extern DrawPixelInfo *_cur_dpi;
TextColour GetContrastColour(uint8 background);
diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp
index c12c6ace4d..019c4f039d 100644
--- a/src/graph_gui.cpp
+++ b/src/graph_gui.cpp
@@ -116,6 +116,7 @@ static NWidgetBase *MakeNWidgetCompanyLines(int *biggest_index)
for (int widnum = WID_GL_FIRST_COMPANY; widnum <= WID_GL_LAST_COMPANY; widnum++) {
NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, widnum);
+ panel->sizing_type = NWST_STEP;
panel->SetMinimalSize(246, line_height);
panel->SetFill(1, 0);
panel->SetDataTip(0x0, STR_GRAPH_KEY_COMPANY_SELECTION_TOOLTIP);
@@ -1130,6 +1131,7 @@ private:
uint ordinal_width; ///< The width of the ordinal number
uint text_width; ///< The width of the actual text
uint icon_width; ///< The width of the company icon
+ uint icon_y_offset; ///< The vertical offset for drawing the company icon.
int line_height; ///< Height of the text lines
/**
@@ -1176,8 +1178,7 @@ public:
{
if (widget != WID_CL_BACKGROUND) return;
- int icon_y_offset = 1 + (FONT_HEIGHT_NORMAL - this->line_height) / 2;
- uint y = r.top + WD_FRAMERECT_TOP - icon_y_offset;
+ uint y = r.top + WD_FRAMERECT_TOP;
bool rtl = _current_text_dir == TD_RTL;
uint ordinal_left = rtl ? r.right - WD_FRAMERECT_LEFT - this->ordinal_width : r.left + WD_FRAMERECT_LEFT;
@@ -1190,7 +1191,7 @@ public:
const Company *c = this->companies[i];
DrawString(ordinal_left, ordinal_right, y, i + STR_ORDINAL_NUMBER_1ST, i == 0 ? TC_WHITE : TC_YELLOW);
- DrawCompanyIcon(c->index, icon_left, y + icon_y_offset);
+ DrawCompanyIcon(c->index, icon_left, y + this->icon_y_offset);
SetDParam(0, c->index);
SetDParam(1, c->index);
@@ -1223,6 +1224,7 @@ public:
Dimension d = GetSpriteSize(SPR_COMPANY_ICON);
this->icon_width = d.width + 2;
this->line_height = max(d.height + 2, FONT_HEIGHT_NORMAL);
+ this->icon_y_offset = Center(1, this->line_height, d.height);
const Company *c;
FOR_ALL_COMPANIES(c) {
diff --git a/src/group_gui.cpp b/src/group_gui.cpp
index 06f56b950b..f932508695 100644
--- a/src/group_gui.cpp
+++ b/src/group_gui.cpp
@@ -70,7 +70,7 @@ static const NWidgetPart _nested_group_widgets[] = {
/* 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_PUSHTXTBTN, COLOUR_GREY, WID_GL_SORT_BY_ORDER), SetSizingType(NWST_STEP), 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(),
@@ -78,7 +78,7 @@ static const NWidgetPart _nested_group_widgets[] = {
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(WWT_PANEL, COLOUR_GREY), 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),
@@ -192,8 +192,9 @@ private:
uint ComputeGroupInfoSize()
{
this->column_size[VGC_NAME] = maxdim(GetStringBoundingBox(STR_GROUP_DEFAULT_TRAINS + this->vli.vtype), GetStringBoundingBox(STR_GROUP_ALL_TRAINS + this->vli.vtype));
- this->column_size[VGC_NAME].width = max(170u, this->column_size[VGC_NAME].width);
- this->tiny_step_height = this->column_size[VGC_NAME].height;
+/* 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 = max(11U, 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);
@@ -215,9 +216,10 @@ private:
this->tiny_step_height = max(this->tiny_step_height, this->column_size[VGC_NUMBER].height);
this->tiny_step_height += WD_MATRIX_TOP;
+ this->tiny_step_height = GetMinSizing(NWST_STEP, this->tiny_step_height);
return WD_FRAMERECT_LEFT + 8 +
- this->column_size[VGC_NAME].width + 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 +
@@ -238,7 +240,7 @@ private:
{
/* 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, right - WD_FRAMERECT_RIGHT, y + this->tiny_step_height - WD_FRAMERECT_BOTTOM - WD_MATRIX_TOP, _colour_gradient[COLOUR_GREY][7]);
+ 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;
@@ -249,6 +251,7 @@ private:
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;
@@ -257,12 +260,16 @@ private:
} 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 + 1 : left + WD_FRAMERECT_LEFT + 8;
- DrawString(x + indent * LEVEL_WIDTH, x + this->column_size[VGC_NAME].width - 1, y + (this->tiny_step_height - this->column_size[VGC_NAME].height) / 2, str, colour);
+ int x = rtl ? right - WD_FRAMERECT_RIGHT - 8 - this->column_size[VGC_NAME].width - longer_name + 1 : left + WD_FRAMERECT_LEFT + 8;
+ DrawString(x + indent * LEVEL_WIDTH, 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 - 8 - this->column_size[VGC_PROTECT].width : x + 8 + this->column_size[VGC_NAME].width;
+ 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 */
@@ -363,16 +370,10 @@ public:
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(WID_GL_CREATE_GROUP)->widget_data).height;
- max_icon_height = max(max_icon_height, GetSpriteSize(this->GetWidget(WID_GL_RENAME_GROUP)->widget_data).height);
- max_icon_height = max(max_icon_height, GetSpriteSize(this->GetWidget(WID_GL_DELETE_GROUP)->widget_data).height);
- max_icon_height = max(max_icon_height, GetSpriteSize(this->GetWidget(WID_GL_REPLACE_PROTECTION)->widget_data).height);
+ size->height = (this->vli.vtype >= VEH_SHIP ? 3 : 6) * GetVehicleListHeight(this->vli.vtype, this->tiny_step_height) - 2 * this->tiny_step_height;
/* Get a multiple of tiny_step_height of that amount */
- size->height = Ceil(size->height - max_icon_height, tiny_step_height);
+ size->height = Ceil(size->height, tiny_step_height);
break;
}
@@ -393,7 +394,7 @@ public:
case WID_GL_LIST_VEHICLE:
this->ComputeGroupInfoSize();
resize->height = GetVehicleListHeight(this->vli.vtype, this->tiny_step_height);
- size->height = 4 * resize->height;
+ size->height = (this->vli.vtype >= VEH_SHIP ? 3 : 6) * resize->height;
break;
case WID_GL_MANAGE_VEHICLES_DROPDOWN: {
@@ -520,15 +521,15 @@ public:
{
switch (widget) {
case WID_GL_ALL_VEHICLES:
- DrawGroupInfo(r.top + WD_FRAMERECT_TOP, r.left, r.right, ALL_GROUP);
+ DrawGroupInfo(r.top, r.left, r.right, ALL_GROUP);
break;
case WID_GL_DEFAULT_VEHICLES:
- DrawGroupInfo(r.top + WD_FRAMERECT_TOP, r.left, r.right, DEFAULT_GROUP);
+ DrawGroupInfo(r.top, r.left, r.right, DEFAULT_GROUP);
break;
case WID_GL_LIST_GROUP: {
- int y1 = r.top + WD_FRAMERECT_TOP;
+ 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];
diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp
index 47ca4fd21f..68ad4ff134 100644
--- a/src/industry_gui.cpp
+++ b/src/industry_gui.cpp
@@ -190,7 +190,7 @@ static const NWidgetPart _nested_build_industry_widgets[] = {
/** Window definition of the dynamic place industries gui */
static WindowDesc _build_industry_desc(
- WDP_AUTO, "build_industry", 170, 212,
+ WDP_ALIGN_TOOLBAR, "build_industry", 170, 212,
WC_BUILD_INDUSTRY, WC_NONE,
WDF_CONSTRUCTION,
_nested_build_industry_widgets, lengthof(_nested_build_industry_widgets)
@@ -207,9 +207,6 @@ class BuildIndustryWindow : public Window {
bool enabled[NUM_INDUSTRYTYPES + 1]; ///< availability state, coming from CBID_INDUSTRY_PROBABILITY (if ever)
Scrollbar *vscroll;
- /** The offset for the text in the matrix. */
- static const int MATRIX_TEXT_OFFSET = 17;
-
void SetupArrays()
{
this->count = 0;
@@ -283,6 +280,10 @@ public:
this->SetButtons();
}
+ ~BuildIndustryWindow() {
+ if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort();
+ }
+
virtual void OnInit()
{
this->SetupArrays();
@@ -297,8 +298,8 @@ public:
if (this->index[i] == INVALID_INDUSTRYTYPE) continue;
d = maxdim(d, GetStringBoundingBox(GetIndustrySpec(this->index[i])->name));
}
- resize->height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
- d.width += MATRIX_TEXT_OFFSET + padding.width;
+ resize->height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM);
+ d.width += FONT_HEIGHT_NORMAL * 5 / 4 + padding.width;
d.height = 5 * resize->height;
*size = maxdim(*size, d);
break;
@@ -382,20 +383,22 @@ public:
switch (widget) {
case WID_DPI_MATRIX_WIDGET: {
uint text_left, text_right, icon_left, icon_right;
+ uint square_size = FONT_HEIGHT_NORMAL - 2;
+ uint text_offset = FONT_HEIGHT_NORMAL * 5 / 4;
if (_current_text_dir == TD_RTL) {
icon_right = r.right - WD_MATRIX_RIGHT;
- icon_left = icon_right - 10;
- text_right = icon_right - BuildIndustryWindow::MATRIX_TEXT_OFFSET;
+ icon_left = icon_right - square_size;
+ text_right = icon_right - text_offset;
text_left = r.left + WD_MATRIX_LEFT;
} else {
icon_left = r.left + WD_MATRIX_LEFT;
- icon_right = icon_left + 10;
- text_left = icon_left + BuildIndustryWindow::MATRIX_TEXT_OFFSET;
+ icon_right = icon_left + square_size;
+ text_left = icon_left + text_offset;
text_right = r.right - WD_MATRIX_RIGHT;
}
- for (byte i = 0; i < this->vscroll->GetCapacity() && i + this->vscroll->GetPosition() < this->count; i++) {
- int y = r.top + WD_MATRIX_TOP + i * this->resize.step_height;
+ int y = Center(r.top, this->resize.step_height);
+ for (byte i = 0; i < this->vscroll->GetCapacity() && i + this->vscroll->GetPosition() < this->count; i++, y += this->resize.step_height) {
bool selected = this->selected_index == i + this->vscroll->GetPosition();
if (this->index[i + this->vscroll->GetPosition()] == INVALID_INDUSTRYTYPE) {
@@ -406,8 +409,8 @@ public:
/* Draw the name of the industry in white is selected, otherwise, in orange */
DrawString(text_left, text_right, y, indsp->name, selected ? TC_WHITE : TC_ORANGE);
- GfxFillRect(icon_left, y + 1, icon_right, y + 7, selected ? PC_WHITE : PC_BLACK);
- GfxFillRect(icon_left + 1, y + 2, icon_right - 1, y + 6, indsp->map_colour);
+ GfxFillRect(icon_left, y + 1, icon_right, y + square_size, selected ? PC_WHITE : PC_BLACK);
+ GfxFillRect(icon_left + 1, y + 2, icon_right - 1, y + square_size - 1, indsp->map_colour);
}
break;
}
@@ -546,6 +549,19 @@ public:
virtual void OnPlaceObject(Point pt, TileIndex tile)
{
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_SINGLE_TILE);
+ }
+
+ 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) return;
+ assert(end_tile == start_tile);
+
bool success = true;
/* We do not need to protect ourselves against "Random Many Industries" in this mode */
const IndustrySpec *indsp = GetIndustrySpec(this->selected_type);
@@ -563,14 +579,14 @@ public:
_generating_world = true;
_ignore_restrictions = true;
- DoCommandP(tile, (InteractiveRandomRange(indsp->num_table) << 8) | this->selected_type, seed,
+ DoCommandP(end_tile, (InteractiveRandomRange(indsp->num_table) << 8) | this->selected_type, seed,
CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY), &CcBuildIndustry);
cur_company.Restore();
_ignore_restrictions = false;
_generating_world = false;
} else {
- success = DoCommandP(tile, (InteractiveRandomRange(indsp->num_table) << 8) | this->selected_type, seed, CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY));
+ success = DoCommandP(end_tile, (InteractiveRandomRange(indsp->num_table) << 8) | this->selected_type, seed, CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY));
}
/* If an industry has been built, just reset the cursor and the system */
@@ -630,7 +646,7 @@ public:
void ShowBuildIndustryWindow()
{
if (_game_mode != GM_EDITOR && !Company::IsValidID(_local_company)) return;
- if (BringWindowToFrontById(WC_BUILD_INDUSTRY, 0)) return;
+ DeleteToolbarLinkedWindows();
new BuildIndustryWindow();
}
@@ -760,7 +776,7 @@ public:
if (first) {
if (has_accept) y += WD_PAR_VSEP_WIDE;
DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y, STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE);
- y += FONT_HEIGHT_NORMAL;
+ y += this->editable == EA_RATE ? GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL) : FONT_HEIGHT_NORMAL;
if (this->editable == EA_RATE) this->production_offset_y = y;
first = false;
}
@@ -775,8 +791,10 @@ public:
if (this->editable == EA_RATE) {
DrawArrowButtons(left + WD_FRAMETEXT_LEFT, y, COLOUR_YELLOW, (this->clicked_line == IL_RATE1 + j) ? this->clicked_button : 0,
i->production_rate[j] > 0, i->production_rate[j] < 255);
+ y += GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL);
+ } else {
+ y += FONT_HEIGHT_NORMAL;
}
- y += FONT_HEIGHT_NORMAL;
}
/* Display production multiplier if editable */
@@ -788,7 +806,7 @@ public:
DrawString(x, right - WD_FRAMERECT_RIGHT, y, STR_INDUSTRY_VIEW_PRODUCTION_LEVEL);
DrawArrowButtons(left + WD_FRAMETEXT_LEFT, y, COLOUR_YELLOW, (this->clicked_line == IL_MULTIPLIER) ? this->clicked_button : 0,
i->prod_level > PRODLEVEL_MINIMUM, i->prod_level < PRODLEVEL_MAXIMUM);
- y += FONT_HEIGHT_NORMAL;
+ y += GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL);
}
/* Get the extra message for the GUI */
@@ -836,12 +854,14 @@ public:
case EA_NONE: break;
case EA_MULTIPLIER:
- if (IsInsideBS(pt.y, this->production_offset_y, FONT_HEIGHT_NORMAL)) line = IL_MULTIPLIER;
+ if (IsInsideBS(pt.y, this->production_offset_y, SETTING_BUTTON_HEIGHT)) line = IL_MULTIPLIER;
break;
case EA_RATE:
if (pt.y >= this->production_offset_y) {
- int row = (pt.y - this->production_offset_y) / FONT_HEIGHT_NORMAL;
+ if ((pt.y - this->production_offset_y) % GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL) > (uint)SETTING_BUTTON_HEIGHT) break;;
+
+ int row = (pt.y - this->production_offset_y) / GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL);
for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
if (i->produced_cargo[j] == CT_INVALID) continue;
row--;
@@ -1057,7 +1077,7 @@ static const NWidgetPart _nested_industry_directory_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(NWID_HORIZONTAL),
- NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_ID_DROPDOWN_ORDER), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
+ NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_ID_DROPDOWN_ORDER), SetSizingType(NWST_STEP), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_ID_DROPDOWN_CRITERIA), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
NWidget(WWT_PANEL, COLOUR_BROWN), SetResize(1, 0), EndContainer(),
EndContainer(),
@@ -1262,7 +1282,7 @@ public:
case WID_ID_INDUSTRY_LIST: {
int n = 0;
- int y = r.top + WD_FRAMERECT_TOP;
+ int y = Center(r.top, this->resize.step_height);
if (this->industries.Length() == 0) {
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_INDUSTRY_DIRECTORY_NONE);
break;
@@ -1305,7 +1325,7 @@ public:
for (uint i = 0; i < this->industries.Length(); i++) {
d = maxdim(d, GetStringBoundingBox(this->GetIndustryString(this->industries[i])));
}
- resize->height = d.height;
+ resize->height = d.height = GetMinSizing(NWST_STEP, d.height);
d.height *= 5;
d.width += padding.width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
d.height += padding.height + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
diff --git a/src/intro_gui.cpp b/src/intro_gui.cpp
index de8b379392..baab3fa5e6 100644
--- a/src/intro_gui.cpp
+++ b/src/intro_gui.cpp
@@ -27,6 +27,7 @@
#include "language.h"
#include "rev.h"
#include "highscore.h"
+#include "tutorial_gui.h"
#include "widgets/intro_widget.h"
@@ -141,13 +142,14 @@ struct SelectGameWindow : public Window {
}
break;
case WID_SGI_AI_SETTINGS: ShowAIConfigWindow(); break;
+ case WID_SGI_TUTORIAL: ShowTutorialWindow(); break;
case WID_SGI_EXIT: HandleExitGameRequest(); break;
}
}
};
static const NWidgetPart _nested_select_game_widgets[] = {
- NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_INTRO_CAPTION, STR_NULL),
+ NWidget(WWT_CAPTION, COLOUR_BROWN), SetSizingType(NWST_BUTTON), SetDataTip(STR_INTRO_CAPTION, STR_NULL),
NWidget(WWT_PANEL, COLOUR_BROWN),
NWidget(NWID_SPACER), SetMinimalSize(0, 8),
@@ -236,11 +238,11 @@ static const NWidgetPart _nested_select_game_widgets[] = {
NWidget(NWID_SPACER), SetMinimalSize(0, 6),
/* 'exit program' button */
- NWidget(NWID_HORIZONTAL),
- NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_EXIT), SetMinimalSize(128, 12),
- SetDataTip(STR_INTRO_QUIT, STR_INTRO_TOOLTIP_QUIT),
- NWidget(NWID_SPACER), SetFill(1, 0),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_TUTORIAL), SetMinimalSize(158, 12),
+ SetDataTip(STR_ABOUT_MENU_TUTORIAL, STR_TUTORIAL_WINDOW_TOOLTIP), SetPadding(0, 0, 0, 10), SetFill(1, 0),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_EXIT), SetMinimalSize(158, 12),
+ SetDataTip(STR_INTRO_QUIT, STR_INTRO_TOOLTIP_QUIT), SetPadding(0, 10, 0, 0), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 8),
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 11ae31c4c3..9e2ce0e239 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -468,7 +468,7 @@ STR_NEWS_MENU_MESSAGE_HISTORY_MENU :Message history
############ range for about menu starts
STR_ABOUT_MENU_LAND_BLOCK_INFO :Land area information
-STR_ABOUT_MENU_SEPARATOR :
+STR_ABOUT_MENU_TUTORIAL :{BLACK}Tutorial
STR_ABOUT_MENU_TOGGLE_CONSOLE :Toggle console
STR_ABOUT_MENU_AI_DEBUG :AI/Game script debug
STR_ABOUT_MENU_SCREENSHOT :Screenshot
@@ -479,6 +479,7 @@ STR_ABOUT_MENU_ABOUT_OPENTTD :About 'OpenTTD'
STR_ABOUT_MENU_SPRITE_ALIGNER :Sprite aligner
STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES :Toggle bounding boxes
STR_ABOUT_MENU_TOGGLE_DIRTY_BLOCKS :Toggle colouring of dirty blocks
+STR_ABOUT_MENU_SEPARATOR :
############ range ends here
############ range for ordinal numbers used for the place in the highscore window
@@ -717,6 +718,7 @@ STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP :{BLACK}Show lan
STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION :{BLACK}Click on an industry type to toggle displaying it. Ctrl+Click disables all types except the selected one. Ctrl+Click on it again to enable all industry types
STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION :{BLACK}Click on a company to toggle displaying its property. Ctrl+Click disables all companies except the selected one. Ctrl+Click on it again to enable all companies
STR_SMALLMAP_TOOLTIP_CARGO_SELECTION :{BLACK}Click on a cargo to toggle displaying its property. Ctrl+Click disables all cargoes except the selected one. Ctrl+Click on it again to enable all cargoes
+STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}Show map legend / description of map symbols
STR_SMALLMAP_LEGENDA_ROADS :{TINY_FONT}{BLACK}Roads
STR_SMALLMAP_LEGENDA_RAILROADS :{TINY_FONT}{BLACK}Railways
@@ -1215,6 +1217,12 @@ STR_CONFIG_SETTING_SIGNALSIDE_HELPTEXT :Select on which
STR_CONFIG_SETTING_SIGNALSIDE_LEFT :On the left
STR_CONFIG_SETTING_SIGNALSIDE_DRIVING_SIDE :On the driving side
STR_CONFIG_SETTING_SIGNALSIDE_RIGHT :On the right
+STR_CONFIG_SETTING_VERTICAL_TOOLBAR :{BLACK}Vertical toolbar
+STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :{BLACK}Main toolbar is split into two vertical toolbars on the sides of the screen
+STR_CONFIG_SETTING_BUTTON_SIZE :{BLACK}Button size
+STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :{BLACK}Size of all user interface elements
+STR_CONFIG_SETTING_FONT_SIZE :{BLACK}Font size
+STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :{BLACK}Size of all game fonts
STR_CONFIG_SETTING_SHOWFINANCES :Show finances window at the end of the year: {STRING2}
STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :If enabled, the finances window pops up at the end of each year to allow easy inspection of the financial status of the company
STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :New orders are 'non-stop' by default: {STRING2}
@@ -2480,6 +2488,14 @@ STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND :{BLACK}Raise a
STR_LANDSCAPING_LEVEL_LAND_TOOLTIP :{BLACK}Level an area of land to the height of the first selected corner. Ctrl selects the area diagonally. Shift toggles building/showing cost estimate
STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}Purchase land for future use. Shift toggles building/showing cost estimate
+# Tablet toolbar
+STR_TABLET_CLOSE :{BLACK}X
+STR_TABLET_CLOSE_TOOLTIP :{BLACK}Close all opened windows (except pinned ones)
+STR_TABLET_SHIFT :{BLACK}{TINY_FONT}Shft
+STR_TABLET_SHIFT_TOOLTIP :{BLACK}Press it for getting an estimated cost of executing an action
+STR_TABLET_CTRL :{BLACK}{TINY_FONT}Ctrl
+STR_TABLET_CTRL_TOOLTIP :{BLACK}Use it for actions that use the "CTRL" key
+
# Object construction window
STR_OBJECT_BUILD_CAPTION :{WHITE}Object Selection
STR_OBJECT_BUILD_TOOLTIP :{BLACK}Select object to build. Shift toggles building/showing cost estimate
@@ -2693,6 +2709,10 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original
STR_ABOUT_VERSION :{BLACK}OpenTTD version {REV}
STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2015 The OpenTTD team
+#Tutorial window
+STR_TUTORIAL_WINDOW_TITLE :{BLACK}Tutorial videos
+STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Open a video player to watch tutorial videos
+
# Save/load game/scenario
STR_SAVELOAD_SAVE_CAPTION :{WHITE}Save Game
STR_SAVELOAD_LOAD_CAPTION :{WHITE}Load Game
@@ -2711,6 +2731,10 @@ STR_SAVELOAD_SAVE_TOOLTIP :{BLACK}Save the
STR_SAVELOAD_LOAD_BUTTON :{BLACK}Load
STR_SAVELOAD_LOAD_TOOLTIP :{BLACK}Load the selected game
STR_SAVELOAD_LOAD_HEIGHTMAP_TOOLTIP :{BLACK}Load the selected heightmap
+STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}Load from network
+STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}Load a game from the network storage
+STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}Save to network
+STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}Back up the game to the network storage
STR_SAVELOAD_DETAIL_CAPTION :{BLACK}Game Details
STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}No information available
STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING1}
diff --git a/src/linkgraph/linkgraph_gui.cpp b/src/linkgraph/linkgraph_gui.cpp
index 1fe34fe79c..ca81fa18d8 100644
--- a/src/linkgraph/linkgraph_gui.cpp
+++ b/src/linkgraph/linkgraph_gui.cpp
@@ -347,6 +347,7 @@ NWidgetBase *MakeCargoesLegendLinkGraphGUI(int *biggest_index)
row = new NWidgetHorizontal(NC_EQUALSIZE);
}
NWidgetBackground * wid = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, i + WID_LGL_CARGO_FIRST);
+ wid->sizing_type = NWST_STEP;
wid->SetMinimalSize(25, FONT_HEIGHT_SMALL);
wid->SetFill(1, 1);
wid->SetResize(0, 0);
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index cdef1e6a6e..820a48623f 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -32,6 +32,7 @@
#include "linkgraph/linkgraph_gui.h"
#include "tilehighlight_func.h"
#include "hotkeys.h"
+#include "tutorial_gui.h"
#include "saveload/saveload.h"
@@ -340,7 +341,7 @@ struct MainWindow : Window
break;
}
- case GHK_RESET_OBJECT_TO_PLACE: ResetObjectToPlace(); break;
+ case GHK_RESET_OBJECT_TO_PLACE: ResetObjectToPlace(); ToolbarSelectLastTool(); break;
case GHK_DELETE_WINDOWS: DeleteNonVitalWindows(); break;
case GHK_DELETE_NONVITAL_WINDOWS: DeleteAllNonVitalWindows(); break;
case GHK_REFRESH_SCREEN: MarkWholeScreenDirty(); break;
@@ -463,6 +464,7 @@ struct MainWindow : Window
if (!gui_scope) return;
/* Forward the message to the appropriate toolbar (ingame or scenario editor) */
InvalidateWindowData(WC_MAIN_TOOLBAR, 0, data, true);
+ InvalidateWindowData(WC_MAIN_TOOLBAR_RIGHT, 0, data, true);
}
static HotkeyList hotkeys;
@@ -562,6 +564,7 @@ void SetupColoursAndInitialWindow()
default: NOT_REACHED();
case GM_MENU:
ShowSelectGameWindow();
+ ShowTutorialWindowOnceAfterInstall();
break;
case GM_NORMAL:
diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp
index ba84733bed..6c4aeb7cf5 100644
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -33,6 +33,10 @@
#include "safeguards.h"
+#ifdef __ANDROID__
+#include
+#endif
+
/** Method to open the OSK. */
enum OskActivation {
OSKA_DISABLED, ///< The OSK shall not be activated at all.
@@ -637,6 +641,8 @@ static WindowDesc _tool_tips_desc(
_nested_tooltips_widgets, lengthof(_nested_tooltips_widgets)
);
+uint _tooltip_width = 194;
+
/** Window for displaying a tooltip. */
struct TooltipsWindow : public Window
{
@@ -685,7 +691,7 @@ struct TooltipsWindow : public Window
/* There is only one widget. */
for (uint i = 0; i != this->paramcount; i++) SetDParam(i, this->params[i]);
- size->width = min(GetStringBoundingBox(this->string_id).width, ScaleGUITrad(194));
+ size->width = min(GetStringBoundingBox(this->string_id).width, _tooltip_width);
size->height = GetStringHeight(this->string_id, size->width);
/* Increase slightly to have some space around the box. */
@@ -758,7 +764,7 @@ void QueryString::DrawEditBox(const Window *w, int wid) const
bool rtl = _current_text_dir == TD_RTL;
Dimension sprite_size = GetSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
- int clearbtn_width = sprite_size.width + WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT;
+ int clearbtn_width = GetMinSizing(NWST_BUTTON, sprite_size.width + WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT);
int clearbtn_left = wi->pos_x + (rtl ? 0 : wi->current_x - clearbtn_width);
int clearbtn_right = wi->pos_x + (rtl ? clearbtn_width : wi->current_x) - 1;
@@ -769,7 +775,7 @@ void QueryString::DrawEditBox(const Window *w, int wid) const
int bottom = wi->pos_y + wi->current_y - 1;
DrawFrameRect(clearbtn_left, top, clearbtn_right, bottom, wi->colour, wi->IsLowered() ? FR_LOWERED : FR_NONE);
- DrawSprite(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT, PAL_NONE, clearbtn_left + WD_IMGBTN_LEFT + (wi->IsLowered() ? 1 : 0), (top + bottom - sprite_size.height) / 2 + (wi->IsLowered() ? 1 : 0));
+ DrawSprite(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT, PAL_NONE, Center(clearbtn_left + wi->IsLowered(), clearbtn_width, sprite_size.width), Center(top + wi->IsLowered(), bottom - top, sprite_size.height));
if (this->text.bytes == 1) GfxFillRect(clearbtn_left + 1, top + 1, clearbtn_right - 1, bottom - 1, _colour_gradient[wi->colour & 0xF][2], FILLRECT_CHECKER);
DrawFrameRect(left, top, right, bottom, wi->colour, FR_LOWERED | FR_DARKENED);
@@ -792,11 +798,12 @@ void QueryString::DrawEditBox(const Window *w, int wid) const
/* If we have a marked area, draw a background highlight. */
if (tb->marklength != 0) GfxFillRect(delta + tb->markxoffs, 0, delta + tb->markxoffs + tb->marklength - 1, bottom - top, PC_GREY);
- DrawString(delta, tb->pixels, 0, tb->buf, TC_YELLOW);
+ DrawString(delta, tb->pixels, Center(0, bottom - top), tb->buf, TC_YELLOW);
+
bool focussed = w->IsWidgetGloballyFocused(wid) || IsOSKOpenedFor(w, wid);
if (focussed && tb->caret) {
int caret_width = GetStringBoundingBox("_").width;
- DrawString(tb->caretxoffs + delta, tb->caretxoffs + delta + caret_width, 0, "_", TC_WHITE);
+ DrawString(tb->caretxoffs + delta, tb->caretxoffs + delta + caret_width, Center(0, bottom - top), "_", TC_WHITE);
}
_cur_dpi = old_dpi;
@@ -927,6 +934,14 @@ void QueryString::ClickEditBox(Window *w, Point pt, int wid, int click_count, bo
/* Open the OSK window */
ShowOnScreenKeyboard(w, wid);
}
+#ifdef __ANDROID__
+ char text[512];
+ strecpy(text, this->text.buf, lastof(text));
+ this->text.DeleteAll();
+ SDL_ANDROID_GetScreenKeyboardTextInput(text, sizeof(text) - 1); /* Invoke Android built-in screen keyboard */
+ this->text.Assign(text);
+ w->OnEditboxChanged(wid);
+#endif
}
/** Class for the string query window. */
@@ -1106,6 +1121,7 @@ struct QueryWindow : public Window {
{
if (widget != WID_Q_TEXT) return;
+ size->width = GetMinSizing(NWST_WINDOW_LENGTH, size->width);
Dimension d = GetStringMultiLineBoundingBox(this->message, *size);
d.width += WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
diff --git a/src/music/libtimidity.cpp b/src/music/libtimidity.cpp
index 1cb2adc0f9..02542fc9b9 100644
--- a/src/music/libtimidity.cpp
+++ b/src/music/libtimidity.cpp
@@ -13,6 +13,7 @@
#include "../openttd.h"
#include "../sound_type.h"
#include "../debug.h"
+#include "../core/math_func.hpp"
#include "libtimidity.h"
#include
#include
@@ -22,6 +23,7 @@
#include
#include
#include
+#include
#if defined(PSP)
#include
#endif /* PSP */
@@ -53,14 +55,34 @@ static void AudioOutCallback(void *buf, unsigned int _reqn, void *userdata)
}
}
#endif /* PSP */
+#ifdef __ANDROID__
+/* Android does not have Midi chip, we have to route the libtimidity output through SDL audio output */
+void Android_MidiMixMusic(Sint16 *stream, int len)
+{
+ if (_midi.status == MIDI_PLAYING) {
+ Sint16 buf[16384];
+ while( len > 0 )
+ {
+ int minlen = min(sizeof(buf), len);
+ mid_song_read_wave(_midi.song, buf, min(sizeof(buf), len*2));
+ for( Uint16 i = 0; i < minlen; i++ )
+ stream[i] += buf[i];
+ stream += minlen;
+ len -= minlen;
+ }
+ }
+}
+#endif /* __ANDROID__ */
/** Factory for the libtimidity driver. */
static FMusicDriver_LibTimidity iFMusicDriver_LibTimidity;
+enum { TIMIDITY_MAX_VOLUME = 50 };
const char *MusicDriver_LibTimidity::Start(const char * const *param)
{
_midi.status = MIDI_STOPPED;
_midi.song = NULL;
+ volume = TIMIDITY_MAX_VOLUME; // Avoid clipping
if (mid_init(param == NULL ? NULL : const_cast(param[0])) < 0) {
/* If init fails, it can be because no configuration was found.
@@ -115,6 +137,7 @@ void MusicDriver_LibTimidity::PlaySong(const char *filename)
return;
}
+ mid_song_set_volume(_midi.song, volume);
mid_song_start(_midi.song);
_midi.status = MIDI_PLAYING;
}
@@ -142,5 +165,6 @@ bool MusicDriver_LibTimidity::IsSongPlaying()
void MusicDriver_LibTimidity::SetVolume(byte vol)
{
+ volume = vol * TIMIDITY_MAX_VOLUME / 127; // I'm not sure about that value
if (_midi.song != NULL) mid_song_set_volume(_midi.song, vol);
}
diff --git a/src/music/libtimidity.h b/src/music/libtimidity.h
index abe17e7703..0a0686499f 100644
--- a/src/music/libtimidity.h
+++ b/src/music/libtimidity.h
@@ -16,6 +16,7 @@
/** Music driver making use of libtimidity. */
class MusicDriver_LibTimidity : public MusicDriver {
+ int volume;
public:
/* virtual */ const char *Start(const char * const *param);
diff --git a/src/music_gui.cpp b/src/music_gui.cpp
index 279f376525..508b06d2e5 100644
--- a/src/music_gui.cpp
+++ b/src/music_gui.cpp
@@ -297,13 +297,32 @@ static void SelectPlaylist(byte list)
}
struct MusicTrackSelectionWindow : public Window {
+ Scrollbar *left_sb;
+ Scrollbar *right_sb;
+
+ /** Count the number of tracks of current tracklist. */
+ uint GetNumberOfTracksOfTracklist() const
+ {
+ uint i = 0;
+ for (; _playlists[_settings_client.music.playlist][i] > 0; i++) {}
+ return i;
+ }
+
MusicTrackSelectionWindow(WindowDesc *desc, WindowNumber number) : Window(desc)
{
- this->InitNested(number);
+
+ this->CreateNestedTree();
+ this->left_sb = this->GetScrollbar(WID_MTS_LEFT_SCROLLBAR);
+ this->right_sb = this->GetScrollbar(WID_MTS_RIGHT_SCROLLBAR);
+
this->LowerWidget(WID_MTS_LIST_LEFT);
this->LowerWidget(WID_MTS_LIST_RIGHT);
this->SetWidgetDisabledState(WID_MTS_CLEAR, _settings_client.music.playlist <= 3);
this->LowerWidget(WID_MTS_ALL + _settings_client.music.playlist);
+ this->FinishInitNested(number);
+
+ this->left_sb->SetCount(NUM_SONGS_AVAILABLE);
+ this->right_sb->SetCount(GetNumberOfTracksOfTracklist());
}
virtual void SetStringParameters(int widget) const
@@ -327,6 +346,7 @@ struct MusicTrackSelectionWindow : public Window {
this->SetWidgetLoweredState(WID_MTS_ALL + i, i == _settings_client.music.playlist);
}
this->SetWidgetDisabledState(WID_MTS_CLEAR, _settings_client.music.playlist <= 3);
+ this->right_sb->SetCount(GetNumberOfTracksOfTracklist());
this->SetDirty();
}
@@ -346,7 +366,8 @@ struct MusicTrackSelectionWindow : public Window {
break;
}
- case WID_MTS_LIST_LEFT: case WID_MTS_LIST_RIGHT: {
+ case WID_MTS_LIST_LEFT:
+ case WID_MTS_LIST_RIGHT: {
Dimension d = {0, 0};
for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
@@ -356,12 +377,11 @@ struct MusicTrackSelectionWindow : public Window {
SetDParam(0, GetTrackNumber(i));
SetDParam(1, 2);
SetDParamStr(2, GetSongName(i));
- Dimension d2 = GetStringBoundingBox(STR_PLAYLIST_TRACK_NAME);
- d.width = max(d.width, d2.width);
- d.height += d2.height;
+ d = maxdim(d, GetStringBoundingBox(STR_PLAYLIST_TRACK_NAME));
}
- d.width += padding.width;
- d.height += padding.height;
+ resize->height = GetMinSizing(NWST_STEP, d.height);
+ d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
+ d.height = 7 * resize->height + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
*size = maxdim(*size, d);
break;
}
@@ -375,15 +395,17 @@ struct MusicTrackSelectionWindow : public Window {
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK);
int y = r.top + WD_FRAMERECT_TOP;
- for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
+ uint vscroll_max = min(this->left_sb->GetPosition() + this->left_sb->GetCapacity(), NUM_SONGS_AVAILABLE);
+
+ for (uint i = this->left_sb->GetPosition(); i < vscroll_max; i++) {
const char *song_name = GetSongName(i);
if (StrEmpty(song_name)) continue;
SetDParam(0, GetTrackNumber(i));
SetDParam(1, 2);
SetDParamStr(2, song_name);
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_PLAYLIST_TRACK_NAME);
- y += FONT_HEIGHT_SMALL;
+ DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(y, this->resize.step_height, FONT_HEIGHT_SMALL), STR_PLAYLIST_TRACK_NAME);
+ y += this->resize.step_height;
}
break;
}
@@ -392,13 +414,15 @@ struct MusicTrackSelectionWindow : public Window {
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK);
int y = r.top + WD_FRAMERECT_TOP;
- for (const byte *p = _playlists[_settings_client.music.playlist]; *p != 0; p++) {
- uint i = *p - 1;
- SetDParam(0, GetTrackNumber(i));
+ uint vscroll_max = min(this->right_sb->GetPosition() + this->right_sb->GetCapacity(), this->GetNumberOfTracksOfTracklist());
+
+ for (uint i = this->right_sb->GetPosition(); i < vscroll_max; i++) {
+ uint j = _playlists[_settings_client.music.playlist][i] - 1;
+ SetDParam(0, GetTrackNumber(j));
SetDParam(1, 2);
- SetDParamStr(2, GetSongName(i));
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_PLAYLIST_TRACK_NAME);
- y += FONT_HEIGHT_SMALL;
+ SetDParamStr(2, GetSongName(j));
+ DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(y, this->resize.step_height, FONT_HEIGHT_SMALL), STR_PLAYLIST_TRACK_NAME);
+ y += this->resize.step_height;
}
break;
}
@@ -409,22 +433,22 @@ struct MusicTrackSelectionWindow : public Window {
{
switch (widget) {
case WID_MTS_LIST_LEFT: { // add to playlist
- int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL);
-
if (_settings_client.music.playlist < 4) return;
- if (!IsInsideMM(y, 0, BaseMusic::GetUsedSet()->num_available)) return;
+ int id_m = this->left_sb->GetScrolledRowFromWidget(pt.y, this, WID_MTS_LIST_LEFT, WD_FRAMERECT_TOP, this->resize.step_height);
+ if (!IsInsideMM(id_m, 0, BaseMusic::GetUsedSet()->num_available)) return;
byte *p = _playlists[_settings_client.music.playlist];
for (uint i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) {
if (p[i] == 0) {
/* Find the actual song number */
for (uint j = 0; j < NUM_SONGS_AVAILABLE; j++) {
- if (GetTrackNumber(j) == y + 1) {
+ if (GetTrackNumber(j) == id_m + 1) {
p[i] = j + 1;
break;
}
}
p[i + 1] = 0;
+ this->right_sb->SetCount(GetNumberOfTracksOfTracklist());
this->SetDirty();
SelectSongToPlay();
break;
@@ -434,16 +458,16 @@ struct MusicTrackSelectionWindow : public Window {
}
case WID_MTS_LIST_RIGHT: { // remove from playlist
- int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL);
-
if (_settings_client.music.playlist < 4) return;
- if (!IsInsideMM(y, 0, NUM_SONGS_PLAYLIST)) return;
+ int id_m = this->right_sb->GetScrolledRowFromWidget(pt.y, this, WID_MTS_LIST_RIGHT, WD_FRAMERECT_TOP, this->resize.step_height);
+ if (!IsInsideMM(id_m, 0, NUM_SONGS_PLAYLIST)) return;
byte *p = _playlists[_settings_client.music.playlist];
- for (uint i = y; i != NUM_SONGS_PLAYLIST - 1; i++) {
+ for (uint i = id_m; i != NUM_SONGS_PLAYLIST - 1; i++) {
p[i] = p[i + 1];
}
+ this->right_sb->SetCount(GetNumberOfTracksOfTracklist());
this->SetDirty();
SelectSongToPlay();
break;
@@ -451,55 +475,74 @@ struct MusicTrackSelectionWindow : public Window {
case WID_MTS_CLEAR: // clear
for (uint i = 0; _playlists[_settings_client.music.playlist][i] != 0; i++) _playlists[_settings_client.music.playlist][i] = 0;
+ this->right_sb->SetCount(GetNumberOfTracksOfTracklist());
this->SetDirty();
StopMusic();
SelectSongToPlay();
break;
- case WID_MTS_ALL: case WID_MTS_OLD: case WID_MTS_NEW:
- case WID_MTS_EZY: case WID_MTS_CUSTOM1: case WID_MTS_CUSTOM2: // set playlist
+ case WID_MTS_ALL:
+ case WID_MTS_OLD:
+ case WID_MTS_NEW:
+ case WID_MTS_EZY:
+ case WID_MTS_CUSTOM1:
+ case WID_MTS_CUSTOM2: // set playlist
SelectPlaylist(widget - WID_MTS_ALL);
+ this->right_sb->SetCount(GetNumberOfTracksOfTracklist());
+ this->SetDirty();
StopMusic();
SelectSongToPlay();
break;
}
}
+
+ virtual void OnResize()
+ {
+ this->left_sb->SetCapacityFromWidget(this, WID_MTS_LIST_LEFT);
+ this->right_sb->SetCapacityFromWidget(this, WID_MTS_LIST_RIGHT);
+ }
};
static const NWidgetPart _nested_music_track_selection_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_PLAYLIST_MUSIC_PROGRAM_SELECTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+ NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
/* Left panel. */
NWidget(NWID_VERTICAL),
NWidget(WWT_LABEL, COLOUR_GREY), SetDataTip(STR_PLAYLIST_TRACK_INDEX, STR_NULL),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_MTS_LIST_LEFT), SetMinimalSize(180, 194), SetDataTip(0x0, STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK), EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_MATRIX, COLOUR_GREY, WID_MTS_LIST_LEFT), SetMinimalSize(180, 100), SetMatrixDataTip(1, 0, STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK),
+ SetFill(1, 0), SetResize(1, 1), SetScrollbar(WID_MTS_LEFT_SCROLLBAR),
+ NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_MTS_LEFT_SCROLLBAR),
+ EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
EndContainer(),
- /* Middle buttons. */
- NWidget(NWID_VERTICAL),
- NWidget(NWID_SPACER), SetMinimalSize(60, 30), // Space above the first button from the title bar.
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_ALL), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_ALL, STR_MUSIC_TOOLTIP_SELECT_ALL_TRACKS_PROGRAM),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_OLD), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_OLD_STYLE, STR_MUSIC_TOOLTIP_SELECT_OLD_STYLE_MUSIC),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_NEW), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_NEW_STYLE, STR_MUSIC_TOOLTIP_SELECT_NEW_STYLE_MUSIC),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_EZY), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_EZY_STREET, STR_MUSIC_TOOLTIP_SELECT_EZY_STREET_STYLE),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_CUSTOM1), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_CUSTOM_1, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_1_USER_DEFINED),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_CUSTOM2), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_CUSTOM_2, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED),
- NWidget(NWID_SPACER), SetMinimalSize(0, 16), // Space above 'clear' button
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_MTS_CLEAR), SetFill(1, 0), SetDataTip(STR_PLAYLIST_CLEAR, STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1),
- NWidget(NWID_SPACER), SetFill(0, 1),
- EndContainer(),
/* Right panel. */
NWidget(NWID_VERTICAL),
NWidget(WWT_LABEL, COLOUR_GREY, WID_MTS_PLAYLIST), SetDataTip(STR_PLAYLIST_PROGRAM, STR_NULL),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_MTS_LIST_RIGHT), SetMinimalSize(180, 194), SetDataTip(0x0, STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK), EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_MATRIX, COLOUR_GREY, WID_MTS_LIST_RIGHT), SetMinimalSize(180, 100), SetMatrixDataTip(1, 0, STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK),
+ SetFill(1, 0), SetResize(1, 1), SetScrollbar(WID_MTS_RIGHT_SCROLLBAR),
+ NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_MTS_RIGHT_SCROLLBAR),
+ EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
EndContainer(),
EndContainer(),
EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_ALL), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_ALL, STR_MUSIC_TOOLTIP_SELECT_ALL_TRACKS_PROGRAM),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_OLD), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_OLD_STYLE, STR_MUSIC_TOOLTIP_SELECT_OLD_STYLE_MUSIC),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_NEW), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_NEW_STYLE, STR_MUSIC_TOOLTIP_SELECT_NEW_STYLE_MUSIC),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_EZY), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_EZY_STREET, STR_MUSIC_TOOLTIP_SELECT_EZY_STREET_STYLE),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_CUSTOM1), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_CUSTOM_1, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_1_USER_DEFINED),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_CUSTOM2), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_CUSTOM_2, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_MTS_CLEAR), SetFill(1, 0), SetDataTip(STR_PLAYLIST_CLEAR, STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1),
+ NWidget(WWT_RESIZEBOX, COLOUR_GREY),
+ EndContainer(),
};
static WindowDesc _music_track_selection_desc(
@@ -577,7 +620,7 @@ struct MusicWindow : public Window {
SetDParam(1, 2);
str = STR_MUSIC_TRACK_DIGIT;
}
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str);
+ DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(r.top, r.bottom - r.top, FONT_HEIGHT_SMALL), str);
break;
}
@@ -588,7 +631,7 @@ struct MusicWindow : public Window {
str = STR_MUSIC_TITLE_NAME;
SetDParamStr(0, GetSongName(_music_wnd_cursong - 1));
}
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_FROMSTRING, SA_HOR_CENTER);
+ DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(r.top, r.bottom - r.top, FONT_HEIGHT_SMALL), str, TC_FROMSTRING, SA_HOR_CENTER);
break;
}
@@ -653,7 +696,7 @@ struct MusicWindow : public Window {
if (_current_text_dir == TD_RTL) new_vol = 127 - new_vol;
if (new_vol != *vol) {
*vol = new_vol;
- if (widget == WID_M_MUSIC_VOL) MusicVolumeChanged(new_vol);
+ if (widget == WID_M_MUSIC_VOL) MusicVolumeChanged((new_vol * new_vol) / 127); // Kinda logarithmic scale
this->SetDirty();
}
@@ -679,7 +722,6 @@ struct MusicWindow : public Window {
SelectPlaylist(widget - WID_M_ALL);
StopMusic();
SelectSongToPlay();
- this->SetDirty();
break;
}
}
@@ -744,11 +786,11 @@ static const NWidgetPart _nested_music_window_widgets[] = {
EndContainer(),
NWidget(NWID_VERTICAL), SetPadding(0, 0, 3, 3),
NWidget(WWT_LABEL, COLOUR_GREY, WID_M_TRACK), SetFill(0, 0), SetDataTip(STR_MUSIC_TRACK, STR_NULL),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_M_TRACK_NR), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_M_TRACK_NR), SetFill(0, 1), EndContainer(),
EndContainer(),
NWidget(NWID_VERTICAL), SetPadding(0, 3, 3, 0),
NWidget(WWT_LABEL, COLOUR_GREY, WID_M_TRACK_TITLE), SetFill(1, 0), SetDataTip(STR_MUSIC_XTITLE, STR_NULL),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_M_TRACK_NAME), SetFill(1, 0), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_M_TRACK_NAME), SetFill(1, 1), EndContainer(),
EndContainer(),
NWidget(NWID_VERTICAL),
NWidget(NWID_SPACER), SetFill(0, 1),
diff --git a/src/network/core/os_abstraction.h b/src/network/core/os_abstraction.h
index 9608f08fa7..f358bf1c1c 100644
--- a/src/network/core/os_abstraction.h
+++ b/src/network/core/os_abstraction.h
@@ -161,7 +161,7 @@ static inline void OTTDfreeaddrinfo(struct addrinfo *ai)
# include
/* According to glibc/NEWS, appeared in glibc-2.3. */
# if !defined(__sgi__) && !defined(SUNOS) && !defined(__MORPHOS__) && !defined(__BEOS__) && !defined(__HAIKU__) && !defined(__INNOTEK_LIBC__) \
- && !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__) && !defined(HPUX)
+ && !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__) && !defined(HPUX) && !defined(__ANDROID__)
/* If for any reason ifaddrs.h does not exist on your system, comment out
* the following two lines and an alternative way will be used to fetch
* the list of IPs from the system. */
diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp
index 3416762d02..10358983ae 100644
--- a/src/network/network_chat_gui.cpp
+++ b/src/network/network_chat_gui.cpp
@@ -486,7 +486,7 @@ struct NetworkChatWindow : public Window {
if (this->dtype == DESTTYPE_CLIENT) {
SetDParamStr(0, NetworkClientInfo::GetByClientID((ClientID)this->dest)->client_name);
}
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, this->dest_string, TC_BLACK, SA_RIGHT);
+ DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(r.top, r.bottom - r.top), this->dest_string, TC_BLACK, SA_RIGHT);
}
virtual void OnClick(Point pt, int widget, int click_count)
diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp
index 1b4b7e0300..abe07de276 100644
--- a/src/network/network_content_gui.cpp
+++ b/src/network/network_content_gui.cpp
@@ -23,6 +23,7 @@
#include "../querystring_gui.h"
#include "../core/geometry_func.hpp"
#include "../textfile_gui.h"
+#include "../settings_type.h"
#include "network_content_gui.h"
@@ -534,7 +535,7 @@ public:
case WID_NCL_MATRIX:
resize->height = max(this->checkbox_size.height, (uint)FONT_HEIGHT_NORMAL) + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
- size->height = 10 * resize->height;
+ size->height = 6 * resize->height;
break;
}
}
@@ -544,7 +545,7 @@ public:
{
switch (widget) {
case WID_NCL_FILTER_CAPT:
- DrawString(r.left, r.right, r.top, STR_CONTENT_FILTER_TITLE, TC_FROMSTRING, SA_RIGHT);
+ DrawString(r.left, r.right, Center(r.top, r.bottom - r.top), STR_CONTENT_FILTER_TITLE, TC_FROMSTRING, SA_RIGHT);
break;
case WID_NCL_DETAILS:
@@ -594,7 +595,7 @@ public:
for (ConstContentIterator iter = this->content.Get(this->vscroll->GetPosition()); iter != this->content.End() && cnt < this->vscroll->GetCapacity(); iter++, cnt++) {
const ContentInfo *ci = *iter;
- if (ci == this->selected) GfxFillRect(r.left + 1, y + 1, r.right - 1, y + this->resize.step_height - 1, PC_GREY);
+ if (ci == this->selected) GfxFillRect(r.left + 1, y + WD_FRAMERECT_TOP, r.right - 1, y + this->resize.step_height - WD_FRAMERECT_BOTTOM, PC_GREY);
SpriteID sprite;
SpriteID pal = PAL_NONE;
@@ -606,7 +607,8 @@ public:
case ContentInfo::DOES_NOT_EXIST: sprite = SPR_BLOT; pal = PALETTE_TO_RED; break;
default: NOT_REACHED();
}
- DrawSprite(sprite, pal, nwi_checkbox->pos_x + (pal == PAL_NONE ? 2 : 3), y + sprite_y_offset + (pal == PAL_NONE ? 1 : 0));
+
+ DrawSprite(sprite, pal, Center(nwi_checkbox->pos_x + (pal == PAL_NONE ? 2 : 3), nwi_checkbox->current_x, sprite_dim.width), Center(y, this->resize.step_height, sprite_dim.height + (pal == PAL_NONE ? 0 : -2)));
StringID str = STR_CONTENT_TYPE_BASE_GRAPHICS + ci->type - CONTENT_TYPE_BASE_GRAPHICS;
DrawString(nwi_type->pos_x, nwi_type->pos_x + nwi_type->current_x - 1, y + text_y_offset, str, TC_BLACK, SA_HOR_CENTER);
@@ -976,14 +978,7 @@ static const NWidgetPart _nested_network_content_list_widgets[] = {
NWidget(WWT_DEFSIZEBOX, COLOUR_LIGHT_BLUE),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_BACKGROUND),
- NWidget(NWID_SPACER), SetMinimalSize(0, 7), SetResize(1, 0),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(8, 8, 8),
- /* Top */
- NWidget(WWT_EMPTY, COLOUR_LIGHT_BLUE, WID_NCL_FILTER_CAPT), SetFill(1, 0), SetResize(1, 0),
- NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NCL_FILTER), SetFill(1, 0), SetResize(1, 0),
- SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
- EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 7), SetResize(1, 0),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 3), SetResize(1, 0),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(8, 8, 8),
/* Left side. */
NWidget(NWID_VERTICAL), SetPIP(0, 4, 0),
@@ -1013,6 +1008,13 @@ static const NWidgetPart _nested_network_content_list_widgets[] = {
EndContainer(),
/* Right side. */
NWidget(NWID_VERTICAL), SetPIP(0, 4, 0),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(8, 8, 8),
+ /* Top */
+ NWidget(WWT_EMPTY, COLOUR_LIGHT_BLUE, WID_NCL_FILTER_CAPT), SetFill(1, 0), SetResize(1, 0),
+ NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NCL_FILTER), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 3), SetResize(1, 0),
NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_DETAILS), SetResize(1, 1), SetFill(1, 1), EndContainer(),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, 8, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp
index 3a36f146c9..839fb43642 100644
--- a/src/network/network_gui.cpp
+++ b/src/network/network_gui.cpp
@@ -505,13 +505,13 @@ public:
switch (widget) {
case WID_NG_CONN_BTN:
*size = maxdim(*size, maxdim(GetStringBoundingBox(_lan_internet_types_dropdown[0]), GetStringBoundingBox(_lan_internet_types_dropdown[1])));
- size->width += padding.width;
+ size->width += padding.width + GetMinSizing(NWST_STEP, 11U);;
size->height += padding.height;
break;
case WID_NG_MATRIX:
resize->height = WD_MATRIX_TOP + max(GetSpriteSize(SPR_BLOT).height, (uint)FONT_HEIGHT_NORMAL) + WD_MATRIX_BOTTOM;
- size->height = 10 * resize->height;
+ size->height = 5 * resize->height;
break;
case WID_NG_LASTJOINED:
@@ -550,7 +550,7 @@ public:
break;
case WID_NG_DETAILS_SPACER:
- size->height = 20 + 12 * FONT_HEIGHT_NORMAL;
+ size->height = 20 + 10 * FONT_HEIGHT_NORMAL;
break;
}
}
@@ -559,7 +559,7 @@ public:
{
switch (widget) {
case WID_NG_MATRIX: {
- uint16 y = r.top;
+ uint16 y = r.top + WD_MATRIX_TOP + this->resize.step_height / 4;
const int max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), (int)this->servers.Length());
@@ -942,12 +942,9 @@ static const NWidgetPart _nested_network_game_widgets[] = {
/* LEFT SIDE */
NWidget(NWID_VERTICAL), SetPIP(0, 7, 0),
NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
- NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_CONNECTION), SetDataTip(STR_NETWORK_SERVER_LIST_ADVERTISED, STR_NULL),
+ NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_CONNECTION), SetSizingType(NWST_STEP), SetDataTip(STR_NETWORK_SERVER_LIST_ADVERTISED, STR_NULL),
NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NG_CONN_BTN),
SetDataTip(STR_BLACK_STRING, STR_NETWORK_SERVER_LIST_ADVERTISED_TOOLTIP),
- NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
- EndContainer(),
- NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_FILTER_LABEL), SetDataTip(STR_LIST_FILTER_TITLE, STR_NULL),
NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NG_FILTER), SetMinimalSize(251, 12), SetFill(1, 0), SetResize(1, 0),
SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
@@ -1091,8 +1088,8 @@ struct NetworkStartServerWindow : public Window {
switch (widget) {
case WID_NSS_CONNTYPE_BTN:
*size = maxdim(GetStringBoundingBox(_connection_types_dropdown[0]), GetStringBoundingBox(_connection_types_dropdown[1]));
- size->width += padding.width;
- size->height += padding.height;
+ size->width = GetMinSizing(NWST_BUTTON, size->width + padding.width);
+ size->height = GetMinSizing(NWST_BUTTON, size->height + padding.height);
break;
}
}
@@ -1275,15 +1272,15 @@ static const NWidgetPart _nested_network_start_server_window_widgets[] = {
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 6, 10),
NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_ADVERTISED, STR_NULL),
- NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_BTN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_SERVER_LIST_ADVERTISED_TOOLTIP),
+ NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_BTN), SetSizingType(NWST_BUTTON), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_SERVER_LIST_ADVERTISED_TOOLTIP),
EndContainer(),
NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_LANGUAGE_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_LANGUAGE_SPOKEN, STR_NULL),
- NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NSS_LANGUAGE_BTN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_START_SERVER_LANGUAGE_TOOLTIP),
+ NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NSS_LANGUAGE_BTN), SetSizingType(NWST_BUTTON), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_START_SERVER_LANGUAGE_TOOLTIP),
EndContainer(),
NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
NWidget(NWID_SPACER), SetFill(1, 1),
- NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_SETPWD), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_SET_PASSWORD, STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_SETPWD), SetSizingType(NWST_BUTTON), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_SET_PASSWORD, STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP),
EndContainer(),
EndContainer(),
@@ -1386,8 +1383,8 @@ struct NetworkLobbyWindow : public Window {
break;
case WID_NL_MATRIX:
- resize->height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
- size->height = 10 * resize->height;
+ resize->height = GetMinSizing(NWST_STEP, WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM);
+ size->height = 6 * resize->height;
break;
case WID_NL_DETAILS:
@@ -1454,7 +1451,7 @@ struct NetworkLobbyWindow : public Window {
uint profit_left = rtl ? left : right - profit_width;
uint lock_left = rtl ? left + profit_width + 2 : right - profit_width - lock_width - 2;
- int y = r.top + WD_MATRIX_TOP;
+ int y = r.top + WD_MATRIX_TOP + this->resize.step_height / 4;
/* Draw company list */
int pos = this->vscroll->GetPosition();
while (pos < this->server->info.companies_on) {
diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp
index 0074af2181..85eb4f62fd 100644
--- a/src/newgrf_debug_gui.cpp
+++ b/src/newgrf_debug_gui.cpp
@@ -437,8 +437,8 @@ struct NewGRFInspectWindow : Window {
GrfSpecFeature f = GetFeatureNum(this->window_number);
int h = GetVehicleImageCellSize((VehicleType)(VEH_TRAIN + (f - GSF_TRAINS)), EIT_IN_DEPOT).height;
- int y = (r.top + r.bottom - h) / 2;
- DrawVehicleImage(v->First(), r.left + WD_BEVEL_LEFT, r.right - WD_BEVEL_RIGHT, y + 1, INVALID_VEHICLE, EIT_IN_DETAILS, skip);
+ int y = Center(r.top, r.bottom - r.top, h);
+ DrawVehicleImage(v->First(), r.left + WD_BEVEL_LEFT, r.right - WD_BEVEL_RIGHT, y + 1, h, INVALID_VEHICLE, EIT_IN_DETAILS, skip);
/* Highlight the articulated part (this is different to the whole-vehicle highlighting of DrawVehicleImage */
if (_current_text_dir == TD_RTL) {
@@ -860,7 +860,7 @@ struct SpriteAlignerWindow : Window {
{
if (widget != WID_SA_LIST) return;
- resize->height = max(11, FONT_HEIGHT_NORMAL + 1);
+ resize->height = GetMinSizing(NWST_STEP, max(11, FONT_HEIGHT_NORMAL + 1));
resize->width = 1;
/* Resize to about 200 pixels (for the preview) */
@@ -897,10 +897,10 @@ struct SpriteAlignerWindow : Window {
SmallVector &list = _newgrf_debug_sprite_picker.sprites;
int max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), list.Length());
- int y = r.top + WD_FRAMERECT_TOP;
+ int y = Center(r.top + WD_FRAMERECT_TOP, step_size, FONT_HEIGHT_NORMAL);
for (int i = this->vscroll->GetPosition(); i < max; i++) {
SetDParam(0, list[i]);
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_BLACK_COMMA, TC_FROMSTRING, SA_RIGHT | SA_FORCE);
+ DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_BLACK_COMMA, TC_FROMSTRING, SA_CENTER | SA_FORCE);
y += step_size;
}
break;
diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp
index 2945f99455..230f47758d 100644
--- a/src/newgrf_gui.cpp
+++ b/src/newgrf_gui.cpp
@@ -658,10 +658,9 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_NS_SCROLLBAR);
- this->vscroll2 = this->GetScrollbar(WID_NS_SCROLL2BAR);
+ this->vscroll2 = this->editable ? this->GetScrollbar(WID_NS_SCROLL2BAR) : NULL;
this->GetWidget(WID_NS_SHOW_REMOVE)->SetDisplayedPlane(this->editable ? 0 : 1);
- this->GetWidget(WID_NS_SHOW_APPLY)->SetDisplayedPlane(this->editable ? 0 : this->show_params ? 1 : SZSP_HORIZONTAL);
this->FinishInitNested(WN_GAME_OPTIONS_NEWGRF_STATE);
this->querystrings[WID_NS_FILTER] = &this->filter_editbox;
@@ -742,14 +741,14 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
case WID_NS_FILE_LIST:
{
Dimension d = maxdim(GetSpriteSize(SPR_SQUARE), GetSpriteSize(SPR_WARNING_SIGN));
- resize->height = max(d.height + 2U, FONT_HEIGHT_NORMAL + 2U);
- size->height = max(size->height, WD_FRAMERECT_TOP + 6 * resize->height + WD_FRAMERECT_BOTTOM);
+ resize->height = GetMinSizing(NWST_STEP, max(d.height + 2U, FONT_HEIGHT_NORMAL + 2U));
+ size->height = max(size->height, WD_FRAMERECT_TOP + 4 * resize->height + WD_FRAMERECT_BOTTOM);
break;
}
case WID_NS_AVAIL_LIST:
- resize->height = max(12, FONT_HEIGHT_NORMAL + 2);
- size->height = max(size->height, WD_FRAMERECT_TOP + 8 * resize->height + WD_FRAMERECT_BOTTOM);
+ resize->height = GetMinSizing(NWST_STEP, max(12, FONT_HEIGHT_NORMAL + 2));
+ size->height = max(size->height, WD_FRAMERECT_TOP + 4 * resize->height + WD_FRAMERECT_BOTTOM);
break;
case WID_NS_NEWGRF_INFO_TITLE: {
@@ -772,6 +771,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
}
}
d.width += padding.width;
+ d.height = GetMinSizing(NWST_BUTTON, d.height);
*size = maxdim(d, *size);
break;
}
@@ -782,6 +782,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
*size = maxdim(d, GetStringBoundingBox(STR_INTRO_ONLINE_CONTENT));
size->width += padding.width;
size->height += padding.height;
+ size->height = GetMinSizing(NWST_BUTTON, size->height);
break;
}
}
@@ -790,7 +791,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
virtual void OnResize()
{
this->vscroll->SetCapacityFromWidget(this, WID_NS_FILE_LIST);
- this->vscroll2->SetCapacityFromWidget(this, WID_NS_AVAIL_LIST);
+ if (this->vscroll2) this->vscroll2->SetCapacityFromWidget(this, WID_NS_AVAIL_LIST);
}
virtual void SetStringParameters(int widget) const
@@ -1299,8 +1300,10 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
widget_data = STR_INTRO_ONLINE_CONTENT;
tool_tip = STR_INTRO_TOOLTIP_ONLINE_CONTENT;
}
- this->GetWidget(WID_NS_CONTENT_DOWNLOAD)->widget_data = widget_data;
- this->GetWidget(WID_NS_CONTENT_DOWNLOAD)->tool_tip = tool_tip;
+ if (this->editable) {
+ this->GetWidget(WID_NS_CONTENT_DOWNLOAD)->widget_data = widget_data;
+ this->GetWidget(WID_NS_CONTENT_DOWNLOAD)->tool_tip = tool_tip;
+ }
this->GetWidget(WID_NS_CONTENT_DOWNLOAD2)->widget_data = widget_data;
this->GetWidget(WID_NS_CONTENT_DOWNLOAD2)->tool_tip = tool_tip;
@@ -1498,7 +1501,7 @@ private:
if (this->avail_pos < 0) this->avail_sel = NULL;
}
- this->vscroll2->SetCount(this->avails.Length()); // Update the scrollbar
+ if (this->vscroll2) this->vscroll2->SetCount(this->avails.Length()); // Update the scrollbar
}
/**
@@ -1633,8 +1636,8 @@ public:
uint min_inf_height = this->inf->smallest_y + this->inf->padding_top + this->inf->padding_bottom;
/* Smallest window is in two column mode. */
- this->smallest_x = max(min_avs_width, min_acs_width) + INTER_COLUMN_SPACING + min_inf_width;
- this->smallest_y = max(min_inf_height, min_acs_height + INTER_LIST_SPACING + min_avs_height);
+ this->smallest_x = min_avs_width + min_acs_width + min_inf_width + INTER_COLUMN_SPACING * 2;
+ this->smallest_y = max(max(min_inf_height, min_acs_height), min_avs_height);
/* Filling. */
this->fill_x = LeastCommonMultiple(this->avs->fill_x, this->acs->fill_x);
@@ -1671,7 +1674,7 @@ public:
/* Use 2 or 3 columns? */
uint min_three_columns = min_avs_width + min_acs_width + min_inf_width + 2 * INTER_COLUMN_SPACING;
uint min_two_columns = min_list_width + min_inf_width + INTER_COLUMN_SPACING;
- bool use_three_columns = this->editable && (min_three_columns + MIN_EXTRA_FOR_3_COLUMNS <= given_width);
+ bool use_three_columns = true; // this->editable;
/* Info panel is a separate column in both modes. Compute its width first. */
uint extra_width, inf_width;
@@ -1779,7 +1782,7 @@ public:
{
if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
- NWidgetCore *nw = (this->editable) ? this->avs->GetWidgetFromPos(x, y) : NULL;
+ NWidgetCore *nw = this->avs->GetWidgetFromPos(x, y);
if (nw == NULL) nw = this->acs->GetWidgetFromPos(x, y);
if (nw == NULL) nw = this->inf->GetWidgetFromPos(x, y);
return nw;
@@ -1787,7 +1790,7 @@ public:
virtual void Draw(const Window *w)
{
- if (this->editable) this->avs->Draw(w);
+ this->avs->Draw(w);
this->acs->Draw(w);
this->inf->Draw(w);
}
@@ -1903,33 +1906,111 @@ static const NWidgetPart _nested_newgrf_infopanel_widgets[] = {
SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
EndContainer(),
EndContainer(),
- NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NS_SHOW_APPLY),
- /* Right side, buttons. */
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, WD_RESIZEBOX_WIDTH, 0),
- NWidget(NWID_VERTICAL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_SET_PARAMETERS), SetFill(1, 0), SetResize(1, 0),
- SetDataTip(STR_NEWGRF_SETTINGS_SET_PARAMETERS, STR_NULL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_TOGGLE_PALETTE), SetFill(1, 0), SetResize(1, 0),
- SetDataTip(STR_NEWGRF_SETTINGS_TOGGLE_PALETTE, STR_NEWGRF_SETTINGS_TOGGLE_PALETTE_TOOLTIP),
- EndContainer(),
- NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_APPLY_CHANGES), SetFill(1, 0), SetResize(1, 0),
- SetDataTip(STR_NEWGRF_SETTINGS_APPLY_CHANGES, STR_NULL),
+ /* Right side, buttons. */
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, WD_RESIZEBOX_WIDTH, 0),
+ NWidget(NWID_VERTICAL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_SET_PARAMETERS), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_NEWGRF_SETTINGS_SET_PARAMETERS, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_TOGGLE_PALETTE), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_NEWGRF_SETTINGS_TOGGLE_PALETTE, STR_NEWGRF_SETTINGS_TOGGLE_PALETTE_TOOLTIP),
EndContainer(),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_APPLY_CHANGES), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_NEWGRF_SETTINGS_APPLY_CHANGES, STR_NULL),
+ EndContainer(),
+};
+
+static const NWidgetPart _nested_newgrf_actives_wide_widgets[] = {
+ /* Left side, presets. */
+ NWidget(NWID_VERTICAL),
+ NWidget(WWT_LABEL, COLOUR_MAUVE), SetDataTip(STR_NEWGRF_SETTINGS_ACTIVE_LIST, STR_NULL),
+ SetFill(1, 0), SetResize(1, 0), SetPadding(3, WD_FRAMETEXT_RIGHT, 0, WD_FRAMETEXT_LEFT),
+ /* Left side, active grfs. */
+ NWidget(NWID_HORIZONTAL), SetPadding(0, 2, 0, 2),
+ NWidget(WWT_PANEL, COLOUR_MAUVE),
+ NWidget(WWT_INSET, COLOUR_MAUVE, WID_NS_FILE_LIST), SetMinimalSize(100, 1), SetPadding(2, 2, 2, 2),
+ SetFill(1, 1), SetResize(1, 1), SetScrollbar(WID_NS_SCROLLBAR), SetDataTip(STR_NULL, STR_NEWGRF_SETTINGS_FILE_TOOLTIP),
+ EndContainer(),
+ EndContainer(),
+ NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_NS_SCROLLBAR),
+ EndContainer(),
+ EndContainer(),
+};
+
+static const NWidgetPart _nested_newgrf_buttons_wide_widgets[] = {
+ NWidget(NWID_VERTICAL),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_TEXT, COLOUR_MAUVE), SetDataTip(STR_NEWGRF_SETTINGS_SELECT_PRESET, STR_NULL),
+ SetPadding(0, WD_FRAMETEXT_RIGHT, 0, 0),
+ NWidget(WWT_DROPDOWN, COLOUR_YELLOW, WID_NS_PRESET_LIST), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_JUST_STRING, STR_NEWGRF_SETTINGS_PRESET_LIST_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_PRESET_SAVE), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_NEWGRF_SETTINGS_PRESET_SAVE, STR_NEWGRF_SETTINGS_PRESET_SAVE_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_PRESET_DELETE), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_NEWGRF_SETTINGS_PRESET_DELETE, STR_NEWGRF_SETTINGS_PRESET_DELETE_TOOLTIP),
+ EndContainer(),
+
+ NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NS_SHOW_REMOVE),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPadding(0, 2, 0, 2), SetPIP(0, WD_RESIZEBOX_WIDTH, 0),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_REMOVE), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_NEWGRF_SETTINGS_REMOVE, STR_NEWGRF_SETTINGS_REMOVE_TOOLTIP),
+ NWidget(NWID_VERTICAL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_MOVE_UP), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_NEWGRF_SETTINGS_MOVEUP, STR_NEWGRF_SETTINGS_MOVEUP_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_MOVE_DOWN), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_NEWGRF_SETTINGS_MOVEDOWN, STR_NEWGRF_SETTINGS_MOVEDOWN_TOOLTIP),
+ EndContainer(),
+ EndContainer(),
+ NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPadding(0, 0, 0, 0),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_RESCAN_FILES2), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_NEWGRF_SETTINGS_RESCAN_FILES, STR_NEWGRF_SETTINGS_RESCAN_FILES_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_CONTENT_DOWNLOAD2), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_INTRO_ONLINE_CONTENT, STR_INTRO_TOOLTIP_ONLINE_CONTENT),
+ EndContainer(),
+ EndContainer(),
+
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_OPEN_URL), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_NEWGRF_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_NEWGRF_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_NEWGRF_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
+ EndContainer(),
+
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_NS_VIEW_PARAMETERS), SetFill(1, 0), SetResize(1, 0),
SetDataTip(STR_NEWGRF_SETTINGS_SHOW_PARAMETERS, STR_NULL),
EndContainer(),
};
+static const NWidgetPart _nested_newgrf_infopanel_wide_widgets[] = {
+ /* Right side, info panel. */
+ NWidget(WWT_PANEL, COLOUR_MAUVE),
+ NWidget(WWT_EMPTY, COLOUR_MAUVE, WID_NS_NEWGRF_INFO_TITLE), SetFill(1, 0), SetResize(1, 0),
+ NWidget(WWT_EMPTY, COLOUR_MAUVE, WID_NS_NEWGRF_INFO), SetFill(1, 1), SetResize(1, 1), SetMinimalSize(100, 100),
+ EndContainer(),
+};
+
/** Construct nested container widget for managing the lists and the info panel of the NewGRF GUI. */
+static bool _newgrf_display_editable = false; // Quick hack
NWidgetBase* NewGRFDisplay(int *biggest_index)
{
- NWidgetBase *avs = MakeNWidgets(_nested_newgrf_availables_widgets, lengthof(_nested_newgrf_availables_widgets), biggest_index, NULL);
+ NWidgetBase *avs = _newgrf_display_editable ?
+ MakeNWidgets(_nested_newgrf_availables_widgets, lengthof(_nested_newgrf_availables_widgets), biggest_index, NULL) :
+ MakeNWidgets(_nested_newgrf_actives_wide_widgets, lengthof(_nested_newgrf_actives_wide_widgets), biggest_index, NULL);
int biggest2;
- NWidgetBase *acs = MakeNWidgets(_nested_newgrf_actives_widgets, lengthof(_nested_newgrf_actives_widgets), &biggest2, NULL);
+ NWidgetBase *acs = _newgrf_display_editable ?
+ MakeNWidgets(_nested_newgrf_actives_widgets, lengthof(_nested_newgrf_actives_widgets), &biggest2, NULL) :
+ MakeNWidgets(_nested_newgrf_buttons_wide_widgets, lengthof(_nested_newgrf_buttons_wide_widgets), &biggest2, NULL);
*biggest_index = max(*biggest_index, biggest2);
- NWidgetBase *inf = MakeNWidgets(_nested_newgrf_infopanel_widgets, lengthof(_nested_newgrf_infopanel_widgets), &biggest2, NULL);
+ NWidgetBase *inf = _newgrf_display_editable ?
+ MakeNWidgets(_nested_newgrf_infopanel_widgets, lengthof(_nested_newgrf_infopanel_widgets), &biggest2, NULL) :
+ MakeNWidgets(_nested_newgrf_infopanel_wide_widgets, lengthof(_nested_newgrf_infopanel_wide_widgets), &biggest2, NULL);
*biggest_index = max(*biggest_index, biggest2);
return new NWidgetNewGRFDisplay(avs, acs, inf);
@@ -2006,6 +2087,7 @@ static void NewGRFConfirmationCallback(Window *w, bool confirmed)
void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFConfig **config)
{
DeleteWindowByClass(WC_GAME_OPTIONS);
+ _newgrf_display_editable = editable;
new NewGRFWindow(&_newgrf_desc, editable, show_params, exec_changes, config);
}
@@ -2168,6 +2250,7 @@ static void ShowSavePresetWindow(const char *initial_text)
/** Widgets for the progress window. */
static const NWidgetPart _nested_scan_progress_widgets[] = {
NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_NEWGRF_SCAN_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+ SetSizingType(NWST_BUTTON),
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(NWID_HORIZONTAL), SetPIP(20, 0, 20),
NWidget(NWID_VERTICAL), SetPIP(11, 8, 11),
diff --git a/src/news_gui.cpp b/src/news_gui.cpp
index 3800af8b57..9f5eb6681e 100644
--- a/src/news_gui.cpp
+++ b/src/news_gui.cpp
@@ -165,7 +165,7 @@ static const NWidgetPart _nested_thin_news_widgets[] = {
EndContainer(),
EndContainer(),
NWidget(WWT_EMPTY, COLOUR_WHITE, WID_N_MESSAGE), SetMinimalSize(428, 48), SetFill(1, 0), SetPadding(0, 5, 0, 5),
- NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_N_VIEWPORT), SetMinimalSize(426, 70), SetPadding(1, 2, 2, 2),
+ NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_N_VIEWPORT), SetSizingType(NWST_VIEWPORT), SetMinimalSize(426, 70), SetPadding(1, 2, 2, 2),
EndContainer(),
};
@@ -187,7 +187,7 @@ static const NWidgetPart _nested_small_news_widgets[] = {
/* Main part */
NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_N_HEADLINE),
NWidget(WWT_INSET, COLOUR_LIGHT_BLUE, WID_N_INSET), SetPadding(2, 2, 2, 2),
- NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_N_VIEWPORT), SetPadding(1, 1, 1, 1), SetMinimalSize(274, 47), SetFill(1, 0),
+ NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_N_VIEWPORT), SetSizingType(NWST_VIEWPORT), SetPadding(1, 1, 1, 1), SetMinimalSize(274, 47), SetFill(1, 0),
EndContainer(),
NWidget(WWT_EMPTY, COLOUR_WHITE, WID_N_MESSAGE), SetMinimalSize(275, 20), SetFill(1, 0), SetPadding(0, 5, 0, 5),
EndContainer(),
@@ -318,6 +318,7 @@ struct NewsWindow : Window {
break;
case WID_N_MESSAGE:
+ size->width = GetMinSizing(NWST_WINDOW_LENGTH, size->width);
CopyInDParam(0, this->ni->params, lengthof(this->ni->params));
str = this->ni->string_id;
break;
@@ -1010,7 +1011,7 @@ struct MessageHistoryWindow : Window {
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
{
if (widget == WID_MH_BACKGROUND) {
- this->line_height = FONT_HEIGHT_NORMAL + 2;
+ this->line_height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL + 2);
resize->height = this->line_height;
/* Months are off-by-one, so it's actually 8. Not using
@@ -1041,7 +1042,7 @@ struct MessageHistoryWindow : Window {
}
/* Fill the widget with news items. */
- int y = r.top + this->top_spacing;
+ int y = Center(r.top + this->top_spacing, this->line_height, FONT_HEIGHT_NORMAL);
bool rtl = _current_text_dir == TD_RTL;
uint date_left = rtl ? r.right - WD_FRAMERECT_RIGHT - this->date_width : r.left + WD_FRAMERECT_LEFT;
uint date_right = rtl ? r.right - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT + this->date_width;
diff --git a/src/openttd.cpp b/src/openttd.cpp
index c149ebbd4d..816488530d 100644
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -69,6 +69,9 @@
#include
#include "safeguards.h"
+#ifdef __ANDROID__
+#include
+#endif
void CallLandscapeTick();
void IncreaseDate();
@@ -81,6 +84,8 @@ bool HandleBootstrap();
extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY);
extern void ShowOSErrorBox(const char *buf, bool system);
extern char *_config_file;
+const char *NETWORK_SAVE_SCREENSHOT_FILE = "OpenTTD-network-save";
+const char *NETWORK_SAVE_SCREENSHOT_FILE_PNG = "OpenTTD-network-save.png";
/**
* Error handling for fatal user errors.
@@ -1161,6 +1166,24 @@ void SwitchToMode(SwitchMode new_mode)
ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
} else {
DeleteWindowById(WC_SAVELOAD, 0);
+#ifdef __ANDROID__
+ if (_settings_client.gui.save_to_network) {
+ char screenshotFile[PATH_MAX] = "";
+ const char* lastPart = strrchr(_file_to_saveload.name, PATHSEPCHAR);
+ if (!lastPart) {
+ lastPart = _file_to_saveload.name;
+ } else {
+ lastPart++;
+ }
+ MakeScreenshot(SC_VIEWPORT, NETWORK_SAVE_SCREENSHOT_FILE);
+ FioFindFullPath(screenshotFile, sizeof(screenshotFile), SCREENSHOT_DIR, NETWORK_SAVE_SCREENSHOT_FILE_PNG);
+ uint64_t playedTime = abs(_date - DAYS_TILL(_settings_newgame.game_creation.starting_year)) * 1000;
+ int ret = SDL_ANDROID_CloudSave(_file_to_saveload.name, lastPart, "OpenTTD", lastPart, screenshotFile, playedTime);
+ if (_settings_client.gui.save_to_network == 2) {
+ _settings_client.gui.save_to_network = ret ? 1 : 0;
+ }
+ }
+#endif
}
break;
diff --git a/src/order_gui.cpp b/src/order_gui.cpp
index d4feae35ca..b01c47ea2e 100644
--- a/src/order_gui.cpp
+++ b/src/order_gui.cpp
@@ -555,13 +555,16 @@ private:
assert(type > OPOS_NONE && type < OPOS_END);
static const HighLightStyle goto_place_style[OPOS_END - 1] = {
- HT_RECT | HT_VEHICLE, // OPOS_GOTO
+ HT_RECT | HT_VEHICLE | HT_SCROLL_VIEWPORT, // OPOS_GOTO
HT_NONE, // OPOS_CONDITIONAL
- HT_VEHICLE, // OPOS_SHARE
+ HT_VEHICLE | HT_SCROLL_VIEWPORT, // OPOS_SHARE
};
SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, goto_place_style[type - 1], this);
this->goto_type = type;
this->SetWidgetDirty(WID_O_GOTO);
+ if (type == OPOS_GOTO) {
+ MoveAllWindowsOffScreen();
+ }
}
/**
diff --git a/src/os/unix/crashlog_unix.cpp b/src/os/unix/crashlog_unix.cpp
index 47de057f7e..c0663a6b06 100644
--- a/src/os/unix/crashlog_unix.cpp
+++ b/src/os/unix/crashlog_unix.cpp
@@ -143,7 +143,11 @@ public:
};
/** The signals we want our crash handler to handle. */
+#ifdef __ANDROID__
+static const int _signals_to_handle[] = { }; // Default Android signal handler will give us stack trace
+#else
static const int _signals_to_handle[] = { SIGSEGV, SIGABRT, SIGFPE, SIGBUS, SIGILL };
+#endif
/**
* Entry point for the crash handler.
diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp
index 59d40cc89f..19cf13a35f 100644
--- a/src/os/unix/unix.cpp
+++ b/src/os/unix/unix.cpp
@@ -26,7 +26,7 @@
#ifdef __APPLE__
#include
-#elif (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)
+#elif ((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)) && !defined(__ANDROID__)
#define HAS_STATVFS
#endif
@@ -257,6 +257,11 @@ void cocoaSetupAutoreleasePool();
void cocoaReleaseAutoreleasePool();
#endif
+#ifdef __ANDROID__
+#define main SDL_main
+extern "C" int CDECL main(int, char *[]);
+#endif
+
int CDECL main(int argc, char *argv[])
{
int ret;
@@ -367,10 +372,23 @@ void OSOpenBrowser(const char *url)
pid_t child_pid = fork();
if (child_pid != 0) return;
+#ifdef __ANDROID__
+ const char *args[9];
+ args[0] = "/system/bin/am";
+ args[1] = "start";
+ args[2] = "-a";
+ args[3] = "android.intent.action.VIEW";
+ args[4] = "--user";
+ args[5] = "0";
+ args[6] = "-d";
+ args[7] = url;
+ args[8] = NULL;
+#else
const char *args[3];
args[0] = "xdg-open";
args[1] = url;
args[2] = NULL;
+#endif
execvp(args[0], const_cast(args));
DEBUG(misc, 0, "Failed to open url: %s", url);
exit(0);
diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp
index 974e465f43..71ae041b1d 100644
--- a/src/osk_gui.cpp
+++ b/src/osk_gui.cpp
@@ -105,7 +105,7 @@ struct OskWindow : public Window {
widget -= WID_OSK_LETTERS;
DrawCharCentered(_keyboard[this->shift][widget],
- r.left + 8,
+ (r.left + r.right) / 2,
r.top + 3,
TC_BLACK);
}
@@ -229,7 +229,8 @@ static const int INTER_KEY_SPACE = 2; // Number of pixels between two keys.
*/
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);
+ int min_half_key = max(GetMinSizing(NWST_BUTTON), HALF_KEY_WIDTH);
+ int key_width = min_half_key + (INTER_KEY_SPACE + min_half_key) * (num_half - 1);
if (widtype == NWID_SPACER) {
if (!hor->IsEmpty()) key_width += INTER_KEY_SPACE;
@@ -252,7 +253,7 @@ static void AddKey(NWidgetHorizontal *hor, int height, int num_half, WidgetType
static NWidgetBase *MakeTopKeys(int *biggest_index)
{
NWidgetHorizontal *hor = new NWidgetHorizontal();
- int key_height = FONT_HEIGHT_NORMAL + 2;
+ int key_height = GetMinSizing(NWST_KEYBOARD, 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);
@@ -264,7 +265,7 @@ static NWidgetBase *MakeTopKeys(int *biggest_index)
static NWidgetBase *MakeNumberKeys(int *biggest_index)
{
NWidgetHorizontal *hor = new NWidgetHorizontalLTR();
- int key_height = FONT_HEIGHT_NORMAL + 6;
+ int key_height = GetMinSizing(NWST_KEYBOARD, 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);
@@ -276,7 +277,7 @@ static NWidgetBase *MakeNumberKeys(int *biggest_index)
static NWidgetBase *MakeQwertyKeys(int *biggest_index)
{
NWidgetHorizontal *hor = new NWidgetHorizontalLTR();
- int key_height = FONT_HEIGHT_NORMAL + 6;
+ int key_height = GetMinSizing(NWST_KEYBOARD, 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++) {
@@ -290,7 +291,7 @@ static NWidgetBase *MakeQwertyKeys(int *biggest_index)
static NWidgetBase *MakeAsdfgKeys(int *biggest_index)
{
NWidgetHorizontal *hor = new NWidgetHorizontalLTR();
- int key_height = FONT_HEIGHT_NORMAL + 6;
+ int key_height = GetMinSizing(NWST_KEYBOARD, 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++) {
@@ -303,7 +304,7 @@ static NWidgetBase *MakeAsdfgKeys(int *biggest_index)
static NWidgetBase *MakeZxcvbKeys(int *biggest_index)
{
NWidgetHorizontal *hor = new NWidgetHorizontalLTR();
- int key_height = FONT_HEIGHT_NORMAL + 6;
+ int key_height = GetMinSizing(NWST_KEYBOARD, 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++) {
@@ -317,7 +318,7 @@ static NWidgetBase *MakeZxcvbKeys(int *biggest_index)
static NWidgetBase *MakeSpacebarKeys(int *biggest_index)
{
NWidgetHorizontal *hor = new NWidgetHorizontal();
- int key_height = FONT_HEIGHT_NORMAL + 6;
+ int key_height = GetMinSizing(NWST_KEYBOARD, 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);
@@ -329,7 +330,7 @@ static NWidgetBase *MakeSpacebarKeys(int *biggest_index)
static const NWidgetPart _nested_osk_widgets[] = {
- NWidget(WWT_CAPTION, COLOUR_GREY, WID_OSK_CAPTION), SetDataTip(STR_WHITE_STRING, STR_NULL),
+ NWidget(WWT_CAPTION, COLOUR_GREY, WID_OSK_CAPTION), SetSizingType(NWST_BUTTON), SetDataTip(STR_WHITE_STRING, STR_NULL),
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(WWT_EDITBOX, COLOUR_GREY, WID_OSK_TEXT), SetMinimalSize(252, 12), SetPadding(2, 2, 2, 2),
EndContainer(),
diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp
index a8c2fc6b33..1319deaf26 100644
--- a/src/rail_gui.cpp
+++ b/src/rail_gui.cpp
@@ -191,15 +191,7 @@ static void PlaceRail_Station(TileIndex tile)
VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_BUILD_STATION);
VpSetPlaceSizingLimit(_settings_game.station.station_spread);
} else {
- uint32 p1 = _cur_railtype | _railstation.orientation << 4 | _settings_client.gui.station_numtracks << 8 | _settings_client.gui.station_platlength << 16 | _ctrl_pressed << 24;
- uint32 p2 = _railstation.station_class | _railstation.station_type << 8 | INVALID_STATION << 16;
-
- int w = _settings_client.gui.station_numtracks;
- int h = _settings_client.gui.station_platlength;
- if (!_railstation.orientation) Swap(w, h);
-
- CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation, "" };
- ShowSelectStationIfNeeded(cmdcont, TileArea(tile, w, h));
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_BUILD_STATION);
}
}
@@ -254,22 +246,6 @@ static void GenericPlaceSignals(TileIndex tile)
}
}
-/**
- * Start placing a rail bridge.
- * @param tile Position of the first tile of the bridge.
- * @param w Rail toolbar window.
- */
-static void PlaceRail_Bridge(TileIndex tile, Window *w)
-{
- if (IsBridgeTile(tile)) {
- TileIndex other_tile = GetOtherTunnelBridgeEnd(tile);
- Point pt = {0, 0};
- w->OnPlaceMouseUp(VPM_X_OR_Y, DDSP_BUILD_BRIDGE, pt, other_tile, tile);
- } else {
- VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
- }
-}
-
/** Command callback for building a tunnel */
void CcBuildRailTunnel(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
{
@@ -431,6 +407,7 @@ struct BuildRailToolbarWindow : Window {
~BuildRailToolbarWindow()
{
+ if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort();
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
}
@@ -557,7 +534,7 @@ struct BuildRailToolbarWindow : Window {
break;
case WID_RAT_BUILD_DEPOT:
- if (HandlePlacePushButton(this, WID_RAT_BUILD_DEPOT, GetRailTypeInfo(_cur_railtype)->cursor.depot, HT_RECT)) {
+ if (HandlePlacePushButton(this, WID_RAT_BUILD_DEPOT, GetRailTypeInfo(_cur_railtype)->cursor.depot, HT_RECT | HT_SCROLL_VIEWPORT)) {
ShowBuildTrainDepotPicker(this);
this->last_user_action = widget;
}
@@ -566,7 +543,7 @@ struct BuildRailToolbarWindow : Window {
case WID_RAT_BUILD_WAYPOINT:
this->last_user_action = widget;
_waypoint_count = StationClass::Get(STAT_CLASS_WAYP)->GetSpecCount();
- if (HandlePlacePushButton(this, WID_RAT_BUILD_WAYPOINT, SPR_CURSOR_WAYPOINT, HT_RECT) && _waypoint_count > 1) {
+ if (HandlePlacePushButton(this, WID_RAT_BUILD_WAYPOINT, SPR_CURSOR_WAYPOINT, HT_RECT | HT_SCROLL_VIEWPORT) && _waypoint_count > 1) {
ShowBuildWaypointPicker(this);
}
break;
@@ -646,9 +623,7 @@ struct BuildRailToolbarWindow : Window {
break;
case WID_RAT_BUILD_DEPOT:
- DoCommandP(tile, _cur_railtype, _build_depot_direction,
- CMD_BUILD_TRAIN_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT),
- CcRailDepot);
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_SINGLE_TILE);
break;
case WID_RAT_BUILD_WAYPOINT:
@@ -664,11 +639,11 @@ struct BuildRailToolbarWindow : Window {
break;
case WID_RAT_BUILD_BRIDGE:
- PlaceRail_Bridge(tile, this);
+ VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
break;
case WID_RAT_BUILD_TUNNEL:
- DoCommandP(tile, _cur_railtype | (TRANSPORT_RAIL << 8), 0, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRailTunnel);
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_BUILD_BRIDGE);
break;
case WID_RAT_CONVERT_RAIL:
@@ -684,6 +659,14 @@ struct BuildRailToolbarWindow : Window {
/* no dragging if you have pressed the convert button */
if (FindWindowById(WC_BUILD_SIGNAL, 0) != NULL && _convert_signal_button && this->IsWidgetLowered(WID_RAT_BUILD_SIGNALS)) return;
+ switch (this->last_user_action) {
+ case WID_RAT_BUILD_TUNNEL:
+ this->OnPlacePresize(pt, TileVirtXY(pt.x, pt.y));
+ return;
+ default:
+ break;
+ }
+
VpSelectTilesWithMethod(pt.x, pt.y, select_method);
}
@@ -692,9 +675,21 @@ struct BuildRailToolbarWindow : Window {
if (pt.x != -1) {
switch (select_proc) {
default: NOT_REACHED();
+ case DDSP_PLACE_AUTOROAD:
+ assert(this->last_user_action == WID_RAT_BUILD_BRIDGE);
case DDSP_BUILD_BRIDGE:
- if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
- ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_RAIL, _cur_railtype);
+ switch (this->last_user_action) {
+ case WID_RAT_BUILD_TUNNEL:
+ if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
+ else VpStartPreSizing();
+ DoCommandP(end_tile, _cur_railtype | (TRANSPORT_RAIL << 8), 0, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRailTunnel);
+ break;
+ case WID_RAT_BUILD_BRIDGE:
+ if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
+ ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_RAIL, _cur_railtype);
+ break;
+ default: NOT_REACHED();
+ }
break;
case DDSP_PLACE_RAIL:
@@ -720,7 +715,19 @@ struct BuildRailToolbarWindow : Window {
if (_remove_button_clicked) {
DoCommandP(end_tile, start_tile, _ctrl_pressed ? 0 : 1, CMD_REMOVE_FROM_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_REMOVE_PART_OF_STATION), CcPlaySound1E);
} else {
- HandleStationPlacement(start_tile, end_tile);
+ if (!_settings_client.gui.station_dragdrop) {
+ uint32 p1 = _cur_railtype | _railstation.orientation << 4 | _settings_client.gui.station_numtracks << 8 | _settings_client.gui.station_platlength << 16 | _ctrl_pressed << 24;
+ uint32 p2 = _railstation.station_class | _railstation.station_type << 8 | INVALID_STATION << 16;
+
+ int w = _settings_client.gui.station_numtracks;
+ int h = _settings_client.gui.station_platlength;
+ if (!_railstation.orientation) Swap(w, h);
+
+ CommandContainer cmdcont = { end_tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation, "" };
+ ShowSelectStationIfNeeded(cmdcont, TileArea(end_tile, w, h));
+ } else {
+ HandleStationPlacement(start_tile, end_tile);
+ }
}
} else {
/* Waypoint */
@@ -736,6 +743,14 @@ struct BuildRailToolbarWindow : Window {
}
}
break;
+
+ case DDSP_SINGLE_TILE:
+ assert(end_tile == start_tile);
+ assert(last_user_action == WID_RAT_BUILD_DEPOT);
+ DoCommandP(end_tile, _cur_railtype, _build_depot_direction,
+ CMD_BUILD_TRAIN_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT),
+ CcRailDepot);
+ break;
}
}
}
@@ -754,10 +769,29 @@ struct BuildRailToolbarWindow : Window {
DeleteWindowByClass(WC_BUILD_BRIDGE);
}
- virtual void OnPlacePresize(Point pt, TileIndex tile)
+ virtual void SelectLastTool()
{
- DoCommand(tile, _cur_railtype | (TRANSPORT_RAIL << 8), 0, DC_AUTO, CMD_BUILD_TUNNEL);
- VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
+ // User misplaced something - activate last selected tool again
+ if (this->last_user_action == WIDGET_LIST_END)
+ return;
+ Point dummy = {0, 0};
+ this->RaiseWidget(this->last_user_action);
+ this->OnClick(dummy, this->last_user_action, 0);
+ }
+
+ virtual void OnPlacePresize(Point pt, TileIndex tile_from)
+ {
+ TileIndex tile_to = tile_from;
+
+ if (this->last_user_action == WID_RAT_BUILD_BRIDGE) {
+ tile_to = IsBridgeTile(tile_from) ? GetOtherBridgeEnd(tile_from) : TileVirtXY(pt.x, pt.y);
+ } else {
+ assert(this->last_user_action == WID_RAT_BUILD_TUNNEL);
+ DoCommand(tile_from, _cur_railtype | (TRANSPORT_RAIL << 8), 0, DC_AUTO, CMD_BUILD_TUNNEL);
+ tile_to = _build_tunnel_endtile == 0 ? tile_from : _build_tunnel_endtile;
+ }
+
+ VpSetPresizeRange(tile_from, tile_to);
}
virtual EventState OnCTRLStateChange()
@@ -868,7 +902,7 @@ Window *ShowBuildRailToolbar(RailType railtype)
if (!Company::IsValidID(_local_company)) return NULL;
if (!ValParamRailtype(railtype)) return NULL;
- DeleteWindowByClass(WC_BUILD_TOOLBAR);
+ DeleteToolbarLinkedWindows();
_cur_railtype = railtype;
_remove_button_clicked = false;
return new BuildRailToolbarWindow(&_build_rail_desc, railtype);
@@ -1394,9 +1428,9 @@ static const NWidgetPart _nested_station_builder_widgets[] = {
NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(144, 11), SetDataTip(STR_STATION_BUILD_ORIENTATION, STR_NULL), SetPadding(1, 2, 0, 2),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetMinimalSize(7, 0), SetFill(1, 0),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAS_PLATFORM_DIR_X), SetMinimalSize(66, 60), SetFill(0, 0), SetDataTip(0x0, STR_STATION_BUILD_RAILROAD_ORIENTATION_TOOLTIP), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAS_PLATFORM_DIR_X), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 60), SetFill(0, 0), SetDataTip(0x0, STR_STATION_BUILD_RAILROAD_ORIENTATION_TOOLTIP), EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(2, 0), SetFill(1, 0),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAS_PLATFORM_DIR_Y), SetMinimalSize(66, 60), SetFill(0, 0), SetDataTip(0x0, STR_STATION_BUILD_RAILROAD_ORIENTATION_TOOLTIP), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAS_PLATFORM_DIR_Y), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 60), SetFill(0, 0), SetDataTip(0x0, STR_STATION_BUILD_RAILROAD_ORIENTATION_TOOLTIP), EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(7, 0), SetFill(1, 0),
EndContainer(),
NWidget(WWT_LABEL, COLOUR_DARK_GREEN, WID_BRAS_SHOW_NEWST_TYPE), SetMinimalSize(144, 11), SetDataTip(STR_ORANGE_STRING, STR_NULL), SetPadding(1, 2, 4, 2),
@@ -1426,19 +1460,24 @@ static const NWidgetPart _nested_station_builder_widgets[] = {
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(NWID_HORIZONTAL),
- NWidget(NWID_SPACER), SetMinimalSize(2, 0), SetFill(1, 0),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_DRAG_N_DROP), SetMinimalSize(75, 12), SetDataTip(STR_STATION_BUILD_DRAG_DROP, STR_STATION_BUILD_DRAG_DROP_TOOLTIP),
- NWidget(NWID_SPACER), SetMinimalSize(2, 0), SetFill(1, 0),
- EndContainer(),
- NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(144, 11), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL), SetPadding(3, 2, 0, 2),
- NWidget(NWID_HORIZONTAL),
- NWidget(NWID_SPACER), SetMinimalSize(2, 0), SetFill(1, 0),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_HIGHLIGHT_OFF), SetMinimalSize(60, 12),
- SetDataTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_HIGHLIGHT_ON), SetMinimalSize(60, 12),
- SetDataTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP),
- NWidget(NWID_SPACER), SetMinimalSize(2, 0), SetFill(1, 0),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(NWID_SPACER), SetMinimalSize(2, 0), SetFill(1, 0),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_DRAG_N_DROP), SetMinimalSize(75, 12), SetDataTip(STR_STATION_BUILD_DRAG_DROP, STR_STATION_BUILD_DRAG_DROP_TOOLTIP),
+ NWidget(NWID_SPACER), SetMinimalSize(2, 0), SetFill(1, 0),
+ EndContainer(),
+ NWidget(NWID_VERTICAL),
+ NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(144, 11), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL), SetPadding(3, 2, 0, 2),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(NWID_SPACER), SetMinimalSize(2, 0), SetFill(1, 0),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_HIGHLIGHT_OFF), SetMinimalSize(60, 12),
+ SetDataTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_HIGHLIGHT_ON), SetMinimalSize(60, 12),
+ SetDataTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP),
+ NWidget(NWID_SPACER), SetMinimalSize(2, 0), SetFill(1, 0),
+ EndContainer(),
+ EndContainer(),
EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 2),
EndContainer(),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_BRAS_SHOW_NEWST_MATRIX),
/* We need an additional background for the matrix, as the matrix cannot handle the scrollbar due to not being an NWidgetCore. */
@@ -1468,7 +1507,7 @@ static const NWidgetPart _nested_station_builder_widgets[] = {
/** High level window description of the station-build window (default & newGRF) */
static WindowDesc _station_builder_desc(
- WDP_AUTO, "build_station_rail", 350, 0,
+ WDP_AUTO, "build_station_rail", 0, 0,
WC_BUILD_STATION, WC_BUILD_TOOLBAR,
WDF_CONSTRUCTION,
_nested_station_builder_widgets, lengthof(_nested_station_builder_widgets)
@@ -1656,6 +1695,9 @@ static const NWidgetPart _nested_signal_builder_widgets[] = {
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_SEMAPHORE_PBS), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP), EndContainer(), SetFill(1, 1),
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_SEMAPHORE_PBS_OWAY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PBS_OWAY_TOOLTIP), EndContainer(), SetFill(1, 1),
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_BS_CONVERT), SetDataTip(SPR_IMG_SIGNAL_CONVERT, STR_BUILD_SIGNAL_CONVERT_TOOLTIP), SetFill(1, 1),
+ NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetFill(1, 1),
+ NWidget(WWT_LABEL, COLOUR_DARK_GREEN, WID_BS_DRAG_SIGNALS_DENSITY_LABEL), SetDataTip(STR_ORANGE_INT, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetFill(1, 1),
+ EndContainer(),
EndContainer(),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_ELECTRIC_NORM), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_NORM_TOOLTIP), EndContainer(), SetFill(1, 1),
@@ -1665,14 +1707,10 @@ static const NWidgetPart _nested_signal_builder_widgets[] = {
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_ELECTRIC_PBS), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP), EndContainer(), SetFill(1, 1),
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_ELECTRIC_PBS_OWAY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP), EndContainer(), SetFill(1, 1),
NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetFill(1, 1),
- NWidget(WWT_LABEL, COLOUR_DARK_GREEN, WID_BS_DRAG_SIGNALS_DENSITY_LABEL), SetDataTip(STR_ORANGE_INT, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetFill(1, 1),
- NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
- NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_BS_DRAG_SIGNALS_DENSITY_DECREASE), SetMinimalSize(9, 12), SetDataTip(AWV_DECREASE, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP),
- NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_BS_DRAG_SIGNALS_DENSITY_INCREASE), SetMinimalSize(9, 12), SetDataTip(AWV_INCREASE, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP),
- NWidget(NWID_SPACER), SetFill(1, 0),
- EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetFill(1, 0),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_BS_DRAG_SIGNALS_DENSITY_DECREASE), SetSizingType(NWST_STEP), SetMinimalSize(9, 12), SetDataTip(AWV_DECREASE, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP),
+ EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetFill(1, 1),
+ NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_BS_DRAG_SIGNALS_DENSITY_INCREASE), SetSizingType(NWST_STEP), SetMinimalSize(9, 12), SetDataTip(AWV_INCREASE, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP),
EndContainer(),
EndContainer(),
EndContainer(),
@@ -1744,18 +1782,18 @@ static const NWidgetPart _nested_build_depot_widgets[] = {
NWidget(NWID_HORIZONTAL_LTR),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
NWidget(NWID_VERTICAL),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_NW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_NW), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_SW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_SW), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
EndContainer(),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(2, 0),
NWidget(NWID_VERTICAL),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_NE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_NE), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_SE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_SE), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
EndContainer(),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
diff --git a/src/rev.cpp.in b/src/rev.cpp.in
index c208382050..756da35753 100644
--- a/src/rev.cpp.in
+++ b/src/rev.cpp.in
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $Id: rev.cpp.in 26740 2014-08-16 18:32:17Z frosch $ */
/*
* This file is part of OpenTTD.
@@ -72,7 +72,7 @@ const byte _openttd_revision_modified = !!MODIFIED!!;
* final release will always have a lower version number than the released
* version, thus making comparisons on specific revisions easy.
*/
-const uint32 _openttd_newgrf_version = 1 << 28 | 5 << 24 | 0 << 20 | 0 << 19 | (!!REVISION!! & ((1 << 19) - 1));
+const uint32 _openttd_newgrf_version = 1 << 28 | 4 << 24 | 2 << 20 | 1 << 19 | (!!REVISION!! & ((1 << 19) - 1));
#ifdef __MORPHOS__
/**
diff --git a/src/road_gui.cpp b/src/road_gui.cpp
index c058c020f9..a69bad050b 100644
--- a/src/road_gui.cpp
+++ b/src/road_gui.cpp
@@ -69,21 +69,6 @@ void CcPlaySound1D(const CommandCost &result, TileIndex tile, uint32 p1, uint32
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);
}
-/**
- * Callback to start placing a bridge.
- * @param tile Start tile of the bridge.
- */
-static void PlaceRoad_Bridge(TileIndex tile, Window *w)
-{
- if (IsBridgeTile(tile)) {
- TileIndex other_tile = GetOtherTunnelBridgeEnd(tile);
- Point pt = {0, 0};
- w->OnPlaceMouseUp(VPM_X_OR_Y, DDSP_BUILD_BRIDGE, pt, other_tile, tile);
- } else {
- VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
- }
-}
-
/**
* Callback executed after a build road tunnel command has been called.
*
@@ -327,6 +312,7 @@ struct BuildRoadToolbarWindow : Window {
~BuildRoadToolbarWindow()
{
+ if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort();
if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
}
@@ -430,7 +416,7 @@ struct BuildRoadToolbarWindow : Window {
case WID_ROT_DEPOT:
if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
- if (HandlePlacePushButton(this, WID_ROT_DEPOT, SPR_CURSOR_ROAD_DEPOT, HT_RECT)) {
+ if (HandlePlacePushButton(this, WID_ROT_DEPOT, SPR_CURSOR_ROAD_DEPOT, HT_RECT | HT_SCROLL_VIEWPORT)) {
ShowRoadDepotPicker(this);
this->last_started_action = widget;
}
@@ -518,8 +504,7 @@ struct BuildRoadToolbarWindow : Window {
break;
case WID_ROT_DEPOT:
- DoCommandP(tile, _cur_roadtype << 2 | _road_depot_orientation, 0,
- CMD_BUILD_ROAD_DEPOT | CMD_MSG(_road_type_infos[_cur_roadtype].err_depot), CcRoadDepot);
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_SINGLE_TILE);
break;
case WID_ROT_BUS_STATION:
@@ -531,12 +516,11 @@ struct BuildRoadToolbarWindow : Window {
break;
case WID_ROT_BUILD_BRIDGE:
- PlaceRoad_Bridge(tile, this);
+ VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
break;
case WID_ROT_BUILD_TUNNEL:
- DoCommandP(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0,
- CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRoadTunnel);
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_BUILD_BRIDGE);
break;
default: NOT_REACHED();
@@ -560,8 +544,23 @@ struct BuildRoadToolbarWindow : Window {
DeleteWindowByClass(WC_BUILD_BRIDGE);
}
+ virtual void SelectLastTool()
+ {
+ // User misplaced something - activate last selected tool again
+ if (this->last_started_action == WIDGET_LIST_END)
+ return;
+ Point dummy = {0, 0};
+ this->RaiseWidget(this->last_started_action);
+ this->OnClick(dummy, this->last_started_action, 0);
+ }
+
virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
{
+ if (this->last_started_action == WID_ROT_BUILD_TUNNEL) {
+ this->OnPlacePresize(pt, TileVirtXY(pt.x, pt.y));
+ return;
+ }
+
/* Here we update the end tile flags
* of the road placement actions.
* At first we reset the end halfroad
@@ -593,7 +592,6 @@ struct BuildRoadToolbarWindow : Window {
/* Set dir = Y */
_place_road_flag |= RF_DIR_Y;
}
-
break;
default:
@@ -609,8 +607,19 @@ struct BuildRoadToolbarWindow : Window {
switch (select_proc) {
default: NOT_REACHED();
case DDSP_BUILD_BRIDGE:
- if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
- ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype));
+ switch (last_started_action) {
+ case WID_ROT_BUILD_TUNNEL:
+ if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
+ else VpStartPreSizing();
+ DoCommandP(end_tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0,
+ CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRoadTunnel);
+ break;
+ case WID_ROT_BUILD_BRIDGE:
+ if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
+ ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype));
+ break;
+ default: NOT_REACHED();
+ }
break;
case DDSP_DEMOLISH_AREA:
@@ -651,6 +660,14 @@ struct BuildRoadToolbarWindow : Window {
DoCommandP(ta.tile, ta.w | ta.h << 8, ROADSTOP_TRUCK, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[ROADSTOP_TRUCK]), CcPlaySound1D);
break;
}
+
+ case DDSP_SINGLE_TILE:
+ /* Build depot. */
+ assert(start_tile == end_tile);
+ assert(last_started_action == WID_ROT_DEPOT);
+ DoCommandP(start_tile, _cur_roadtype << 2 | _road_depot_orientation, 0,
+ CMD_BUILD_ROAD_DEPOT | CMD_MSG(_road_type_infos[_cur_roadtype].err_depot), CcRoadDepot);
+ break;
}
}
}
@@ -807,7 +824,7 @@ Window *ShowBuildRoadToolbar(RoadType roadtype)
if (!Company::IsValidID(_local_company)) return NULL;
_cur_roadtype = roadtype;
- DeleteWindowByClass(WC_BUILD_TOOLBAR);
+ DeleteToolbarLinkedWindows();
return AllocateWindowDescFront(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD);
}
@@ -839,7 +856,7 @@ static const NWidgetPart _nested_build_road_scen_widgets[] = {
};
static WindowDesc _build_road_scen_desc(
- WDP_AUTO, "toolbar_road_scen", 0, 0,
+ WDP_ALIGN_TOOLBAR, "toolbar_road_scen", 0, 0,
WC_SCEN_BUILD_TOOLBAR, WC_NONE,
WDF_CONSTRUCTION,
_nested_build_road_scen_widgets, lengthof(_nested_build_road_scen_widgets),
@@ -852,6 +869,7 @@ static WindowDesc _build_road_scen_desc(
*/
Window *ShowBuildRoadScenToolbar()
{
+ DeleteToolbarLinkedWindows();
_cur_roadtype = ROADTYPE_ROAD;
return AllocateWindowDescFront(&_build_road_scen_desc, TRANSPORT_ROAD);
}
@@ -915,18 +933,18 @@ static const NWidgetPart _nested_build_road_depot_widgets[] = {
NWidget(NWID_HORIZONTAL_LTR),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
NWidget(NWID_VERTICAL),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_NW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_NW), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_SW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_SW), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(2, 0),
NWidget(NWID_VERTICAL),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_NE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_NE), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_SE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_SE), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
@@ -1018,6 +1036,10 @@ struct BuildRoadStationWindow : public PickerWindowBase {
{
if (!IsInsideMM(widget, WID_BROS_STATION_NE, WID_BROS_STATION_Y + 1)) return;
+ int x = Center(r.left + TILE_PIXELS, r.right - r.left, 2 * TILE_PIXELS);
+ /* Height of bus/truck sprite in OpenGFX is TILE_PIXELS + 11. */
+ int y = Center(r.top + WD_FRAMERECT_TOP - WD_MATRIX_BOTTOM + IsWidgetLowered(widget) + 11, r.bottom - r.top, TILE_PIXELS + 11);
+
StationType st = (this->window_class == WC_BUS_STATION) ? STATION_BUS : STATION_TRUCK;
StationPickerDrawSprite(r.left + 1 + ScaleGUITrad(31), r.bottom - ScaleGUITrad(31), st, INVALID_RAILTYPE, widget < WID_BROS_STATION_X ? ROADTYPE_ROAD : _cur_roadtype, widget - WID_BROS_STATION_NE);
}
@@ -1069,17 +1091,17 @@ static const NWidgetPart _nested_rv_station_picker_widgets[] = {
NWidget(NWID_SPACER), SetMinimalSize(0, 3),
NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0),
NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_NW), SetMinimalSize(66, 50), EndContainer(),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_NE), SetMinimalSize(66, 50), EndContainer(),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_X), SetMinimalSize(66, 50), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_NW), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_NE), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_X), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), EndContainer(),
NWidget(NWID_SPACER), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0),
NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_SW), SetMinimalSize(66, 50), EndContainer(),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_SE), SetMinimalSize(66, 50), EndContainer(),
- NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y), SetMinimalSize(66, 50), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_SW), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_SE), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), EndContainer(),
NWidget(NWID_SPACER), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 1),
diff --git a/src/screenshot.cpp b/src/screenshot.cpp
index a24cc6b211..438b816502 100644
--- a/src/screenshot.cpp
+++ b/src/screenshot.cpp
@@ -25,6 +25,7 @@
#include "window_func.h"
#include "tile_map.h"
#include "landscape.h"
+#include "blitter/16bpp_base.hpp"
#include "table/strings.h"
@@ -36,7 +37,7 @@ static const char * const HEIGHTMAP_NAME = "heightmap"; ///< Default filename
char _screenshot_format_name[8]; ///< Extension of the current screenshot format (corresponds with #_cur_screenshot_format).
uint _num_screenshot_formats; ///< Number of available screenshot formats.
uint _cur_screenshot_format; ///< Index of the currently selected screenshot format in #_screenshot_formats.
-static char _screenshot_name[128]; ///< Filename of the screenshot file.
+static char _screenshot_name[256]; ///< Filename of the screenshot file.
char _full_screenshot_name[MAX_PATH]; ///< Pathname of the screenshot file.
/**
@@ -272,7 +273,8 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
png_infop info_ptr;
/* only implemented for 8bit and 32bit images so far. */
- if (pixelformat != 8 && pixelformat != 32) return false;
+ if (pixelformat != 8 && pixelformat != 32 && pixelformat != 16) return false;
+ if (pixelformat == 16) bpp = 3;
f = fopen(name, "wb");
if (f == NULL) return false;
@@ -386,6 +388,17 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
/* render the pixels into the buffer */
callb(userdata, buff, y, w, n);
y += n;
+ if (pixelformat == 16) {
+ // Convert to 24bpp
+ Blitter_16bppBase::Colour16 *inp = (Blitter_16bppBase::Colour16 *)buff;
+ uint8 *outp = (uint8 *)buff;
+ for (i = 1; i <= w * n; i++) {
+ outp[(w * n - i) * 3 ] = inp[w * n - i].r << 3;
+ outp[(w * n - i) * 3 + 1] = inp[w * n - i].g << 2;
+ outp[(w * n - i) * 3 + 2] = inp[w * n - i].b << 3;
+ //outp[(w * n - i) * 3] = 0xff;
+ }
+ }
/* write them to png */
for (i = 0; i != n; i++) {
@@ -858,7 +871,7 @@ bool MakeScreenshot(ScreenshotType t, const char *name)
if (ret) {
SetDParamStr(0, _screenshot_name);
- ShowErrorMessage(STR_MESSAGE_SCREENSHOT_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING);
+ //ShowErrorMessage(STR_MESSAGE_SCREENSHOT_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING); // No need for message when we're doing cloudsave
} else {
ShowErrorMessage(STR_ERROR_SCREENSHOT_FAILED, INVALID_STRING_ID, WL_ERROR);
}
diff --git a/src/script/api/game/game_window.hpp.sq b/src/script/api/game/game_window.hpp.sq
index 23627ca665..4454709728 100644
--- a/src/script/api/game/game_window.hpp.sq
+++ b/src/script/api/game/game_window.hpp.sq
@@ -627,8 +627,10 @@ void SQGSWindow_Register(Squirrel *engine)
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TF_VSCROLLBAR, "WID_TF_VSCROLLBAR");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TF_HSCROLLBAR, "WID_TF_HSCROLLBAR");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_LIST_LEFT, "WID_MTS_LIST_LEFT");
+ SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_LEFT_SCROLLBAR, "WID_MTS_LEFT_SCROLLBAR");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_PLAYLIST, "WID_MTS_PLAYLIST");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_LIST_RIGHT, "WID_MTS_LIST_RIGHT");
+ SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_RIGHT_SCROLLBAR, "WID_MTS_RIGHT_SCROLLBAR");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_ALL, "WID_MTS_ALL");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_OLD, "WID_MTS_OLD");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_NEW, "WID_MTS_NEW");
@@ -1192,6 +1194,9 @@ void SQGSWindow_Register(Squirrel *engine)
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_MESSAGES, "WID_TN_MESSAGES");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_HELP, "WID_TN_HELP");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_SWITCH_BAR, "WID_TN_SWITCH_BAR");
+ SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_CTRL, "WID_TN_CTRL");
+ SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_SHIFT, "WID_TN_SHIFT");
+ SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_DELETE, "WID_TN_DELETE");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_END, "WID_TN_END");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_PAUSE, "WID_TE_PAUSE");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_FAST_FORWARD, "WID_TE_FAST_FORWARD");
diff --git a/src/script/api/script_date.cpp b/src/script/api/script_date.cpp
index 2f5b399633..4290a4feb5 100644
--- a/src/script/api/script_date.cpp
+++ b/src/script/api/script_date.cpp
@@ -9,8 +9,8 @@
/** @file script_date.cpp Implementation of ScriptDate. */
+#include "../../stdafx.h" /* Have to be included before time.h, if we want UINT32_MAX macro defined on Android */
#include
-#include "../../stdafx.h"
#include "script_date.hpp"
#include "../../date_func.h"
diff --git a/src/script/api/script_window.hpp b/src/script/api/script_window.hpp
index f1d2c5b191..a2e4eac613 100644
--- a/src/script/api/script_window.hpp
+++ b/src/script/api/script_window.hpp
@@ -135,6 +135,13 @@ public:
*/
WC_MAIN_TOOLBAR = ::WC_MAIN_TOOLBAR,
+ /**
+ * Main toolbar (the long bar at the top); %Window numbers:
+ * - 0 = #ToolbarNormalWidgets
+ * - 0 = #ToolbarEditorWidgets
+ */
+ WC_MAIN_TOOLBAR_RIGHT = ::WC_MAIN_TOOLBAR_RIGHT,
+
/**
* Statusbar (at the bottom of your screen); %Window numbers:
* - 0 = #StatusbarWidgets
@@ -1581,9 +1588,11 @@ public:
/* automatically generated from ../../widgets/music_widget.h */
/** Widgets of the #MusicTrackSelectionWindow class. */
enum MusicTrackSelectionWidgets {
- WID_MTS_LIST_LEFT = ::WID_MTS_LIST_LEFT, ///< Left button.
- WID_MTS_PLAYLIST = ::WID_MTS_PLAYLIST, ///< Playlist.
- WID_MTS_LIST_RIGHT = ::WID_MTS_LIST_RIGHT, ///< Right button.
+ WID_MTS_LIST_LEFT = ::WID_MTS_LIST_LEFT, ///< Left list.
+ WID_MTS_LEFT_SCROLLBAR = ::WID_MTS_LEFT_SCROLLBAR, ///< Scrollbar of left list.
+ WID_MTS_PLAYLIST = ::WID_MTS_PLAYLIST, ///< Playlist name.
+ WID_MTS_LIST_RIGHT = ::WID_MTS_LIST_RIGHT, ///< Right list.
+ WID_MTS_RIGHT_SCROLLBAR = ::WID_MTS_RIGHT_SCROLLBAR, ///< Scrollbar of right list.
WID_MTS_ALL = ::WID_MTS_ALL, ///< All button.
WID_MTS_OLD = ::WID_MTS_OLD, ///< Old button.
WID_MTS_NEW = ::WID_MTS_NEW, ///< New button.
@@ -2393,6 +2402,9 @@ public:
WID_TN_MESSAGES = ::WID_TN_MESSAGES, ///< Messages menu.
WID_TN_HELP = ::WID_TN_HELP, ///< Help menu.
WID_TN_SWITCH_BAR = ::WID_TN_SWITCH_BAR, ///< Only available when toolbar has been split to switch between different subsets.
+ WID_TN_CTRL = ::WID_TN_CTRL, ///< On-screen Ctrl key
+ WID_TN_SHIFT = ::WID_TN_SHIFT, ///< On-screen Sgift key
+ WID_TN_DELETE = ::WID_TN_DELETE, ///< Close all windows
WID_TN_END = ::WID_TN_END, ///< Helper for knowing the amount of widgets.
};
diff --git a/src/settings.cpp b/src/settings.cpp
index ecad0239cc..e68f5242c7 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -54,6 +54,7 @@
#include "base_media_base.h"
#include "gamelog.h"
#include "settings_func.h"
+#include "settings_gui.h"
#include "ini_type.h"
#include "ai/ai_config.hpp"
#include "ai/ai.hpp"
@@ -64,6 +65,7 @@
#include "roadveh.h"
#include "fios.h"
#include "strings_func.h"
+#include "toolbar_gui.h"
#include "void_map.h"
#include "station_base.h"
@@ -1077,6 +1079,16 @@ static bool ZoomMinMaxChanged(int32 p1)
return true;
}
+static bool VerticalToolbarChanged(int32 p1)
+{
+ if (FindWindowByClass(WC_MAIN_TOOLBAR)) {
+ HideVitalWindows();
+ ShowVitalWindows();
+ ReInitAllWindows();
+ }
+ return true;
+}
+
/**
* Update any possible saveload window and delete any newgrf dialogue as
* its widget parts might change. Reinit all windows as it allows access to the
diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp
index f1af4804e4..225e014fe7 100644
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -36,11 +36,13 @@
#include "textfile_gui.h"
#include "stringfilter_type.h"
#include "querystring_gui.h"
+#include "fontcache.h"
#include
#include "safeguards.h"
+enum { MIN_BUTTON_SIZE = 10, MAX_BUTTON_SIZE = 40 };
static const StringID _driveside_dropdown[] = {
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT,
@@ -113,6 +115,8 @@ static int GetCurRes()
static void ShowCustCurrency();
+static void ReconstructUserInterface();
+
template
static DropDownList *BuiltSetDropDownList(int *selected_index)
{
@@ -296,6 +300,19 @@ struct GameOptionsWindow : Window {
break;
}
+ case WID_GO_BUTTON_SIZE_DROPDOWN: // Setup screenshot format dropdown
+ case WID_GO_TEXT_SIZE_DROPDOWN: // Setup screenshot format dropdown
+ list = new DropDownList();
+ *selected_index = (widget == WID_GO_BUTTON_SIZE_DROPDOWN) ?
+ _settings_client.gui.min_button :
+ _freetype.medium.size;
+ for (uint i = MIN_BUTTON_SIZE; i <= MAX_BUTTON_SIZE; i++) {
+ DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false);
+ item->SetParam(0, i);
+ *list->Append() = item;
+ }
+ break;
+
case WID_GO_BASE_GRF_DROPDOWN:
list = BuiltSetDropDownList(selected_index);
break;
@@ -325,6 +342,8 @@ struct GameOptionsWindow : Window {
case WID_GO_LANG_DROPDOWN: SetDParamStr(0, _current_language->own_name); break;
case WID_GO_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _num_resolutions ? STR_GAME_OPTIONS_RESOLUTION_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break;
case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[ZOOM_LVL_OUT_4X - _gui_zoom]); break;
+ case WID_GO_BUTTON_SIZE_DROPDOWN:SetDParam(0, _settings_client.gui.min_button); break;
+ case WID_GO_TEXT_SIZE_DROPDOWN: SetDParam(0, _freetype.medium.size); break;
case WID_GO_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->name); break;
case WID_GO_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break;
case WID_GO_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->name); break;
@@ -338,17 +357,17 @@ struct GameOptionsWindow : Window {
switch (widget) {
case WID_GO_BASE_GRF_DESCRIPTION:
SetDParamStr(0, BaseGraphics::GetUsedSet()->GetDescription(GetCurrentLanguageIsoCode()));
- DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
+ DrawString(r.left, r.right, r.top, STR_BLACK_RAW_STRING);
break;
case WID_GO_BASE_SFX_DESCRIPTION:
SetDParamStr(0, BaseSounds::GetUsedSet()->GetDescription(GetCurrentLanguageIsoCode()));
- DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
+ DrawString(r.left, r.right, r.top, STR_BLACK_RAW_STRING);
break;
case WID_GO_BASE_MUSIC_DESCRIPTION:
SetDParamStr(0, BaseMusic::GetUsedSet()->GetDescription(GetCurrentLanguageIsoCode()));
- DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
+ DrawString(r.left, r.right, r.top, STR_BLACK_RAW_STRING);
break;
}
}
@@ -359,7 +378,7 @@ struct GameOptionsWindow : Window {
case WID_GO_BASE_GRF_DESCRIPTION:
/* Find the biggest description for the default size. */
for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
- SetDParamStr(0, BaseGraphics::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
+ SetDParamStr(0, "123");
size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
}
break;
@@ -378,7 +397,7 @@ struct GameOptionsWindow : Window {
case WID_GO_BASE_SFX_DESCRIPTION:
/* Find the biggest description for the default size. */
for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
- SetDParamStr(0, BaseSounds::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
+ SetDParamStr(0, "123");
size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
}
break;
@@ -386,7 +405,7 @@ struct GameOptionsWindow : Window {
case WID_GO_BASE_MUSIC_DESCRIPTION:
/* Find the biggest description for the default size. */
for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
- SetDParamStr(0, BaseMusic::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
+ SetDParamStr(0, "123");
size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
}
break;
@@ -450,6 +469,13 @@ struct GameOptionsWindow : Window {
this->SetDirty();
break;
+ case WID_GO_VERTICAL_TOOLBAR:
+ _settings_client.gui.vertical_toolbar = !_settings_client.gui.vertical_toolbar;
+ this->SetWidgetLoweredState(WID_GO_VERTICAL_TOOLBAR, _settings_client.gui.vertical_toolbar);
+ this->SetDirty();
+ ReconstructUserInterface();
+ break;
+
default: {
int selected;
DropDownList *list = this->BuildDropDownList(widget, &selected);
@@ -523,6 +549,7 @@ struct GameOptionsWindow : Window {
case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
if (index < _num_resolutions && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
+ ReconstructUserInterface();
this->SetDirty();
}
break;
@@ -532,6 +559,19 @@ struct GameOptionsWindow : Window {
_gui_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
UpdateCursorSize();
LoadStringWidthTable();
+
+ case WID_GO_BUTTON_SIZE_DROPDOWN: // Setup screenshot format dropdown
+ _settings_client.gui.min_button = index;
+ _settings_client.gui.min_step = index;
+ ReconstructUserInterface();
+ break;
+
+ case WID_GO_TEXT_SIZE_DROPDOWN: // Setup screenshot format dropdown
+ _freetype.medium.size = index;
+ _freetype.small.size = _freetype.medium.size * 10 / 12;
+ _freetype.large.size = _freetype.medium.size * 16 / 12;
+ _freetype.mono.size = _freetype.medium.size;
+ ReconstructUserInterface();
break;
case WID_GO_BASE_GRF_DROPDOWN:
@@ -557,6 +597,7 @@ struct GameOptionsWindow : Window {
{
if (!gui_scope) return;
this->SetWidgetLoweredState(WID_GO_FULLSCREEN_BUTTON, _fullscreen);
+ this->SetWidgetLoweredState(WID_GO_VERTICAL_TOOLBAR, _settings_client.gui.vertical_toolbar);
bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
this->GetWidget(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
@@ -605,49 +646,62 @@ static const NWidgetPart _nested_game_options_widgets[] = {
NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_LANG_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_LANGUAGE_TOOLTIP), SetFill(1, 0),
EndContainer(),
+ NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_CONFIG_SETTING_BUTTON_SIZE, STR_NULL),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BUTTON_SIZE_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_JUST_INT, STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP), SetFill(1, 0),
+ EndContainer(),
+ NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_CONFIG_SETTING_FONT_SIZE, STR_NULL),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_TEXT_SIZE_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_JUST_INT, STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP), SetFill(1, 0),
+ EndContainer(),
+ NWidget(WWT_FRAME, COLOUR_GREY),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_CONFIG_SETTING_VERTICAL_TOOLBAR, STR_NULL),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VERTICAL_TOOLBAR), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT),
+ EndContainer(),
NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_CURRENCY_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1),
EndContainer(),
- EndContainer(),
- NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
- NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
- NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
- NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
- EndContainer(),
- NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
- EndContainer(),
- EndContainer(),
+ NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
+ NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
+ NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
+ NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
+ EndContainer(),
+ NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
+ EndContainer(),
+ EndContainer(),
- NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPadding(0, 10, 0, 10),
- NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
- NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP),
- NWidget(NWID_SPACER), SetFill(1, 0),
- EndContainer(),
- NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_SFX_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
- EndContainer(),
- EndContainer(),
+ NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPadding(0, 10, 0, 10),
+ NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP),
+ NWidget(NWID_SPACER), SetFill(1, 0),
+ EndContainer(),
+ NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_SFX_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
+ EndContainer(),
+ EndContainer(),
- NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10),
- NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
- NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP),
- NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
- EndContainer(),
- NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
+ NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10),
+ NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP),
+ NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
+ EndContainer(),
+ NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
+ EndContainer(),
+ EndContainer(),
EndContainer(),
EndContainer(),
EndContainer(),
@@ -1062,7 +1116,6 @@ bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
return visible;
}
-
static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd)
{
if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
@@ -2667,3 +2720,32 @@ static void ShowCustCurrency()
DeleteWindowById(WC_CUSTOM_CURRENCY, 0);
new CustomCurrencyWindow(&_cust_currency_desc);
}
+
+void ReconstructUserInterface()
+{
+ // Reinit all GUI elements and fonts, so they will rescale
+ InitFreeType(true);
+ CheckForMissingGlyphs();
+
+ DeleteAllNonVitalWindows();
+
+ switch (_game_mode) {
+ case GM_MENU:
+ DeleteWindowById(WC_SELECT_GAME, 0);
+ extern void ShowSelectGameWindow();
+ ShowSelectGameWindow();
+ break;
+
+ case GM_NORMAL:
+ case GM_EDITOR:
+ HideVitalWindows();
+ ShowVitalWindows();
+ break;
+
+ default:
+ break;
+ }
+
+ ReInitAllWindows();
+ ShowGameOptions();
+}
diff --git a/src/settings_type.h b/src/settings_type.h
index 41366a7719..a02f067155 100644
--- a/src/settings_type.h
+++ b/src/settings_type.h
@@ -77,6 +77,9 @@ struct GUISettings {
bool lost_vehicle_warn; ///< if a vehicle can't find its destination, show a warning
uint8 order_review_system; ///< perform order reviews on vehicles
bool vehicle_income_warn; ///< if a vehicle isn't generating income, show a warning
+ bool vertical_toolbar; ///< main toolbar is split into two vertical toolbars
+ uint min_button; ///< min size of most button widgets
+ uint min_step; ///< min size of scrollbar/dropdown elements
bool show_finances; ///< show finances at end of year
bool sg_new_nonstop; ///< ttdpatch compatible nonstop handling read from pre v93 savegames
bool new_nonstop; ///< ttdpatch compatible nonstop handling
@@ -102,6 +105,7 @@ struct GUISettings {
ZoomLevelByte zoom_max; ///< maximum zoom out level
bool disable_unsuitable_building; ///< disable infrastructure building when no suitable vehicles are available
byte autosave; ///< how often should we do autosaves?
+ byte save_to_network; ///< backup all savegames to network
bool threaded_saves; ///< should we do threaded saves?
bool keep_all_autosave; ///< name the autosave in a different way
bool autosave_on_exit; ///< save an autosave when you quit the game, but do not ask "Do you really want to quit?"
diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp
index a34f1db077..c90c3cff19 100644
--- a/src/signs_gui.cpp
+++ b/src/signs_gui.cpp
@@ -196,7 +196,7 @@ struct SignListWindow : Window, SignList {
{
switch (widget) {
case WID_SIL_LIST: {
- uint y = r.top + WD_FRAMERECT_TOP; // Offset from top of widget.
+ uint y = Center(r.top + WD_FRAMERECT_TOP, this->resize.step_height); // Offset from top of widget.
/* No signs? */
if (this->vscroll->GetCount() == 0) {
DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, STR_STATION_LIST_NONE);
@@ -268,6 +268,7 @@ struct SignListWindow : Window, SignList {
Dimension spr_dim = GetSpriteSize(SPR_COMPANY_ICON);
this->text_offset = WD_FRAMETEXT_LEFT + spr_dim.width + 2; // 2 pixels space between icon and the sign text.
resize->height = max(FONT_HEIGHT_NORMAL, spr_dim.height);
+ resize->height = GetMinSizing(NWST_STEP, resize->height);
Dimension d = {this->text_offset + WD_FRAMETEXT_RIGHT, WD_FRAMERECT_TOP + 5 * resize->height + WD_FRAMERECT_BOTTOM};
*size = maxdim(*size, d);
break;
diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp
index ef0f4dd0f3..ab12336344 100644
--- a/src/smallmap_gui.cpp
+++ b/src/smallmap_gui.cpp
@@ -1040,7 +1040,11 @@ void SmallMapWindow::SetupWidgetData()
this->GetWidget(WID_SM_SELECT_BUTTONS)->SetDisplayedPlane(plane);
}
-SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(desc), refresh(FORCE_REFRESH_PERIOD)
+SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) :
+ Window(desc),
+ show_legend(false),
+ row_height(max(GetMinSizing(NWST_STEP, FONT_HEIGHT_SMALL) * 2 / 3, uint(FONT_HEIGHT_SMALL))), // Default spacing makes legend too tall - shrink it by 1/3
+ refresh(FORCE_REFRESH_PERIOD)
{
_smallmap_industry_highlight = INVALID_INDUSTRYTYPE;
this->overlay = new LinkGraphOverlay(this, WID_SM_MAP, 0, this->GetOverlayCompanyMask(), 1);
@@ -1176,9 +1180,8 @@ void SmallMapWindow::RebuildColourIndexIfNecessary()
bool rtl = _current_text_dir == TD_RTL;
uint y_org = r.top + WD_FRAMERECT_TOP;
uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
- uint y = y_org;
+ uint y = Center(y_org, this->row_height, FONT_HEIGHT_SMALL);
uint i = 0; // Row counter for industry legend.
- uint row_height = FONT_HEIGHT_SMALL;
uint text_left = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
@@ -1205,7 +1208,7 @@ void SmallMapWindow::RebuildColourIndexIfNecessary()
/* Column break needed, continue at top, COLUMN_WIDTH pixels
* (one "row") to the right. */
x += rtl ? -(int)this->column_width : this->column_width;
- y = y_org;
+ y = Center(y_org, this->row_height, FONT_HEIGHT_SMALL);
i = 1;
}
@@ -1233,7 +1236,7 @@ void SmallMapWindow::RebuildColourIndexIfNecessary()
DrawString(x + text_left, x + text_right, y, string, TC_GREY);
} else {
DrawString(x + text_left, x + text_right, y, string, TC_BLACK);
- GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour
+ GfxFillRect(x + blob_left, y + 1, x + blob_right, y + FONT_HEIGHT_SMALL - 1, PC_BLACK); // Outer border of the legend colour
}
break;
}
@@ -1241,13 +1244,13 @@ void SmallMapWindow::RebuildColourIndexIfNecessary()
default:
if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
/* Anything that is not an industry or a company is using normal process */
- GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
+ GfxFillRect(x + blob_left, y + 1, x + blob_right, y + FONT_HEIGHT_SMALL - 1, PC_BLACK);
DrawString(x + text_left, x + text_right, y, tbl->legend);
break;
}
- GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, legend_colour); // Legend colour
+ GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + FONT_HEIGHT_SMALL - 2, legend_colour); // Legend colour
- y += row_height;
+ y += this->row_height;
}
}
}
@@ -1339,7 +1342,7 @@ void SmallMapWindow::SetOverlayCargoMask()
int SmallMapWindow::GetPositionOnLegend(Point pt)
{
const NWidgetBase *wi = this->GetWidget(WID_SM_LEGEND);
- uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL;
+ uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / this->row_height;
uint columns = this->GetNumberColumnsLegend(wi->current_x);
uint number_of_rows = this->GetNumberRowsLegend(columns);
if (line >= number_of_rows) return -1;
@@ -1430,6 +1433,14 @@ int SmallMapWindow::GetPositionOnLegend(Point pt)
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
break;
+ case WID_SM_SHOW_LEGEND: {
+ int oldHeight = this->GetLegendHeight(this->min_number_of_columns);
+ this->show_legend = !this->show_legend;
+ this->SetWidgetLoweredState(WID_SM_SHOW_LEGEND, this->show_legend);
+ this->ReInit(0, this->GetLegendHeight(this->min_number_of_columns) - oldHeight);
+ break;
+ }
+
case WID_SM_LEGEND: // Legend
if (this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) {
int click_pos = this->GetPositionOnLegend(pt);
@@ -1678,7 +1689,7 @@ public:
this->smallmap_window = dynamic_cast(w);
assert(this->smallmap_window != NULL);
- this->smallest_x = max(display->smallest_x, bar->smallest_x + smallmap_window->GetMinLegendWidth());
+ this->smallest_x = max(display->smallest_x, max(bar->smallest_x, smallmap_window->GetMinLegendWidth()));
this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetLegendHeight(smallmap_window->min_number_of_columns));
this->fill_x = max(display->fill_x, bar->fill_x);
this->fill_y = (display->fill_y == 0 && bar->fill_y == 0) ? 0 : min(display->fill_y, bar->fill_y);
@@ -1729,7 +1740,7 @@ public:
/** Widget parts of the smallmap display. */
static const NWidgetPart _nested_smallmap_display[] = {
NWidget(WWT_PANEL, COLOUR_BROWN, WID_SM_MAP_BORDER),
- NWidget(WWT_INSET, COLOUR_BROWN, WID_SM_MAP), SetMinimalSize(346, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(),
+ NWidget(WWT_INSET, COLOUR_BROWN, WID_SM_MAP), SetMinimalSize(140, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(),
EndContainer(),
};
@@ -1737,27 +1748,23 @@ static const NWidgetPart _nested_smallmap_display[] = {
static const NWidgetPart _nested_smallmap_bar[] = {
NWidget(WWT_PANEL, COLOUR_BROWN),
NWidget(NWID_HORIZONTAL),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SM_LEGEND), SetResize(1, 1),
- NWidget(NWID_VERTICAL),
+ NWidget(NWID_HORIZONTAL),
/* Top button row. */
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_SHOW_LEGEND),
+ SetDataTip(SPR_IMG_QUERY, STR_SMALLMAP_TOOLTIP_SHOW_LEGEND), SetFill(1, 1),
NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_ZOOM_IN),
SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN), SetFill(1, 1),
+ NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_ZOOM_OUT),
+ SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), SetFill(1, 1),
NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_CENTERMAP),
SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER), SetFill(1, 1),
- NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_BLANK),
- SetDataTip(SPR_DOT_SMALL, STR_NULL), SetFill(1, 1),
NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_CONTOUR),
SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP), SetFill(1, 1),
NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_VEHICLES),
SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP), SetFill(1, 1),
NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_INDUSTRIES),
SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP), SetFill(1, 1),
- EndContainer(),
- /* Bottom button row. */
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
- NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_ZOOM_OUT),
- SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), SetFill(1, 1),
NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_TOGGLETOWNNAME),
SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF), SetFill(1, 1),
NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_LINKSTATS),
@@ -1772,6 +1779,7 @@ static const NWidgetPart _nested_smallmap_bar[] = {
NWidget(NWID_SPACER), SetResize(0, 1),
EndContainer(),
EndContainer(),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SM_LEGEND), SetResize(1, 1),
EndContainer(),
};
@@ -1812,7 +1820,7 @@ static const NWidgetPart _nested_smallmap_widgets[] = {
};
static WindowDesc _smallmap_desc(
- WDP_AUTO, "smallmap", 484, 314,
+ WDP_AUTO, "smallmap", 180, 180,
WC_SMALLMAP, WC_NONE,
0,
_nested_smallmap_widgets, lengthof(_nested_smallmap_widgets)
diff --git a/src/smallmap_gui.h b/src/smallmap_gui.h
index 2903544a69..191554a0cd 100644
--- a/src/smallmap_gui.h
+++ b/src/smallmap_gui.h
@@ -70,9 +70,11 @@ protected:
static const uint FORCE_REFRESH_PERIOD = 0x1F; ///< map is redrawn after that many ticks
static const uint BLINK_PERIOD = 0x0F; ///< highlight blinking interval
+ bool show_legend; ///< Display legend.
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.
+ const uint row_height; ///< Heigth of each row 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.
@@ -114,7 +116,7 @@ protected:
*/
inline uint GetMinLegendWidth() const
{
- return WD_FRAMERECT_LEFT + this->min_number_of_columns * this->column_width;
+ return show_legend ? WD_FRAMERECT_LEFT + this->min_number_of_columns * this->column_width : 0;
}
/**
@@ -123,7 +125,7 @@ protected:
*/
inline uint GetNumberColumnsLegend(uint width) const
{
- return width / this->column_width;
+ return max(2u, width / this->column_width);
}
/**
@@ -133,8 +135,8 @@ protected:
*/
inline uint GetLegendHeight(uint num_columns) const
{
- return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM +
- this->GetNumberRowsLegend(num_columns) * FONT_HEIGHT_SMALL;
+ return show_legend ? WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM +
+ this->GetNumberRowsLegend(num_columns) * this->row_height : 0;
}
/**
diff --git a/src/sound/sdl_s.cpp b/src/sound/sdl_s.cpp
index e3fb99eaa7..8c0849dfb2 100644
--- a/src/sound/sdl_s.cpp
+++ b/src/sound/sdl_s.cpp
@@ -23,6 +23,10 @@
/** Factory for the SDL sound driver. */
static FSoundDriver_SDL iFSoundDriver_SDL;
+#ifdef __ANDROID__
+extern void Android_MidiMixMusic(Sint16 *stream, int len);
+#endif
+
/**
* Callback that fills the sound buffer.
* @param userdata Ignored.
@@ -32,6 +36,9 @@ static FSoundDriver_SDL iFSoundDriver_SDL;
static void CDECL fill_sound_buffer(void *userdata, Uint8 *stream, int len)
{
MxMixSamples(stream, len / 4);
+#if defined(__ANDROID__) && defined(LIBTIMIDITY)
+ Android_MidiMixMusic((Sint16 *)stream, len / 2);
+#endif
}
const char *SoundDriver_SDL::Start(const char * const *parm)
diff --git a/src/spritecache.cpp b/src/spritecache.cpp
index 908e7599ab..3e8a34b4ab 100644
--- a/src/spritecache.cpp
+++ b/src/spritecache.cpp
@@ -400,6 +400,10 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty
/* Try for 32bpp sprites first. */
sprite_avail = sprite_loader.LoadSprite(sprite, file_slot, file_pos, sprite_type, true);
}
+ if (sprite_type != ST_MAPGEN && BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 16) {
+ /* 32bpp sprites for 16bpp videomode. */
+ sprite_avail = sprite_loader.LoadSprite(sprite, file_slot, file_pos, sprite_type, true);
+ }
if (sprite_avail == 0) {
sprite_avail = sprite_loader.LoadSprite(sprite, file_slot, file_pos, sprite_type, false);
}
diff --git a/src/station_base.h b/src/station_base.h
index af4d206ba0..cf0ea6fc0a 100644
--- a/src/station_base.h
+++ b/src/station_base.h
@@ -299,6 +299,14 @@ struct GoodsEntry {
FlowStatMap::const_iterator flow_it(this->flows.find(source));
return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
}
+
+ /**
+ * Return true if a cargo type has a rating here or if there is cargo waiting for this type.
+ */
+ inline bool IsSourceStationForCargo() const
+ {
+ return this->HasRating() || this->cargo.TotalCount() > 0;
+ }
};
/** All airport-related information. Only valid if tile != INVALID_TILE. */
diff --git a/src/station_gui.cpp b/src/station_gui.cpp
index 666e66d8b5..7b9cbaee41 100644
--- a/src/station_gui.cpp
+++ b/src/station_gui.cpp
@@ -104,44 +104,44 @@ void CheckRedrawStationCoverage(const Window *w)
* @param type Cargo type
* @param amount Cargo amount
* @param rating ratings data for that particular cargo
- *
- * @note Each cargo-bar is 16 pixels wide and 6 pixels high
- * @note Each rating 14 pixels wide and 1 pixel high and is 1 pixel below the cargo-bar
*/
static void StationsWndShowStationRating(int left, int right, int y, CargoID type, uint amount, byte rating)
{
- static const uint units_full = 576; ///< number of units to show station as 'full'
- static const uint rating_full = 224; ///< rating needed so it is shown as 'full'
+ static const uint units_full = 1 << 9; ///< Number of units to show station as full.
+ static const uint rating_full = 224; ///< Rating needed so it is shown as full.
const CargoSpec *cs = CargoSpec::Get(type);
if (!cs->IsValid()) return;
+ y++; ///< Make boxes 1 pixel shorter.
+ int left_start = left;
+ int right_start = right;
+ int height = GetCharacterHeight(FS_SMALL) - 2;
int colour = cs->rating_colour;
- TextColour tc = GetContrastColour(colour);
- uint w = (minu(amount, units_full) + 5) / 36;
- int height = GetCharacterHeight(FS_SMALL);
+ /* Get width of the box to draw. */
+ uint width = minu(amount, units_full) * (right - left) / units_full;
- /* Draw total cargo (limited) on station (fits into 16 pixels) */
- if (w != 0) GfxFillRect(left, y, left + w - 1, y + height, colour);
+ /* Update the end margin, adding the width of the box not to be drawn... */
+ if (width != 0) UpdateMarginsWidth(right - left - width, left_start, right_start, true);
+ /* ... or prepare margins in case width == 0 and amount > 0 (just one pixel bar). */
+ else left_start = right_start = _current_text_dir ? right : left;
- /* Draw a one pixel-wide bar of additional cargo meter, useful
- * for stations with only a small amount (<=30) */
- if (w == 0) {
- uint rest = amount / 5;
- if (rest != 0) {
- w += left;
- GfxFillRect(w, y + height - rest, w, y + height, colour);
- }
- }
+ /* Draw total cargo (limited) on station */
+ if (amount > 0) GfxFillRect(left_start, y, right_start, y + height, colour);
- DrawString(left + 1, right, y, cs->abbrev, tc);
+ DrawString(left, right, y, cs->abbrev, GetContrastColour(colour), SA_CENTER);
- /* Draw green/red ratings bar (fits into 14 pixels) */
+ /* Draw green/red ratings bar*/
y += height + 2;
- GfxFillRect(left + 1, y, left + 14, y, PC_RED);
- rating = minu(rating, rating_full) / 16;
- if (rating != 0) GfxFillRect(left + 1, y, left + rating, y, PC_GREEN);
+ left_start = left + 1;
+ right_start = right - 1;
+ if (rating != 0) {
+ GfxFillRect(left_start, y, right_start, y, PC_GREEN);
+ width = minu(rating, rating_full) * (right_start - left_start) / rating_full;
+ UpdateMarginsWidth(width, left_start, right_start, false);
+ }
+ GfxFillRect(left_start, y, right_start, y, PC_RED);
}
typedef GUIList GUIStationList;
@@ -360,7 +360,7 @@ public:
}
case WID_STL_LIST:
- resize->height = FONT_HEIGHT_NORMAL;
+ resize->height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL);
size->height = WD_FRAMERECT_TOP + 5 * resize->height + WD_FRAMERECT_BOTTOM;
break;
@@ -412,7 +412,8 @@ public:
case WID_STL_LIST: {
bool rtl = _current_text_dir == TD_RTL;
int max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->stations.Length());
- int y = r.top + WD_FRAMERECT_TOP;
+ uint line_height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL);
+ int y = Center(r.top + WD_FRAMERECT_TOP, line_height);
for (int i = this->vscroll->GetPosition(); i < max; ++i) { // do until max number of stations of owner
const Station *st = this->stations[i];
assert(st->xy != INVALID_TILE);
@@ -424,6 +425,7 @@ public:
SetDParam(0, st->index);
SetDParam(1, st->facilities);
int x = DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_STATION_LIST_STATION);
+
x += rtl ? -5 : 5;
/* show cargo waiting and station ratings */
@@ -445,7 +447,8 @@ public:
}
}
}
- y += FONT_HEIGHT_NORMAL;
+
+ y += line_height;
}
if (this->vscroll->GetCount() == 0) { // company has no stations
@@ -497,7 +500,7 @@ public:
{
switch (widget) {
case WID_STL_LIST: {
- uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_STL_LIST, 0, FONT_HEIGHT_NORMAL);
+ uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_STL_LIST, 0, this->resize.step_height);
if (id_v >= this->stations.Length()) return; // click out of list bound
const Station *st = this->stations[id_v];
@@ -722,7 +725,7 @@ static const NWidgetPart _nested_company_stations_widgets[] = {
NWidget(WWT_PANEL, COLOUR_GREY), SetDataTip(0x0, STR_NULL), SetResize(1, 0), SetFill(1, 1), EndContainer(),
EndContainer(),
NWidget(NWID_HORIZONTAL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_STL_SORTBY), SetMinimalSize(81, 12), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_STL_SORTBY), SetSizingType(NWST_STEP), SetMinimalSize(81, 12), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_STL_SORTDROPBTN), SetMinimalSize(163, 12), SetDataTip(STR_SORT_BY_NAME, STR_TOOLTIP_SORT_CRITERIA), // widget_data gets overwritten.
NWidget(WWT_PANEL, COLOUR_GREY), SetDataTip(0x0, STR_NULL), SetResize(1, 0), SetFill(1, 1), EndContainer(),
EndContainer(),
@@ -763,12 +766,12 @@ static const NWidgetPart _nested_station_view_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_GREY),
EndContainer(),
NWidget(NWID_HORIZONTAL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_SORT_ORDER), SetMinimalSize(81, 12), SetFill(1, 1), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
- NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SV_SORT_BY), SetMinimalSize(168, 12), SetResize(1, 0), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_SORT_ORDER), SetMinimalSize(81, 12), SetFill(0, 1), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SV_SORT_BY), SetMinimalSize(168, 12), SetResize(1, 0), SetFill(1, 1), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA),
EndContainer(),
NWidget(NWID_HORIZONTAL),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SV_GROUP), SetMinimalSize(81, 12), SetFill(1, 1), SetDataTip(STR_STATION_VIEW_GROUP, 0x0),
- NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SV_GROUP_BY), SetMinimalSize(168, 12), SetResize(1, 0), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_GROUP_ORDER),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SV_GROUP), SetMinimalSize(81, 12), SetFill(0, 1), SetDataTip(STR_STATION_VIEW_GROUP, 0x0),
+ NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SV_GROUP_BY), SetMinimalSize(168, 12), SetResize(1, 0), SetFill(1, 1), SetDataTip(0x0, STR_TOOLTIP_GROUP_ORDER),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PANEL, COLOUR_GREY, WID_SV_WAITING), SetMinimalSize(237, 44), SetResize(1, 10), SetScrollbar(WID_SV_SCROLLBAR), EndContainer(),
@@ -804,13 +807,17 @@ static const NWidgetPart _nested_station_view_widgets[] = {
* @param y y coordinate
* @param width the width of the view
*/
-static void DrawCargoIcons(CargoID i, uint waiting, int left, int right, int y)
+static void DrawCargoIcons(CargoID i, uint waiting, int left, int right, int top, int bottom)
{
int width = ScaleGUITrad(10);
uint num = min((waiting + (width / 2)) / width, (right - left) / width); // maximum is width / 10 icons so it won't overflow
if (num == 0) return;
SpriteID sprite = CargoSpec::Get(i)->GetCargoIcon();
+ Dimension d = GetSpriteSize(sprite);
+
+ uint num = min((waiting + 5) / d.width, (right - left) / d.width); // maximum is width / 10 icons so it won't overflow
+ if (num == 0) return;
int x = _current_text_dir == TD_RTL ? left : right - num * width;
do {
@@ -1384,6 +1391,12 @@ struct StationViewWindow : public Window {
fill->width = 0;
}
break;
+
+ case WID_SV_SORT_ORDER:
+ case WID_SV_GROUP:
+ *size = maxdim(GetStringBoundingBox(STR_BUTTON_SORT_BY), GetStringBoundingBox(STR_STATION_VIEW_GROUP));
+ size->width += padding.width;
+ break;
}
}
@@ -1733,7 +1746,7 @@ struct StationViewWindow : public Window {
if (this->groupings[column] == GR_CARGO) {
str = STR_STATION_VIEW_WAITING_CARGO;
- DrawCargoIcons(cd->GetCargo(), cd->GetCount(), r.left + WD_FRAMERECT_LEFT + this->expand_shrink_width, r.right - WD_FRAMERECT_RIGHT - this->expand_shrink_width, y);
+ DrawCargoIcons(cd->GetCargo(), cd->GetCount(), r.left + WD_FRAMERECT_LEFT + this->expand_shrink_width, r.right - WD_FRAMERECT_RIGHT - this->expand_shrink_width, y, y + FONT_HEIGHT_NORMAL);
} else {
if (!auto_distributed) grouping = GR_SOURCE;
StationID station = cd->GetStation();
@@ -2264,8 +2277,8 @@ struct SelectStationWindow : Window {
d = maxdim(d, GetStringBoundingBox(T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_STATION_LIST_WAYPOINT : STR_STATION_LIST_STATION));
}
- resize->height = d.height;
- d.height *= 5;
+ resize->height = GetMinSizing(NWST_STEP, d.height);
+ d.height = 5 * resize->height;
d.width += WD_FRAMERECT_RIGHT + WD_FRAMERECT_LEFT;
d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
*size = d;
@@ -2275,7 +2288,7 @@ struct SelectStationWindow : Window {
{
if (widget != WID_JS_PANEL) return;
- uint y = r.top + WD_FRAMERECT_TOP;
+ uint y = Center(r.top, this->resize.step_height);
if (this->vscroll->GetPosition() == 0) {
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT : STR_JOIN_STATION_CREATE_SPLITTED_STATION);
y += this->resize.step_height;
diff --git a/src/statusbar_gui.cpp b/src/statusbar_gui.cpp
index 25efa6bb1c..1aa54f63c3 100644
--- a/src/statusbar_gui.cpp
+++ b/src/statusbar_gui.cpp
@@ -70,7 +70,7 @@ static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left
DrawPixelInfo *old_dpi = _cur_dpi;
_cur_dpi = &tmp_dpi;
- DrawString(pos, INT16_MAX, 0, buffer, TC_LIGHT_BLUE, SA_LEFT | SA_FORCE);
+ DrawString(pos, INT16_MAX, Center(0, bottom - top), buffer, TC_LIGHT_BLUE, SA_LEFT | SA_FORCE);
_cur_dpi = old_dpi;
return (_current_text_dir == TD_RTL) ? (pos < right - left) : (pos + width > 0);
@@ -111,20 +111,30 @@ struct StatusBarWindow : Window {
{
Dimension d;
switch (widget) {
+ /* Left and right should have same sizing. */
case WID_S_LEFT:
+ case WID_S_RIGHT: {
SetDParamMaxValue(0, MAX_YEAR * DAYS_IN_YEAR);
d = GetStringBoundingBox(STR_WHITE_DATE_LONG);
- break;
- case WID_S_RIGHT: {
int64 max_money = UINT32_MAX;
const Company *c;
FOR_ALL_COMPANIES(c) max_money = max(c->money, max_money);
SetDParam(0, 100LL * max_money);
- d = GetStringBoundingBox(STR_COMPANY_MONEY);
+ d = maxdim(d, GetStringBoundingBox(STR_COMPANY_MONEY));
break;
}
+ case WID_S_MIDDLE:
+ d = GetStringBoundingBox(STR_STATUSBAR_AUTOSAVE);
+ d = maxdim(d, GetStringBoundingBox(STR_STATUSBAR_PAUSED));
+
+ if (Company::IsValidID(_local_company)) {
+ SetDParam(0, _local_company);
+ d = maxdim(d, GetStringBoundingBox(STR_STATUSBAR_COMPANY_NAME));
+ }
+ break;
+
default:
return;
}
@@ -136,11 +146,13 @@ struct StatusBarWindow : Window {
virtual void DrawWidget(const Rect &r, int widget) const
{
+ StringID str = INVALID_STRING_ID;
+
switch (widget) {
case WID_S_LEFT:
/* Draw the date */
SetDParam(0, _date);
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_WHITE_DATE_LONG, TC_FROMSTRING, SA_HOR_CENTER);
+ str = STR_WHITE_DATE_LONG;
break;
case WID_S_RIGHT: {
@@ -148,7 +160,7 @@ struct StatusBarWindow : Window {
const Company *c = Company::GetIfValid(_local_company);
if (c != NULL) {
SetDParam(0, c->money);
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_COMPANY_MONEY, TC_FROMSTRING, SA_HOR_CENTER);
+ str = STR_COMPANY_MONEY;
}
break;
}
@@ -156,11 +168,11 @@ struct StatusBarWindow : Window {
case WID_S_MIDDLE:
/* Draw status bar */
if (this->saving) { // true when saving is active
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_SAVING_GAME, TC_FROMSTRING, SA_HOR_CENTER);
+ str = STR_STATUSBAR_SAVING_GAME;
} else if (_do_autosave) {
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_AUTOSAVE, TC_FROMSTRING, SA_HOR_CENTER);
+ str = STR_STATUSBAR_AUTOSAVE;
} else if (_pause_mode != PM_UNPAUSED) {
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_PAUSED, TC_FROMSTRING, SA_HOR_CENTER);
+ str = STR_STATUSBAR_PAUSED;
} else if (this->ticker_scroll < TICKER_STOP && FindWindowById(WC_NEWS_WINDOW, 0) == NULL && _statusbar_news_item != NULL && _statusbar_news_item->string_id != 0) {
/* Draw the scrolling news text */
if (!DrawScrollingStatusText(_statusbar_news_item, this->ticker_scroll, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, r.bottom)) {
@@ -168,23 +180,27 @@ struct StatusBarWindow : Window {
if (Company::IsValidID(_local_company)) {
/* This is the default text */
SetDParam(0, _local_company);
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_COMPANY_NAME, TC_FROMSTRING, SA_HOR_CENTER);
+ str = STR_STATUSBAR_COMPANY_NAME;
}
}
} else {
if (Company::IsValidID(_local_company)) {
/* This is the default text */
SetDParam(0, _local_company);
- DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_COMPANY_NAME, TC_FROMSTRING, SA_HOR_CENTER);
+ str = STR_STATUSBAR_COMPANY_NAME;
}
}
-
- if (this->reminder_timeout > 0) {
- Dimension icon_size = GetSpriteSize(SPR_UNREAD_NEWS);
- DrawSprite(SPR_UNREAD_NEWS, PAL_NONE, r.right - WD_FRAMERECT_RIGHT - icon_size.width, r.top + WD_FRAMERECT_TOP + (int)(FONT_HEIGHT_NORMAL - icon_size.height) / 2);
- }
break;
}
+
+ int center_top = Center(r.top + WD_FRAMERECT_TOP, r.bottom - r.top);
+ if (str != INVALID_STRING_ID) DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, center_top, str, TC_FROMSTRING, SA_HOR_CENTER);
+
+ if (widget == WID_S_MIDDLE && this->reminder_timeout > 0) {
+ Dimension icon_size = GetSpriteSize(SPR_UNREAD_NEWS);
+ center_top = Center(r.top + WD_FRAMERECT_TOP, r.bottom - r.top, icon_size.height);
+ DrawSprite(SPR_UNREAD_NEWS, PAL_NONE, r.right - WD_FRAMERECT_RIGHT - icon_size.width, center_top);
+ }
}
/**
@@ -238,7 +254,7 @@ struct StatusBarWindow : Window {
static const NWidgetPart _nested_main_status_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PANEL, COLOUR_GREY, WID_S_LEFT), SetMinimalSize(140, 12), EndContainer(),
- NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_MIDDLE), SetMinimalSize(40, 12), SetDataTip(0x0, STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS), SetResize(1, 0),
+ NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_MIDDLE), SetMinimalSize(360, 12), SetDataTip(0x0, STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS), SetResize(1, 0),
NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_RIGHT), SetMinimalSize(140, 12),
EndContainer(),
};
diff --git a/src/strings.cpp b/src/strings.cpp
index a7e60f846b..7f800bd111 100644
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -2000,7 +2000,7 @@ const char *GetCurrentLanguageIsoCode()
* @return If glyphs are missing, return \c true, else return \c false.
* @post If \c true is returned and str is not NULL, *str points to a string that is found to contain at least one missing glyph.
*/
-bool MissingGlyphSearcher::FindMissingGlyphs(const char **str)
+int MissingGlyphSearcher::FindMissingGlyphs(const char **str)
{
InitFreeType(this->Monospace());
const Sprite *question_mark[FS_END];
@@ -2010,6 +2010,7 @@ bool MissingGlyphSearcher::FindMissingGlyphs(const char **str)
}
this->Reset();
+ int missing = 0;
for (const char *text = this->NextString(); text != NULL; text = this->NextString()) {
FontSize size = this->DefaultSize();
if (str != NULL) *str = text;
@@ -2020,11 +2021,11 @@ bool MissingGlyphSearcher::FindMissingGlyphs(const char **str)
size = FS_LARGE;
} else if (!IsInsideMM(c, SCC_SPRITE_START, SCC_SPRITE_END) && IsPrintable(c) && !IsTextDirectionChar(c) && c != '?' && GetGlyph(size, c) == question_mark[size]) {
/* The character is printable, but not in the normal font. This is the case we were testing for. */
- return true;
+ missing++;
}
}
}
- return false;
+ return missing;
}
/** Helper for searching through the language pack. */
diff --git a/src/strings_func.h b/src/strings_func.h
index 2c7809d020..6be4992d69 100644
--- a/src/strings_func.h
+++ b/src/strings_func.h
@@ -235,7 +235,7 @@ public:
*/
virtual void SetFontNames(struct FreeTypeSettings *settings, const char *font_name) = 0;
- bool FindMissingGlyphs(const char **str);
+ int FindMissingGlyphs(const char **str);
};
void CheckForMissingGlyphs(bool base_font = true, MissingGlyphSearcher *search = NULL);
diff --git a/src/table/gameopt_settings.ini b/src/table/gameopt_settings.ini
index 3a47c09e33..762ccaa3f2 100644
--- a/src/table/gameopt_settings.ini
+++ b/src/table/gameopt_settings.ini
@@ -19,6 +19,7 @@ static const char *_locale_units = "imperial|metric|si";
static const char *_town_names = "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovak|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan";
static const char *_climates = "temperate|arctic|tropic|toyland";
static const char *_autosave_interval = "off|monthly|quarterly|half year|yearly";
+static const char *_save_to_network = "disabled|enabled|ask";
static const char *_roadsides = "left|right";
static const char *_savegame_date = "long|short|iso";
#ifdef ENABLE_NETWORK
@@ -173,6 +174,15 @@ max = 4
full = _autosave_interval
cat = SC_BASIC
+[SDTC_OMANY]
+var = gui.save_to_network
+type = SLE_UINT8
+flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
+def = 2
+max = 2
+full = _save_to_network
+cat = SC_BASIC
+
[SDT_OMANY]
base = GameSettings
var = vehicle.road_side
diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini
index 52ca2d16ef..5755356437 100644
--- a/src/table/misc_settings.ini
+++ b/src/table/misc_settings.ini
@@ -231,6 +231,25 @@ name = ""mono_aa""
var = _freetype.mono.aa
def = false
+[SDTG_VAR]
+name = ""min_button_size""
+type = SLE_UINT
+var = _settings_client.gui.min_button
+def = 0
+min = 0
+max = 100
+cat = SC_EXPERT
+
+[SDTG_VAR]
+name = ""min_step_size""
+type = SLE_UINT
+var = _settings_client.gui.min_step
+def = 0
+min = 0
+max = 100
+cat = SC_EXPERT
+
+
[SDTG_VAR]
name = ""sprite_cache_size_px""
type = SLE_UINT
diff --git a/src/table/settings.ini b/src/table/settings.ini
index 24ad486323..2bd89af5b9 100644
--- a/src/table/settings.ini
+++ b/src/table/settings.ini
@@ -42,6 +42,7 @@ static bool InvalidateCompanyInfrastructureWindow(int32 p1);
static bool InvalidateCompanyWindow(int32 p1);
static bool ZoomMinMaxChanged(int32 p1);
static bool MaxVehiclesChanged(int32 p1);
+static bool VerticalToolbarChanged(int32 p1);
#ifdef ENABLE_NETWORK
static bool UpdateClientName(int32 p1);
@@ -2521,6 +2522,15 @@ strhelp = STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT
strval = STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF
cat = SC_BASIC
+[SDTC_OMANY]
+var = gui.save_to_network
+type = SLE_UINT8
+flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
+def = 2
+max = 2
+full = _save_to_network
+cat = SC_BASIC
+
[SDTC_BOOL]
var = gui.threaded_saves
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
@@ -2539,6 +2549,15 @@ str = STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES
strhelp = STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_HELPTEXT
strval = STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_LONG
+[SDTC_BOOL]
+var = gui.vertical_toolbar
+flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
+def = true
+str = STR_CONFIG_SETTING_VERTICAL_TOOLBAR
+strhelp = STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT
+proc = VerticalToolbarChanged
+cat = SC_BASIC
+
[SDTC_BOOL]
var = gui.show_finances
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp
index 06b66cad44..91074e3ae5 100644
--- a/src/terraform_gui.cpp
+++ b/src/terraform_gui.cpp
@@ -161,6 +161,7 @@ struct TerraformToolbarWindow : Window {
~TerraformToolbarWindow()
{
+ if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort();
}
virtual void OnInit()
@@ -242,15 +243,9 @@ struct TerraformToolbarWindow : Window {
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);
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_SINGLE_TILE);
break;
default: NOT_REACHED();
@@ -262,13 +257,6 @@ struct TerraformToolbarWindow : Window {
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) {
@@ -280,6 +268,21 @@ struct TerraformToolbarWindow : Window {
case DDSP_LEVEL_AREA:
GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
break;
+
+ case DDSP_SINGLE_TILE:
+ assert(start_tile == end_tile);
+ switch (this->last_user_action) {
+ case WID_TT_BUY_LAND:
+ DoCommandP(end_tile, OBJECT_OWNED_LAND, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_PURCHASE_THIS_LAND), CcPlaySound1E);
+ break;
+ case WID_TT_PLACE_SIGN:
+ PlaceProc_Sign(end_tile);
+ break;
+ case WID_TT_PLACE_OBJECT:
+ PlaceProc_Object(end_tile);
+ break;
+ default: NOT_REACHED();
+ }
}
}
}
@@ -288,6 +291,17 @@ struct TerraformToolbarWindow : Window {
{
DeleteWindowById(WC_BUILD_OBJECT, 0);
this->RaiseButtons();
+ ResetObjectToPlace();
+ }
+
+ virtual void SelectLastTool()
+ {
+ // User misplaced something - activate last selected tool again
+ if (this->last_user_action == WIDGET_LIST_END)
+ return;
+ Point dummy = {0, 0};
+ this->RaiseWidget(this->last_user_action);
+ this->OnClick(dummy, this->last_user_action, 0);
}
static HotkeyList hotkeys;
@@ -351,7 +365,7 @@ static const NWidgetPart _nested_terraform_widgets[] = {
};
static WindowDesc _terraform_desc(
- WDP_MANUAL, "toolbar_landscape", 0, 0,
+ WDP_ALIGN_TOOLBAR, "toolbar_landscape", 0, 0,
WC_SCEN_LAND_GEN, WC_NONE,
WDF_CONSTRUCTION,
_nested_terraform_widgets, lengthof(_nested_terraform_widgets),
@@ -369,6 +383,7 @@ Window *ShowTerraformToolbar(Window *link)
Window *w;
if (link == NULL) {
+ DeleteToolbarLinkedWindows();
w = AllocateWindowDescFront(&_terraform_desc, 0);
return w;
}
@@ -377,7 +392,6 @@ Window *ShowTerraformToolbar(Window *link)
DeleteWindowById(WC_SCEN_LAND_GEN, 0, true);
w = AllocateWindowDescFront(&_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);
@@ -754,7 +768,7 @@ static Hotkey terraform_editor_hotkeys[] = {
HotkeyList ScenarioEditorLandscapeGenerationWindow::hotkeys("terraform_editor", terraform_editor_hotkeys, TerraformToolbarEditorGlobalHotkeys);
static WindowDesc _scen_edit_land_gen_desc(
- WDP_AUTO, "toolbar_landscape_scen", 0, 0,
+ WDP_ALIGN_TOOLBAR, "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),
@@ -767,5 +781,6 @@ static WindowDesc _scen_edit_land_gen_desc(
*/
Window *ShowEditorTerraformToolbar()
{
+ DeleteToolbarLinkedWindows();
return AllocateWindowDescFront(&_scen_edit_land_gen_desc, 0);
}
diff --git a/src/tilehighlight_func.h b/src/tilehighlight_func.h
index 3edef509a2..ac1567277b 100644
--- a/src/tilehighlight_func.h
+++ b/src/tilehighlight_func.h
@@ -25,10 +25,12 @@ void ResetObjectToPlace();
void VpSelectTilesWithMethod(int x, int y, ViewportPlaceMethod method);
void VpStartPlaceSizing(TileIndex tile, ViewportPlaceMethod method, ViewportDragDropSelectionProcess process);
+void VpStartPreSizing();
void VpSetPresizeRange(TileIndex from, TileIndex to);
void VpSetPlaceSizingLimit(int limit);
void UpdateTileSelection();
+void SetSelectionTilesDirty();
extern TileHighlightData _thd;
diff --git a/src/tilehighlight_type.h b/src/tilehighlight_type.h
index 3d64248dff..207f865a35 100644
--- a/src/tilehighlight_type.h
+++ b/src/tilehighlight_type.h
@@ -28,6 +28,7 @@ enum HighLightStyle {
HT_RAIL = 0x080, ///< autorail (one piece), lower bits: direction
HT_VEHICLE = 0x100, ///< vehicle is accepted as target as well (bitmask)
HT_DIAGONAL = 0x200, ///< Also allow 'diagonal rectangles'. Only usable in combination with #HT_RECT or #HT_POINT.
+ HT_SCROLL_VIEWPORT = 0x400, ///< Allow scrolling viewport with left mouse button, this disables drag&drop, use only when selection cannot grow.
HT_DRAG_MASK = 0x0F8, ///< Mask for the tile drag-type modes.
/* lower bits (used with HT_LINE and HT_RAIL):
diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp
index 45d751dc56..d1f082873e 100644
--- a/src/toolbar_gui.cpp
+++ b/src/toolbar_gui.cpp
@@ -47,6 +47,7 @@
#include "goal_base.h"
#include "story_base.h"
#include "toolbar_gui.h"
+#include "tutorial_gui.h"
#include "widgets/toolbar_widget.h"
@@ -64,6 +65,7 @@ RailType _last_built_railtype;
RoadType _last_built_roadtype;
static ScreenshotType _confirmed_screenshot_type; ///< Screenshot type the current query is about to confirm.
+int _last_clicked_toolbar_idx = 0;
/** Toobar modes */
enum ToolbarMode {
@@ -103,9 +105,9 @@ public:
{
bool rtl = _current_text_dir == TD_RTL;
if (this->checked) {
- DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_JUST_CHECKMARK, sel ? TC_WHITE : TC_BLACK);
+ DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, Center(top, bottom - top), STR_JUST_CHECKMARK, sel ? TC_WHITE : TC_BLACK);
}
- DrawString(left + WD_FRAMERECT_LEFT + (rtl ? 0 : this->checkmark_width), right - WD_FRAMERECT_RIGHT - (rtl ? this->checkmark_width : 0), top, this->String(), sel ? TC_WHITE : TC_BLACK);
+ DrawString(left + WD_FRAMERECT_LEFT + (rtl ? 0 : this->checkmark_width), right - WD_FRAMERECT_RIGHT - (rtl ? this->checkmark_width : 0), Center(top, bottom - top), this->String(), sel ? TC_WHITE : TC_BLACK);
}
};
@@ -139,7 +141,7 @@ public:
uint Height(uint width) const
{
- return max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL);
+ return GetMinSizing(NWST_STEP, max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL));
}
void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
@@ -176,7 +178,17 @@ public:
*/
static void PopupMainToolbMenu(Window *w, int widget, DropDownList *list, int def)
{
- ShowDropDownList(w, list, def, widget, 0, true, true);
+ if (!_settings_client.gui.vertical_toolbar) {
+ ShowDropDownList(w, list, def, widget, 0, true, list->Length() <= 1);
+ } else {
+ Rect wi_rect;
+ NWidgetCore *nwi = w->GetWidget(widget);
+ wi_rect.left = nwi->pos_x;
+ wi_rect.right = nwi->pos_x + nwi->current_x;
+ wi_rect.top = nwi->pos_y;
+ wi_rect.bottom = nwi->pos_y + nwi->current_y;
+ ShowDropDownListAt(w, list, def, widget, wi_rect, nwi->colour, true, list->Length() <= 1);
+ }
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
}
@@ -329,7 +341,7 @@ static CallBackFunction ToolbarOptionsClick(Window *w)
*list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES));
*list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS));
- ShowDropDownList(w, list, 0, WID_TN_SETTINGS, 140, true, true);
+ ShowDropDownList(w, list, 0, WID_TN_SETTINGS, 140, true);
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
return CBF_NONE;
}
@@ -865,7 +877,7 @@ static CallBackFunction ToolbarZoomOutClick(Window *w)
static CallBackFunction ToolbarBuildRailClick(Window *w)
{
- ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, true, true);
+ ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, true);
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
return CBF_NONE;
}
@@ -902,7 +914,7 @@ static CallBackFunction ToolbarBuildRoadClick(Window *w)
*list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM));
break;
}
- ShowDropDownList(w, list, _last_built_roadtype, WID_TN_ROADS, 140, true, true);
+ ShowDropDownList(w, list, _last_built_roadtype, WID_TN_ROADS, 140, true, list->Length() <= 1);
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
return CBF_NONE;
}
@@ -1035,7 +1047,7 @@ static CallBackFunction PlaceLandBlockInfo()
ResetObjectToPlace();
return CBF_NONE;
} else {
- SetObjectToPlace(SPR_CURSOR_QUERY, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
+ SetObjectToPlace(SPR_CURSOR_QUERY, PAL_NONE, HT_RECT, _settings_client.gui.vertical_toolbar ? WC_MAIN_TOOLBAR_RIGHT : WC_MAIN_TOOLBAR, 0);
return CBF_PLACE_LANDINFO;
}
}
@@ -1138,6 +1150,7 @@ static CallBackFunction MenuClickHelp(int index)
{
switch (index) {
case 0: return PlaceLandBlockInfo();
+ case 1: ShowTutorialWindow(); break;
case 2: IConsoleSwitch(); break;
case 3: ShowAIDebugWindow(); break;
case 4: MenuClickSmallScreenshot(); break;
@@ -1168,6 +1181,40 @@ static CallBackFunction ToolbarSwitchClick(Window *w)
return CBF_NONE;
}
+static CallBackFunction ToolbarCtrlClick(Window *w)
+{
+ _ctrl_pressed = !_ctrl_pressed;
+ //DEBUG(misc, 1, "ToolbarCtrlClick: pressed %d", _ctrl_pressed);
+ w->SetWidgetLoweredState(WID_TN_CTRL, _ctrl_pressed);
+ w->SetWidgetDirty(WID_TN_CTRL);
+ HandleCtrlChanged();
+ if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
+ return CBF_NONE;
+}
+
+static CallBackFunction ToolbarShiftClick(Window *w)
+{
+ _shift_pressed = !_shift_pressed;
+ //DEBUG(misc, 1, "ToolbarShiftClick: pressed %d", _shift_pressed);
+ w->SetWidgetLoweredState(WID_TN_SHIFT, _shift_pressed);
+ w->SetWidgetDirty(WID_TN_SHIFT);
+ if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
+ return CBF_NONE;
+}
+
+static CallBackFunction ToolbarDeleteClick(Window *w)
+{
+ DeleteNonVitalWindows();
+ _ctrl_pressed = false;
+ w->SetWidgetLoweredState(WID_TN_CTRL, _ctrl_pressed);
+ w->SetWidgetDirty(WID_TN_CTRL);
+ _shift_pressed = false;
+ w->SetWidgetLoweredState(WID_TN_SHIFT, _shift_pressed);
+ w->SetWidgetDirty(WID_TN_SHIFT);
+ if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
+ return CBF_NONE;
+}
+
/* --- Scenario editor specific handlers. */
/**
@@ -1310,7 +1357,7 @@ protected:
uint spacers; ///< Number of spacer widgets in this toolbar
public:
- NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL)
+ NWidgetToolbarContainer(WidgetType widgetType = NWID_HORIZONTAL) : NWidgetContainer(widgetType)
{
}
@@ -1321,27 +1368,35 @@ public:
*/
bool IsButton(WidgetType type) const
{
- return type == WWT_IMGBTN || type == WWT_IMGBTN_2 || type == WWT_PUSHIMGBTN;
+ return type == WWT_IMGBTN || type == WWT_IMGBTN_2 || type == WWT_PUSHIMGBTN || type == WWT_PUSHTXTBTN || type == WWT_TEXTBTN;
}
void SetupSmallestSize(Window *w, bool init_array)
{
this->smallest_x = 0; // Biggest child
this->smallest_y = 0; // Biggest child
- this->fill_x = 1;
- this->fill_y = 0;
- this->resize_x = 1; // We only resize in this direction
- this->resize_y = 0; // We never resize in this direction
+ this->fill_x = (type == NWID_HORIZONTAL);
+ this->fill_y = (type == NWID_VERTICAL);
+ this->resize_x = (type == NWID_HORIZONTAL); // We only resize in this direction
+ this->resize_y = (type == NWID_VERTICAL); // We never resize in this direction
this->spacers = 0;
uint nbuttons = 0;
/* First initialise some variables... */
for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
child_wid->SetupSmallestSize(w, init_array);
- this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
+ if (type == NWID_HORIZONTAL) {
+ this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
+ } else {
+ this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
+ }
if (this->IsButton(child_wid->type)) {
nbuttons++;
- this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
+ if (type == NWID_HORIZONTAL) {
+ this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
+ } else {
+ this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
+ }
} else if (child_wid->type == NWID_SPACER) {
this->spacers++;
}
@@ -1349,12 +1404,24 @@ public:
/* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
- child_wid->current_y = this->smallest_y;
- if (!this->IsButton(child_wid->type)) {
- child_wid->current_x = child_wid->smallest_x;
+ if (type == NWID_HORIZONTAL) {
+ child_wid->current_y = this->smallest_y;
+ if (!this->IsButton(child_wid->type)) {
+ child_wid->current_x = child_wid->smallest_x;
+ }
+ } else {
+ child_wid->current_x = this->smallest_x;
+ if (!this->IsButton(child_wid->type)) {
+ child_wid->current_y = child_wid->smallest_y;
+ }
}
}
_toolbar_width = nbuttons * this->smallest_x;
+ if (type == NWID_HORIZONTAL) {
+ w->window_desc->default_width = nbuttons * this->smallest_x;
+ } else {
+ w->window_desc->default_height = nbuttons * this->smallest_y;
+ }
}
void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
@@ -1385,6 +1452,10 @@ public:
uint position = 0; // Place to put next child relative to origin of the container.
uint spacer_space = max(0, (int)given_width - (int)(button_count * this->smallest_x)); // Remaining spacing for 'spacer' widgets
uint button_space = given_width - spacer_space; // Remaining spacing for the buttons
+ if (type == NWID_VERTICAL) {
+ spacer_space = max(0, (int)given_height - (int)(button_count * this->smallest_y));
+ button_space = given_height - spacer_space;
+ }
uint spacer_i = 0;
uint button_i = 0;
@@ -1405,12 +1476,22 @@ public:
/* Buttons can be scaled, the others not. */
if (this->IsButton(child_wid->type)) {
- child_wid->current_x = button_space / (button_count - button_i);
- button_space -= child_wid->current_x;
+ if (type == NWID_HORIZONTAL) {
+ child_wid->current_x = button_space / (button_count - button_i);
+ button_space -= child_wid->current_x;
+ } else {
+ child_wid->current_y = button_space / (button_count - button_i);
+ button_space -= child_wid->current_y;
+ }
button_i++;
}
- child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
- position += child_wid->current_x;
+ if (type == NWID_HORIZONTAL) {
+ child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
+ position += child_wid->current_x;
+ } else {
+ child_wid->AssignSizePosition(sizing, x, y + position, this->current_x, child_wid->current_y, rtl);
+ position += child_wid->current_y;
+ }
if (rtl) {
cur_wid--;
@@ -1464,54 +1545,78 @@ public:
class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
/* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
{
- static const uint SMALLEST_ARRANGEMENT = 14;
- static const uint BIGGEST_ARRANGEMENT = 20;
- static const byte arrange14[] = {
- 0, 1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 29,
- 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
+ static const uint BIGGEST_ARRANGEMENT = 28;
+ static const uint ARRANGEMENT_30 = 24;
+ static const byte arrange_android_28[] = {
+ 0, 1, 3, 4, 5, 6, 7, 8, 9, 14, 21, 22, 23, 24, 25, 19, 20, 29, 30, 31, 32,
+ 0, 1, 2, 4, 5, 10, 11, 12, 15, 16, 17, 18, 26, 27, 28, 19, 20, 29, 30, 31, 32,
};
- static const byte arrange15[] = {
- 0, 1, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
- 0, 2, 4, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
+ static const byte arrange_android_30[] = {
+ 0, 1, 3, 4, 5, 6, 7, 12, 8, 9, 14, 21, 22, 23, 24, 25, 19, 20, 29, 30, 31, 32,
+ 0, 1, 2, 4, 5, 10, 11, 12, 13, 15, 16, 17, 18, 26, 27, 28, 19, 20, 29, 30, 31, 32,
};
- static const byte arrange16[] = {
- 0, 1, 2, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
- 0, 1, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
- };
- static const byte arrange17[] = {
- 0, 1, 2, 4, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
- 0, 1, 3, 4, 6, 5, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
- };
- static const byte arrange18[] = {
- 0, 1, 2, 4, 5, 6, 7, 8, 9, 14, 21, 22, 23, 24, 25, 19, 20, 29,
- 0, 1, 3, 4, 5, 6, 7, 12, 15, 16, 17, 18, 26, 27, 28, 19, 20, 29,
- };
- static const byte arrange19[] = {
- 0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 19, 20, 29,
- 0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 28, 19, 20, 29,
- };
- static const byte arrange20[] = {
- 0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 11, 19, 20, 29,
- 0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 10, 28, 19, 20, 29,
- };
- static const byte arrange_all[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
+ static const byte arrange_android_all[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32
};
- /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
- uint full_buttons = max(CeilDiv(width, this->smallest_x), SMALLEST_ARRANGEMENT);
- if (full_buttons > BIGGEST_ARRANGEMENT) {
- button_count = arrangable_count = lengthof(arrange_all);
- spacer_count = this->spacers;
- return arrange_all;
+ spacer_count = this->spacers;
+ if (width > BIGGEST_ARRANGEMENT * this->smallest_x) {
+ button_count = arrangable_count = lengthof(arrange_android_all);
+ return arrange_android_all;
+ }
+ if (width > ARRANGEMENT_30 * this->smallest_x) {
+ button_count = arrangable_count = lengthof(arrange_android_30) / 2;
+ return &arrange_android_30[((_toolbar_mode == TB_LOWER) ? button_count : 0)];
+ }
+ button_count = arrangable_count = lengthof(arrange_android_28) / 2;
+ return &arrange_android_28[((_toolbar_mode == TB_LOWER) ? button_count : 0)];
+ }
+};
+
+/** Container for the vertical main toolbar */
+class NWidgetVerticalToolbarContainer : public NWidgetToolbarContainer {
+ int side;
+
+ public:
+ NWidgetVerticalToolbarContainer(int side) : NWidgetToolbarContainer(NWID_VERTICAL), side(side)
+ {
+ }
+
+ /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
+ {
+ static const byte arrange_left[] = {
+ 32, 30, 31, 19, 20, 0, 1, 2, 3, 4, 5, 6,
+ };
+ // Some rather artistic button arrangement, I'm proud of myself
+ static const byte arrange_right[] = {
+ 29, 21, 22, 23, 24, 25, 7, 8, 9, 12, 14, 28,
+ 29, 15, 16, 17, 18, 13, 7, 10, 11, 26, 27, 28,
+ };
+ // Full-length toolbar without switch button, if enough space
+ static const byte arrange_left_all[] = {
+ 32, 30, 31, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 13,
+ };
+ static const byte arrange_right_all[] = {
+ 10, 11, 12, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28,
+ };
+
+ spacer_count = 0;
+
+ if (_screen.height / this->smallest_y >= lengthof(arrange_left_all))
+ {
+ button_count = arrangable_count = lengthof(arrange_left_all);
+ if (side == 0) {
+ return arrange_left_all;
+ }
+ return arrange_right_all;
}
- /* Introduce the split toolbar */
- static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20 };
-
- button_count = arrangable_count = full_buttons;
- spacer_count = this->spacers;
- return arrangements[full_buttons - SMALLEST_ARRANGEMENT] + ((_toolbar_mode == TB_LOWER) ? full_buttons : 0);
+ if (side == 0) {
+ button_count = arrangable_count = lengthof(arrange_left);
+ return arrange_left;
+ }
+ button_count = arrangable_count = lengthof(arrange_right) / 2;
+ return &arrange_right[((_toolbar_mode == TB_LOWER) ? button_count : 0)];
}
};
@@ -1611,6 +1716,9 @@ static ToolbarButtonProc * const _toolbar_button_procs[] = {
ToolbarNewspaperClick,
ToolbarHelpClick,
ToolbarSwitchClick,
+ ToolbarCtrlClick,
+ ToolbarShiftClick,
+ ToolbarDeleteClick,
};
enum MainToolbarHotkeys {
@@ -1657,8 +1765,10 @@ enum MainToolbarHotkeys {
/** Main toolbar. */
struct MainToolbarWindow : Window {
CallBackFunction last_started_action; ///< Last started user action.
+ int *clickedFlag;
+ int clickedValue;
- MainToolbarWindow(WindowDesc *desc) : Window(desc)
+ MainToolbarWindow(WindowDesc *desc, int *clickedFlag = NULL, int clickedValue = 0) : Window(desc), clickedFlag(clickedFlag), clickedValue(clickedValue)
{
this->InitNested(0);
@@ -1695,11 +1805,15 @@ struct MainToolbarWindow : Window {
virtual void OnClick(Point pt, int widget, int click_count)
{
+ if (clickedFlag)
+ *clickedFlag = clickedValue;
if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this);
}
virtual void OnDropdownSelect(int widget, int index)
{
+ if (clickedFlag)
+ *clickedFlag = clickedValue;
CallBackFunction cbf = _menu_clicked_procs[widget](index);
if (cbf != CBF_NONE) this->last_started_action = cbf;
}
@@ -1763,7 +1877,7 @@ struct MainToolbarWindow : Window {
ShowLandInfo(tile);
break;
- default: NOT_REACHED();
+ default: return; //NOT_REACHED();
}
}
@@ -1856,51 +1970,56 @@ static Hotkey maintoolbar_hotkeys[] = {
};
HotkeyList MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys);
+/** Sprites to use for the different toolbar buttons */
+static const SpriteID _toolbar_button_sprites[] = {
+ SPR_IMG_PAUSE, // WID_TN_PAUSE
+ SPR_IMG_FASTFORWARD, // WID_TN_FAST_FORWARD
+ SPR_IMG_SETTINGS, // WID_TN_SETTINGS
+ SPR_IMG_SAVE, // WID_TN_SAVE
+ SPR_IMG_SMALLMAP, // WID_TN_SMALL_MAP
+ SPR_IMG_TOWN, // WID_TN_TOWNS
+ SPR_IMG_SUBSIDIES, // WID_TN_SUBSIDIES
+ SPR_IMG_COMPANY_LIST, // WID_TN_STATIONS
+ SPR_IMG_COMPANY_FINANCE, // WID_TN_FINANCES
+ SPR_IMG_COMPANY_GENERAL, // WID_TN_COMPANIES
+ SPR_IMG_STORY_BOOK, // WID_TN_STORY
+ SPR_IMG_GOAL, // WID_TN_GOAL
+ SPR_IMG_GRAPHS, // WID_TN_GRAPHS
+ SPR_IMG_COMPANY_LEAGUE, // WID_TN_LEAGUE
+ SPR_IMG_INDUSTRY, // WID_TN_INDUSTRIES
+ SPR_IMG_TRAINLIST, // WID_TN_TRAINS
+ SPR_IMG_TRUCKLIST, // WID_TN_ROADVEHS
+ SPR_IMG_SHIPLIST, // WID_TN_SHIPS
+ SPR_IMG_AIRPLANESLIST, // WID_TN_AIRCRAFT
+ SPR_IMG_ZOOMIN, // WID_TN_ZOOMIN
+ SPR_IMG_ZOOMOUT, // WID_TN_ZOOMOUT
+ SPR_IMG_BUILDRAIL, // WID_TN_RAILS
+ SPR_IMG_BUILDROAD, // WID_TN_ROADS
+ SPR_IMG_BUILDWATER, // WID_TN_WATER
+ SPR_IMG_BUILDAIR, // WID_TN_AIR
+ SPR_IMG_LANDSCAPING, // WID_TN_LANDSCAPE
+ SPR_IMG_MUSIC, // WID_TN_MUSIC_SOUND
+ SPR_IMG_MESSAGES, // WID_TN_MESSAGES
+ SPR_IMG_QUERY, // WID_TN_HELP
+ SPR_IMG_SWITCH_TOOLBAR, // WID_TN_SWITCH_BAR
+};
+
static NWidgetBase *MakeMainToolbar(int *biggest_index)
{
- /** Sprites to use for the different toolbar buttons */
- static const SpriteID toolbar_button_sprites[] = {
- SPR_IMG_PAUSE, // WID_TN_PAUSE
- SPR_IMG_FASTFORWARD, // WID_TN_FAST_FORWARD
- SPR_IMG_SETTINGS, // WID_TN_SETTINGS
- SPR_IMG_SAVE, // WID_TN_SAVE
- SPR_IMG_SMALLMAP, // WID_TN_SMALL_MAP
- SPR_IMG_TOWN, // WID_TN_TOWNS
- SPR_IMG_SUBSIDIES, // WID_TN_SUBSIDIES
- SPR_IMG_COMPANY_LIST, // WID_TN_STATIONS
- SPR_IMG_COMPANY_FINANCE, // WID_TN_FINANCES
- SPR_IMG_COMPANY_GENERAL, // WID_TN_COMPANIES
- SPR_IMG_STORY_BOOK, // WID_TN_STORY
- SPR_IMG_GOAL, // WID_TN_GOAL
- SPR_IMG_GRAPHS, // WID_TN_GRAPHS
- SPR_IMG_COMPANY_LEAGUE, // WID_TN_LEAGUE
- SPR_IMG_INDUSTRY, // WID_TN_INDUSTRIES
- SPR_IMG_TRAINLIST, // WID_TN_TRAINS
- SPR_IMG_TRUCKLIST, // WID_TN_ROADVEHS
- SPR_IMG_SHIPLIST, // WID_TN_SHIPS
- SPR_IMG_AIRPLANESLIST, // WID_TN_AIRCRAFT
- SPR_IMG_ZOOMIN, // WID_TN_ZOOMIN
- SPR_IMG_ZOOMOUT, // WID_TN_ZOOMOUT
- SPR_IMG_BUILDRAIL, // WID_TN_RAILS
- SPR_IMG_BUILDROAD, // WID_TN_ROADS
- SPR_IMG_BUILDWATER, // WID_TN_WATER
- SPR_IMG_BUILDAIR, // WID_TN_AIR
- SPR_IMG_LANDSCAPING, // WID_TN_LANDSCAPE
- SPR_IMG_MUSIC, // WID_TN_MUSIC_SOUND
- SPR_IMG_MESSAGES, // WID_TN_MESSAGES
- SPR_IMG_QUERY, // WID_TN_HELP
- SPR_IMG_SWITCH_TOOLBAR, // WID_TN_SWITCH_BAR
- };
-
NWidgetMainToolbarContainer *hor = new NWidgetMainToolbarContainer();
- for (uint i = 0; i < WID_TN_END; i++) {
+ for (uint i = 0; i <= WID_TN_SWITCH_BAR; i++) {
switch (i) {
case 4: case 8: case 15: case 19: case 21: case 26: hor->Add(new NWidgetSpacer(0, 0)); break;
}
- hor->Add(new NWidgetLeaf(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i));
+ hor->Add(new NWidgetLeaf(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, _toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i));
}
- *biggest_index = max(*biggest_index, WID_TN_SWITCH_BAR);
+ hor->Add(new NWidgetSpacer(0, 0));
+ hor->Add(new NWidgetLeaf(WWT_TEXTBTN, COLOUR_GREY, WID_TN_CTRL, STR_TABLET_CTRL, STR_TABLET_CTRL_TOOLTIP));
+ hor->Add(new NWidgetLeaf(WWT_TEXTBTN, COLOUR_GREY, WID_TN_SHIFT, STR_TABLET_SHIFT, STR_TABLET_SHIFT_TOOLTIP));
+ hor->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TN_DELETE, STR_TABLET_CLOSE, STR_TABLET_CLOSE_TOOLTIP));
+
+ *biggest_index = max(*biggest_index, WID_TN_DELETE);
return hor;
}
@@ -1916,6 +2035,59 @@ static WindowDesc _toolb_normal_desc(
&MainToolbarWindow::hotkeys
);
+static NWidgetBase *MakeVerticalLeftToolbar(int *biggest_index)
+{
+ NWidgetVerticalToolbarContainer *tb = new NWidgetVerticalToolbarContainer(0);
+ for (uint i = 0; i <= WID_TN_SWITCH_BAR; i++) {
+ tb->Add(new NWidgetLeaf(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, _toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i));
+ }
+
+ tb->Add(new NWidgetLeaf(WWT_TEXTBTN, COLOUR_GREY, WID_TN_CTRL, STR_TABLET_CTRL, STR_TABLET_CTRL_TOOLTIP));
+ tb->Add(new NWidgetLeaf(WWT_TEXTBTN, COLOUR_GREY, WID_TN_SHIFT, STR_TABLET_SHIFT, STR_TABLET_SHIFT_TOOLTIP));
+ tb->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TN_DELETE, STR_TABLET_CLOSE, STR_TABLET_CLOSE_TOOLTIP));
+
+ *biggest_index = max(*biggest_index, WID_TN_DELETE);
+ return tb;
+}
+
+static const NWidgetPart _nested_toolbar_vertical_left_widgets[] = {
+ NWidgetFunction(MakeVerticalLeftToolbar),
+};
+
+static WindowDesc _toolb_vertical_left_desc(
+ WDP_MANUAL, NULL, 22, 480,
+ WC_MAIN_TOOLBAR, WC_NONE,
+ WDF_NO_FOCUS,
+ _nested_toolbar_vertical_left_widgets, lengthof(_nested_toolbar_vertical_left_widgets),
+ &MainToolbarWindow::hotkeys
+);
+
+static NWidgetBase *MakeVerticalRightToolbar(int *biggest_index)
+{
+ NWidgetVerticalToolbarContainer *tb = new NWidgetVerticalToolbarContainer(1);
+ for (uint i = 0; i <= WID_TN_SWITCH_BAR; i++) {
+ tb->Add(new NWidgetLeaf(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, _toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i));
+ }
+
+ tb->Add(new NWidgetLeaf(WWT_TEXTBTN, COLOUR_GREY, WID_TN_CTRL, STR_TABLET_CTRL, STR_TABLET_CTRL_TOOLTIP));
+ tb->Add(new NWidgetLeaf(WWT_TEXTBTN, COLOUR_GREY, WID_TN_SHIFT, STR_TABLET_SHIFT, STR_TABLET_SHIFT_TOOLTIP));
+ tb->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TN_DELETE, STR_TABLET_CLOSE, STR_TABLET_CLOSE_TOOLTIP));
+
+ *biggest_index = max(*biggest_index, WID_TN_DELETE);
+ return tb;
+}
+
+static const NWidgetPart _nested_toolbar_vertical_right_widgets[] = {
+ NWidgetFunction(MakeVerticalRightToolbar),
+};
+
+static WindowDesc _toolb_vertical_right_desc(
+ WDP_MANUAL, NULL, 22, 480,
+ WC_MAIN_TOOLBAR_RIGHT, WC_NONE,
+ WDF_NO_FOCUS,
+ _nested_toolbar_vertical_right_widgets, lengthof(_nested_toolbar_vertical_right_widgets),
+ &MainToolbarWindow::hotkeys
+);
/* --- Toolbar handling for the scenario editor */
@@ -2241,6 +2413,14 @@ void AllocateToolbar()
if (_game_mode == GM_EDITOR) {
new ScenarioEditorToolbarWindow(&_toolb_scen_desc);
} else {
- new MainToolbarWindow(&_toolb_normal_desc);
+ if (_settings_client.gui.vertical_toolbar) {
+ MainToolbarWindow *w = new MainToolbarWindow(&_toolb_vertical_left_desc, &_last_clicked_toolbar_idx, 0);
+ w->left = 0;
+ w = new MainToolbarWindow(&_toolb_vertical_right_desc, &_last_clicked_toolbar_idx, 1);
+ w->left = _screen.width - w->width;
+ SetDirtyBlocks(0, w->top, _screen.width, w->top + w->height);
+ } else {
+ new MainToolbarWindow(&_toolb_normal_desc);
+ }
}
}
diff --git a/src/toolbar_gui.h b/src/toolbar_gui.h
index 37fc8f0e9f..eb7ada67d8 100644
--- a/src/toolbar_gui.h
+++ b/src/toolbar_gui.h
@@ -17,5 +17,6 @@ void ToggleBoundingBoxes();
void ToggleDirtyBlocks();
extern uint _toolbar_width;
+extern int _last_clicked_toolbar_idx;
#endif /* TOOLBAR_GUI_H */
diff --git a/src/town_gui.cpp b/src/town_gui.cpp
index 6ae37d71af..29942a1c2e 100644
--- a/src/town_gui.cpp
+++ b/src/town_gui.cpp
@@ -49,12 +49,12 @@ static const NWidgetPart _nested_town_authority_widgets[] = {
NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
NWidget(WWT_STICKYBOX, COLOUR_BROWN),
EndContainer(),
- NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_RATING_INFO), SetMinimalSize(317, 92), SetResize(1, 1), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_RATING_INFO), SetMinimalSize(317, 92), SetResize(1, 1), SetFill(1, 1), EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_COMMAND_LIST), SetMinimalSize(305, 52), SetResize(1, 0), SetDataTip(0x0, STR_LOCAL_AUTHORITY_ACTIONS_TOOLTIP), SetScrollbar(WID_TA_SCROLLBAR), EndContainer(),
NWidget(NWID_VSCROLLBAR, COLOUR_BROWN, WID_TA_SCROLLBAR),
EndContainer(),
- NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_ACTION_INFO), SetMinimalSize(317, 52), SetResize(1, 0), EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_ACTION_INFO), SetMinimalSize(317, 52), SetResize(1, 1), SetFill(1, 1), EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TA_EXECUTE), SetMinimalSize(317, 12), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_LOCAL_AUTHORITY_DO_IT_BUTTON, STR_LOCAL_AUTHORITY_DO_IT_TOOLTIP),
NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
@@ -67,6 +67,7 @@ private:
Town *town; ///< Town being displayed.
int sel_index; ///< Currently selected town action, \c 0 to \c TACT_COUNT-1, \c -1 means no action selected.
Scrollbar *vscroll;
+ uint actions_step;
uint displayed_actions_on_previous_painting; ///< Actions that were available on the previous call to OnPaint()
/**
@@ -96,7 +97,8 @@ public:
this->town = Town::Get(window_number);
this->InitNested(window_number);
this->vscroll = this->GetScrollbar(WID_TA_SCROLLBAR);
- this->vscroll->SetCapacity((this->GetWidget(WID_TA_COMMAND_LIST)->current_y - WD_FRAMERECT_TOP - WD_FRAMERECT_BOTTOM) / FONT_HEIGHT_NORMAL);
+ this->actions_step = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL);
+ this->vscroll->SetCapacity((this->GetWidget(WID_TA_COMMAND_LIST)->current_y - WD_FRAMERECT_TOP - WD_FRAMERECT_BOTTOM) / this->actions_step);
}
virtual void OnPaint()
@@ -199,12 +201,12 @@ public:
case WID_TA_COMMAND_LIST: {
int numact;
uint buttons = GetMaskOfTownActions(&numact, _local_company, this->town);
- int y = r.top + WD_FRAMERECT_TOP;
+ int y = Center(r.top, this->actions_step);
int pos = this->vscroll->GetPosition();
if (--pos < 0) {
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_LOCAL_AUTHORITY_ACTIONS_TITLE);
- y += FONT_HEIGHT_NORMAL;
+ y += this->actions_step;
}
for (int i = 0; buttons; i++, buttons >>= 1) {
@@ -213,7 +215,7 @@ public:
if ((buttons & 1) && --pos < 0) {
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y,
STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + i, this->sel_index == i ? TC_WHITE : TC_ORANGE);
- y += FONT_HEIGHT_NORMAL;
+ y += this->actions_step;
}
}
break;
@@ -240,7 +242,8 @@ public:
}
case WID_TA_COMMAND_LIST:
- size->height = WD_FRAMERECT_TOP + 5 * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM;
+ resize->height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL);
+ size->height = WD_FRAMERECT_TOP + 3 * resize->height + WD_FRAMERECT_BOTTOM;
size->width = GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTIONS_TITLE).width;
for (uint i = 0; i < TACT_COUNT; i++ ) {
size->width = max(size->width, GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + i).width);
@@ -259,7 +262,7 @@ public:
{
switch (widget) {
case WID_TA_COMMAND_LIST: {
- int y = this->GetRowFromWidget(pt.y, WID_TA_COMMAND_LIST, 1, FONT_HEIGHT_NORMAL);
+ int y = this->GetRowFromWidget(pt.y, WID_TA_COMMAND_LIST, 1, this->actions_step);
if (!IsInsideMM(y, 0, 5)) return;
y = GetNthSetBit(GetMaskOfTownActions(NULL, _local_company, this->town), y + this->vscroll->GetPosition() - 1);
@@ -613,7 +616,7 @@ static const NWidgetPart _nested_town_directory_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(NWID_HORIZONTAL),
- NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TD_SORT_ORDER), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
+ NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TD_SORT_ORDER), SetSizingType(NWST_STEP), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_TD_SORT_CRITERIA), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
NWidget(WWT_PANEL, COLOUR_BROWN), SetResize(1, 0), EndContainer(),
EndContainer(),
@@ -825,7 +828,7 @@ public:
}
Dimension icon_size = GetSpriteSize(SPR_TOWN_RATING_GOOD);
d.width += icon_size.width + 2;
- d.height = max(d.height, icon_size.height);
+ d.height = GetMinSizing(NWST_STEP, max(d.height, icon_size.height));
resize->height = d.height;
d.height *= 5;
d.width += padding.width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
@@ -977,61 +980,65 @@ static const NWidgetPart _nested_found_town_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
EndContainer(),
/* Construct new town(s) buttons. */
- NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
- NWidget(NWID_SPACER), SetMinimalSize(0, 2),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_NEW_TOWN), SetMinimalSize(156, 12), SetFill(1, 0),
- SetDataTip(STR_FOUND_TOWN_NEW_TOWN_BUTTON, STR_FOUND_TOWN_NEW_TOWN_TOOLTIP), SetPadding(0, 2, 1, 2),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_RANDOM_TOWN), SetMinimalSize(156, 12), SetFill(1, 0),
- SetDataTip(STR_FOUND_TOWN_RANDOM_TOWN_BUTTON, STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP), SetPadding(0, 2, 1, 2),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_MANY_RANDOM_TOWNS), SetMinimalSize(156, 12), SetFill(1, 0),
- SetDataTip(STR_FOUND_TOWN_MANY_RANDOM_TOWNS, STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP), SetPadding(0, 2, 0, 2),
- /* Town name selection. */
- NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(156, 14), SetPadding(0, 2, 0, 2), SetDataTip(STR_FOUND_TOWN_NAME_TITLE, STR_NULL),
- NWidget(WWT_EDITBOX, COLOUR_GREY, WID_TF_TOWN_NAME_EDITBOX), SetMinimalSize(156, 12), SetPadding(0, 2, 3, 2),
- SetDataTip(STR_FOUND_TOWN_NAME_EDITOR_TITLE, STR_FOUND_TOWN_NAME_EDITOR_HELP),
- NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_TOWN_NAME_RANDOM), SetMinimalSize(78, 12), SetPadding(0, 2, 0, 2), SetFill(1, 0),
- SetDataTip(STR_FOUND_TOWN_NAME_RANDOM_BUTTON, STR_FOUND_TOWN_NAME_RANDOM_TOOLTIP),
- /* Town size selection. */
- NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
- NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(148, 14), SetDataTip(STR_FOUND_TOWN_INITIAL_SIZE_TITLE, STR_NULL),
- NWidget(NWID_SPACER), SetFill(1, 0),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 2),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_NEW_TOWN), SetMinimalSize(156, 12), SetFill(1, 0),
+ SetDataTip(STR_FOUND_TOWN_NEW_TOWN_BUTTON, STR_FOUND_TOWN_NEW_TOWN_TOOLTIP), SetPadding(0, 2, 1, 2),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_RANDOM_TOWN), SetMinimalSize(156, 12), SetFill(1, 0),
+ SetDataTip(STR_FOUND_TOWN_RANDOM_TOWN_BUTTON, STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP), SetPadding(0, 2, 1, 2),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_MANY_RANDOM_TOWNS), SetMinimalSize(156, 12), SetFill(1, 0),
+ SetDataTip(STR_FOUND_TOWN_MANY_RANDOM_TOWNS, STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP), SetPadding(0, 2, 0, 2),
+ /* Town name selection. */
+ NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(156, 14), SetPadding(0, 2, 0, 2), SetDataTip(STR_FOUND_TOWN_NAME_TITLE, STR_NULL),
+ NWidget(WWT_EDITBOX, COLOUR_GREY, WID_TF_TOWN_NAME_EDITBOX), SetMinimalSize(156, 12), SetPadding(0, 2, 3, 2),
+ SetDataTip(STR_FOUND_TOWN_NAME_EDITOR_TITLE, STR_FOUND_TOWN_NAME_EDITOR_HELP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_TOWN_NAME_RANDOM), SetMinimalSize(78, 12), SetPadding(0, 2, 0, 2), SetFill(1, 0),
+ SetDataTip(STR_FOUND_TOWN_NAME_RANDOM_BUTTON, STR_FOUND_TOWN_NAME_RANDOM_TOOLTIP),
+ /* Town size selection. */
+ NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
+ NWidget(NWID_SPACER), SetFill(1, 0),
+ NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(148, 14), SetDataTip(STR_FOUND_TOWN_INITIAL_SIZE_TITLE, STR_NULL),
+ NWidget(NWID_SPACER), SetFill(1, 0),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(2, 0, 2),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_SMALL), SetMinimalSize(78, 12), SetFill(1, 0),
+ SetDataTip(STR_FOUND_TOWN_INITIAL_SIZE_SMALL_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_MEDIUM), SetMinimalSize(78, 12), SetFill(1, 0),
+ SetDataTip(STR_FOUND_TOWN_INITIAL_SIZE_MEDIUM_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 1),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(2, 0, 2),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_LARGE), SetMinimalSize(78, 12), SetFill(1, 0),
+ SetDataTip(STR_FOUND_TOWN_INITIAL_SIZE_LARGE_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_RANDOM), SetMinimalSize(78, 12), SetFill(1, 0),
+ SetDataTip(STR_FOUND_TOWN_SIZE_RANDOM, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 3),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_CITY), SetPadding(0, 2, 0, 2), SetMinimalSize(156, 12), SetFill(1, 0),
+ SetDataTip(STR_FOUND_TOWN_CITY, STR_FOUND_TOWN_CITY_TOOLTIP), SetFill(1, 0),
EndContainer(),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(2, 0, 2),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_SMALL), SetMinimalSize(78, 12), SetFill(1, 0),
- SetDataTip(STR_FOUND_TOWN_INITIAL_SIZE_SMALL_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_MEDIUM), SetMinimalSize(78, 12), SetFill(1, 0),
- SetDataTip(STR_FOUND_TOWN_INITIAL_SIZE_MEDIUM_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
+ /* Town roads selection. */
+ NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
+ NWidget(NWID_SPACER), SetFill(1, 0),
+ NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(148, 14), SetDataTip(STR_FOUND_TOWN_ROAD_LAYOUT, STR_NULL),
+ NWidget(NWID_SPACER), SetFill(1, 0),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(2, 0, 2),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_ORIGINAL), SetMinimalSize(78, 12), SetFill(1, 0), SetDataTip(STR_FOUND_TOWN_SELECT_LAYOUT_ORIGINAL, STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_BETTER), SetMinimalSize(78, 12), SetFill(1, 0), SetDataTip(STR_FOUND_TOWN_SELECT_LAYOUT_BETTER_ROADS, STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 1),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(2, 0, 2),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_GRID2), SetMinimalSize(78, 12), SetFill(1, 0), SetDataTip(STR_FOUND_TOWN_SELECT_LAYOUT_2X2_GRID, STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_GRID3), SetMinimalSize(78, 12), SetFill(1, 0), SetDataTip(STR_FOUND_TOWN_SELECT_LAYOUT_3X3_GRID, STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 1),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_RANDOM), SetPadding(0, 2, 0, 2), SetMinimalSize(0, 12), SetFill(1, 0),
+ SetDataTip(STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM, STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT), SetFill(1, 0),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 2),
EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 1),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(2, 0, 2),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_LARGE), SetMinimalSize(78, 12), SetFill(1, 0),
- SetDataTip(STR_FOUND_TOWN_INITIAL_SIZE_LARGE_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_RANDOM), SetMinimalSize(78, 12), SetFill(1, 0),
- SetDataTip(STR_FOUND_TOWN_SIZE_RANDOM, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP),
- EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 3),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_CITY), SetPadding(0, 2, 0, 2), SetMinimalSize(156, 12), SetFill(1, 0),
- SetDataTip(STR_FOUND_TOWN_CITY, STR_FOUND_TOWN_CITY_TOOLTIP), SetFill(1, 0),
- /* Town roads selection. */
- NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
- NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(148, 14), SetDataTip(STR_FOUND_TOWN_ROAD_LAYOUT, STR_NULL),
- NWidget(NWID_SPACER), SetFill(1, 0),
- EndContainer(),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(2, 0, 2),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_ORIGINAL), SetMinimalSize(78, 12), SetFill(1, 0), SetDataTip(STR_FOUND_TOWN_SELECT_LAYOUT_ORIGINAL, STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_BETTER), SetMinimalSize(78, 12), SetFill(1, 0), SetDataTip(STR_FOUND_TOWN_SELECT_LAYOUT_BETTER_ROADS, STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT),
- EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 1),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(2, 0, 2),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_GRID2), SetMinimalSize(78, 12), SetFill(1, 0), SetDataTip(STR_FOUND_TOWN_SELECT_LAYOUT_2X2_GRID, STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_GRID3), SetMinimalSize(78, 12), SetFill(1, 0), SetDataTip(STR_FOUND_TOWN_SELECT_LAYOUT_3X3_GRID, STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT),
- EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 1),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_RANDOM), SetPadding(0, 2, 0, 2), SetMinimalSize(0, 12), SetFill(1, 0),
- SetDataTip(STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM, STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT), SetFill(1, 0),
- NWidget(NWID_SPACER), SetMinimalSize(0, 2),
EndContainer(),
};
@@ -1060,6 +1067,10 @@ public:
this->UpdateButtons(true);
}
+ ~FoundTownWindow() {
+ if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort();
+ }
+
void RandomTownName()
{
this->townnamevalid = GenerateTownName(&this->townnameparts);
@@ -1163,7 +1174,18 @@ public:
virtual void OnPlaceObject(Point pt, TileIndex tile)
{
- this->ExecuteFoundTownCommand(tile, false, STR_ERROR_CAN_T_FOUND_TOWN_HERE, CcFoundTown);
+ VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_SINGLE_TILE);
+ }
+
+ 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)
+ {
+ assert(start_tile == end_tile);
+ this->ExecuteFoundTownCommand(end_tile, false, STR_ERROR_CAN_T_FOUND_TOWN_HERE, CcFoundTown);
}
virtual void OnPlaceObjectAbort()
@@ -1185,7 +1207,7 @@ public:
};
static WindowDesc _found_town_desc(
- WDP_AUTO, "build_town", 160, 162,
+ WDP_ALIGN_TOOLBAR, "build_town", 160, 162,
WC_FOUND_TOWN, WC_NONE,
WDF_CONSTRUCTION,
_nested_found_town_widgets, lengthof(_nested_found_town_widgets)
@@ -1194,5 +1216,6 @@ static WindowDesc _found_town_desc(
void ShowFoundTownWindow()
{
if (_game_mode != GM_EDITOR && !Company::IsValidID(_local_company)) return;
+ DeleteToolbarLinkedWindows();
AllocateWindowDescFront(&_found_town_desc, 0);
}
diff --git a/src/transparency_gui.cpp b/src/transparency_gui.cpp
index 4bad2b0561..af4c7d1d00 100644
--- a/src/transparency_gui.cpp
+++ b/src/transparency_gui.cpp
@@ -144,7 +144,7 @@ static const NWidgetPart _nested_transparency_widgets[] = {
NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetFill(1, 1), EndContainer(),
EndContainer(),
/* Panel with 'invisibility' buttons. */
- NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_TT_BUTTONS), SetMinimalSize(219, 13), SetDataTip(0x0, STR_TRANSPARENT_INVISIBLE_TOOLTIP),
+ NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_TT_BUTTONS), SetSizingType(NWST_STEP), SetMinimalSize(219, 13), SetDataTip(0x0, STR_TRANSPARENT_INVISIBLE_TOOLTIP),
EndContainer(),
};
diff --git a/src/tree_gui.cpp b/src/tree_gui.cpp
index f21eeaef2e..e46ee027ac 100644
--- a/src/tree_gui.cpp
+++ b/src/tree_gui.cpp
@@ -18,6 +18,7 @@
#include "command_func.h"
#include "sound_func.h"
#include "tree_map.h"
+#include "window_func.h"
#include "widgets/tree_widget.h"
@@ -60,6 +61,11 @@ public:
ResetObjectToPlace();
}
+ ~BuildTreesWindow()
+ {
+ if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort();
+ }
+
/**
* Calculate the maximum size of all tree sprites
* @return Dimension of the largest tree sprite
@@ -168,6 +174,8 @@ public:
virtual void OnPlaceObjectAbort()
{
this->RaiseButtons();
+
+ ResetObjectToPlace();
}
};
diff --git a/src/tutorial_gui.cpp b/src/tutorial_gui.cpp
new file mode 100644
index 0000000000..26d3dfb1e0
--- /dev/null
+++ b/src/tutorial_gui.cpp
@@ -0,0 +1,201 @@
+/* $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 .
+ */
+
+/**
+ * @file tutorial_gui.cpp
+ * Links to video tutorials on Youtube.
+ */
+
+#include "stdafx.h"
+
+#include
+
+#include "tutorial_gui.h"
+#include "debug.h"
+#include "strings_func.h"
+#include "window_func.h"
+#include "fios.h"
+#include "string_func.h"
+#include "language.h"
+#include "widget_type.h"
+#include "window_type.h"
+#include "window_func.h"
+#include "window_gui.h"
+#include "widgets/station_widget.h"
+#include "table/strings.h"
+#include "table/sprites.h"
+
+
+static bool showTutorialMainMenu = false;
+
+static const char * ANY_LANG = "ANY_LANG";
+
+struct VideoLink_t {
+ const char *lang;
+ const char *video;
+};
+
+static VideoLink_t busTutorial[] = {
+ { "en", "https://www.youtube.com/watch?v=EULXRMR4PyE" },
+ { ANY_LANG, "https://www.youtube.com/watch?v=EULXRMR4PyE" },
+ { NULL, NULL }
+};
+
+void OpenExternTutorialVideo(VideoLink_t *tutorial)
+{
+ const char *link = NULL;
+ for (; tutorial->lang != NULL; tutorial++) {
+ if (strcmp(tutorial->lang, _current_language->isocode) == 0) {
+ link = tutorial->video;
+ break;
+ }
+ if (strcmp(tutorial->lang, ANY_LANG) == 0) {
+ link = tutorial->video;
+ break;
+ }
+ }
+ if (!link) {
+ return;
+ }
+ SDL_ANDROID_OpenExternalWebBrowser(link);
+}
+
+static const NWidgetPart _nested_tutorial_widgets[] = {
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_CLOSEBOX, COLOUR_GREY),
+ NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_TUTORIAL_WINDOW_TITLE, STR_TUTORIAL_WINDOW_TOOLTIP),
+ EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_GREY),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(NWID_SPACER), SetMinimalSize(6, 0), SetFill(1, 0),
+ NWidget(NWID_VERTICAL), SetPIP(16, 2, 6),
+ // TODO: make different button IDs
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_BUS_STATION, STR_SMALLMAP_LEGENDA_BUS_STATION), SetFill(1, 1),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_ROAD_VEHICLES, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY), SetFill(1, 1),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_BUS), SetMinimalSize(120, 20), SetDataTip(SPR_VEH_BUS_SW_VIEW, STR_SMALLMAP_LEGENDA_BUS_STATION), SetFill(1, 1),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_TRUCK), SetMinimalSize(120, 20), SetDataTip(SPR_IMG_TRUCKLIST, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY), SetFill(1, 1),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetFill(1, 0),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_RAILROADS, STR_SMALLMAP_LEGENDA_RAILROAD_STATION), SetFill(1, 1),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_SHIPS, STR_SMALLMAP_LEGENDA_DOCK), SetFill(1, 1),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_TRAIN), SetMinimalSize(120, 20), SetDataTip(SPR_IMG_TRAINLIST, STR_SMALLMAP_LEGENDA_RAILROAD_STATION), SetFill(0, 1),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_SHIP), SetMinimalSize(120, 20), SetDataTip(SPR_IMG_SHIPLIST, STR_SMALLMAP_LEGENDA_DOCK), SetFill(0, 1),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetFill(1, 0),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_AIRCRAFT, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT), SetFill(1, 1),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_INDUSTRIES, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES), SetFill(1, 1),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_AIRPLANE), SetMinimalSize(120, 20), SetDataTip(SPR_IMG_AIRPLANESLIST, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT), SetFill(0, 1),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_FACILALL), SetMinimalSize(120, 20), SetDataTip(SPR_IMG_COMPANY_FINANCE, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES), SetFill(0, 1),
+ EndContainer(),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(6, 0), SetFill(1, 0),
+ EndContainer(),
+ EndContainer(),
+};
+
+static WindowDesc _tutorial_desc(
+ WDP_CENTER, NULL, 0, 0,
+ WC_GAME_OPTIONS, WC_NONE,
+ 0,
+ _nested_tutorial_widgets, lengthof(_nested_tutorial_widgets)
+);
+
+
+struct TutorialWindow : public Window {
+ VideoLink_t *video;
+ int counter;
+ TutorialWindow() : Window(&_tutorial_desc)
+ {
+ this->InitNested(WN_GAME_OPTIONS_ABOUT);
+ this->SetWidgetDisabledState(WID_STL_TRUCK, true);
+ this->SetWidgetDisabledState(WID_STL_TRAIN, true);
+ this->SetWidgetDisabledState(WID_STL_SHIP, true);
+ this->SetWidgetDisabledState(WID_STL_AIRPLANE, true);
+ this->SetWidgetDisabledState(WID_STL_FACILALL, true);
+ video = NULL;
+ counter = 0;
+ }
+
+ virtual void OnClick(Point pt, int widget, int click_count)
+ {
+ showTutorialMainMenu = false;
+ counter = 5;
+ this->LowerWidget(widget);
+ this->SetDirty();
+ switch (widget) {
+ case WID_STL_BUS:
+ video = busTutorial;
+ break;
+ case WID_STL_TRUCK:
+ break;
+ case WID_STL_TRAIN:
+ break;
+ case WID_STL_SHIP:
+ break;
+ case WID_STL_AIRPLANE:
+ break;
+ case WID_STL_FACILALL:
+ break;
+ }
+ }
+
+ virtual void OnTick()
+ {
+ // Open video with delay, to make visual feedback of button pressing,
+ // because youtube app freezes a screen for a second before launching.
+ if (counter > 0) {
+ counter--;
+ if (counter == 0) {
+ if (video) {
+ OpenExternTutorialVideo(video);
+ }
+ video = NULL;
+ this->RaiseWidget(WID_STL_BUS);
+ this->RaiseWidget(WID_STL_TRUCK);
+ this->RaiseWidget(WID_STL_TRAIN);
+ this->RaiseWidget(WID_STL_SHIP);
+ this->RaiseWidget(WID_STL_AIRPLANE);
+ this->RaiseWidget(WID_STL_FACILALL);
+ this->SetDirty();
+ }
+ }
+ }
+};
+
+void ShowTutorialWindow()
+{
+ DeleteWindowByClass(WC_GAME_OPTIONS);
+ new TutorialWindow();
+}
+
+void ShowTutorialWindowOnceAfterInstall()
+{
+ static const char * TUTORIAL_SHOWN_FLAG = ".tutorial-shown-1.flag";
+
+ FILE *ff = fopen(TUTORIAL_SHOWN_FLAG, "r");
+ if (ff) {
+ fclose(ff);
+ if (!showTutorialMainMenu)
+ return;
+ }
+ showTutorialMainMenu = true;
+ ff = fopen(TUTORIAL_SHOWN_FLAG, "w");
+ fprintf(ff, "Tutorial shown");
+ fclose(ff);
+ ShowTutorialWindow();
+}
diff --git a/src/tutorial_gui.h b/src/tutorial_gui.h
new file mode 100644
index 0000000000..04840ee2c6
--- /dev/null
+++ b/src/tutorial_gui.h
@@ -0,0 +1,18 @@
+/* $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 .
+ */
+
+/** @file tutorial_gui.h Links to video tutorials. */
+
+#ifndef TUTORIAL_GUI_H
+#define TUTORIAL_GUI_H
+
+void ShowTutorialWindow();
+void ShowTutorialWindowOnceAfterInstall();
+
+#endif /* TUTORIAL_GUI_H */
diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp
index 4ace090dda..f7bed85f38 100644
--- a/src/vehicle_gui.cpp
+++ b/src/vehicle_gui.cpp
@@ -330,7 +330,7 @@ typedef SmallVector SubtypeList; ///< List of refit subtypes as
*/
static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int sel[2], uint pos, uint rows, uint delta, const Rect &r)
{
- uint y = r.top + WD_MATRIX_TOP;
+ uint y = Center(r.top, delta);
uint current = 0;
bool rtl = _current_text_dir == TD_RTL;
@@ -660,8 +660,8 @@ struct RefitWindow : public Window {
{
switch (widget) {
case WID_VR_MATRIX:
- resize->height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
- size->height = resize->height * 8;
+ resize->height = GetMinSizing(NWST_STEP, WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM);
+ size->height = resize->height * 6;
break;
case WID_VR_VEHICLE_PANEL_DISPLAY:
@@ -725,11 +725,12 @@ struct RefitWindow : public Window {
case WID_VR_VEHICLE_PANEL_DISPLAY: {
Vehicle *v = Vehicle::Get(this->window_number);
DrawVehicleImage(v, this->sprite_left + WD_FRAMERECT_LEFT, this->sprite_right - WD_FRAMERECT_RIGHT,
- r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, this->hscroll != NULL ? this->hscroll->GetPosition() : 0);
+ r.top, r.bottom - r.top + 1, INVALID_VEHICLE, EIT_IN_DETAILS, this->hscroll != NULL ? this->hscroll->GetPosition() : 0);
/* Highlight selected vehicles. */
if (this->order != INVALID_VEH_ORDER_ID) break;
int x = 0;
+ int y_offset_frame = Center(0, r.bottom - r.top + 1, 14);
switch (v->type) {
case VEH_TRAIN: {
VehicleSet vehicles_to_refit;
@@ -1323,8 +1324,9 @@ static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y, Veh
* @param selection Selected vehicle to draw a frame around
* @param skip Number of pixels to skip at the front (for scrolling)
*/
-void DrawVehicleImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip)
+void DrawVehicleImage(const Vehicle *v, int left, int right, int y, int height, VehicleID selection, EngineImageType image_type, int skip)
{
+ y = Center(y, height, GetVehicleHeight(v->type));
switch (v->type) {
case VEH_TRAIN: DrawTrainImage(Train::From(v), left, right, y, selection, image_type, skip); break;
case VEH_ROAD: DrawRoadVehImage(v, left, right, y, selection, image_type, skip); break;
@@ -1389,7 +1391,7 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int
SetDParam(0, v->GetDisplayProfitThisYear());
SetDParam(1, v->GetDisplayProfitLastYear());
- DrawVehicleImage(v, image_left, image_right, y + FONT_HEIGHT_SMALL - 1, selected_vehicle, EIT_IN_LIST, 0);
+ DrawVehicleImage(v, image_left, image_right, y, line_height, selected_vehicle, EIT_IN_LIST, 0);
DrawString(text_left, text_right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 1, STR_VEHICLE_LIST_PROFIT_THIS_YEAR_LAST_YEAR);
if (v->name != NULL) {
@@ -1491,7 +1493,7 @@ public:
break;
case VEH_SHIP:
case VEH_AIRCRAFT:
- size->height = 4 * resize->height;
+ size->height = 3 * resize->height;
break;
default: NOT_REACHED();
}
@@ -1683,6 +1685,7 @@ public:
virtual void OnResize()
{
this->vscroll->SetCapacityFromWidget(this, WID_VL_LIST);
+ this->GetWidget(WID_VL_LIST)->widget_data = (this->vscroll->GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
}
/**
@@ -2102,12 +2105,12 @@ struct VehicleDetailsWindow : Window {
/* Articulated road vehicles use a complete line. */
if (v->type == VEH_ROAD && v->HasArticulatedPart()) {
- DrawVehicleImage(v, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, 0);
+ DrawVehicleImage(v, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top, r.bottom - r.top, INVALID_VEHICLE, EIT_IN_DETAILS, 0);
} else {
uint sprite_left = rtl ? text_right : r.left;
uint sprite_right = rtl ? r.right : text_left;
- DrawVehicleImage(v, sprite_left + WD_FRAMERECT_LEFT, sprite_right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, 0);
+ DrawVehicleImage(v, sprite_left + WD_FRAMERECT_LEFT, sprite_right - WD_FRAMERECT_RIGHT, r.top, r.bottom - r.top, INVALID_VEHICLE, EIT_IN_DETAILS, 0);
}
DrawVehicleDetails(v, text_left + WD_FRAMERECT_LEFT, text_right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, 0, 0, this->tab);
break;
@@ -2642,14 +2645,15 @@ public:
/* Draw the flag plus orders. */
bool rtl = (_current_text_dir == TD_RTL);
- uint text_offset = max(GetSpriteSize(SPR_FLAG_VEH_STOPPED).width, GetSpriteSize(SPR_FLAG_VEH_RUNNING).width) + WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT;
+ int image = ((v->vehstatus & VS_STOPPED) != 0) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING;
+ Dimension d = GetSpriteSize(image);
+ uint text_offset = d.width + WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT;
int text_left = r.left + (rtl ? (uint)WD_FRAMERECT_LEFT : text_offset);
int text_right = r.right - (rtl ? text_offset : (uint)WD_FRAMERECT_RIGHT);
int image_left = (rtl ? text_right + 1 : r.left) + WD_IMGBTN_LEFT;
- int image = ((v->vehstatus & VS_STOPPED) != 0) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING;
int lowered = this->IsWidgetLowered(WID_VV_START_STOP) ? 1 : 0;
- DrawSprite(image, PAL_NONE, image_left + lowered, r.top + WD_IMGBTN_TOP + lowered);
- DrawString(text_left + lowered, text_right + lowered, r.top + WD_FRAMERECT_TOP + lowered, str, TC_FROMSTRING, SA_HOR_CENTER);
+ DrawSprite(image, PAL_NONE, image_left + lowered, Center(r.top + WD_IMGBTN_TOP + lowered, r.bottom - r.top, d.height));
+ DrawString(text_left + lowered, text_right + lowered, Center(r.top + lowered, r.bottom - r.top), str, TC_FROMSTRING, SA_HOR_CENTER);
}
virtual void OnClick(Point pt, int widget, int click_count)
diff --git a/src/vehicle_gui.h b/src/vehicle_gui.h
index 83e098dcd9..935e6efe8d 100644
--- a/src/vehicle_gui.h
+++ b/src/vehicle_gui.h
@@ -99,6 +99,6 @@ 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);
+void DrawVehicleImage(const Vehicle *v, int left, int right, int y, int height, VehicleID selection, EngineImageType image_type, int skip);
#endif /* VEHICLE_GUI_H */
diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp
index ea68c21656..b649d8c294 100644
--- a/src/video/sdl_v.cpp
+++ b/src/video/sdl_v.cpp
@@ -23,8 +23,14 @@
#include "../core/random_func.hpp"
#include "../core/math_func.hpp"
#include "../fileio_func.h"
+#include "../settings_type.h"
+#include "../tilehighlight_func.h"
+#include "../viewport_func.h"
#include "sdl_v.h"
#include
+#ifdef __ANDROID__
+#include
+#endif
#include "../safeguards.h"
@@ -150,6 +156,16 @@ static void DrawSurfaceToScreen()
{
int n = _num_dirty_rects;
if (n == 0) return;
+ static int frameskip = 0;
+
+#ifdef __ANDROID__
+ if (_fast_forward) {
+ frameskip++;
+ if (frameskip < 5)
+ return;
+ frameskip = 0;
+ }
+#endif
_num_dirty_rects = 0;
if (n > MAX_DIRTY_RECTS) {
@@ -523,6 +539,8 @@ static uint ConvertSdlKeyIntoMy(SDL_keysym *sym, WChar *character)
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
@@ -545,7 +563,12 @@ int VideoDriver_SDL::PollEvent()
switch (ev.type) {
case SDL_MOUSEMOTION:
+#ifdef __ANDROID__
+ // No mouse warping on Android, mouse strictly follows finger
+ if (false) {
+#else
if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) {
+#endif
SDL_CALL SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y);
}
HandleMouseEvents();
@@ -564,6 +587,13 @@ int VideoDriver_SDL::PollEvent()
case SDL_BUTTON_RIGHT:
_right_button_down = true;
_right_button_clicked = true;
+ _right_button_down_pos.x = ev.motion.x;
+ _right_button_down_pos.y = ev.motion.y;
+#ifdef __ANDROID__
+ // Right button click on Android - cancel whatever action we were doing
+ ResetObjectToPlace();
+ ToolbarSelectLastTool();
+#endif
break;
case SDL_BUTTON_WHEELUP: _cursor.wheel--; break;
@@ -582,12 +612,20 @@ int VideoDriver_SDL::PollEvent()
} else if (ev.button.button == SDL_BUTTON_LEFT) {
_left_button_down = false;
_left_button_clicked = false;
+#ifdef __ANDROID__
+ if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON_RMASK) {
+ // Two-finger click - hacky way to determine if the right mouse button is already pressed without processing the left button event
+ // Cancel whatever action we were doing, to allow two finger scrolling
+ ResetObjectToPlace();
+ ToolbarSelectLastTool();
+ }
+#endif
} 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;
@@ -598,7 +636,7 @@ int VideoDriver_SDL::PollEvent()
_cursor.in_window = false;
}
break;
-
+#endif /* not __ANDROID__ */
case SDL_QUIT:
HandleExitGameRequest();
break;
@@ -611,15 +649,30 @@ int VideoDriver_SDL::PollEvent()
WChar character;
uint keycode = ConvertSdlKeyIntoMy(&ev.key.keysym, &character);
HandleKeypress(keycode, character);
+#ifdef __ANDROID__
+ if (ev.key.keysym.sym == SDLK_LCTRL || ev.key.keysym.sym == SDLK_RCTRL)
+ _ctrl_pressed = true;
+ if (ev.key.keysym.sym == SDLK_LSHIFT || ev.key.keysym.sym == SDLK_RSHIFT)
+ _shift_pressed = true;
+#endif
}
break;
-
+ case SDL_KEYUP:
+#ifdef __ANDROID__
+ if (ev.key.keysym.sym == SDLK_LCTRL || ev.key.keysym.sym == SDLK_RCTRL)
+ _ctrl_pressed = false;
+ if (ev.key.keysym.sym == SDLK_LSHIFT || ev.key.keysym.sym == SDLK_RSHIFT)
+ _shift_pressed = false;
+#endif
+ 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
@@ -651,6 +704,9 @@ const char *VideoDriver_SDL::Start(const char * const *parm)
SetupKeyboard();
_draw_threaded = GetDriverParam(parm, "no_threads") == NULL && GetDriverParam(parm, "no_thread") == NULL;
+#ifdef __ANDROID__
+ _draw_threaded = false;
+#endif
return NULL;
}
@@ -741,8 +797,10 @@ void VideoDriver_SDL::MainLoop()
bool old_ctrl_pressed = _ctrl_pressed;
+#ifndef __ANDROID__
_ctrl_pressed = !!(mod & KMOD_CTRL);
_shift_pressed = !!(mod & KMOD_SHIFT);
+#endif
/* determine which directional keys are down */
_dirkeys =
diff --git a/src/viewport.cpp b/src/viewport.cpp
index ef23f18126..8de53b1f96 100644
--- a/src/viewport.cpp
+++ b/src/viewport.cpp
@@ -1930,7 +1930,7 @@ void MarkTileDirtyByTileOutsideMap(int x, int y)
*
* @ingroup dirty
*/
-static void SetSelectionTilesDirty()
+void SetSelectionTilesDirty()
{
int x_size = _thd.size.x;
int y_size = _thd.size.y;
@@ -2164,13 +2164,28 @@ static void PlaceObject()
bool HandleViewportClicked(const ViewPort *vp, int x, int y)
{
+ if (_move_pressed) return false;
+
+ // Allow scrolling viewport with mouse even in selection mode,
+ // unless we select line or area, or perform drag&drop
+ if ((_thd.place_mode & HT_DRAG_MASK) != HT_NONE && !(_thd.place_mode & HT_SCROLL_VIEWPORT)) {
+ PlaceObject();
+ return true;
+ }
+
+ return false;
+}
+
+bool HandleViewportMouseUp(const ViewPort *vp, int x, int y)
+{
+ if (_move_pressed) return false;
+
const Vehicle *v = CheckClickOnVehicle(vp, x, y);
if (_thd.place_mode & HT_VEHICLE) {
if (v != NULL && VehicleClicked(v)) return true;
}
- /* Vehicle placement mode already handled above. */
if ((_thd.place_mode & HT_DRAG_MASK) != HT_NONE) {
PlaceObject();
return true;
@@ -2484,7 +2499,9 @@ void VpStartPlaceSizing(TileIndex tile, ViewportPlaceMethod method, ViewportDrag
}
HighLightStyle others = _thd.place_mode & ~(HT_DRAG_MASK | HT_DIR_MASK);
- if ((_thd.place_mode & HT_DRAG_MASK) == HT_RECT) {
+ if (method == VPM_SINGLE_TILE) {
+ /* Nothing to do. */
+ } else if ((_thd.place_mode & HT_DRAG_MASK) == HT_RECT) {
_thd.place_mode = HT_SPECIAL | others;
_thd.next_drawstyle = HT_RECT | others;
} else if (_thd.place_mode & (HT_RAIL | HT_LINE)) {
@@ -2521,7 +2538,7 @@ void VpSetPresizeRange(TileIndex from, TileIndex to)
if (distance > 1) ShowMeasurementTooltips(STR_MEASURE_LENGTH, 1, &distance, TCC_HOVER);
}
-static void VpStartPreSizing()
+void VpStartPreSizing()
{
_thd.selend.x = -1;
_special_mouse_mode = WSM_PRESIZE;
@@ -2963,6 +2980,11 @@ void VpSelectTilesWithMethod(int x, int y, ViewportPlaceMethod method)
int limit = 0;
switch (method) {
+ case VPM_SINGLE_TILE:
+ _thd.selstart.x = x;
+ _thd.selstart.y = y;
+ break;
+
case VPM_X_OR_Y: // drag in X or Y direction
if (abs(sy - y) < abs(sx - x)) {
y = sy;
@@ -3121,7 +3143,9 @@ EventState VpHandlePlaceSizingDrag()
* keep the selected tool, but reset it to the original mode. */
_special_mouse_mode = WSM_NONE;
HighLightStyle others = _thd.place_mode & ~(HT_DRAG_MASK | HT_DIR_MASK);
- if ((_thd.next_drawstyle & HT_DRAG_MASK) == HT_RECT) {
+ if (_thd.select_method == VPM_SINGLE_TILE) {
+ goto place_mouseup;
+ } else if ((_thd.next_drawstyle & HT_DRAG_MASK) == HT_RECT) {
_thd.place_mode = HT_RECT | others;
} else if (_thd.select_method & VPM_SIGNALDIRS) {
_thd.place_mode = HT_RECT | others;
@@ -3132,8 +3156,8 @@ EventState VpHandlePlaceSizingDrag()
}
SetTileSelectSize(1, 1);
+place_mouseup:
w->OnPlaceMouseUp(_thd.select_method, _thd.select_proc, _thd.selend, TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y));
-
return ES_HANDLED;
}
@@ -3144,6 +3168,9 @@ void SetObjectToPlaceWnd(CursorID icon, PaletteID pal, HighLightStyle mode, Wind
#include "table/animcursors.h"
+static WindowClass _last_selected_window_class;
+static WindowNumber _last_selected_window_number;
+
void SetObjectToPlace(CursorID icon, PaletteID pal, HighLightStyle mode, WindowClass window_class, WindowNumber window_num)
{
if (_thd.window_class != WC_INVALID) {
@@ -3190,7 +3217,19 @@ void SetObjectToPlace(CursorID icon, PaletteID pal, HighLightStyle mode, WindowC
void ResetObjectToPlace()
{
+ if (_thd.window_class != WC_INVALID) {
+ _last_selected_window_class = _thd.window_class;
+ _last_selected_window_number = _thd.window_number;
+ }
SetObjectToPlace(SPR_CURSOR_MOUSE, PAL_NONE, HT_NONE, WC_MAIN_WINDOW, 0);
+ MoveAllHiddenWindowsBackToScreen();
+}
+
+void ToolbarSelectLastTool()
+{
+ Window *w = FindWindowById(_last_selected_window_class, _last_selected_window_number);
+ if (w != NULL) w->SelectLastTool();
+ _last_selected_window_class = WC_INVALID;
}
Point GetViewportStationMiddle(const ViewPort *vp, const Station *st)
diff --git a/src/viewport_func.h b/src/viewport_func.h
index cbdcc5019a..a52cccc2e1 100644
--- a/src/viewport_func.h
+++ b/src/viewport_func.h
@@ -60,6 +60,7 @@ void StartSpriteCombine();
void EndSpriteCombine();
bool HandleViewportClicked(const ViewPort *vp, int x, int y);
+bool HandleViewportMouseUp(const ViewPort *vp, int x, int y);
void SetRedErrorSquare(TileIndex tile);
void SetTileSelectSize(int w, int h);
void SetTileSelectBigSize(int ox, int oy, int sx, int sy);
@@ -84,4 +85,6 @@ void MarkTileDirtyByTileOutsideMap(int x, int y);
Point GetViewportStationMiddle(const ViewPort *vp, const Station *st);
+void ToolbarSelectLastTool();
+
#endif /* VIEWPORT_FUNC_H */
diff --git a/src/viewport_gui.cpp b/src/viewport_gui.cpp
index 90b0e1468f..df2f21b364 100644
--- a/src/viewport_gui.cpp
+++ b/src/viewport_gui.cpp
@@ -34,7 +34,7 @@ static const NWidgetPart _nested_extra_view_port_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_GREY),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY),
- NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_EV_VIEWPORT), SetPadding(2, 2, 2, 2), SetResize(1, 1), SetFill(1, 1),
+ NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_EV_VIEWPORT), SetSizingType(NWST_VIEWPORT), SetPadding(2, 2, 2, 2), SetResize(1, 1), SetFill(1, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_EV_ZOOM_IN), SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
diff --git a/src/viewport_type.h b/src/viewport_type.h
index 800c8b4952..3566c4144b 100644
--- a/src/viewport_type.h
+++ b/src/viewport_type.h
@@ -84,6 +84,7 @@ enum ViewportPlaceMethod {
VPM_FIX_VERTICAL = 6, ///< drag only in vertical direction
VPM_X_LIMITED = 7, ///< Drag only in X axis with limited size
VPM_Y_LIMITED = 8, ///< Drag only in Y axis with limited size
+ VPM_SINGLE_TILE = 9, ///< Drag around the screen, selecting only the end tile
VPM_RAILDIRS = 0x40, ///< all rail directions
VPM_SIGNALDIRS = 0x80, ///< similar to VMP_RAILDIRS, but with different cursor
};
@@ -120,6 +121,9 @@ enum ViewportDragDropSelectionProcess {
DDSP_BUILD_TRUCKSTOP, ///< Road stop placement (trucks)
DDSP_REMOVE_BUSSTOP, ///< Road stop removal (buses)
DDSP_REMOVE_TRUCKSTOP, ///< Road stop removal (trucks)
+
+ /* Single tile dragging */
+ DDSP_SINGLE_TILE, ///< Single tile actions (build industry, town, etc.)
};
#endif /* VIEWPORT_TYPE_H */
diff --git a/src/widget.cpp b/src/widget.cpp
index 471840a419..810476e104 100644
--- a/src/widget.cpp
+++ b/src/widget.cpp
@@ -47,6 +47,11 @@ static Point HandleScrollbarHittest(const Scrollbar *sb, int top, int bottom, bo
}
top += button_size; // top points to just below the up-button
bottom -= button_size; // bottom points to top of the down-button
+ bool wide_enough = false;
+ if (bottom > top + button_size * 2) {
+ bottom -= button_size; // Slider should be no smaller than a regular button, reserve some size from bottom
+ wide_enough = true;
+ }
int height = (bottom - top);
int pos = sb->GetPosition();
@@ -57,10 +62,11 @@ static Point HandleScrollbarHittest(const Scrollbar *sb, int top, int bottom, bo
if (cap > count) cap = count;
if (count != 0) bottom -= (count - pos - cap) * height / count;
+ if (wide_enough) bottom += button_size;
Point pt;
if (horizontal && _current_text_dir == TD_RTL) {
- pt.x = rev_base - bottom;
+ pt.x = rev_base - bottom - button_size;
pt.y = rev_base - top;
} else {
pt.x = top;
@@ -96,7 +102,7 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in
/* Pressing the upper button? */
SetBit(sb->disp_flags, NDB_SCROLLBAR_UP);
if (_scroller_click_timeout <= 1) {
- _scroller_click_timeout = 3;
+ _scroller_click_timeout = SCROLLER_CLICK_DELAY;
sb->UpdatePosition(rtl ? 1 : -1);
}
w->scrolling_scrollbar = sb->index;
@@ -105,7 +111,7 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in
SetBit(sb->disp_flags, NDB_SCROLLBAR_DOWN);
if (_scroller_click_timeout <= 1) {
- _scroller_click_timeout = 3;
+ _scroller_click_timeout = SCROLLER_CLICK_DELAY;
sb->UpdatePosition(rtl ? -1 : 1);
}
w->scrolling_scrollbar = sb->index;
@@ -119,6 +125,8 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in
} else {
_scrollbar_start_pos = pt.x - mi - button_size;
_scrollbar_size = ma - mi - button_size * 2;
+ if (_scrollbar_size > button_size * 2)
+ _scrollbar_size -= button_size;
w->scrolling_scrollbar = sb->index;
_cursorpos_drag_start = _cursor.pos;
}
@@ -221,7 +229,8 @@ static inline void DrawImageButtons(const Rect &r, WidgetType type, Colours colo
DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
if ((type & WWT_MASK) == WWT_IMGBTN_2 && clicked) img++; // Show different image when clicked for #WWT_IMGBTN_2.
- DrawSprite(img, PAL_NONE, r.left + WD_IMGBTN_LEFT + clicked, r.top + WD_IMGBTN_TOP + clicked);
+ Dimension d2 = GetSpriteSize(img);
+ DrawSprite(img, PAL_NONE, Center(r.left + clicked, r.right - r.left, d2.width), Center(r.top + clicked, r.bottom - r.top, d2.height));
}
/**
@@ -376,12 +385,13 @@ static inline void DrawHorizontalScrollbar(const Rect &r, Colours colour, bool l
{
int centre = (r.bottom - r.top) / 2;
int width = NWidgetScrollbar::GetHorizontalDimension().width;
+ int height = NWidgetScrollbar::GetVerticalDimension().height;
DrawFrameRect(r.left, r.top, r.left + width - 1, r.bottom, colour, left_clicked ? FR_LOWERED : FR_NONE);
- DrawSprite(SPR_ARROW_LEFT, PAL_NONE, r.left + 1 + left_clicked, r.top + 1 + left_clicked);
+ DrawSprite(SPR_ARROW_LEFT, PAL_NONE, r.left + 1 + left_clicked, r.top + height / 2 + 1 + left_clicked);
DrawFrameRect(r.right - (width - 1), r.top, r.right, r.bottom, colour, right_clicked ? FR_LOWERED : FR_NONE);
- DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - (width - 2) + right_clicked, r.top + 1 + right_clicked);
+ DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - (width - 2) + right_clicked, r.top + height / 2 + 1 + right_clicked);
int c1 = _colour_gradient[colour & 0xF][3];
int c2 = _colour_gradient[colour & 0xF][7];
@@ -451,54 +461,6 @@ static inline void DrawFrame(const Rect &r, Colours colour, StringID str)
GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2);
}
-/**
- * Draw a shade box.
- * @param r Rectangle of the box.
- * @param colour Colour of the shade box.
- * @param clicked Box is lowered.
- */
-static inline void DrawShadeBox(const Rect &r, Colours colour, bool clicked)
-{
- DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawSprite((clicked) ? SPR_WINDOW_SHADE : SPR_WINDOW_UNSHADE, PAL_NONE, r.left + WD_SHADEBOX_LEFT + clicked, r.top + WD_SHADEBOX_TOP + clicked);
-}
-
-/**
- * Draw a sticky box.
- * @param r Rectangle of the box.
- * @param colour Colour of the sticky box.
- * @param clicked Box is lowered.
- */
-static inline void DrawStickyBox(const Rect &r, Colours colour, bool clicked)
-{
- DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawSprite((clicked) ? SPR_PIN_UP : SPR_PIN_DOWN, PAL_NONE, r.left + WD_STICKYBOX_LEFT + clicked, r.top + WD_STICKYBOX_TOP + clicked);
-}
-
-/**
- * Draw a defsize box.
- * @param r Rectangle of the box.
- * @param colour Colour of the defsize box.
- * @param clicked Box is lowered.
- */
-static inline void DrawDefSizeBox(const Rect &r, Colours colour, bool clicked)
-{
- DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawSprite(SPR_WINDOW_DEFSIZE, PAL_NONE, r.left + WD_DEFSIZEBOX_LEFT + clicked, r.top + WD_DEFSIZEBOX_TOP + clicked);
-}
-
-/**
- * Draw a NewGRF debug box.
- * @param r Rectangle of the box.
- * @param colour Colour of the debug box.
- * @param clicked Box is lowered.
- */
-static inline void DrawDebugBox(const Rect &r, Colours colour, bool clicked)
-{
- DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
- DrawSprite(SPR_WINDOW_DEBUG, PAL_NONE, r.left + WD_DEBUGBOX_LEFT + clicked, r.top + WD_DEBUGBOX_TOP + clicked);
-}
-
/**
* Draw a resize box.
* @param r Rectangle of the box.
@@ -509,12 +471,13 @@ static inline void DrawDebugBox(const Rect &r, Colours colour, bool clicked)
static inline void DrawResizeBox(const Rect &r, Colours colour, bool at_left, bool clicked)
{
DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
+ Dimension d = GetSpriteSize(at_left ? SPR_WINDOW_RESIZE_LEFT : SPR_WINDOW_RESIZE_RIGHT);
if (at_left) {
- DrawSprite(SPR_WINDOW_RESIZE_LEFT, PAL_NONE, r.left + WD_RESIZEBOX_RIGHT + clicked,
- r.bottom - WD_RESIZEBOX_BOTTOM - GetSpriteSize(SPR_WINDOW_RESIZE_LEFT).height + clicked);
+ DrawSprite(SPR_WINDOW_RESIZE_LEFT, PAL_NONE, r.left + WD_RESIZEBOX_LEFT + clicked,
+ r.bottom - WD_RESIZEBOX_BOTTOM - d.height + clicked);
} else {
- DrawSprite(SPR_WINDOW_RESIZE_RIGHT, PAL_NONE, r.left + WD_RESIZEBOX_LEFT + clicked,
- r.bottom - WD_RESIZEBOX_BOTTOM - GetSpriteSize(SPR_WINDOW_RESIZE_RIGHT).height + clicked);
+ DrawSprite(SPR_WINDOW_RESIZE_RIGHT, PAL_NONE, r.right - WD_RESIZEBOX_RIGHT - d.width + clicked,
+ r.bottom - WD_RESIZEBOX_BOTTOM - d.height + clicked);
}
}
@@ -568,8 +531,8 @@ static inline void DrawButtonDropdown(const Rect &r, Colours colour, bool clicke
{
int text_offset = max(0, ((int)(r.bottom - r.top + 1) - FONT_HEIGHT_NORMAL) / 2); // Offset for rendering the text vertically centered
- int dd_width = NWidgetLeaf::dropdown_dimension.width;
- int dd_height = NWidgetLeaf::dropdown_dimension.height;
+ int dd_width = GetMinSizing(NWST_STEP, NWidgetLeaf::dropdown_dimension.width);
+ int dd_height = GetMinSizing(NWST_STEP, NWidgetLeaf::dropdown_dimension.height);
int image_offset = max(0, ((int)(r.bottom - r.top + 1) - dd_height) / 2);
if (_current_text_dir == TD_LTR) {
@@ -804,6 +767,7 @@ NWidgetBase *NWidgetBase::GetWidgetOfType(WidgetType tp)
*/
NWidgetResizeBase::NWidgetResizeBase(WidgetType tp, uint fill_x, uint fill_y) : NWidgetBase(tp)
{
+ this->sizing_type = NWST_NONE;
this->fill_x = fill_x;
this->fill_y = fill_y;
}
@@ -817,6 +781,27 @@ void NWidgetResizeBase::SetMinimalSize(uint min_x, uint min_y)
{
this->min_x = max(this->min_x, min_x);
this->min_y = max(this->min_y, min_y);
+ uint min_size = 0;
+ switch (this->sizing_type) {
+ case NWST_NONE:
+ case NWST_OVERRIDE:
+ min_size = 0;
+ break;
+ case NWST_BUTTON:
+ min_size = _settings_client.gui.min_button;
+ break;
+ case NWST_STEP:
+ min_size = _settings_client.gui.min_step;
+ break;
+ case NWST_VIEWPORT:
+ min_size = 3 * _settings_client.gui.min_button;
+ break;
+ default: NOT_REACHED();
+ }
+ min_size = RescaleFrom854x480(min_size);
+
+ this->min_x = max(min_x, min_size);
+ this->min_y = max(min_y, min_size);
}
/**
@@ -868,6 +853,7 @@ void NWidgetResizeBase::AssignSizePosition(SizingType sizing, uint x, uint y, ui
*/
NWidgetCore::NWidgetCore(WidgetType tp, Colours colour, uint fill_x, uint fill_y, uint32 widget_data, StringID tool_tip) : NWidgetResizeBase(tp, fill_x, fill_y)
{
+ this->sizing_type = NWST_NONE;
this->colour = colour;
this->index = -1;
this->widget_data = widget_data;
@@ -1988,6 +1974,7 @@ void Scrollbar::SetCapacityFromWidget(Window *w, int widget, int padding)
NWidgetScrollbar::NWidgetScrollbar(WidgetType tp, Colours colour, int index) : NWidgetCore(tp, colour, 1, 1, 0x0, STR_NULL), Scrollbar(tp != NWID_HSCROLLBAR)
{
assert(tp == NWID_HSCROLLBAR || tp == NWID_VSCROLLBAR);
+ this->sizing_type = NWST_STEP;
this->SetIndex(index);
}
@@ -2062,7 +2049,9 @@ void NWidgetScrollbar::Draw(const Window *w)
if (vertical_dimension.width == 0) {
vertical_dimension = maxdim(GetSpriteSize(SPR_ARROW_UP), GetSpriteSize(SPR_ARROW_DOWN));
vertical_dimension.width += extra.width;
+ vertical_dimension.width = GetMinSizing(NWST_STEP, vertical_dimension.width);
vertical_dimension.height += extra.height;
+ vertical_dimension.height = GetMinSizing(NWST_STEP, vertical_dimension.height);
}
return vertical_dimension;
}
@@ -2073,9 +2062,14 @@ void NWidgetScrollbar::Draw(const Window *w)
if (horizontal_dimension.width == 0) {
horizontal_dimension = maxdim(GetSpriteSize(SPR_ARROW_LEFT), GetSpriteSize(SPR_ARROW_RIGHT));
horizontal_dimension.width += extra.width;
+ horizontal_dimension.width = GetMinSizing(NWST_STEP, horizontal_dimension.width);
horizontal_dimension.height += extra.height;
+ horizontal_dimension.height = GetMinSizing(NWST_STEP, horizontal_dimension.height);
}
return horizontal_dimension;
+ SETTING_BUTTON_HEIGHT = max(GetMinSizing(NWST_STEP) - 10, 10);
+ SETTING_BUTTON_WIDTH = 2 * SETTING_BUTTON_HEIGHT;
+
}
Dimension NWidgetScrollbar::vertical_dimension = {0, 0};
@@ -2111,10 +2105,44 @@ Dimension NWidgetLeaf::dropdown_dimension = {0, 0};
*/
NWidgetLeaf::NWidgetLeaf(WidgetType tp, Colours colour, int index, uint32 data, StringID tip) : NWidgetCore(tp, colour, 1, 1, data, tip)
{
+ assert(this->sizing_type < NWST_END);
assert(index >= 0 || tp == WWT_LABEL || tp == WWT_TEXT || tp == WWT_CAPTION || tp == WWT_RESIZEBOX || tp == WWT_SHADEBOX || tp == WWT_DEFSIZEBOX || tp == WWT_DEBUGBOX || tp == WWT_STICKYBOX || tp == WWT_CLOSEBOX);
if (index >= 0) this->SetIndex(index);
this->min_x = 0;
this->min_y = 0;
+
+ if (this->sizing_type == NWST_NONE) {
+ switch (tp) {
+ case WWT_PUSHBTN:
+ case WWT_IMGBTN:
+ case WWT_PUSHIMGBTN:
+ case WWT_IMGBTN_2:
+ case WWT_TEXTBTN:
+ case WWT_PUSHTXTBTN:
+ case WWT_TEXTBTN_2:
+ case WWT_PUSHARROWBTN:
+ case WWT_EDITBOX:
+ case WWT_CAPTION:
+ case WWT_STICKYBOX:
+ case WWT_SHADEBOX:
+ case WWT_DEBUGBOX:
+ case WWT_DEFSIZEBOX:
+ case WWT_RESIZEBOX:
+ case WWT_CLOSEBOX:
+ this->sizing_type = NWST_BUTTON;
+ break;
+ case NWID_PUSHBUTTON_DROPDOWN:
+ case NWID_BUTTON_DROPDOWN:
+ case WWT_DROPDOWN:
+ case WWT_ARROWBTN:
+ case WWT_PUSHARROWBTN:
+ this->sizing_type = NWST_STEP;
+ break;
+ default:
+ this->sizing_type = NWST_OVERRIDE;
+ }
+ }
+
this->SetResize(0, 0);
switch (tp) {
@@ -2352,7 +2380,7 @@ void NWidgetLeaf::SetupSmallestSize(Window *w, bool init_array)
padding = &extra;
if (this->index >= 0) w->SetStringParameters(this->index);
Dimension d2 = GetStringBoundingBox(this->widget_data);
- d2.width += extra.width;
+ d2.width += extra.width + GetMinSizing(NWST_STEP, 11U);
d2.height += extra.height;
size = maxdim(size, d2);
break;
@@ -2467,21 +2495,23 @@ void NWidgetLeaf::Draw(const Window *w)
case WWT_SHADEBOX:
assert(this->widget_data == 0);
- DrawShadeBox(r, this->colour, w->IsShaded());
+ DrawImageButtons(r, WWT_SHADEBOX, this->colour, w->IsShaded(), w->IsShaded() ? SPR_WINDOW_SHADE : SPR_WINDOW_UNSHADE);
break;
case WWT_DEBUGBOX:
- DrawDebugBox(r, this->colour, clicked);
+ DrawImageButtons(r, WWT_DEBUGBOX, this->colour, clicked, SPR_WINDOW_DEBUG);
break;
- case WWT_STICKYBOX:
+ case WWT_STICKYBOX: {
assert(this->widget_data == 0);
- DrawStickyBox(r, this->colour, !!(w->flags & WF_STICKY));
+ bool clicked = !!(w->flags & WF_STICKY);
+ DrawImageButtons(r, WWT_STICKYBOX, this->colour, clicked, clicked ? SPR_PIN_DOWN : SPR_PIN_UP);
break;
+ }
case WWT_DEFSIZEBOX:
assert(this->widget_data == 0);
- DrawDefSizeBox(r, this->colour, clicked);
+ DrawImageButtons(r, WWT_DEFSIZEBOX, this->colour, clicked, SPR_WINDOW_DEFSIZE);
break;
case WWT_RESIZEBOX:
@@ -2523,11 +2553,12 @@ void NWidgetLeaf::Draw(const Window *w)
*/
bool NWidgetLeaf::ButtonHit(const Point &pt)
{
+ uint button_size = GetMinSizing(NWST_STEP, 12);
if (_current_text_dir == TD_LTR) {
- int button_width = this->pos_x + this->current_x - 12;
+ int button_width = this->pos_x + this->current_x - button_size;
return pt.x < button_width;
} else {
- int button_left = this->pos_x + 12;
+ int button_left = this->pos_x + button_size;
return pt.x >= button_left;
}
}
@@ -2620,6 +2651,16 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest,
break;
}
+ case WPT_SIZINGTYPE: {
+ NWidgetResizeBase *nwrb = dynamic_cast(*dest);
+ if (nwrb != NULL) {
+ assert(parts->u.sizing_type < NWST_END);
+ nwrb->sizing_type = parts->u.sizing_type;
+ nwrb->SetMinimalSize(0, 0);
+ }
+ break;
+ }
+
case WPT_MINSIZE: {
NWidgetResizeBase *nwrb = dynamic_cast(*dest);
if (nwrb != NULL) {
@@ -2876,6 +2917,7 @@ NWidgetBase *MakeCompanyButtonRows(int *biggest_index, int widget_first, int wid
}
NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, widnum);
+ panel->sizing_type = NWST_STEP;
panel->SetMinimalSize(sprite_size.width, sprite_size.height);
panel->SetFill(1, 1);
panel->SetResize(1, 0);
@@ -2896,3 +2938,35 @@ NWidgetBase *MakeCompanyButtonRows(int *biggest_index, int widget_first, int wid
if (hor != NULL) vert->Add(hor);
return vert;
}
+
+/**
+ * Return the minimal automatic size for a widget.
+ * @param type The automatic sizing type to use.
+ * @param min_1 Minimal passed value.
+ * @return At least the passed value, or the minimal size for the associated sizing type.
+ */
+uint GetMinSizing(NWidSizingType type, uint min_1)
+{
+ uint min_sizing;
+ switch (type) {
+ case NWST_NONE:
+ case NWST_OVERRIDE:
+ return min_1;
+ case NWST_BUTTON:
+ min_sizing = _settings_client.gui.min_button;
+ break;
+ case NWST_STEP:
+ min_sizing = _settings_client.gui.min_step;
+ break;
+ case NWST_KEYBOARD:
+ min_sizing = 2 * _settings_client.gui.min_button;
+ break;
+ case NWST_WINDOW_LENGTH:
+ min_sizing = 8 * _settings_client.gui.min_button;
+ break;
+ default: NOT_REACHED();
+ }
+ min_sizing = RescaleFrom854x480(min_sizing);
+
+ return max(min_sizing, min_1);
+}
diff --git a/src/widget_type.h b/src/widget_type.h
index 39efbb4637..49a75a955d 100644
--- a/src/widget_type.h
+++ b/src/widget_type.h
@@ -40,6 +40,20 @@ enum ArrowWidgetValues {
AWV_RIGHT, ///< Force the arrow to the right
};
+/** Values for different minimal sizing of widgets. */
+enum NWidSizingType {
+ NWST_NONE, ///< No sizing type is yet defined.
+ ///< Most buttons and scrollbars are initialized with this value.
+ ///< Later, they are automatically set to NWST_BUTTON or NWST_STEP.
+ NWST_BUTTON, ///< Size will be set at least _settings_client.gui.min_button.
+ NWST_STEP, ///< Size will be set at least _settings_client.gui.min_step (scrollbars and dropdowns).
+ NWST_KEYBOARD, ///< Size for keyboard keys.
+ NWST_WINDOW_LENGTH, ///< Width for command errors, message windows and statusbar middle part.
+ NWST_VIEWPORT, ///< Sizing type for viewports.
+ NWST_OVERRIDE, ///< Avoid widgets to use automatic minimal sizing.
+ NWST_END
+};
+
/**
* Window widget types, nested widget types, and nested widget part types.
*/
@@ -85,6 +99,7 @@ enum WidgetType {
/* Nested widget part types. */
WPT_RESIZE, ///< Widget part for specifying resizing.
+ WPT_SIZINGTYPE, ///< Widget part for specifying sizing mode.
WPT_MINSIZE, ///< Widget part for specifying minimal size.
WPT_MINTEXTLINES, ///< Widget part for specifying minimal number of lines of text.
WPT_FILL, ///< Widget part for specifying fill.
@@ -160,11 +175,12 @@ public:
virtual void Draw(const Window *w) = 0;
virtual void SetDirty(const Window *w) const;
- WidgetType type; ///< Type of the widget / nested widget.
- uint fill_x; ///< Horizontal fill stepsize (from initial size, \c 0 means not resizable).
- uint fill_y; ///< Vertical fill stepsize (from initial size, \c 0 means not resizable).
- uint resize_x; ///< Horizontal resize step (\c 0 means not resizable).
- uint resize_y; ///< Vertical resize step (\c 0 means not resizable).
+ WidgetType type; ///< Type of the widget / nested widget.
+ NWidSizingType sizing_type; ///< Type for deciding minimal sizes of the widget.
+ uint fill_x; ///< Horizontal fill stepsize (from initial size, \c 0 means not resizable).
+ uint fill_y; ///< Vertical fill stepsize (from initial size, \c 0 means not resizable).
+ uint resize_x; ///< Horizontal resize step (\c 0 means not resizable).
+ uint resize_y; ///< Vertical resize step (\c 0 means not resizable).
/* Size of the widget in the smallest window possible.
* Computed by #SetupSmallestSize() followed by #AssignSizePosition().
*/
@@ -757,6 +773,7 @@ public:
static void InvalidateDimensionCache();
static Dimension GetVerticalDimension();
static Dimension GetHorizontalDimension();
+ static void ResetAllWidgetMinSizes(); ///< Called when screen size or font size or button size changes
private:
static Dimension vertical_dimension; ///< Cached size of vertical scrollbar button.
@@ -918,6 +935,7 @@ struct NWidgetPart {
NWidgetPartTextLines text_lines; ///< Part with text line data.
NWidgetFunctionType *func_ptr; ///< Part with a function call.
NWidContainerFlags cont_flags; ///< Part with container flags.
+ NWidSizingType sizing_type; ///< Part with sizing type.
} u;
};
@@ -938,6 +956,23 @@ static inline NWidgetPart SetResize(int16 dx, int16 dy)
return part;
}
+/**
+ * Widget part function for setting the automatic minimal size.
+ * @param type How to decide the minimal size of the widget.
+ * @ingroup NestedWidgetParts
+ */
+static inline NWidgetPart SetSizingType(NWidSizingType type)
+{
+ NWidgetPart part;
+
+ part.type = WPT_SIZINGTYPE;
+ part.u.sizing_type = type;
+
+ return part;
+}
+
+uint GetMinSizing(NWidSizingType type, uint min_1 = 0);
+
/**
* Widget part function for setting the minimal size.
* @param x Horizontal minimal size.
diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp
index aecfc6b2f0..a7c248d494 100644
--- a/src/widgets/dropdown.cpp
+++ b/src/widgets/dropdown.cpp
@@ -40,7 +40,7 @@ uint DropDownListStringItem::Width() const
void DropDownListStringItem::Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
{
- DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, this->String(), sel ? TC_WHITE : TC_BLACK);
+ DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, Center(top, bottom - top), this->String(), sel ? TC_WHITE : TC_BLACK);
}
/**
@@ -96,6 +96,7 @@ struct DropdownWindow : Window {
byte click_delay; ///< Timer to delay selection.
bool drag_mode;
bool instant_close; ///< Close the window when the mouse button is raised.
+ bool left_button_state; ///< Close the window when the mouse button is clicked outside the window.
int scrolling; ///< If non-zero, auto-scroll the item list (one time).
Point position; ///< Position of the topleft corner of the window.
Scrollbar *vscroll;
@@ -154,8 +155,9 @@ struct DropdownWindow : Window {
this->list = list;
this->selected_index = selected;
this->click_delay = 0;
- this->drag_mode = true;
+ this->drag_mode = instant_close;
this->instant_close = instant_close;
+ this->left_button_state = _left_button_down;
}
~DropdownWindow()
@@ -260,8 +262,11 @@ struct DropdownWindow : Window {
if (this->scrolling != 0) {
int pos = this->vscroll->GetPosition();
- this->vscroll->UpdatePosition(this->scrolling);
- this->scrolling = 0;
+ if (_scroller_click_timeout <= 1) {
+ _scroller_click_timeout = SCROLLER_CLICK_DELAY;
+ this->vscroll->UpdatePosition(this->scrolling);
+ this->scrolling = 0;
+ }
if (pos != this->vscroll->GetPosition()) {
this->SetDirty();
@@ -317,6 +322,16 @@ struct DropdownWindow : Window {
this->SetDirty();
}
}
+
+ // Close dropdown if user clicks outside of it
+ if (_left_button_down && !this->left_button_state && (
+ _cursor.pos.x < this->left || _cursor.pos.x > this->left + this->width ||
+ _cursor.pos.y < this->top || _cursor.pos.y > this->top + this->height)) {
+ delete this;
+ return;
+ } else {
+ this->left_button_state = _left_button_down;
+ }
}
};
@@ -347,6 +362,14 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b
/* Longest item in the list, if auto_width is enabled */
uint max_item_width = 0;
+ if (auto_width) {
+ /* Find the longest item in the list */
+ for (const DropDownListItem * const *it = list->Begin(); it != list->End(); ++it) {
+ const DropDownListItem *item = *it;
+ max_item_width = max(max_item_width, item->Width() + 5);
+ }
+ }
+
/* Total length of list */
int height = 0;
@@ -360,11 +383,14 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b
int screen_bottom = GetMainViewBottom();
bool scroll = false;
- /* Check if the dropdown will fully fit below the widget */
- if (top + height + 4 >= screen_bottom) {
- /* If not, check if it will fit above the widget */
- if (w->top + wi_rect.top - height > GetMainViewTop()) {
- top = w->top + wi_rect.top - height - 4;
+ enum { DISPLAY_BORDER = 20, TOP_BORDER = 4 };
+
+ /* Check if the dropdown will fully fit below the widget. */
+ if (top + height + DISPLAY_BORDER >= screen_bottom) {
+ /* If not, check if it will fit above the widget. */
+ int screen_top = GetMainViewTop();
+ if (w->top + wi_rect.top - TOP_BORDER > screen_top + height) {
+ top = w->top + wi_rect.top - height - TOP_BORDER;
} else {
/* ... and lastly if it won't, enable the scroll bar and fit the
* list in below the widget */
@@ -372,9 +398,30 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b
int rows = (screen_bottom - 4 - top) / avg_height;
height = rows * avg_height;
scroll = true;
- /* Add space for the scroll bar if we automatically determined
- * the width of the list. */
+
+ /* ... and choose whether to put the list above or below the widget. */
+ bool put_above = false;
+ int available_height = screen_bottom - w->top - wi_rect.bottom;
+ if (w->top + wi_rect.top - screen_top > available_height) {
+ // Put it above.
+ available_height = w->top + wi_rect.top - screen_top - DISPLAY_BORDER - TOP_BORDER;
+ put_above = true;
+ }
+
+ /* Check at least there is space for one item. */
+ assert(available_height >= avg_height);
+
+ /* And lastly, fit the list,... */
+ int rows = available_height / avg_height;
+ height = rows * avg_height;
+
+ /* ... add space for the scrollbar,... */
max_item_width += NWidgetScrollbar::GetVerticalDimension().width;
+
+ /* ... and set the top position if needed. */
+ if (put_above) {
+ top = w->top + wi_rect.top - height - TOP_BORDER;
+ }
}
}
diff --git a/src/widgets/dropdown_type.h b/src/widgets/dropdown_type.h
index b65d4557bd..4c330117e7 100644
--- a/src/widgets/dropdown_type.h
+++ b/src/widgets/dropdown_type.h
@@ -13,6 +13,7 @@
#define WIDGETS_DROPDOWN_TYPE_H
#include "../window_type.h"
+#include "../widget_type.h"
#include "../gfx_func.h"
#include "../core/smallvec_type.hpp"
#include "table/strings.h"
@@ -30,7 +31,7 @@ public:
virtual ~DropDownListItem() {}
virtual bool Selectable() const { return false; }
- virtual uint Height(uint width) const { return FONT_HEIGHT_NORMAL; }
+ virtual uint Height(uint width) const { return GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL); }
virtual uint Width() const { return 0; }
virtual void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const;
};
diff --git a/src/widgets/fios_widget.h b/src/widgets/fios_widget.h
index c94655d767..3f4b49fbee 100644
--- a/src/widgets/fios_widget.h
+++ b/src/widgets/fios_widget.h
@@ -31,6 +31,8 @@ enum SaveLoadWidgets {
WID_SL_NEWGRF_INFO, ///< Button to open NewGgrf configuration.
WID_SL_LOAD_BUTTON, ///< Button to load game/scenario.
WID_SL_MISSING_NEWGRFS, ///< Button to find missing NewGRFs online.
+ WID_SL_SAVE_NETWORK_BUTTON, ///< Toggle button to back up savegame to the network storage.
+ WID_SL_LOAD_NETWORK_BUTTON, ///< Button to load game from the network storage.
};
#endif /* WIDGETS_FIOS_WIDGET_H */
diff --git a/src/widgets/intro_widget.h b/src/widgets/intro_widget.h
index 6a67fe64ca..7447fbdb5f 100644
--- a/src/widgets/intro_widget.h
+++ b/src/widgets/intro_widget.h
@@ -32,6 +32,7 @@ enum SelectGameIntroWidgets {
WID_SGI_GRF_SETTINGS, ///< NewGRF button.
WID_SGI_CONTENT_DOWNLOAD, ///< Content Download button.
WID_SGI_AI_SETTINGS, ///< AI button.
+ WID_SGI_TUTORIAL, ///< Tutorial button.
WID_SGI_EXIT, ///< Exit button.
};
diff --git a/src/widgets/music_widget.h b/src/widgets/music_widget.h
index 3a99bc6150..ebd7ea057d 100644
--- a/src/widgets/music_widget.h
+++ b/src/widgets/music_widget.h
@@ -14,16 +14,18 @@
/** Widgets of the #MusicTrackSelectionWindow class. */
enum MusicTrackSelectionWidgets {
- WID_MTS_LIST_LEFT, ///< Left button.
- WID_MTS_PLAYLIST, ///< Playlist.
- WID_MTS_LIST_RIGHT, ///< Right button.
- WID_MTS_ALL, ///< All button.
- WID_MTS_OLD, ///< Old button.
- WID_MTS_NEW, ///< New button.
- WID_MTS_EZY, ///< Ezy button.
- WID_MTS_CUSTOM1, ///< Custom1 button.
- WID_MTS_CUSTOM2, ///< Custom2 button.
- WID_MTS_CLEAR, ///< Clear button.
+ WID_MTS_LIST_LEFT, ///< Left list.
+ WID_MTS_LEFT_SCROLLBAR, ///< Scrollbar of left list.
+ WID_MTS_PLAYLIST, ///< Playlist name.
+ WID_MTS_LIST_RIGHT, ///< Right list.
+ WID_MTS_RIGHT_SCROLLBAR, ///< Scrollbar of right list.
+ WID_MTS_ALL, ///< All button.
+ WID_MTS_OLD, ///< Old button.
+ WID_MTS_NEW, ///< New button.
+ WID_MTS_EZY, ///< Ezy button.
+ WID_MTS_CUSTOM1, ///< Custom1 button.
+ WID_MTS_CUSTOM2, ///< Custom2 button.
+ WID_MTS_CLEAR, ///< Clear button.
};
/** Widgets of the #MusicWindow class. */
diff --git a/src/widgets/settings_widget.h b/src/widgets/settings_widget.h
index 661f788cd7..e89fb47288 100644
--- a/src/widgets/settings_widget.h
+++ b/src/widgets/settings_widget.h
@@ -24,6 +24,9 @@ enum GameOptionsWidgets {
WID_GO_RESOLUTION_DROPDOWN, ///< Dropdown for the resolution.
WID_GO_FULLSCREEN_BUTTON, ///< Toggle fullscreen.
WID_GO_GUI_ZOOM_DROPDOWN, ///< Dropdown for the GUI zoom level.
+ WID_GO_BUTTON_SIZE_DROPDOWN, ///< Size of in-game UI elements, such as buttons.
+ WID_GO_TEXT_SIZE_DROPDOWN, ///< Size of medium font, sizes of other fonts are derived from it.
+ WID_GO_VERTICAL_TOOLBAR, ///< Enable vertical toolbar.
WID_GO_BASE_GRF_DROPDOWN, ///< Use to select a base GRF.
WID_GO_BASE_GRF_STATUS, ///< Info about missing files etc.
WID_GO_BASE_GRF_TEXTFILE, ///< Open base GRF readme, changelog (+1) or license (+2).
diff --git a/src/widgets/smallmap_widget.h b/src/widgets/smallmap_widget.h
index 0b1daea03f..753dcb74e3 100644
--- a/src/widgets/smallmap_widget.h
+++ b/src/widgets/smallmap_widget.h
@@ -34,6 +34,7 @@ enum SmallMapWidgets {
WID_SM_ENABLE_ALL, ///< Button to enable display of all legend entries.
WID_SM_DISABLE_ALL, ///< Button to disable display of all legend entries.
WID_SM_SHOW_HEIGHT, ///< Show heightmap toggle button.
+ WID_SM_SHOW_LEGEND, ///< Show/hide legend area.
};
#endif /* WIDGETS_SMALLMAP_WIDGET_H */
diff --git a/src/widgets/toolbar_widget.h b/src/widgets/toolbar_widget.h
index 6ede3ad634..172564b883 100644
--- a/src/widgets/toolbar_widget.h
+++ b/src/widgets/toolbar_widget.h
@@ -45,6 +45,9 @@ enum ToolbarNormalWidgets {
WID_TN_MESSAGES, ///< Messages menu.
WID_TN_HELP, ///< Help menu.
WID_TN_SWITCH_BAR, ///< Only available when toolbar has been split to switch between different subsets.
+ WID_TN_CTRL, ///< Press CTRL.
+ WID_TN_SHIFT, ///< Press SHIFT.
+ WID_TN_DELETE, ///< Press DELETE.
WID_TN_END, ///< Helper for knowing the amount of widgets.
};
diff --git a/src/window.cpp b/src/window.cpp
index 18e8f35881..80cbae413d 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -36,6 +36,14 @@
#include "error.h"
#include "game/game.hpp"
#include "video/video_driver.hpp"
+#include "settings_gui.h"
+#include "fontcache.h"
+#include "error.h"
+#include "station_base.h"
+#include "waypoint_base.h"
+#include "command_func.h"
+
+#include "table/strings.h"
#include "safeguards.h"
@@ -74,6 +82,7 @@ byte _scroller_click_timeout = 0;
bool _scrolling_viewport; ///< A viewport is being scrolled with the mouse.
bool _mouse_hovering; ///< The mouse is hovering over the same point.
+static bool _left_button_dragged;
SpecialMouseMode _special_mouse_mode; ///< Mode of the mouse.
@@ -1244,6 +1253,7 @@ static inline bool IsVitalWindow(const Window *w)
{
switch (w->window_class) {
case WC_MAIN_TOOLBAR:
+ case WC_MAIN_TOOLBAR_RIGHT:
case WC_STATUS_BAR:
case WC_NEWS_WINDOW:
case WC_SEND_NETWORK_MSG:
@@ -1282,6 +1292,7 @@ static uint GetWindowZPriority(const Window *w)
++z_priority;
case WC_MAIN_TOOLBAR:
+ case WC_MAIN_TOOLBAR_RIGHT:
case WC_STATUS_BAR:
++z_priority;
@@ -1481,6 +1492,7 @@ void Window::FindWindowPlacementAndResize(int def_width, int def_height)
{
def_width = max(def_width, this->width); // Don't allow default size to be smaller than smallest size
def_height = max(def_height, this->height);
+ bool vertical_toolbar = _settings_client.gui.vertical_toolbar && _game_mode != GM_EDITOR;
/* Try to make windows smaller when our window is too small.
* w->(width|height) is normally the same as min_(width|height),
* but this way the GUIs can be made a little more dynamic;
@@ -1492,10 +1504,13 @@ void Window::FindWindowPlacementAndResize(int def_width, int def_height)
const Window *wt = FindWindowById(WC_STATUS_BAR, 0);
if (wt != NULL) free_height -= wt->height;
wt = FindWindowById(WC_MAIN_TOOLBAR, 0);
- if (wt != NULL) free_height -= wt->height;
+ if (wt != NULL && !vertical_toolbar) free_height -= wt->height;
int enlarge_x = max(min(def_width - this->width, _screen.width - this->width), 0);
int enlarge_y = max(min(def_height - this->height, free_height - this->height), 0);
+ if (wt && vertical_toolbar && enlarge_x > _screen.width - wt->width * 2) {
+ enlarge_x = _screen.width - wt->width * 2;
+ }
/* X and Y has to go by step.. calculate it.
* The cast to int is necessary else x/y are implicitly casted to
@@ -1516,8 +1531,13 @@ void Window::FindWindowPlacementAndResize(int def_width, int def_height)
if (nx + this->width > _screen.width) nx -= (nx + this->width - _screen.width);
const Window *wt = FindWindowById(WC_MAIN_TOOLBAR, 0);
- ny = max(ny, (wt == NULL || this == wt || this->top == 0) ? 0 : wt->height);
- nx = max(nx, 0);
+ if (!vertical_toolbar) {
+ ny = max(ny, (wt == NULL || this == wt || this->top == 0) ? 0 : wt->height);
+ nx = max(nx, 0);
+ } else {
+ nx = max(nx, (wt == NULL || this == wt || this == FindWindowById(WC_MAIN_TOOLBAR_RIGHT, 0) || this->left == 0) ? 0 : wt->width);
+ ny = max(ny, 0);
+ }
if (this->viewport != NULL) {
this->viewport->left += nx - this->left;
@@ -1546,7 +1566,12 @@ static bool IsGoodAutoPlace1(int left, int top, int width, int height, Point &po
int bottom = height + top;
const Window *main_toolbar = FindWindowByClass(WC_MAIN_TOOLBAR);
- if (left < 0 || (main_toolbar != NULL && top < main_toolbar->height) || right > _screen.width || bottom > _screen.height) return false;
+ bool vertical_toolbar = _settings_client.gui.vertical_toolbar && _game_mode != GM_EDITOR;
+ if (!vertical_toolbar || !main_toolbar) {
+ if (left < 0 || (main_toolbar != NULL && top < main_toolbar->height) || right > _screen.width || bottom > _screen.height) return false;
+ } else {
+ if (left < main_toolbar->width || top < 0 || right > _screen.width - main_toolbar->width * 2 || bottom > _screen.height) return false;
+ }
/* Make sure it is not obscured by any window. */
const Window *w;
@@ -1613,10 +1638,15 @@ static bool IsGoodAutoPlace2(int left, int top, int width, int height, Point &po
static Point GetAutoPlacePosition(int width, int height)
{
Point pt;
+ bool vertical_toolbar = _settings_client.gui.vertical_toolbar && _game_mode != GM_EDITOR;
/* First attempt, try top-left of the screen */
const Window *main_toolbar = FindWindowByClass(WC_MAIN_TOOLBAR);
- if (IsGoodAutoPlace1(0, main_toolbar != NULL ? main_toolbar->height + 2 : 2, width, height, pt)) return pt;
+ if (vertical_toolbar) {
+ if (IsGoodAutoPlace1(main_toolbar != NULL ? main_toolbar->width : 0, 0, width, height, pt)) return pt;
+ } else {
+ if (IsGoodAutoPlace1(0, main_toolbar != NULL ? main_toolbar->height : 0, width, height, pt)) return pt;
+ }
/* Second attempt, try around all existing windows with a distance of 2 pixels.
* The new window must be entirely on-screen, and not overlap with an existing window.
@@ -1653,6 +1683,10 @@ static Point GetAutoPlacePosition(int width, int height)
* of (+5, +5)
*/
int left = 0, top = 24;
+ if (vertical_toolbar) {
+ left = main_toolbar != NULL ? main_toolbar->width : 0;
+ top = 0;
+ }
restart:
FOR_ALL_WINDOWS_FROM_BACK(w) {
@@ -1678,7 +1712,15 @@ Point GetToolbarAlignedWindowPosition(int window_width)
{
const Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
assert(w != NULL);
- Point pt = { _current_text_dir == TD_RTL ? w->left : (w->left + w->width) - window_width, w->top + w->height };
+ Point pt;
+ if (_settings_client.gui.vertical_toolbar && _game_mode != GM_EDITOR) {
+ // Retermine if the window was opened from the left or the right toolbar
+ pt.x = (_last_clicked_toolbar_idx == 0) ? w->left + w->width : _screen.width - w->width - window_width;
+ pt.y = w->top;
+ } else {
+ pt.x = _current_text_dir == TD_RTL ? w->left : (w->left + w->width) - window_width;
+ pt.y = w->top + w->height;
+ }
return pt;
}
@@ -1707,7 +1749,7 @@ static Point LocalGetWindowPlacement(const WindowDesc *desc, int16 sm_width, int
int16 default_width = max(desc->GetDefaultWidth(), sm_width);
int16 default_height = max(desc->GetDefaultHeight(), sm_height);
- if (desc->parent_cls != 0 /* WC_MAIN_WINDOW */ &&
+ if (desc->parent_cls != WC_NONE &&
(w = FindWindowById(desc->parent_cls, window_number)) != NULL &&
w->left < _screen.width - 20 && w->left > -60 && w->top < _screen.height - 20) {
@@ -1715,6 +1757,13 @@ static Point LocalGetWindowPlacement(const WindowDesc *desc, int16 sm_width, int
if (pt.x > _screen.width + 10 - default_width) {
pt.x = (_screen.width + 10 - default_width) - 20;
}
+ const Window *wt = FindWindowById(WC_MAIN_TOOLBAR_RIGHT, 0);
+ if (wt && (pt.x + default_width > _screen.width - wt->width ||
+ desc->parent_cls == WC_BUILD_TOOLBAR || desc->parent_cls == WC_SCEN_LAND_GEN)) {
+ // Move all build toolbar windows to the right, because all build toolbars are always at the right part of the screen
+ pt.x = _screen.width - wt->width - default_width;
+ }
+
pt.y = w->top + ((desc->parent_cls == WC_BUILD_TOOLBAR || desc->parent_cls == WC_SCEN_LAND_GEN) ? w->height : 10);
return pt;
}
@@ -1740,6 +1789,8 @@ static Point LocalGetWindowPlacement(const WindowDesc *desc, int16 sm_width, int
NOT_REACHED();
}
+ // try to put it to
+
return pt;
}
@@ -1817,6 +1868,21 @@ Window *FindWindowFromPt(int x, int y)
return NULL;
}
+/**
+ * Set button size of settings. If automatic sizing is also enabled, it also sets
+ * the sizing of buttons, scrollbars and font size (recommend restart).
+ * @todo Check if it can be moved to another file, so we do not need to include error, string and fontcache headers.
+ * @todo Fix magic numbers 16/18/20/30/32
+ */
+void NWidgetScrollbar::ResetAllWidgetMinSizes()
+{
+ NWidgetScrollbar::vertical_dimension = {0, 0};
+ NWidgetScrollbar::horizontal_dimension = {0, 0};
+
+ extern uint _tooltip_width;
+ _tooltip_width = max(194, 10 * RescaleFrom854x480(_settings_client.gui.min_button)); // ScaleGUITrad(194);
+}
+
/**
* (re)initialize the windowing system
*/
@@ -2045,6 +2111,7 @@ static void EnsureVisibleCaption(Window *w, int nx, int ny)
/* Make sure the title bar isn't hidden behind the main tool bar or the status bar. */
PreventHiding(&nx, &ny, caption_rect, FindWindowById(WC_MAIN_TOOLBAR, 0), w->left, PHD_DOWN);
+ PreventHiding(&nx, &ny, caption_rect, FindWindowById(WC_MAIN_TOOLBAR_RIGHT, 0), w->left, PHD_DOWN);
PreventHiding(&nx, &ny, caption_rect, FindWindowById(WC_STATUS_BAR, 0), w->left, PHD_UP);
}
@@ -2105,6 +2172,7 @@ void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen)
*/
int GetMainViewTop()
{
+ if (_settings_client.gui.vertical_toolbar && _game_mode != GM_EDITOR) return 0;
Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
return (w == NULL) ? 0 : w->top + w->height;
}
@@ -2360,7 +2428,7 @@ static EventState HandleScrollbarScrolling()
if (sb->disp_flags & ND_SCROLLBAR_BTN) {
if (_scroller_click_timeout == 1) {
- _scroller_click_timeout = 3;
+ _scroller_click_timeout = SCROLLER_CLICK_DELAY;
sb->UpdatePosition(rtl == HasBit(sb->disp_flags, NDB_SCROLLBAR_UP) ? 1 : -1);
w->SetDirty();
}
@@ -2389,6 +2457,21 @@ static EventState HandleViewportScroll()
{
bool scrollwheel_scrolling = _settings_client.gui.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
+ if (_settings_client.gui.left_mouse_btn_scrolling) {
+ // Do not open vehicle/town info window while scrolling with left mouse button
+ static int oldDx = 0, oldDy = 0;
+ if (_left_button_down) {
+ oldDx += _cursor.delta.x;
+ oldDy += _cursor.delta.y;
+ if (!_left_button_dragged && abs(oldDx) + abs(oldDy) > 20) {
+ _left_button_dragged = true;
+ }
+ } else {
+ oldDx = 0;
+ oldDy = 0;
+ }
+ }
+
if (!_scrolling_viewport) return ES_NOT_HANDLED;
/* When we don't have a last scroll window we are starting to scroll.
@@ -2396,7 +2479,9 @@ static EventState HandleViewportScroll()
* outside of the window and should not left-mouse scroll anymore. */
if (_last_scroll_window == NULL) _last_scroll_window = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
- if (_last_scroll_window == NULL || !(_right_button_down || scrollwheel_scrolling || (_settings_client.gui.left_mouse_btn_scrolling && _left_button_down))) {
+
+ if (_last_scroll_window == NULL || !(_right_button_down || scrollwheel_scrolling ||
+ (_left_button_down && (_move_pressed || _settings_client.gui.left_mouse_btn_scrolling)))) {
_cursor.fix_at = false;
_scrolling_viewport = false;
_last_scroll_window = NULL;
@@ -2685,12 +2770,14 @@ static int _input_events_this_tick = 0;
*/
static void HandleAutoscroll()
{
+ _move_pressed = false;
if (_game_mode == GM_MENU || HasModalProgress()) return;
if (_settings_client.gui.auto_scrolling == VA_DISABLED) return;
if (_settings_client.gui.auto_scrolling == VA_MAIN_VIEWPORT_FULLSCREEN && !_fullscreen) return;
int x = _cursor.pos.x;
int y = _cursor.pos.y;
+ int border = RescaleFrom854x480(_settings_client.gui.min_button);
Window *w = FindWindowFromPt(x, y);
if (w == NULL || w->flags & WF_DISABLE_VP_SCROLL) return;
if (_settings_client.gui.auto_scrolling != VA_EVERY_VIEWPORT && w->window_class != WC_MAIN_WINDOW) return;
@@ -2702,16 +2789,38 @@ static void HandleAutoscroll()
y -= vp->top;
/* here allows scrolling in both x and y axis */
-#define scrollspeed 3
- if (x - 15 < 0) {
- w->viewport->dest_scrollpos_x += ScaleByZoom((x - 15) * scrollspeed, vp->zoom);
- } else if (15 - (vp->width - x) > 0) {
- w->viewport->dest_scrollpos_x += ScaleByZoom((15 - (vp->width - x)) * scrollspeed, vp->zoom);
+#define scrollspeed 15
+ if (x - border < 0) {
+ _move_pressed = true;
+ w->viewport->dest_scrollpos_x += ScaleByZoom(-scrollspeed, vp->zoom);
+ } else if (border - (vp->width - x) > 0) {
+ _move_pressed = true;
+ w->viewport->dest_scrollpos_x += ScaleByZoom(scrollspeed, vp->zoom);
}
- if (y - 15 < 0) {
- w->viewport->dest_scrollpos_y += ScaleByZoom((y - 15) * scrollspeed, vp->zoom);
- } else if (15 - (vp->height - y) > 0) {
- w->viewport->dest_scrollpos_y += ScaleByZoom((15 - (vp->height - y)) * scrollspeed, vp->zoom);
+ if (y - border * 2 < 0) { // Border twice thicker, to accomodate top toolbar
+ _move_pressed = true;
+ w->viewport->dest_scrollpos_y += ScaleByZoom(-scrollspeed, vp->zoom);
+ } else if (border - (vp->height - y) > 0) { // Same thickness, because bottom toolbar does not cover whole screen width
+ _move_pressed = true;
+ w->viewport->dest_scrollpos_y += ScaleByZoom(scrollspeed, vp->zoom);
+ }
+#undef scrollspeed
+}
+
+/**
+ * Perform small continuous scrolling with right button press and drag.
+ */
+static void HandleContinuousScroll()
+{
+#define scrollspeed 0.05f
+ if (_scrolling_viewport && _right_button_down) {
+ Window *w = FindWindowFromPt(_right_button_down_pos.x, _right_button_down_pos.y);
+ if (w == NULL || w->flags & WF_DISABLE_VP_SCROLL) return;
+ ViewPort *vp = IsPtInWindowViewport(w, _right_button_down_pos.x, _right_button_down_pos.y);
+ if (vp == NULL) return;
+
+ w->viewport->dest_scrollpos_x += ScaleByZoom(scrollspeed * (_right_button_down_pos.x - _cursor.pos.x), vp->zoom);
+ w->viewport->dest_scrollpos_y += ScaleByZoom(scrollspeed * (_right_button_down_pos.y - _cursor.pos.y), vp->zoom);
}
#undef scrollspeed
}
@@ -2719,6 +2828,7 @@ static void HandleAutoscroll()
enum MouseClick {
MC_NONE = 0,
MC_LEFT,
+ MC_LEFT_UP,
MC_RIGHT,
MC_DOUBLE_LEFT,
MC_HOVER,
@@ -2786,6 +2896,16 @@ static void MouseLoop(MouseClick click, int mousewheel)
* But there is no company related window open anyway, so _current_company is not used. */
assert(HasModalProgress() || IsLocalCompany());
+ static bool mouse_down_on_viewport = false;
+ int x = _cursor.pos.x;
+ int y = _cursor.pos.y;
+ Window *w = FindWindowFromPt(x, y);
+ if (w == NULL) return;
+ ViewPort *vp = IsPtInWindowViewport(w, x, y);
+
+ /* Don't allow any action in a viewport if either in menu or when having a modal progress window */
+ if (vp != NULL && (_game_mode == GM_MENU || HasModalProgress())) return;
+
HandlePlacePresize();
UpdateTileSelection();
@@ -2800,16 +2920,9 @@ static void MouseLoop(MouseClick click, int mousewheel)
bool scrollwheel_scrolling = _settings_client.gui.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
if (click == MC_NONE && mousewheel == 0 && !scrollwheel_scrolling) return;
- int x = _cursor.pos.x;
- int y = _cursor.pos.y;
- Window *w = FindWindowFromPt(x, y);
if (w == NULL) return;
- if (click != MC_HOVER && !MaybeBringWindowToFront(w)) return;
- ViewPort *vp = IsPtInWindowViewport(w, x, y);
-
- /* Don't allow any action in a viewport if either in menu or when having a modal progress window */
- if (vp != NULL && (_game_mode == GM_MENU || HasModalProgress())) return;
+ if (click != MC_NONE && click != MC_HOVER && click != MC_LEFT_UP && !MaybeBringWindowToFront(w)) return;
if (mousewheel != 0) {
/* Send mousewheel event to window */
@@ -2824,13 +2937,26 @@ static void MouseLoop(MouseClick click, int mousewheel)
switch (click) {
case MC_DOUBLE_LEFT:
case MC_LEFT:
- DEBUG(misc, 2, "Cursor: 0x%X (%d)", _cursor.sprite, _cursor.sprite);
+ //DEBUG(misc, 2, "Cursor: 0x%X (%d)", _cursor.sprite, _cursor.sprite);
if (!HandleViewportClicked(vp, x, y) &&
!(w->flags & WF_DISABLE_VP_SCROLL) &&
- _settings_client.gui.left_mouse_btn_scrolling) {
+ (_settings_client.gui.left_mouse_btn_scrolling || _move_pressed)) {
_scrolling_viewport = true;
_cursor.fix_at = false;
+ } else {
+ // Viewport already clicked, prevent sending same event on mouse-up
+ _left_button_dragged = true;
}
+ mouse_down_on_viewport = true;
+ break;
+
+ case MC_LEFT_UP:
+ if (!_left_button_dragged && mouse_down_on_viewport) {
+ HandleViewportMouseUp(vp, x, y);
+ MoveAllHiddenWindowsBackToScreen();
+ }
+ _left_button_dragged = false;
+ mouse_down_on_viewport = false;
break;
case MC_RIGHT:
@@ -2849,6 +2975,9 @@ static void MouseLoop(MouseClick click, int mousewheel)
}
} else {
switch (click) {
+ case MC_LEFT_UP:
+ break;
+
case MC_LEFT:
case MC_DOUBLE_LEFT:
DispatchLeftClickEvent(w, x - w->left, y - w->top, click == MC_DOUBLE_LEFT ? 2 : 1);
@@ -2878,6 +3007,7 @@ void HandleMouseEvents()
static int double_click_time = 0;
static Point double_click_pos = {0, 0};
+ static bool left_button_released = false;
/* Mouse event? */
MouseClick click = MC_NONE;
@@ -2891,11 +3021,17 @@ void HandleMouseEvents()
double_click_time = _realtime_tick;
double_click_pos = _cursor.pos;
_left_button_clicked = true;
+ left_button_released = false;
_input_events_this_tick++;
} else if (_right_button_clicked) {
_right_button_clicked = false;
click = MC_RIGHT;
_input_events_this_tick++;
+ } else if(!_left_button_down && !left_button_released) {
+ click = MC_LEFT_UP;
+ left_button_released = true;
+ _left_button_clicked = false;
+ _input_events_this_tick++;
}
int mousewheel = 0;
@@ -3010,6 +3146,7 @@ void InputLoop()
/* HandleMouseEvents was already called for this tick */
HandleMouseEvents();
HandleAutoscroll();
+ HandleContinuousScroll();
}
/**
@@ -3222,6 +3359,7 @@ restart_search:
if (w->window_class != WC_MAIN_WINDOW &&
w->window_class != WC_SELECT_GAME &&
w->window_class != WC_MAIN_TOOLBAR &&
+ w->window_class != WC_MAIN_TOOLBAR_RIGHT &&
w->window_class != WC_STATUS_BAR &&
w->window_class != WC_TOOLTIPS &&
(w->flags & WF_STICKY) == 0) { // do not delete windows which are 'pinned'
@@ -3280,10 +3418,33 @@ restart_search:
FOR_ALL_WINDOWS_FROM_BACK(w) w->SetDirty();
}
+/**
+ * Delete all windows that are linked to the main toolbar.
+ * Once done with that, refresh other windows too.
+ */
+void DeleteToolbarLinkedWindows()
+{
+ Window *w;
+
+restart_search:
+ /* When we find the window to delete, we need to restart the search
+ * as deleting this window could cascade in deleting (many) others
+ * anywhere in the z-array */
+ FOR_ALL_WINDOWS_FROM_BACK(w) {
+ if (w->window_desc->default_pos == WDP_ALIGN_TOOLBAR) {
+ delete w;
+ goto restart_search;
+ }
+ }
+
+ FOR_ALL_WINDOWS_FROM_BACK(w) w->SetDirty();
+}
+
/** Delete all always on-top windows to get an empty screen */
void HideVitalWindows()
{
DeleteWindowById(WC_MAIN_TOOLBAR, 0);
+ DeleteWindowById(WC_MAIN_TOOLBAR_RIGHT, 0);
DeleteWindowById(WC_STATUS_BAR, 0);
}
@@ -3342,6 +3503,7 @@ static int PositionWindow(Window *w, WindowClass clss, int setting)
*/
int PositionMainToolbar(Window *w)
{
+ if (_settings_client.gui.vertical_toolbar && _game_mode != GM_EDITOR) return 0; /* Always at the left */
DEBUG(misc, 5, "Repositioning Main Toolbar...");
return PositionWindow(w, WC_MAIN_TOOLBAR, _settings_client.gui.toolbar_pos);
}
@@ -3423,6 +3585,13 @@ void RelocateAllWindows(int neww, int newh)
left = PositionMainToolbar(w); // changes toolbar orientation
break;
+ case WC_MAIN_TOOLBAR_RIGHT:
+ ResizeWindow(w, min(neww, w->window_desc->default_width) - w->width, 0, false);
+
+ top = w->top;
+ left = neww - w->width;
+ break;
+
case WC_NEWS_WINDOW:
top = newh - w->height;
left = PositionNewsMessage(w);
@@ -3467,6 +3636,64 @@ void RelocateAllWindows(int neww, int newh)
}
}
+static void MoveAllWindowsOffScreen(bool moveOffScreen)
+{
+ Window *w;
+ bool updateScreen = false;
+
+ FOR_ALL_WINDOWS_FROM_BACK(w) {
+ switch (w->window_class) {
+ case WC_MAIN_WINDOW:
+ case WC_BOOTSTRAP:
+ case WC_MAIN_TOOLBAR:
+ case WC_MAIN_TOOLBAR_RIGHT:
+ case WC_NEWS_WINDOW:
+ case WC_STATUS_BAR:
+ case WC_SEND_NETWORK_MSG:
+ case WC_CONSOLE:
+ continue;
+
+ default:
+ if (moveOffScreen) {
+ if (w->left < _screen.width) {
+ w->left += _screen.width;
+ if (w->viewport != NULL) {
+ w->viewport->left += _screen.width;
+ }
+ //w->SetDirty();
+ updateScreen = true;
+ }
+ } else {
+ if (w->left >= _screen.width) {
+ w->left -= _screen.width;
+ if (w->viewport != NULL) {
+ w->viewport->left -= _screen.width;
+ }
+ w->SetDirty();
+ //updateScreen = true;
+ }
+ }
+ break;
+ }
+ }
+ if (updateScreen) {
+ w = FindWindowById(WC_MAIN_WINDOW, 0);
+ if (w) {
+ w->SetDirty();
+ }
+ }
+}
+
+void MoveAllWindowsOffScreen()
+{
+ MoveAllWindowsOffScreen(true);
+}
+
+void MoveAllHiddenWindowsBackToScreen()
+{
+ MoveAllWindowsOffScreen(false);
+}
+
/**
* Destructor of the base class PickerWindowBase
* Main utility is to stop the base Window destructor from triggering
diff --git a/src/window_func.h b/src/window_func.h
index 453b889789..8dff11baff 100644
--- a/src/window_func.h
+++ b/src/window_func.h
@@ -41,6 +41,7 @@ void InvalidateWindowClassesData(WindowClass cls, int data = 0, bool gui_scope =
void DeleteNonVitalWindows();
void DeleteAllNonVitalWindows();
void DeleteConstructionWindows();
+void DeleteToolbarLinkedWindows();
void HideVitalWindows();
void ShowVitalWindows();
diff --git a/src/window_gui.h b/src/window_gui.h
index b81b06e391..1a02df14bf 100644
--- a/src/window_gui.h
+++ b/src/window_gui.h
@@ -747,6 +747,10 @@ public:
*/
virtual void OnPlaceObjectAbort() {}
+ /**
+ * Select the cancelled tool again, this is called after OnPlaceObjectAbort()
+ */
+ virtual void SelectLastTool() {}
/**
* The user is dragging over the map when the tile highlight mode
@@ -864,6 +868,8 @@ Wcls *AllocateWindowDescFront(WindowDesc *desc, int window_number, bool return_e
}
void RelocateAllWindows(int neww, int newh);
+void MoveAllWindowsOffScreen();
+void MoveAllHiddenWindowsBackToScreen();
/* misc_gui.cpp */
enum TooltipCloseCondition {
@@ -888,6 +894,9 @@ extern Point _cursorpos_drag_start;
extern int _scrollbar_start_pos;
extern int _scrollbar_size;
extern byte _scroller_click_timeout;
+enum {
+ SCROLLER_CLICK_DELAY = 6 ///< Delay in video frames between scrollbar doing scroll, we don't want to get to the bottom of the list in an instant
+};
extern bool _scrolling_viewport;
extern bool _mouse_hovering;
diff --git a/src/window_type.h b/src/window_type.h
index a8a8128f58..7386f6e809 100644
--- a/src/window_type.h
+++ b/src/window_type.h
@@ -52,6 +52,13 @@ enum WindowClass {
*/
WC_MAIN_TOOLBAR,
+ /**
+ * Right part of split main toolbar; %Window numbers:
+ * - 0 = #ToolbarNormalWidgets
+ * - 0 = #ToolbarEditorWidgets
+ */
+ WC_MAIN_TOOLBAR_RIGHT,
+
/**
* Statusbar (at the bottom of your screen); %Window numbers:
* - 0 = #StatusbarWidgets
diff --git a/todo.txt b/todo.txt
new file mode 100644
index 0000000000..88b5fa450e
--- /dev/null
+++ b/todo.txt
@@ -0,0 +1,10 @@
+Minor bugs, which I'm too lazy to fix - serious bugs go to https://github.com/pelya/commandergenius/blob/sdl_android/todo.txt
+=============================================================================================================================
+
+- OpenTTD: All menus in the scenario editor are out of the screen.
+
+- OpenTTD: 16bpp blitter with palette animation support.
+
+- OpenTTD: screen navigation buttons bug on Moto G - not reproduced on Nexus 7.
+
+- OpenTTD: Cheats menu closes itself randomly.
diff --git a/version-override b/version-override
new file mode 100644
index 0000000000..f31dc5e020
--- /dev/null
+++ b/version-override
@@ -0,0 +1 @@
+1.4.0 26440 0 1.4.0