diff --git a/.ottdrev b/.ottdrev new file mode 100644 index 0000000000..fdb7582eca --- /dev/null +++ b/.ottdrev @@ -0,0 +1 @@ +1.8.0 28002 0 1.8.0 diff --git a/android-extract-strings.sh b/android-extract-strings.sh new file mode 100755 index 0000000000..6f0d4a8edb --- /dev/null +++ b/android-extract-strings.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +mkdir -p ../translations/lang +git diff 1.7/master -- src/lang/english.txt | tail -n +5 | grep '^[+]' | cut -b 2- | \ +grep -v "^STR_TABLET_CLOSE\b" | \ +grep -v "^STR_TABLET_SHIFT\b" | \ +grep -v "^STR_TABLET_CTRL\b" | \ +cat > ../translations/lang/english.txt + +for f in src/lang/*.txt; do + [ "$f" = src/lang/english.txt ] && continue + rm -f ../translations/lang/`basename $f` + cat ../translations/lang/english.txt | grep '^STR' | while read name text; do + grep "^$name\b" $f >> ../translations/lang/`basename $f` + done +done diff --git a/android-store-strings.sh b/android-store-strings.sh new file mode 100755 index 0000000000..7a9d540c25 --- /dev/null +++ b/android-store-strings.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +for f in ../translations/lang/*.txt; do + [ "$f" = ../translations/lang/english.txt ] && continue + out=src/lang/`basename $f` + grep "^# Android strings" $out > /dev/null || [ -z "`tail -c 2 $out`" ] || echo >> $out + { grep -v "^# Android strings" $out ; echo "# Android strings" ; } > $out.new + mv -f $out.new $out + cat $f | grep '^STR' | while read name text; do + [ "$name" = "STR_ABOUT_MENU_SEPARATOR" ] && continue + { grep -v "^$name\b" $out ; printf "%-64s%s\n" "$name" "$text" ; } > $out.new + mv -f $out.new $out + done +done diff --git a/config.lib b/config.lib index 2bcc643fba..11896f31b3 100644 --- a/config.lib +++ b/config.lib @@ -1099,7 +1099,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" @@ -1823,14 +1823,14 @@ make_cflags_and_ldflags() { CFLAGS="$CFLAGS -DWITH_XAUDIO2" fi - if [ -n "$libtimidity_config" ]; then + if [ -n "$libtimidity" ]; then CFLAGS="$CFLAGS -DLIBTIMIDITY" - CFLAGS="$CFLAGS `$libtimidity_config --cflags | tr '\n\r' ' '`" + CFLAGS="$CFLAGS `$libtimidity --cflags | tr '\n\r' ' '`" if [ "$enable_static" != "0" ]; then - LIBS="$LIBS `$libtimidity_config --libs --static | tr '\n\r' ' '`" + LIBS="$LIBS `$libtimidity --libs --static | tr '\n\r' ' '`" else - LIBS="$LIBS `$libtimidity_config --libs | tr '\n\r' ' '`" + LIBS="$LIBS `$libtimidity --libs | tr '\n\r' ' '`" fi fi @@ -2772,7 +2772,7 @@ detect_lzo2() { } detect_libtimidity() { - detect_pkg_config "$with_libtimidity" "libtimidity" "libtimidity_config" "0.1" "1" + detect_pkg_config "$with_libtimidity" "libtimidity" "libtimidity" "0.1" "1" } detect_fluidsynth() { diff --git a/findversion.sh b/findversion.sh index 95a041bac0..a744c6fba8 100755 --- a/findversion.sh +++ b/findversion.sh @@ -59,7 +59,11 @@ ROOT_DIR=`pwd` # Determine if we are using a modified version # Assume the dir is not modified MODIFIED="0" -if [ -d "$ROOT_DIR/.git" ]; then +if [ -f "$ROOT_DIR/.ottdrev" ]; then + # We are an exported source bundle + cat $ROOT_DIR/.ottdrev + exit +elif [ -d "$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 @@ -93,11 +97,6 @@ if [ -d "$ROOT_DIR/.git" ]; then ISTAG="0" ISSTABLETAG="0" fi - -elif [ -f "$ROOT_DIR/.ottdrev" ]; then - # We are an exported source bundle - cat $ROOT_DIR/.ottdrev - exit else # We don't know MODIFIED="1" diff --git a/projects/openttd_vs142.vcxproj b/projects/openttd_vs142.vcxproj index 5999d00d6c..997ec829b5 100644 --- a/projects/openttd_vs142.vcxproj +++ b/projects/openttd_vs142.vcxproj @@ -676,6 +676,7 @@ + diff --git a/projects/openttd_vs142.vcxproj.filters b/projects/openttd_vs142.vcxproj.filters index 751e54887c..a301b9ddcc 100644 --- a/projects/openttd_vs142.vcxproj.filters +++ b/projects/openttd_vs142.vcxproj.filters @@ -1116,6 +1116,9 @@ Header Files + + Header Files + Header Files diff --git a/source.list b/source.list index ce6c4cf150..c9ba04c0ee 100644 --- a/source.list +++ b/source.list @@ -90,6 +90,7 @@ tgp.cpp tile_map.cpp tilearea.cpp townname.cpp +tutorial_gui.cpp #if WIN32 #else #if OS2 @@ -137,6 +138,7 @@ base_media_func.h base_station_base.h bmp.h bridge.h +build_confirmation_func.h cargo_type.h cargoaction.h cargomonitor.h @@ -363,6 +365,7 @@ tilehighlight_func.h tilehighlight_type.h tilematrix_type.hpp timetable.h +toolbar_type.h toolbar_gui.h town.h town_type.h @@ -452,6 +455,7 @@ airport_gui.cpp autoreplace_gui.cpp bootstrap_gui.cpp bridge_gui.cpp +build_confirmation_gui.cpp build_vehicle_gui.cpp cheat_gui.cpp company_gui.cpp @@ -913,6 +917,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/3rdparty/squirrel/squirrel/sqobject.h b/src/3rdparty/squirrel/squirrel/sqobject.h index d71e515a8d..0b4576f3d4 100644 --- a/src/3rdparty/squirrel/squirrel/sqobject.h +++ b/src/3rdparty/squirrel/squirrel/sqobject.h @@ -2,6 +2,7 @@ #ifndef _SQOBJECT_H_ #define _SQOBJECT_H_ +#include #include "squtils.h" #define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R')) diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index 73806da15e..4a949267fd 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -110,7 +110,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; @@ -123,16 +123,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; } } @@ -349,7 +349,7 @@ struct AISettingsWindow : public Window { virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) { if (widget == WID_AIS_BACKGROUND) { - this->line_height = max(SETTING_BUTTON_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; @@ -371,7 +371,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; @@ -416,7 +415,7 @@ struct AISettingsWindow : public Window { } } - DrawString(text_left, text_right, y + text_y_offset, str, colour); + DrawString(text_left, text_right, Center(y, this->line_height), str, colour); y += this->line_height; } } @@ -674,39 +673,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(), }; @@ -771,12 +772,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; @@ -830,14 +831,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; @@ -849,7 +850,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; } @@ -1101,7 +1102,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; } } @@ -1117,6 +1118,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); @@ -1137,7 +1140,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. */ @@ -1216,7 +1219,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 243f91b247..efd9d1b97a 100644 --- a/src/airport_gui.cpp +++ b/src/airport_gui.cpp @@ -28,6 +28,8 @@ #include "hotkeys.h" #include "vehicle_func.h" #include "gui.h" +#include "command_func.h" +#include "build_confirmation_func.h" #include "widgets/airport_widget.h" @@ -73,12 +75,13 @@ struct BuildAirToolbarWindow : Window { BuildAirToolbarWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc) { this->InitNested(window_number); - if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this); + if (_settings_client.gui.link_terraform_toolbar || _settings_client.gui.compact_vertical_toolbar) ShowTerraformToolbar(); this->last_user_action = WIDGET_LIST_END; } ~BuildAirToolbarWindow() { + if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort(); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); } @@ -113,13 +116,13 @@ 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); break; + } case WID_AT_DEMOLISH: PlaceProc_DemolishArea(tile); @@ -127,6 +130,7 @@ struct BuildAirToolbarWindow : Window { default: NOT_REACHED(); } + MoveAllWindowsOffScreen(); } virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) @@ -136,17 +140,29 @@ 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; + MoveAllHiddenWindowsBackToScreen(); + switch (select_proc) { + case DDSP_BUILD_STATION: + assert(start_tile == end_tile); + PlaceAirport(end_tile); + break; + case DDSP_DEMOLISH_AREA: + GUIPlaceProcDragXY(select_proc, start_tile, end_tile); + break; + default: NOT_REACHED(); } } virtual void OnPlaceObjectAbort() { + MoveAllHiddenWindowsBackToScreen(); this->RaiseButtons(); - - DeleteWindowById(WC_BUILD_STATION, TRANSPORT_AIR); - DeleteWindowById(WC_SELECT_STATION, 0); + if (!ConfirmationWindowShown()) { + DeleteWindowById(WC_BUILD_STATION, TRANSPORT_AIR); + DeleteWindowById(WC_SELECT_STATION, 0); + } + ResetObjectToPlace(); } static HotkeyList hotkeys; @@ -204,7 +220,7 @@ Window *ShowBuildAirToolbar() { if (!Company::IsValidID(_local_company)) return NULL; - DeleteWindowByClass(WC_BUILD_TOOLBAR); + DeleteToolbarLinkedWindows(); return AllocateWindowDescFront(&_air_toolbar_desc, TRANSPORT_AIR); } @@ -305,6 +321,7 @@ public: d.width += padding.width; d.height += padding.height; *size = maxdim(*size, d); + size->height = GetMinSizing(NWST_STEP, size->height); break; } @@ -316,7 +333,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 +385,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 +573,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 eae0a378eb..7f18efc862 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -22,6 +22,7 @@ #include "window_gui.h" #include "engine_gui.h" #include "settings_func.h" +#include "settings_gui.h" #include "core/geometry_func.hpp" #include "rail_gui.h" #include "widgets/dropdown_func.h" @@ -242,7 +243,7 @@ public: switch (widget) { case WID_RV_SORT_ASCENDING_DESCENDING: { 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.width += padding.width + Window::SortButtonWidth(); d.height += padding.height; *size = maxdim(*size, d); break; @@ -251,7 +252,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 = (widget == WID_RV_LEFT_MATRIX ? 3 : 4) * resize->height; break; case WID_RV_LEFT_DETAILS: @@ -298,6 +299,7 @@ public: d = maxdim(d, GetStringBoundingBox(rti->strings.replace_text)); } d.width += padding.width; + d.width += SETTING_BUTTON_HEIGHT; d.height += padding.height; *size = maxdim(*size, d); break; @@ -309,6 +311,7 @@ public: d = maxdim(d, GetStringBoundingBox(_start_replace_dropdown[i])); } d.width += padding.width; + d.width += SETTING_BUTTON_HEIGHT; d.height += padding.height; *size = maxdim(*size, d); break; @@ -376,7 +379,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, TC_BLACK, SA_HOR_CENTER); break; } @@ -601,30 +604,26 @@ static const NWidgetPart _nested_replace_rail_vehicle_widgets[] = { NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_RAILTYPE_DROPDOWN), SetMinimalSize(136, 12), SetDataTip(0x0, STR_REPLACE_HELP_RAILTYPE), SetFill(1, 0), SetResize(1, 0), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN), SetDataTip(STR_BLACK_STRING, STR_REPLACE_ENGINE_WAGON_SELECT_HELP), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_WAGONREMOVE_TOGGLE), SetMinimalSize(138, 12), SetDataTip(STR_REPLACE_REMOVE_WAGON, STR_REPLACE_REMOVE_WAGON_HELP), SetFill(1, 0), SetResize(1, 0), + NWidget(NWID_HORIZONTAL), + NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR), + NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_LEFT_SCROLLBAR), + EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(), EndContainer(), NWidget(NWID_VERTICAL), NWidget(NWID_HORIZONTAL), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), SetFill(1, 1), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetDataTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA), EndContainer(), NWidget(NWID_HORIZONTAL), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetDataTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP), - NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(), + NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR), + NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_RIGHT_SCROLLBAR), + EndContainer(), + NWidget(NWID_VERTICAL), + NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(), EndContainer(), - EndContainer(), - EndContainer(), - NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), - NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR), - NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_LEFT_SCROLLBAR), - NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR), - NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_RIGHT_SCROLLBAR), - EndContainer(), - NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), - NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(), - NWidget(NWID_VERTICAL), - NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_WAGONREMOVE_TOGGLE), SetMinimalSize(138, 12), SetDataTip(STR_REPLACE_REMOVE_WAGON, STR_REPLACE_REMOVE_WAGON_HELP), SetFill(1, 0), SetResize(1, 0), EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), @@ -660,28 +659,26 @@ static const NWidgetPart _nested_replace_vehicle_widgets[] = { EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), - NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(), + NWidget(NWID_VERTICAL), + NWidget(NWID_HORIZONTAL), + NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR), + NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_LEFT_SCROLLBAR), + EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(228, 92), SetResize(1, 0), EndContainer(), + EndContainer(), NWidget(NWID_VERTICAL), NWidget(NWID_HORIZONTAL), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetDataTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA), EndContainer(), NWidget(NWID_HORIZONTAL), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetDataTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP), - NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(), + NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR), + NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_RIGHT_SCROLLBAR), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(228, 92), SetResize(1, 0), EndContainer(), EndContainer(), EndContainer(), - NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), - NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR), - NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_LEFT_SCROLLBAR), - NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR), - NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_RIGHT_SCROLLBAR), - EndContainer(), - NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), - NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(228, 92), SetResize(1, 0), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(228, 92), SetResize(1, 0), EndContainer(), - EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetDataTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_HELP_START_BUTTON), NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetDataTip(0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB), SetResize(1, 0), EndContainer(), 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..fc0e83fff3 --- /dev/null +++ b/src/blitter/16bpp_simple.cpp @@ -0,0 +1,173 @@ +/* $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; + + case BM_BLACK_REMAP: + if (src->a != 0) { + *dst = Colour16(0, 0, 0); + } + 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; + case BM_BLACK_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 768691f080..b9122fafad 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" @@ -198,6 +199,7 @@ public: sprite_dim.height++; // Sprite is rendered one pixel down in the matrix field. text_dim.height++; // Allowing the bottom row pixels to be rendered on the edge of the matrix field. resize->height = max(sprite_dim.height, text_dim.height) + 2; // Max of both sizes + account for matrix edges. + resize->height = GetMinSizing(NWST_STEP, resize->height); this->bridgetext_offset = WD_MATRIX_LEFT + sprite_dim.width + 1; // Left edge of text, 1 pixel distance from the sprite. size->width = this->bridgetext_offset + text_dim.width + WD_MATRIX_RIGHT; @@ -233,7 +235,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 +433,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_confirmation_func.h b/src/build_confirmation_func.h new file mode 100644 index 0000000000..7bbbba24ef --- /dev/null +++ b/src/build_confirmation_func.h @@ -0,0 +1,27 @@ +/* $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 build_confirmation_func.h Transparent confirmation dialog for building anything on the map. */ + +#ifndef BUILD_CONFIRMATION_FUNC_H +#define BUILD_CONFIRMATION_FUNC_H + +#include "stdafx.h" +#include "window_func.h" +#include "widget_type.h" + + +void ShowBuildConfirmationWindow(); +void HideBuildConfirmationWindow(); +bool ConfirmationWindowShown(); +bool BuildConfirmationWindowProcessViewportClick(); +bool ConfirmationWindowEstimatingCost(); +void ConfirmationWindowSetEstimatedCost(Money cost); + +#endif /* BUILD_CONFIRMATION_FUNC_H */ diff --git a/src/build_confirmation_gui.cpp b/src/build_confirmation_gui.cpp new file mode 100644 index 0000000000..7d9d044af5 --- /dev/null +++ b/src/build_confirmation_gui.cpp @@ -0,0 +1,310 @@ +/* $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 build_confirmation_gui.cpp Transparent confirmation dialog for building anything on the map. */ + +#include "stdafx.h" +#include "string_func.h" +#include "strings_func.h" +#include "window_func.h" +#include "widget_type.h" +#include "window_gui.h" +#include "gfx_func.h" +#include "tilehighlight_func.h" +#include "viewport_func.h" +#include "zoom_func.h" +#include "settings_type.h" +#include "station_gui.h" +#include "error.h" +#include "build_confirmation_func.h" +#include "widgets/build_confirmation_widget.h" +#include "widgets/misc_widget.h" + +#include "table/strings.h" + +#include "safeguards.h" + +static const NWidgetPart _nested_build_info_widgets[] = { + NWidget(WWT_PANEL, COLOUR_GREY, WID_TT_BACKGROUND), SetMinimalSize(200, 32), EndContainer(), +}; + +static WindowDesc _build_info_desc( + WDP_MANUAL, NULL, 0, 0, // Coordinates and sizes are not used, + WC_TOOLTIPS, WC_NONE, + WDF_NO_FOCUS, + _nested_build_info_widgets, lengthof(_nested_build_info_widgets) +); + +/** Window for displaying accepted goods for a station. */ +struct BuildInfoWindow : public Window +{ + StationCoverageType sct; + bool station; + static Money cost; + + static void show() + { + bool station = _settings_client.gui.station_show_coverage; // Station info is inaccurate when station coverage area option is disabled + StationCoverageType sct = SCT_ALL; + if (FindWindowByClass(WC_BUILD_STATION) != NULL) sct = SCT_ALL; + else if (FindWindowByClass(WC_BUS_STATION) != NULL) sct = SCT_PASSENGERS_ONLY; + else if (FindWindowByClass(WC_TRUCK_STATION) != NULL) sct = SCT_NON_PASSENGERS_ONLY; + else station = false; + new BuildInfoWindow(station, sct); + } + + BuildInfoWindow(bool station, StationCoverageType sct) : Window(&_build_info_desc) + { + this->station = station; + this->sct = sct; + this->InitNested(); + + CLRBITS(this->flags, WF_WHITE_BORDER); + } + + virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) + { + Point pt; + pt.y = GetMainViewTop(); + pt.x = _screen.width - sm_width - FindWindowById(WC_MAIN_TOOLBAR, 0)->width; + return pt; + } + + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) + { + size->width = GetStringBoundingBox(STR_STATION_BUILD_COVERAGE_AREA_TITLE).width * 2.5; + size->height = GetStringHeight(STR_STATION_BUILD_COVERAGE_AREA_TITLE, size->width) * (this->station ? 3 : 1); + + /* Increase slightly to have some space around the box. */ + size->width += 2 + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; + size->height += 2 + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; + } + + virtual void DrawWidget(const Rect &r, int widget) const + { + /* There is only one widget. */ + GfxFillRect(r.left, r.top, r.right, r.bottom, PC_BLACK); + GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_LIGHT_YELLOW); + + int top = r.top + WD_FRAMERECT_TOP; + Money cost = BuildInfoWindow::cost; + StringID msg = STR_MESSAGE_ESTIMATED_COST; + SetDParam(0, cost); + if (cost < 0) { + msg = STR_MESSAGE_ESTIMATED_INCOME; + SetDParam(0, -cost); + } + top = DrawStringMultiLine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, top, INT32_MAX, msg); + + if (!this->station) return; + + top = DrawStationCoverageAreaText(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, top, sct, _thd.outersize.x / TILE_SIZE / 2, false); + if (top - r.top <= GetStringHeight(STR_STATION_BUILD_COVERAGE_AREA_TITLE, r.right - r.left) * 1.5) { + DrawStationCoverageAreaText(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, top, sct, _thd.outersize.x / TILE_SIZE / 2, true); + } + } +}; + +Money BuildInfoWindow::cost = 0; + +/** GUI for confirming building actions. */ +struct BuildConfirmationWindow : Window { + + // TODO: show estimated price + static bool shown; ///< Just to speed up window hiding, HideBuildConfirmationWindow() is called very often. + static bool estimating_cost; ///< Calculate action cost instead of executing action. + Point selstart; ///< The selection start on the viewport. + Point selend; ///< The selection end on the viewport. + + BuildConfirmationWindow(WindowDesc *desc) : Window(desc) + { + // Save tile selection points, they will be reset by subsequent code, and we must keep them + selstart = _thd.selstart; + selend = _thd.selend; + + this->InitNested(0); + + Point pt; + const Window *w = FindWindowById(WC_MAIN_WINDOW, 0); + NWidgetViewport *nvp = this->GetWidget(WID_BC_OK); + + pt.x = w->viewport->scrollpos_x + ScaleByZoom(_cursor.pos.x - nvp->current_x / 2, w->viewport->zoom); + pt.y = w->viewport->scrollpos_y + ScaleByZoom(_cursor.pos.y - nvp->current_y / 4, w->viewport->zoom); + + nvp->InitializeViewport(this, 0, w->viewport->zoom); + nvp->disp_flags |= ND_SHADE_DIMMED; + + this->viewport->scrollpos_x = pt.x; + this->viewport->scrollpos_y = pt.y; + this->viewport->dest_scrollpos_x = this->viewport->scrollpos_x; + this->viewport->dest_scrollpos_y = this->viewport->scrollpos_y; + + BuildConfirmationWindow::shown = true; + BuildConfirmationWindow::estimating_cost = true; + ConfirmationWindowSetEstimatedCost(0); // Clear old value, just in case + // This is a hack - we invoke the build command with estimating_cost flag, which is equal to _shift_pressed, + // then we select last build tool, restore viewport selection, and hide all windows, which pop up when command is invoked, + // and all that just to get cost estimate value. + ConfirmPlacingObject(); + ToolbarSelectLastTool(); + _thd.selstart = selstart; + _thd.selend = selend; + BuildConfirmationWindow::estimating_cost = false; + MoveAllWindowsOffScreen(); + } + + ~BuildConfirmationWindow() + { + BuildConfirmationWindow::shown = false; + } + + void OnClick(Point pt, int widget, int click_count) + { + switch (widget) { + case WID_BC_OK: + if (pt.y <= (int)GetWidget(WID_BC_OK)->current_y / 2) { + _thd.selstart = selstart; + _thd.selend = selend; + ConfirmPlacingObject(); + ToolbarSelectLastTool(); + } else { + ResetObjectToPlace(); + DeleteWindowByClass(WC_BUILD_BRIDGE); + //ClearErrorMessages(); + Window *w = FindWindowById(WC_ERRMSG, 0); + if (w != NULL) delete w; + } + break; + } + HideBuildConfirmationWindow(); // this == NULL after this call + } + + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) + { + switch (widget) { + case WID_BC_OK: + size->width = GetMinSizing(NWST_BUTTON) * 2; + size->height = GetMinSizing(NWST_BUTTON) * 3; + break; + } + } + + virtual void OnPaint() + { + this->DrawWidgets(); + + DrawButtonFrame(0, 0, this->width - 1, this->height / 2 - 2, STR_BUTTON_OK); + DrawButtonFrame(0, this->height / 2, this->width - 1, this->height / 2 - 1, STR_BUTTON_CANCEL); + } + + void DrawButtonFrame(int x, int y, int w, int h, int str) + { + DrawFrameRect(x, y, x + w, y + h, COLOUR_GREY, FR_BORDERONLY); + Dimension d = GetStringBoundingBox(str); + DrawFrameRect(x + w / 2 - d.width / 2 - 1, + Center(y, h) - 2, + x + w / 2 + d.width / 2 + 1, + Center(y, h) + d.height, + COLOUR_GREY, FR_NONE); + DrawString(x, x + w, Center(y, h), str, TC_FROMSTRING, SA_HOR_CENTER); + } +}; + +bool BuildConfirmationWindow::shown = false; +bool BuildConfirmationWindow::estimating_cost = false; + +static const NWidgetPart _nested_build_confirmation_widgets[] = { + NWidget(WWT_PANEL, COLOUR_GREY, WID_BC_PANEL), + NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_BC_OK), SetSizingType(NWST_VIEWPORT), SetResize(1, 1), SetFill(1, 1), //SetPadding(2, 2, 2, 2), + EndContainer(), +}; + +static WindowDesc _build_confirmation_desc( + WDP_MANUAL, "build_confirmation", 0, 0, + WC_BUILD_CONFIRMATION, WC_NONE, + 0, + _nested_build_confirmation_widgets, lengthof(_nested_build_confirmation_widgets) +); + +/** + * Show build confirmation window under the mouse cursor +*/ +void ShowBuildConfirmationWindow() +{ + if (ConfirmationWindowEstimatingCost()) return; // Special case, ignore recursive call + + HideBuildConfirmationWindow(); + + if (!_settings_client.gui.build_confirmation || _shift_pressed) { + ConfirmPlacingObject(); + return; + } + + BuildConfirmationWindow *w = new BuildConfirmationWindow(&_build_confirmation_desc); + + int old_left = w->left; + int old_top = w->top; + w->left = _cursor.pos.x - w->width / 2; + w->top = _cursor.pos.y - w->height / 4; + w->viewport->left += w->left - old_left; + w->viewport->top += w->top - old_top; + w->SetDirty(); + SetDirtyBlocks(0, 0, _screen.width, _screen.height); // I don't know what does this do, but it looks important + + BuildInfoWindow::show(); +} + +/** + * Destroy build confirmation window, this does not cancel current action +*/ +void HideBuildConfirmationWindow() +{ + if (ConfirmationWindowEstimatingCost()) return; // Special case, ignore recursive call + + if (!BuildConfirmationWindow::shown) return; + + DeleteWindowById(WC_BUILD_CONFIRMATION, 0); + DeleteWindowById(WC_TOOLTIPS, 0); +} + +bool ConfirmationWindowShown() +{ + return BuildConfirmationWindow::shown; +} + +bool BuildConfirmationWindowProcessViewportClick() +{ + if (!BuildConfirmationWindow::shown) return false; + Window *w = FindWindowById(WC_BUILD_CONFIRMATION, 0); + if (w != NULL && IsInsideBS(_cursor.pos.x, w->left, w->width) && IsInsideBS(_cursor.pos.y, w->top, w->height)) { + if (_settings_client.gui.windows_titlebars || !_left_button_down) { + Point pt; + pt.x = _cursor.pos.x - w->left; + pt.y = _cursor.pos.y - w->top; + w->OnClick(pt, WID_BC_OK, 1); + } + return true; + } + + HideBuildConfirmationWindow(); + + _thd.new_outersize = _thd.outersize; // Revert station catchment area highlight, which is getting set to zero inside drawing funcs + + return false; +} + +bool ConfirmationWindowEstimatingCost() +{ + return BuildConfirmationWindow::estimating_cost; +} + +void ConfirmationWindowSetEstimatedCost(Money cost) +{ + BuildInfoWindow::cost = cost; +} diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 0ac23cfde6..631dff67ce 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[] = { @@ -57,25 +58,30 @@ static const NWidgetPart _nested_build_vehicle_widgets[] = { NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY), + NWidget(NWID_HORIZONTAL), 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_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), 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), 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. */ 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_MATRIX, COLOUR_GREY, WID_BV_LIST), SetResize(1, 1), SetFill(1, 0), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_BV_SCROLLBAR), + NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_BV_SCROLLBAR), EndContainer(), EndContainer(), + /* Panel with details. */ + NWidget(WWT_PANEL, COLOUR_GREY, WID_BV_PANEL), SetMinimalSize(240, 122), SetResize(1, 1), EndContainer(), EndContainer(), - /* Vehicle list. */ - NWidget(NWID_HORIZONTAL), - NWidget(WWT_MATRIX, COLOUR_GREY, WID_BV_LIST), SetResize(1, 1), SetFill(1, 0), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_BV_SCROLLBAR), - NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_BV_SCROLLBAR), - EndContainer(), - /* Panel with details. */ - NWidget(WWT_PANEL, COLOUR_GREY, WID_BV_PANEL), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(), /* Build/rename buttons, resize button. */ NWidget(NWID_HORIZONTAL), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_BV_BUILD_SEL), @@ -1407,6 +1413,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 70258aaa1d..904353175d 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -26,6 +26,9 @@ #include "signal_func.h" #include "core/backup_type.hpp" #include "object_base.h" +#include "string_func.h" +#include "tilehighlight_func.h" +#include "build_confirmation_func.h" #include "table/strings.h" @@ -555,11 +558,18 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallbac * However, in case of incoming network commands, * map generation or the pause button we do want * to execute. */ - bool estimate_only = _shift_pressed && IsLocalCompany() && + bool estimate_only = (_shift_pressed || ConfirmationWindowEstimatingCost()) && + IsLocalCompany() && !_generating_world && !(cmd & CMD_NETWORK_COMMAND) && (cmd & CMD_ID_MASK) != CMD_PAUSE; + if (ConfirmationWindowEstimatingCost() && !estimate_only) { + // We cannot estimate cost, so abort the command - it will be repeated by confirmation dialog later + ShowEstimatedCostOrIncome(0, 0, 0); + return false; + } + /* We're only sending the command, so don't do * fancy things for 'success'. */ bool only_sending = _networking && !(cmd & CMD_NETWORK_COMMAND); diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 651b216a56..3426451f58 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -911,7 +911,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 a3885ec960..e526acb3e7 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -35,6 +35,7 @@ #include "road_func.h" #include "water.h" #include "station_func.h" +#include "widget_type.h" #include "zoom_func.h" #include "sortlist_type.h" @@ -219,7 +220,7 @@ static const NWidgetPart _nested_company_finances_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_CF_CAPTION), SetDataTip(STR_FINANCES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_IMGBTN, COLOUR_GREY, WID_CF_TOGGLE_SIZE), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW), + //NWidget(WWT_IMGBTN, COLOUR_GREY, WID_CF_TOGGLE_SIZE), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), EndContainer(), @@ -528,7 +529,7 @@ public: uint Height(uint width) const { - return max(FONT_HEIGHT_NORMAL, ScaleGUITrad(12) + 2); + return GetMinSizing(NWST_STEP, max(FONT_HEIGHT_NORMAL, ScaleGUITrad(12) + 2)); } bool Selectable() const @@ -1158,7 +1159,7 @@ static const NWidgetPart _nested_select_company_manager_face_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetDataTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_FACE_ADVANCED_TOOLTIP), + //NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_FACE_ADVANCED_TOOLTIP), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY, WID_SCMF_SELECT_FACE), NWidget(NWID_SPACER), SetMinimalSize(0, 2), @@ -1181,102 +1182,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), @@ -1326,7 +1337,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); } } @@ -1376,6 +1387,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++) { @@ -1519,12 +1534,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: @@ -1536,7 +1551,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 732ace6a2b..3edf53b433 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -417,6 +417,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) { @@ -1959,6 +1973,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/debug.cpp b/src/debug.cpp index 13df98db34..5c140122a6 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 #if defined(_WIN32) #include "os/windows/win32.h" @@ -111,6 +114,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 39accd65f1..22e14c7ad6 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(), @@ -331,7 +331,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; } @@ -341,26 +341,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); } } @@ -400,7 +402,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]; @@ -680,6 +682,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 e2224dfa28..87a0342efb 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 "build_confirmation_func.h" #include "widgets/dock_widget.h" @@ -100,11 +101,12 @@ struct BuildDocksToolbarWindow : Window { this->last_clicked_widget = WID_DT_INVALID; this->InitNested(window_number); this->OnInvalidateData(); - if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this); + if (_settings_client.gui.link_terraform_toolbar || _settings_client.gui.compact_vertical_toolbar) ShowTerraformToolbar(); } ~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,22 @@ 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_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)); + VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_BUILD_STATION); break; } + case WID_DT_DEPOT: // Build depot button 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,16 +206,26 @@ 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(); } + MoveAllWindowsOffScreen(); } 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,24 +241,73 @@ 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), CcPlaySound_SPLAT_WATER); 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; } + MoveAllHiddenWindowsBackToScreen(); } } virtual void OnPlaceObjectAbort() { + MoveAllHiddenWindowsBackToScreen(); this->RaiseButtons(); + if (ConfirmationWindowShown() && _ctrl_pressed) return; DeleteWindowById(WC_BUILD_STATION, TRANSPORT_WATER); DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_WATER); DeleteWindowById(WC_SELECT_STATION, 0); - 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 +397,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 +423,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 +436,7 @@ static WindowDesc _build_docks_scen_toolbar_desc( */ Window *ShowBuildDocksScenToolbar() { + DeleteToolbarLinkedWindows(); return AllocateWindowDescFront(&_build_docks_scen_toolbar_desc, TRANSPORT_WATER); } @@ -556,10 +607,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/economy.cpp b/src/economy.cpp index 32c6b85862..fc2759bd2c 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1705,7 +1705,9 @@ static void LoadUnloadVehicle(Vehicle *front) } } - amount_unloaded = v->cargo.Unload(amount_unloaded, &ge->cargo, payment); + if (payment != NULL) { + amount_unloaded = v->cargo.Unload(amount_unloaded, &ge->cargo, payment); + } remaining = v->cargo.UnloadCount() > 0; if (amount_unloaded > 0) { dirty_vehicle = true; diff --git a/src/error_gui.cpp b/src/error_gui.cpp index 1c59b7e8d0..90f1698f1b 100644 --- a/src/error_gui.cpp +++ b/src/error_gui.cpp @@ -37,7 +37,10 @@ static const NWidgetPart _nested_errmsg_widgets[] = { NWidget(WWT_CAPTION, COLOUR_RED, WID_EM_CAPTION), SetDataTip(STR_ERROR_MESSAGE_CAPTION, STR_NULL), EndContainer(), NWidget(WWT_PANEL, COLOUR_RED), - NWidget(WWT_EMPTY, COLOUR_RED, WID_EM_MESSAGE), SetPadding(0, 2, 0, 2), SetMinimalSize(236, 32), + NWidget(WWT_TEXT, COLOUR_RED), SetDataTip(STR_EMPTY, STR_NULL), // Add some borders + NWidget(WWT_EMPTY, COLOUR_RED, WID_EM_MESSAGE), SetPadding(4, 4, 4, 4), SetMinimalSize(236, 32), + NWidget(WWT_TEXT, COLOUR_RED), SetDataTip(STR_EMPTY, STR_NULL), + NWidget(WWT_PUSHTXTBTN, COLOUR_RED, WID_EM_CLOSE), SetPadding(4, 4, 4, 4), SetDataTip(STR_BUTTON_OK, STR_NULL), EndContainer(), }; @@ -54,10 +57,13 @@ static const NWidgetPart _nested_errmsg_face_widgets[] = { NWidget(WWT_CAPTION, COLOUR_RED, WID_EM_CAPTION), SetDataTip(STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY, STR_NULL), EndContainer(), NWidget(WWT_PANEL, COLOUR_RED), + NWidget(WWT_TEXT, COLOUR_RED), SetDataTip(STR_EMPTY, STR_NULL), // Add some borders NWidget(NWID_HORIZONTAL), SetPIP(2, 1, 2), - NWidget(WWT_EMPTY, COLOUR_RED, WID_EM_FACE), SetMinimalSize(92, 119), SetFill(0, 1), SetPadding(2, 0, 1, 0), - NWidget(WWT_EMPTY, COLOUR_RED, WID_EM_MESSAGE), SetFill(0, 1), SetMinimalSize(238, 123), + NWidget(WWT_EMPTY, COLOUR_RED, WID_EM_FACE), SetMinimalSize(92, 119), SetFill(0, 1), SetPadding(4, 4, 4, 4), + NWidget(WWT_EMPTY, COLOUR_RED, WID_EM_MESSAGE), SetFill(0, 1), SetMinimalSize(238, 123), SetPadding(4, 4, 4, 4), EndContainer(), + NWidget(WWT_TEXT, COLOUR_RED), SetDataTip(STR_EMPTY, STR_NULL), + NWidget(WWT_PUSHTXTBTN, COLOUR_RED, WID_EM_CLOSE), SetPadding(4, 4, 4, 4), SetDataTip(STR_BUTTON_OK, STR_NULL), EndContainer(), }; @@ -320,6 +326,18 @@ public: return ES_HANDLED; } + virtual void OnClick(Point pt, int widget, int click_count) + { + switch (widget) { + case WID_EM_CLOSE: + delete this; + break; + + default: + break; + } + } + /** * Check whether the currently shown error message was critical or not. * @return True iff the message was critical. diff --git a/src/fileio.cpp b/src/fileio.cpp index 0e6d86e3c7..e5e2875b87 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); @@ -1279,6 +1283,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 58242e71e2..55ff76e6bd 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -36,11 +36,15 @@ #include "table/strings.h" #include "safeguards.h" +#ifdef __ANDROID__ +#include +#endif 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"; /** @@ -121,6 +125,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(), @@ -219,7 +226,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(), @@ -357,6 +364,7 @@ public: this->LowerWidget(WID_SL_DRIVES_DIRECTORIES_LIST); this->querystrings[WID_SL_FILTER] = &this->filter_editbox; this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR; + if (this->fop == SLO_SAVE) 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. */ @@ -450,7 +458,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[GetDetailedFileType(item->type)]); + DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(y, this->resize.step_height), item->title, _fios_colours[GetDetailedFileType(item->type)]); y += this->resize.step_height; if (y >= this->vscroll->GetCapacity() * this->resize.step_height + r.top + WD_FRAMERECT_TOP) break; } @@ -561,8 +569,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: { @@ -719,6 +727,27 @@ 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, lastof(savePath)); +#ifdef __ANDROID__ + if (!SDL_ANDROID_CloudLoad(savePath, NULL, "OpenTTD")) { + break; + } +#endif + _file_to_saveload.SetMode(FIOS_TYPE_FILE); + _file_to_saveload.SetName(savePath); + _file_to_saveload.SetTitle("Network Save"); + _switch_mode = SM_LOAD_GAME; + break; + } } } diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 2811f17989..3677441a2b 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -398,7 +398,7 @@ static void LoadFreeTypeFont(FontSize fs) return; found_face: - new FreeTypeFontCache(fs, face, settings->size); + new FreeTypeFontCache(fs, face, RescaleFrom854x480(settings->size)); } @@ -479,7 +479,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 4279d60f3b..39e7b2eca9 100644 --- a/src/fontdetection.cpp +++ b/src/fontdetection.cpp @@ -663,7 +663,8 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i if (split != NULL) *split = '\0'; /* First create a pattern to match the wanted language. */ - FcPattern *pat = FcNameParse((FcChar8*)lang); + //FcPattern *pat = FcNameParse((FcChar8*)lang); + FcPattern *pat = FcPatternCreate(); /* We only want to know the filename. */ FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SPACING, FC_SLANT, FC_WEIGHT, NULL); /* Get the list of filenames matching the wanted language. */ @@ -676,6 +677,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]; @@ -685,28 +687,32 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i if (res != FcResultMatch || file == NULL) { continue; } + DEBUG(freetype, 1, "Got font %s", file); + int missing = 0; /* Get a font with the right spacing .*/ int value = 0; FcPatternGetInteger(font, FC_SPACING, 0, &value); - if (callback->Monospace() != (value == FC_MONO) && value != FC_DUAL) continue; + if (callback->Monospace() != (value == FC_MONO) && value != FC_DUAL) missing += 1; /* Do not use those that explicitly say they're slanted. */ FcPatternGetInteger(font, FC_SLANT, 0, &value); - if (value != 0) continue; + if (value != 0) missing += 1; /* We want the fatter font as they look better at small sizes. */ FcPatternGetInteger(font, FC_WEIGHT, 0, &value); - if (value <= best_weight) continue; + if (value <= best_weight) missing += 1; callback->SetFontNames(settings, (const char*)file); - bool missing = callback->FindMissingGlyphs(NULL); - DEBUG(freetype, 1, "Font \"%s\" misses%s glyphs", file, missing ? "" : " no"); + 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; + if (missing == 0) break; } } @@ -714,6 +720,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 b22ba5287e..76aa7a5452 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -29,6 +29,7 @@ #include "saveload/saveload.h" #include "progress.h" #include "error.h" +#include "settings_gui.h" #include "widgets/genworld_widget.h" @@ -63,47 +64,43 @@ 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), NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_MAPSIZE, STR_MAPGEN_MAPSIZE_TOOLTIP), SetFill(1, 1), + NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_BY, STR_NULL), SetPadding(1, 0, 0, 0), SetFill(1, 1), NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_LAND_GENERATOR, STR_NULL), SetFill(1, 1), NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_NUMBER_OF_TOWNS, STR_NULL), SetFill(1, 1), NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_TERRAIN_TYPE, STR_NULL), SetFill(1, 1), NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_VARIETY, STR_NULL), SetFill(1, 1), NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_QUANTITY_OF_SEA_LAKES, STR_NULL), SetFill(1, 1), NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_TREE_PLACER, STR_NULL), SetFill(1, 1), - NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_BORDER_TYPE, STR_NULL), SetFill(1, 1), EndContainer(), /* Widgets at the right of the labels. */ NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 4, 0), /* Mapsize X * Y. */ - NWidget(NWID_HORIZONTAL), SetPIP(0, 4, 0), - NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_MAPSIZE_X_PULLDOWN), SetDataTip(STR_JUST_INT, STR_MAPGEN_MAPSIZE_TOOLTIP), SetFill(1, 0), - NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_BY, STR_NULL), SetPadding(1, 0, 0, 0), SetFill(1, 1), - NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_MAPSIZE_Y_PULLDOWN), SetDataTip(STR_JUST_INT, STR_MAPGEN_MAPSIZE_TOOLTIP), SetFill(1, 0), - EndContainer(), + NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_MAPSIZE_X_PULLDOWN), SetDataTip(STR_JUST_INT, STR_MAPGEN_MAPSIZE_TOOLTIP), SetFill(1, 0), + NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_MAPSIZE_Y_PULLDOWN), SetDataTip(STR_JUST_INT, STR_MAPGEN_MAPSIZE_TOOLTIP), SetFill(1, 0), NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_LANDSCAPE_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_TOWN_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_TERRAIN_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_VARIETY_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_WATER_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_TREE_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), - NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_BORDERS_RANDOM), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), EndContainer(), EndContainer(), NWidget(NWID_VERTICAL), SetPIP(0, 4, 0), @@ -115,6 +112,7 @@ static const NWidgetPart _nested_generate_landscape_widgets[] = { NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_NUMBER_OF_INDUSTRIES, STR_NULL), SetFill(1, 1), NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_SMOOTHNESS, STR_NULL), SetFill(1, 1), NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_QUANTITY_OF_RIVERS, STR_NULL), SetFill(1, 1), + NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_BORDER_TYPE, STR_NULL), SetFill(1, 1), EndContainer(), NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 4, 0), /* Max. heightlevel. */ @@ -138,6 +136,7 @@ static const NWidgetPart _nested_generate_landscape_widgets[] = { NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_INDUSTRY_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_SMOOTHNESS_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_RIVER_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), + NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_BORDERS_RANDOM), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0), EndContainer(), EndContainer(), NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, WID_GL_GENERATE_BUTTON), SetMinimalSize(84, 0), SetDataTip(STR_MAPGEN_GENERATE, STR_NULL), SetFill(1, 1), @@ -146,30 +145,12 @@ static const NWidgetPart _nested_generate_landscape_widgets[] = { NWidget(NWID_SPACER), SetMinimalSize(0, 4), /* Map borders buttons for each edge. */ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 0, 10), - NWidget(NWID_HORIZONTAL), SetPIP(0, 0, 3), - NWidget(NWID_SPACER), SetFill(1, 1), - NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_NORTHWEST, STR_NULL), SetPadding(1, 0, 0, 0), SetFill(0, 1), - EndContainer(), NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_NW), SetDataTip(STR_JUST_STRING, STR_MAPGEN_NORTHWEST), SetFill(1, 1), NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_NE), SetDataTip(STR_JUST_STRING, STR_MAPGEN_NORTHEAST), SetFill(1, 1), - NWidget(NWID_HORIZONTAL), SetPIP(3, 0, 0), - NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_NORTHEAST, STR_NULL), SetPadding(1, 0, 0, 0), SetFill(0, 1), - NWidget(NWID_SPACER), SetFill(1, 1), - EndContainer(), - EndContainer(), - NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 0, 10), - NWidget(NWID_HORIZONTAL), SetPIP(0, 0, 3), - NWidget(NWID_SPACER), SetFill(1, 1), - NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_SOUTHWEST, STR_NULL), SetPadding(1, 0, 0, 0), SetFill(0, 1), - EndContainer(), NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_SW), SetDataTip(STR_JUST_STRING, STR_MAPGEN_SOUTHWEST), SetFill(1, 1), NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_SE), SetDataTip(STR_JUST_STRING, STR_MAPGEN_SOUTHEAST), SetFill(1, 1), - NWidget(NWID_HORIZONTAL), SetPIP(3, 0, 0), - NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_SOUTHEAST, STR_NULL), SetPadding(1, 0, 0, 0), SetFill(0, 1), - NWidget(NWID_SPACER), SetFill(1, 1), - EndContainer(), EndContainer(), - NWidget(NWID_SPACER), SetMinimalSize(0, 9), SetFill(1, 1), + NWidget(NWID_SPACER), SetMinimalSize(0, 10), EndContainer(), }; @@ -458,6 +439,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: @@ -468,7 +450,8 @@ struct GenerateLandscapeWindow : public Window { case WID_GL_HEIGHTMAP_SIZE_TEXT: SetDParam(0, this->x); SetDParam(1, this->y); - *size = maxdim(*size, GetStringBoundingBox(STR_MAPGEN_HEIGHTMAP_SIZE)); + //*size = maxdim(*size, GetStringBoundingBox(STR_MAPGEN_HEIGHTMAP_SIZE)); + size->height = SETTING_BUTTON_HEIGHT; break; case WID_GL_TOWN_PULLDOWN: @@ -492,18 +475,19 @@ struct GenerateLandscapeWindow : public Window { case WID_GL_VARIETY_PULLDOWN: strs = _variety; break; case WID_GL_HEIGHTMAP_ROTATION_PULLDOWN: strs = _rotation; break; case WID_GL_BORDERS_RANDOM: - *size = maxdim(GetStringBoundingBox(STR_MAPGEN_BORDER_RANDOMIZE), GetStringBoundingBox(STR_MAPGEN_BORDER_MANUAL)); + //*size = maxdim(GetStringBoundingBox(STR_MAPGEN_BORDER_RANDOMIZE), GetStringBoundingBox(STR_MAPGEN_BORDER_MANUAL)); break; case WID_GL_WATER_NE: case WID_GL_WATER_NW: case WID_GL_WATER_SE: case WID_GL_WATER_SW: - *size = maxdim(GetStringBoundingBox(STR_MAPGEN_BORDER_RANDOM), maxdim(GetStringBoundingBox(STR_MAPGEN_BORDER_WATER), GetStringBoundingBox(STR_MAPGEN_BORDER_FREEFORM))); + //*size = maxdim(GetStringBoundingBox(STR_MAPGEN_BORDER_RANDOM), maxdim(GetStringBoundingBox(STR_MAPGEN_BORDER_WATER), GetStringBoundingBox(STR_MAPGEN_BORDER_FREEFORM))); break; case WID_GL_HEIGHTMAP_NAME_TEXT: size->width = 0; + size->height = SETTING_BUTTON_HEIGHT; break; default: @@ -947,7 +931,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) @@ -1066,11 +1052,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 7a6b827b7a..5ba8f0dc62 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -35,14 +35,19 @@ 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; +bool _restart_game; GameMode _game_mode; SwitchMode _switch_mode; ///< The next mainloop command. PauseModeByte _pause_mode; @@ -849,6 +854,50 @@ void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, } } +/** + * Draw a sprite, centered at x:y, not in a viewport + * @param img Image number to draw + * @param pal Palette to use. + * @param x Left coordinate of image in pixels + * @param y Top coordinate of image in pixels + * @param sub If available, draw only specified part of the sprite + * @param zoom Zoom level of sprite + */ +void DrawSpriteCentered(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom) +{ + Dimension size = GetSpriteSize(img, NULL, zoom); + DrawSprite(img, pal, x - size.width / 2, y - size.height / 2, sub, zoom); +} + +/** + * Draw a sprite, centered in rect, not in a viewport + * @param img Image number to draw + * @param pal Palette to use. + * @param left Left coordinate of image bounding box in pixels + * @param top Top coordinate of image bounding box in pixels + * @param right Right coordinate of image bounding box in pixels + * @param bottom Bottom coordinate of image bounding box in pixels + * @param sub If available, draw only specified part of the sprite + * @param zoom Zoom level of sprite + */ +void DrawSpriteCenteredRect(SpriteID img, PaletteID pal, int left, int top, int right, int bottom, const SubSprite *sub, ZoomLevel zoom) +{ + DrawSpriteCentered(img, pal, (left + right) / 2, (top + bottom) / 2, sub, zoom); +} + +/** + * Draw a sprite, centered in rect, not in a viewport + * @param img Image number to draw + * @param pal Palette to use. + * @param rect Image bounding box in pixels + * @param sub If available, draw only specified part of the sprite + * @param zoom Zoom level of sprite + */ +void DrawSpriteCenteredRect(SpriteID img, PaletteID pal, const Rect &rect, const SubSprite *sub, ZoomLevel zoom) +{ + DrawSpriteCenteredRect(img, pal, rect.left, rect.top, rect.right, rect.bottom, sub, zoom); +} + /** * The code for setting up the blitter mode and sprite information before finally drawing the sprite. * @param sprite The sprite to draw. @@ -1200,6 +1249,8 @@ void ScreenSizeChanged() /* screen size changed and the old bitmap is invalid now, so we don't want to undraw it */ _cursor.visible = false; + + CheckWindowMinSizings(); } void UndrawMouseCursor() @@ -1712,3 +1763,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 9f7cb9153d..4486874462 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) @@ -92,6 +96,9 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo); Dimension GetSpriteSize(SpriteID sprid, Point *offset = NULL, ZoomLevel zoom = ZOOM_LVL_GUI); void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = NULL); void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = NULL, ZoomLevel zoom = ZOOM_LVL_GUI); +void DrawSpriteCentered(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = NULL, ZoomLevel zoom = ZOOM_LVL_GUI); +void DrawSpriteCenteredRect(SpriteID img, PaletteID pal, int left, int top, int right, int bottom, const SubSprite *sub = NULL, ZoomLevel zoom = ZOOM_LVL_GUI); +void DrawSpriteCenteredRect(SpriteID img, PaletteID pal, const Rect &r, const SubSprite *sub = NULL, ZoomLevel zoom = ZOOM_LVL_GUI); /** How to align the to-be drawn text. */ enum StringAlignment { @@ -185,6 +192,39 @@ int GetCharacterHeight(FontSize size); /** Height of characters in the large (#FS_MONO) font. @note Some characters may be oversized. */ #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, uint8 threshold = 128); diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 39df8ab6e2..e36f64e760 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); @@ -472,7 +473,7 @@ protected: format_str_y_axis(format_str_y_axis) { SetWindowDirty(WC_GRAPH_LEGEND, 0); - this->num_vert_lines = 24; + this->num_vert_lines = 12; this->graph_widget = widget; } @@ -631,7 +632,6 @@ static const NWidgetPart _nested_operating_profit_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GRAPH_OPERATING_PROFIT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CV_KEY_BUTTON), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), @@ -641,6 +641,7 @@ static const NWidgetPart _nested_operating_profit_widgets[] = { NWidget(WWT_EMPTY, COLOUR_GREY, WID_CV_GRAPH), SetMinimalSize(576, 160), SetFill(1, 1), SetResize(1, 1), NWidget(NWID_VERTICAL), NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CV_KEY_BUTTON), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP), SetSizingType(NWST_STEP), NWidget(WWT_RESIZEBOX, COLOUR_GREY, WID_CV_RESIZE), EndContainer(), EndContainer(), @@ -682,7 +683,6 @@ static const NWidgetPart _nested_income_graph_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GRAPH_INCOME_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CV_KEY_BUTTON), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), @@ -692,6 +692,7 @@ static const NWidgetPart _nested_income_graph_widgets[] = { NWidget(WWT_EMPTY, COLOUR_GREY, WID_CV_GRAPH), SetMinimalSize(576, 128), SetFill(1, 1), SetResize(1, 1), NWidget(NWID_VERTICAL), NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CV_KEY_BUTTON), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP), SetSizingType(NWST_STEP), NWidget(WWT_RESIZEBOX, COLOUR_GREY, WID_CV_RESIZE), EndContainer(), EndContainer(), @@ -731,7 +732,6 @@ static const NWidgetPart _nested_delivered_cargo_graph_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GRAPH_CARGO_DELIVERED_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CV_KEY_BUTTON), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), @@ -741,6 +741,7 @@ static const NWidgetPart _nested_delivered_cargo_graph_widgets[] = { NWidget(WWT_EMPTY, COLOUR_GREY, WID_CV_GRAPH), SetMinimalSize(576, 128), SetFill(1, 1), SetResize(1, 1), NWidget(NWID_VERTICAL), NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CV_KEY_BUTTON), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP), SetSizingType(NWST_STEP), NWidget(WWT_RESIZEBOX, COLOUR_GREY, WID_CV_RESIZE), EndContainer(), EndContainer(), @@ -786,8 +787,6 @@ static const NWidgetPart _nested_performance_history_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GRAPH_COMPANY_PERFORMANCE_RATINGS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_PHG_DETAILED_PERFORMANCE), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_PERFORMANCE_DETAIL_KEY, STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_PHG_KEY), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), @@ -797,6 +796,8 @@ static const NWidgetPart _nested_performance_history_widgets[] = { NWidget(WWT_EMPTY, COLOUR_GREY, WID_PHG_GRAPH), SetMinimalSize(576, 224), SetFill(1, 1), SetResize(1, 1), NWidget(NWID_VERTICAL), NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_PHG_DETAILED_PERFORMANCE), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_PERFORMANCE_DETAIL_KEY, STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP), SetSizingType(NWST_STEP), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_PHG_KEY), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP), SetSizingType(NWST_STEP), NWidget(WWT_RESIZEBOX, COLOUR_GREY, WID_PHG_RESIZE), EndContainer(), EndContainer(), @@ -836,7 +837,6 @@ static const NWidgetPart _nested_company_value_graph_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GRAPH_COMPANY_VALUES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CV_KEY_BUTTON), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), @@ -846,6 +846,7 @@ static const NWidgetPart _nested_company_value_graph_widgets[] = { NWidget(WWT_EMPTY, COLOUR_GREY, WID_CV_GRAPH), SetMinimalSize(576, 224), SetFill(1, 1), SetResize(1, 1), NWidget(NWID_VERTICAL), NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CV_KEY_BUTTON), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP), SetSizingType(NWST_STEP), NWidget(WWT_RESIZEBOX, COLOUR_GREY, WID_CV_RESIZE), EndContainer(), EndContainer(), @@ -1127,6 +1128,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 /** @@ -1173,8 +1175,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; @@ -1187,7 +1188,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); @@ -1220,6 +1221,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 b5f33ff52a..b9a5eabedc 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -48,8 +48,7 @@ static const NWidgetPart _nested_group_widgets[] = { NWidget(NWID_HORIZONTAL), /* left part */ NWidget(NWID_VERTICAL), - NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalTextLines(1, WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM), SetFill(1, 0), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_GL_ALL_VEHICLES), SetFill(1, 0), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_GL_ALL_VEHICLES), SetFill(1, 0), SetMinimalTextLines(1, WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY, WID_GL_DEFAULT_VEHICLES), SetFill(1, 0), EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(WWT_MATRIX, COLOUR_GREY, WID_GL_LIST_GROUP), SetMatrixDataTip(1, 0, STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP), @@ -74,7 +73,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(), @@ -82,7 +81,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), @@ -195,8 +194,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); @@ -218,6 +218,7 @@ 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 + @@ -241,7 +242,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; @@ -367,7 +368,7 @@ 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; + size->height = (this->vli.vtype >= VEH_SHIP ? 3.5 : 7) * 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; @@ -379,7 +380,7 @@ public: max_icon_height += (FONT_HEIGHT_NORMAL * 3) + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; /* 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; } @@ -400,7 +401,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: { diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 78bf3f4a01..483094344e 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -261,7 +261,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) @@ -278,8 +278,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; /** The largest allowed minimum-width of the window, given in line heights */ static const int MAX_MINWIDTH_LINEHEIGHTS = 20; @@ -403,6 +401,10 @@ public: this->SetButtons(); } + ~BuildIndustryWindow() { + if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort(); + } + virtual void OnInit() { this->SetupArrays(); @@ -417,8 +419,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; @@ -499,20 +501,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) { @@ -523,8 +527,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; } @@ -643,6 +647,21 @@ public: virtual void OnPlaceObject(Point pt, TileIndex tile) { + VpStartPlaceSizing(tile, VPM_SINGLE_TILE, DDSP_SINGLE_TILE); + MoveAllWindowsOffScreen(); + } + + 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); + + MoveAllHiddenWindowsBackToScreen(); bool success = true; /* We do not need to protect ourselves against "Random Many Industries" in this mode */ const IndustrySpec *indsp = GetIndustrySpec(this->selected_type); @@ -660,14 +679,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 */ @@ -704,6 +723,7 @@ public: virtual void OnPlaceObjectAbort() { + MoveAllHiddenWindowsBackToScreen(); this->RaiseButtons(); } @@ -726,7 +746,7 @@ public: void ShowBuildIndustryWindow() { if (_game_mode != GM_EDITOR && !Company::IsValidID(_local_company)) return; - if (BringWindowToFrontById(WC_BUILD_INDUSTRY, 0)) return; + DeleteToolbarLinkedWindows(); new BuildIndustryWindow(); } @@ -869,7 +889,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; } @@ -884,8 +904,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 */ @@ -897,7 +919,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 */ @@ -945,12 +967,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--; @@ -1166,7 +1190,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(), @@ -1371,7 +1395,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; @@ -1414,7 +1438,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/ini.cpp b/src/ini.cpp index 6767d8525d..ae0750ffd1 100644 --- a/src/ini.cpp +++ b/src/ini.cpp @@ -15,7 +15,7 @@ #include "string_func.h" #include "fileio_func.h" -#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500) +#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500) || defined(__ANDROID__) # include #endif diff --git a/src/intro_gui.cpp b/src/intro_gui.cpp index 3659b033cf..d0ac774027 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" @@ -61,9 +62,13 @@ struct SelectGameWindow : public Window { virtual void OnInit() { bool missing_sprites = _missing_extra_graphics > 0 && !IsReleasedVersion(); + missing_sprites = false; this->GetWidget(WID_SGI_BASESET_SELECTION)->SetDisplayedPlane(missing_sprites ? 0 : SZSP_NONE); bool missing_lang = _current_language->missing >= _settings_client.gui.missing_strings_threshold && !IsReleasedVersion(); +#ifdef __ANDROID__ + missing_lang = false; +#endif this->GetWidget(WID_SGI_TRANSLATION_SELECTION)->SetDisplayedPlane(missing_lang ? 0 : SZSP_NONE); } @@ -158,13 +163,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), @@ -258,11 +264,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/afrikaans.txt b/src/lang/afrikaans.txt index 3fd6ff7dae..1a7376de1f 100644 --- a/src/lang/afrikaans.txt +++ b/src/lang/afrikaans.txt @@ -4950,3 +4950,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/arabic_egypt.txt b/src/lang/arabic_egypt.txt index 2f658115c7..c95ca0aa87 100644 --- a/src/lang/arabic_egypt.txt +++ b/src/lang/arabic_egypt.txt @@ -4409,3 +4409,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/basque.txt b/src/lang/basque.txt index e5ea6a873b..d22da6cdec 100644 --- a/src/lang/basque.txt +++ b/src/lang/basque.txt @@ -4816,3 +4816,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/belarusian.txt b/src/lang/belarusian.txt index 5560ef785b..9928e3254b 100644 --- a/src/lang/belarusian.txt +++ b/src/lang/belarusian.txt @@ -5457,3 +5457,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 660e9caa7c..7abcb2bf9e 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -5027,3 +5027,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/bulgarian.txt b/src/lang/bulgarian.txt index 50229f6d0a..b6a787df7e 100644 --- a/src/lang/bulgarian.txt +++ b/src/lang/bulgarian.txt @@ -4879,3 +4879,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index fa6b17868e..d915b8a058 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -5068,3 +5068,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/croatian.txt b/src/lang/croatian.txt index f8d00dc199..5b434d912e 100644 --- a/src/lang/croatian.txt +++ b/src/lang/croatian.txt @@ -5201,3 +5201,41 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL :{BLACK}Uputstva +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}Prikaži legendu mape / opis simbola na mapi +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :Okomita alatna traka: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :Glavna alatna traka je podijeljena na dvije okomite alatne trake na rubovima ekrana +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR :Kompaktna okomita alatna traka: {STRING} +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR_HELPTEXT :Ne postoji dugme 'Izmijeni alatnu traku' u okomitoj alatnoj traci ali postoje pod-meniji +STR_CONFIG_SETTING_BUTTON_SIZE :{BLACK}Veličina tipki +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :{BLACK}Veličina svih elemenata korisničkog sučelja +STR_CONFIG_SETTING_FONT_SIZE :{BLACK}Veličina fonta +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :{BLACK}Veličina svih fontova u igri +STR_CONFIG_SETTING_BUILD_CONFIRMATION :Potvrdi akcije: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :Prikaži dijalog potvrde pri gradnji cesta i stanica +STR_CONFIG_SETTING_WINDOWS_TITLEBARS :{BLACK}Naslovne trake +STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT :{BLACK}Prikaži naslovne trake za sve prozore ili ih sakrij za uštedu prostora na ekranu +STR_CONFIG_SETTING_WINDOWS_DECORATIONS :Ukrasi prozora: {STRING} +STR_CONFIG_SETTING_WINDOWS_DECORATIONS_HELPTEXT :Ukrasi na rubovima prozora +STR_CONFIG_SETTING_VIDEO_8BPP :{BLACK}8 bita +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :{BLACK}Postavi dubinu boja videa na 8 bitova po pikselu, ovaj način podržava animaciju vode +STR_CONFIG_SETTING_VIDEO_16BPP :{BLACK}16 bita +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :{BLACK}Postavi dubinu boja videa na 16 bitova po pikselu, za ovo treba restart, ovaj način ne podržava animaciju vode +STR_CONFIG_SETTING_VIDEO_24BPP :{BLACK}24 bita +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :{BLACK}Postavi dubinu boja videa na 24 bita po pikselu, ovaj način podržava animaciju vode +STR_TABLET_CLOSE_TOOLTIP :{BLACK}Zatvori sve otvorene prozore (osim zakačenih) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}Pritisnuti za procjenu troškova izvođenja neke akcije +STR_TABLET_CTRL_TOOLTIP :{BLACK}Koristiti za sve akcije za koje se koristi tipka "CTRL" +STR_TUTORIAL_WINDOW_TITLE :{BLACK}Videi za učenje +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Otvori prikazivač videa za gledanje videa za učenje +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}Građenje cesta i stanica, kupnja vozila +STR_TUTORIAL_RAILWAYS :{BLACK}Pruge i vlakovi +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}Cestovna vozila +STR_TUTORIAL_SHIPS :{BLACK}Brodovi i dokovi +STR_TUTORIAL_CARGO :{BLACK}Vrste tereta +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}Učitaj sa mreže +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}Učitaj igru sa mrežne pohrane podataka +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}Spremi na mrežu +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}Spremi igru na mrežnu pohranu podataka diff --git a/src/lang/czech.txt b/src/lang/czech.txt index 2e622b1422..ebb716e0f8 100644 --- a/src/lang/czech.txt +++ b/src/lang/czech.txt @@ -5214,3 +5214,41 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL :{BLACK}Tutoriál +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}Zobrazit legendu mapy / popis symbolů na mapě +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :Svislý panel nástrojů: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :Hlavní panel nástrojů je rozdělen ma dva svislé panely nástrojů na krajích obrazovky +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR :Kompaktní svislý panel nástrojů: {STRING} +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR_HELPTEXT :Žádné 'Přepnout panely nástrojů' tlačítko ve svislém panelu nástrojů, avšak více podmenu +STR_CONFIG_SETTING_BUTTON_SIZE :{BLACK}Velikost tlačítka +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :{BLACK}Velikost všech prvků uživatelského rozhraní +STR_CONFIG_SETTING_FONT_SIZE :{BLACK}Veliksot fontu +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :{BLACK}Velikost všech fontů ve hře +STR_CONFIG_SETTING_BUILD_CONFIRMATION :Potvrdit akce: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :Zobrazitr potvrzující okno při stavbě silnic a stanic +STR_CONFIG_SETTING_WINDOWS_TITLEBARS :{BLACK}Titulní pruhy +STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT :{BLACK}Zobrazit titulní pruhy u všech oken, nebo je schovat pro ušetření místa na displeji +STR_CONFIG_SETTING_WINDOWS_DECORATIONS :Ozdoby oken: {STRING} +STR_CONFIG_SETTING_WINDOWS_DECORATIONS_HELPTEXT :Ozdoby na hranách oken +STR_CONFIG_SETTING_VIDEO_8BPP :{BLACK}8 bitů +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :{BLACK}Nastavit hloubku videa na 8 bitů / pixel, tento mód podporuje animaci vody. +STR_CONFIG_SETTING_VIDEO_16BPP :{BLACK}16 bitů +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :{BLACK}Nastavit hloubku videa na 16 bitů / pixel, vyžaduje restart, tento mód nepodporuje animaci vody. +STR_CONFIG_SETTING_VIDEO_24BPP :{BLACK}24 bitů +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :{BLACK}Nastavit hloubku videa na 24 bitů / pixel, tento mód podporuje animaci vody. +STR_TABLET_CLOSE_TOOLTIP :{BLACK}Zavřít všechna otevřená okna (vyjma připnutých) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}Podrž pro zobrazení odhadované ceny akce +STR_TABLET_CTRL_TOOLTIP :{BLACK}Použij pro akce, které užívají klávesu"CTRL" +STR_TUTORIAL_WINDOW_TITLE :{BLACK}Tutoriálová videa +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Otevřít video přehrávač ke shlédnutí tutoriálových videí +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}Stavba silnic a stanic, koupě vozidel +STR_TUTORIAL_RAILWAYS :{BLACK}Železnice a vlaky +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}Silniční vozidla +STR_TUTORIAL_SHIPS :{BLACK}Lodě a doky +STR_TUTORIAL_CARGO :{BLACK}Typy nákladů +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}Nahrát ze sítě +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}Nahrát hru ze síťového uložiště +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}Uložit na síť +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}Zálohovat hru na síťové uložiště diff --git a/src/lang/danish.txt b/src/lang/danish.txt index 28b0778a00..99fe68921d 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -5068,3 +5068,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index b837036998..ea507ae5fc 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -5068,3 +5068,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/english.txt b/src/lang/english.txt index b4688d5e27..5cf249d458 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -405,11 +405,11 @@ STR_MAP_MENU_SIGN_LIST :Sign list ############ range for town menu starts STR_TOWN_MENU_TOWN_DIRECTORY :Town directory -STR_TOWN_MENU_FOUND_TOWN :Found town -############ range ends here - -############ range for subsidies menu starts STR_SUBSIDIES_MENU_SUBSIDIES :Subsidies +STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY :Industry directory +STR_INDUSTRY_MENU_INDUSTRY_CHAIN :Industry chains +STR_INDUSTRY_MENU_FUND_NEW_INDUSTRY :Fund new industry +STR_TOWN_MENU_FOUND_TOWN :Found town ############ range ends here ############ range for graph menu starts @@ -427,12 +427,6 @@ STR_GRAPH_MENU_DETAILED_PERFORMANCE_RATING :Detailed perfor STR_GRAPH_MENU_HIGHSCORE :Highscore table ############ range ends here -############ range for industry menu starts -STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY :Industry directory -STR_INDUSTRY_MENU_INDUSTRY_CHAIN :Industry chains -STR_INDUSTRY_MENU_FUND_NEW_INDUSTRY :Fund new industry -############ range ends here - ############ range for railway construction menu starts STR_RAIL_MENU_RAILROAD_CONSTRUCTION :Railway construction STR_RAIL_MENU_ELRAIL_CONSTRUCTION :Electrified railway construction @@ -472,6 +466,7 @@ STR_NEWS_MENU_DELETE_ALL_MESSAGES :Delete all mess ############ 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 @@ -722,6 +717,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 @@ -1226,6 +1222,26 @@ 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 :Vertical toolbar: {STRING2} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :Main toolbar is split into two vertical toolbars on the sides of the screen +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR :Compact vertical toolbar: {STRING2} +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR_HELPTEXT :No 'Switch toolbars' button in the vertical toolbar, but more sub-menus +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_BUILD_CONFIRMATION :Confirm actions: {STRING2} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :Show confirmation dialog when building roads and stations +STR_CONFIG_SETTING_WINDOWS_TITLEBARS :{BLACK}Title bars +STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT :{BLACK}Show title bars for all windows, or hide them to save screen space +STR_CONFIG_SETTING_WINDOWS_DECORATIONS :Window decorations: {STRING2} +STR_CONFIG_SETTING_WINDOWS_DECORATIONS_HELPTEXT :Ornaments on window edges +STR_CONFIG_SETTING_VIDEO_8BPP :{BLACK}8 bit +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :{BLACK}Set video color depth to 8 bits per pixel, this video mode supports water animation +STR_CONFIG_SETTING_VIDEO_16BPP :{BLACK}16 bit +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :{BLACK}Set video color depth to 16 bits per pixel, this requires restart, this video mode does not support water animation +STR_CONFIG_SETTING_VIDEO_24BPP :{BLACK}24 bit +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :{BLACK}Set video color depth to 24 bits per pixel, this video mode supports water animation 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} @@ -2500,6 +2516,13 @@ 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 +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 @@ -2770,6 +2793,14 @@ STR_FRAMETIME_CAPTION_AI :AI {NUM} {RAW_S ############ End of leave-in-this-order +STR_TUTORIAL_WINDOW_TITLE :{BLACK}Tutorial videos +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Open a video player to watch tutorial videos +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}Building roads and stations, buying vehicles +STR_TUTORIAL_RAILWAYS :{BLACK}Railways and trains +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}Road vehicles +STR_TUTORIAL_SHIPS :{BLACK}Ships and docks +STR_TUTORIAL_CARGO :{BLACK}Cargo types + # Save/load game/scenario STR_SAVELOAD_SAVE_CAPTION :{WHITE}Save Game STR_SAVELOAD_LOAD_CAPTION :{WHITE}Load Game @@ -2788,6 +2819,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/lang/english_AU.txt b/src/lang/english_AU.txt index 4ca2bf1b59..d63f021e1d 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -4897,3 +4897,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index f2c0c8d321..9161686d9a 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -5068,3 +5068,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/esperanto.txt b/src/lang/esperanto.txt index c82ca05527..e367b6682c 100644 --- a/src/lang/esperanto.txt +++ b/src/lang/esperanto.txt @@ -4311,3 +4311,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index 458c9e9e15..38c8b62600 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -5033,3 +5033,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/faroese.txt b/src/lang/faroese.txt index b738ba9bbe..1b7b1a062c 100644 --- a/src/lang/faroese.txt +++ b/src/lang/faroese.txt @@ -4455,3 +4455,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index d8574e05e9..f6dc2c7054 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -5068,3 +5068,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/french.txt b/src/lang/french.txt index 41755d2b40..adb212fc83 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -5068,3 +5068,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/gaelic.txt b/src/lang/gaelic.txt index f2096687f1..013a1f808f 100644 --- a/src/lang/gaelic.txt +++ b/src/lang/gaelic.txt @@ -5404,3 +5404,41 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL :Oideachadh +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}Seall treòir a' mhapa / tuairisgeulan air samhlaidhean a' mhapa +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :Bàr-inneal inghearach: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :Thèid am prìomh bhàr-inneal a sgoltadh 'na bhàraichean-inneal inghearach ri dà thaobh an sgrìn +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR :Bàr-inneal inghearach dùmhlaichte: {STRING} +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR_HELPTEXT :Cha bhi putan air a' bhàr-inneal inghearach gus leum a ghearradh gu bàr-inneal eile ach bidh barrachd fo-chlàran-taice aige +STR_CONFIG_SETTING_BUTTON_SIZE :Meud nam putan +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :Meud aig a h-uile nì an eadar-aghaidh +STR_CONFIG_SETTING_FONT_SIZE :Meud a' chrutha-chlò +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :{BLACK}Am meud air gach cruth-clò a' gheama +STR_CONFIG_SETTING_BUILD_CONFIRMATION :Dearbhaich na gnìomhan: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :Seall còmhradh dearbhaidh le togail rathaidean is stèiseanan +STR_CONFIG_SETTING_WINDOWS_TITLEBARS :{BLACK}Bàraichean-tiotail +STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT :{BLACK}Seall bàr-tiotail air gach uinneag no falaich iad gus rum a shàbhaladh air an sgrìn +STR_CONFIG_SETTING_WINDOWS_DECORATIONS :Sgeadachadh nan uinneagan: {STRING} +STR_CONFIG_SETTING_WINDOWS_DECORATIONS_HELPTEXT :Sgeadachadh air oirean nan uinneagan +STR_CONFIG_SETTING_VIDEO_8BPP :8 biod +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :Suidhich doimhneachd nan dath aig a' video gu 8 biod gach piogsail. Cuiridh am modh video sin taic ri beòthachadh uisge +STR_CONFIG_SETTING_VIDEO_16BPP :16 biod +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :Suidhich doimhneachd nan dath aig a' video gu 16 biod gach piogsail. Bidh feum air ath-thòiseachadh. Cha chuir am modh video sin taic ri beòthachadh uisge +STR_CONFIG_SETTING_VIDEO_24BPP :24 biod +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :Suidhich doimhneachd nan dath aig a' video gu 24 biod gach piogsail. Cuiridh am modh video sin taic ri beòthachadh uisge +STR_TABLET_CLOSE_TOOLTIP :{BLACK}Dùin a h-uile uinneag (seach an fheadhainn phrìnichte) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}Brùth air gus tuairmse air cosgaisean gnìomha fhaighinn +STR_TABLET_CTRL_TOOLTIP :{BLACK}Cleachd e airson gnìomhan a chleachdas an iuchair "CTRL" +STR_TUTORIAL_WINDOW_TITLE :{BLACK}Videothan oideachaidh +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Fosgail cluicheadair video gus coimhead air videothan oideachaidh +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}Togail rathaidean is stèiseanan, ceannach charbadan +STR_TUTORIAL_RAILWAYS :{BLACK}Slighean rèile is trèanaichean +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}Carbadan-rathaid +STR_TUTORIAL_SHIPS :{BLACK}Longan is puirt +STR_TUTORIAL_CARGO :{BLACK}Seòrsaichean carago +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}Luchdaich on lìonra +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}Luchdaich geama o stòras an lìonraidh +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}Sàbhail dhan lìonra +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}Cuir lethbhreac-glèidhidh dhen gheama gu stòras an lìonraidh diff --git a/src/lang/galician.txt b/src/lang/galician.txt index f301e71f1f..6c8e3bf181 100644 --- a/src/lang/galician.txt +++ b/src/lang/galician.txt @@ -4969,3 +4969,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/german.txt b/src/lang/german.txt index 42490b2a39..1d7e4d8abb 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -5053,3 +5053,38 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL :Tutorial +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}Zeige Kartenlegende / Beschreibung der Kartensymbole +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :Vertikale Werkzeugsleiste: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :Hauptwerzeugleiste ist in zwei vertikale Leisten an den Bildschirmseiten aufgeteilt +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR :Kompakte vertikale Werkzeugleiste: {STRING} +STR_CONFIG_SETTING_BUTTON_SIZE :Schaltflächengröße +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :Größe aller Elemente der Benutzeroberfläche +STR_CONFIG_SETTING_FONT_SIZE :{BLACK}Schriftgröße +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :Größe aller Schriftarten +STR_CONFIG_SETTING_BUILD_CONFIRMATION :Aktionen bestätigen: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :Zeige Bestätigungsdialog bei Straßen- und Haltenstellebau +STR_CONFIG_SETTING_WINDOWS_TITLEBARS :{BLACK}Titelleisten +STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT :{BLACK}Zeige in allen Fenstern die Titelleiste an oder verbirg sie, um Platz zu sparen. +STR_CONFIG_SETTING_VIDEO_8BPP :8 bit +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :Setzt die Farbtiefe auf 8 Bits per Pixel. Dieser Modus unterstützt Wasseranimation +STR_CONFIG_SETTING_VIDEO_16BPP :16 bit +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :{BLACK}Setzt die Farbtiefe auf 16 Bit per Pixel. Erfordert einen Neustart. Dieser Modus unterstützt keine Wasseranimation +STR_CONFIG_SETTING_VIDEO_24BPP :24 bit +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :Setzt die Farbtiefe auf 24 Bits per Pixel. Dieser Modus unterstützt Wasseranimation +STR_TABLET_CLOSE_TOOLTIP :{BLACK}Schließe alle offene Fenster (außer festgepinnte) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}Drücke hier, um eine Kostenabschätzung für die Durchführung einer Aktion zu erhalten +STR_TABLET_CTRL_TOOLTIP :{BLACK}Für Aktionen benutzen, welche die "STRG" Taste benutzen +STR_TUTORIAL_WINDOW_TITLE :{BLACK}Tutorial Videos +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Öffne einen Videoplayer, um Tutorial videos anzuschauen +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}Strassen und Haltestellen bauen, Fahrzeuge kaufen +STR_TUTORIAL_RAILWAYS :{BLACK}Eisenbahnen und Züge +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}Straßenfahrzeuge +STR_TUTORIAL_SHIPS :{BLACK}Schiffe und Docks +STR_TUTORIAL_CARGO :{BLACK}Warentypen +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}Laden vom Netzwerk +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}Öffne ein Spiel aus dem Netzwerkspeicher +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}Speichern ins Netzwerk +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}Spiel zurück in den Netzwerkspeicher backupen diff --git a/src/lang/greek.txt b/src/lang/greek.txt index 7ea02340e4..d12be9ad74 100644 --- a/src/lang/greek.txt +++ b/src/lang/greek.txt @@ -5185,3 +5185,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/hebrew.txt b/src/lang/hebrew.txt index 05fb5fe1d7..f6d9a5eb82 100644 --- a/src/lang/hebrew.txt +++ b/src/lang/hebrew.txt @@ -5028,3 +5028,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt index c66e0fdf4f..8ce4f446fb 100644 --- a/src/lang/hungarian.txt +++ b/src/lang/hungarian.txt @@ -5173,3 +5173,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/icelandic.txt b/src/lang/icelandic.txt index 44f3b40598..bcb6dabb4c 100644 --- a/src/lang/icelandic.txt +++ b/src/lang/icelandic.txt @@ -4706,3 +4706,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt index fe1991d835..214c0d1de4 100644 --- a/src/lang/indonesian.txt +++ b/src/lang/indonesian.txt @@ -5000,3 +5000,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/irish.txt b/src/lang/irish.txt index 73a86c940b..112e9322da 100644 --- a/src/lang/irish.txt +++ b/src/lang/irish.txt @@ -4949,3 +4949,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/italian.txt b/src/lang/italian.txt index 3f1014cbf8..c0c5a57871 100644 --- a/src/lang/italian.txt +++ b/src/lang/italian.txt @@ -5098,3 +5098,35 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL :Istruzioni +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}Mostra la legenda della mappa / descrizione dei simboli della mappa +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :Barra degli strumenti verticale: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :La barra degli strumenti è divisa in due barre verticali sui lati dello schermo +STR_CONFIG_SETTING_BUTTON_SIZE :Dimensioni dei pulsanti +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :Dimensioni degli elementi dell'interfaccia +STR_CONFIG_SETTING_FONT_SIZE :Dimensioni dei caratteri +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :Dimensioni dei caratteri nel gioco +STR_CONFIG_SETTING_BUILD_CONFIRMATION :Conferma: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :Mostra il dialogo di conferma durante la costruzione di strade e stazioni +STR_CONFIG_SETTING_VIDEO_8BPP :8 bit +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :Imposta i colori a 8 bit per pixel. Questa modalità video supporta l'animazione dell'acqua +STR_CONFIG_SETTING_VIDEO_16BPP :16 bit +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :Imposta i colori a 16 bit per pixel (richiede il riavvio). Questa modalità video non supporta l'animazione dell'acqua +STR_CONFIG_SETTING_VIDEO_24BPP :24 bit +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :Imposta i colori a 24 bit per pixel. Questa modalità video supporta l'animazione dell'acqua +STR_TABLET_CLOSE_TOOLTIP :{BLACK}Chiude tutte le schermate aperte (eccetto quelle permanenti) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}Premi questo tasto per una stima dei costi dell'azione desiderata +STR_TABLET_CTRL_TOOLTIP :{BLACK}Usa per le azioni che usano il tasto "CTRL" +STR_TUTORIAL_WINDOW_TITLE :{BLACK}Video di aiuto +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Apri un'applicazione video per guardare i video di aiuto +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}Costruzione di strade e stazioni; acquisto di veicoli +STR_TUTORIAL_RAILWAYS :{BLACK}Ferrovie e treni +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}Veicoli stradali +STR_TUTORIAL_SHIPS :{BLACK}Navi e attracchi +STR_TUTORIAL_CARGO :{BLACK}Tipi di merce +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}Carica dalla rete +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}Carica il gioco dalla memoria di rete +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}Salva sulla rete +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}Salva il gioco nella memoria di rete diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index d9291ebcd2..7ffe70b4c8 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -4952,3 +4952,41 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL : {BLACK}チュートリアル +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}マップシンボルについての説明の表示 +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :垂直ツールバー: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :メインツールバーをスクリーンの両脇に垂直に2つに分割します +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR :コンパクト垂直ツールバー: {STRING} +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR_HELPTEXT :ツールバー切り替えボタンを垂直ツールバーから無くすかわりに、サブメニューを増やします +STR_CONFIG_SETTING_BUTTON_SIZE : {BLACK}ボタンサイズ +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP : {BLACK}すべてのユーザーインターフェースの構成サイズ +STR_CONFIG_SETTING_FONT_SIZE : {BLACK}フォントサイズ +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP : {BLACK}全てのゲームのフォント +STR_CONFIG_SETTING_BUILD_CONFIRMATION :アクションの確認: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :道路とステーションの建設時に確認のダイアログの表示 +STR_CONFIG_SETTING_WINDOWS_TITLEBARS :{BLACK}タイトルバー +STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT :{BLACK}ウィンドウのタイトルバーを表示するか、隠して画面のスペースを確保するか選べます +STR_CONFIG_SETTING_WINDOWS_DECORATIONS :ウィンドウの装飾: {STRING} +STR_CONFIG_SETTING_WINDOWS_DECORATIONS_HELPTEXT :ウィンドウの縁を装飾します +STR_CONFIG_SETTING_VIDEO_8BPP : {BLACK}8 bit +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT : {BLACK}色深度を8 bppに設定します 再起動が必要です このビデオモードは水のアニメーションに対応していません +STR_CONFIG_SETTING_VIDEO_16BPP :{BLACK}16 bit +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT : {BLACK}色深度を16 bppに設定します 再起動が必要です このビデオモードは水のアニメーションに対応していません +STR_CONFIG_SETTING_VIDEO_24BPP : {BLACK}24 bit +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT : {BLACK}色深度を24 bppに設定します 再起動が必要です このビデオモードは水のアニメーションに対応していません +STR_TABLET_CLOSE_TOOLTIP :{BLACK}全ての開いているウィンドウを閉じます (固定してあるものは除く) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}押すことでアクションの決定時に費用の見積もりができます +STR_TABLET_CTRL_TOOLTIP :{BLACK} "CTRL" キーを使うアクションのために使います +STR_TUTORIAL_WINDOW_TITLE :{BLACK}チュートリアル動画 +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}チュートリアル動画を見るためにビデオプレイヤーを開きます +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}道路とステーションの建設と、車両の購入 +STR_TUTORIAL_RAILWAYS :{BLACK}鉄道と列車 +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}道路車両 +STR_TUTORIAL_SHIPS :{BLACK}船とドック +STR_TUTORIAL_CARGO :{BLACK}貨物のタイプ +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}ネットワークからロード +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}ネットワークストレージからゲームをロード +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}ネットワークにセーブ +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}ネットワークストレージにゲームをバックアップ diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 755e3a8500..dea5b0600b 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -5069,3 +5069,41 @@ STR_PLANE :{G=f}{BLACK}{PL STR_SHIP :{G=f}{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL : {BLACK}튜토리얼 +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}지도 범례 / 기호 설명을 보여줌 +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :수직 작업창: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :메인 작업창이 두 개의 화면 양쪽 두개의 수직 작업창으로 나뉨 +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR :소형 수직 작업창: {STRING} +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR_HELPTEXT :수직 작업창에 '작업창 바꾸기'메뉴가 없지만, 부 메뉴가 추가로 있음 +STR_CONFIG_SETTING_BUTTON_SIZE : {BLACK}버튼 크기 +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP : {BLACK}모든 사용자 인터페이스의 크기 +STR_CONFIG_SETTING_FONT_SIZE :{BLACK}폰트 크기 +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :{BLACK}모든 게임 폰트의 크기 +STR_CONFIG_SETTING_BUILD_CONFIRMATION :명령 확인: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :도로와 정류장을 건설시 확인 팝업을 보임 +STR_CONFIG_SETTING_WINDOWS_TITLEBARS :이름 창 +STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT :모든 창에 대해 이름을 보여주거나, 화면 공간 절약을 위해 이름을 가리기 +STR_CONFIG_SETTING_WINDOWS_DECORATIONS :창 꾸미기: {STRING} +STR_CONFIG_SETTING_WINDOWS_DECORATIONS_HELPTEXT :창 모서리에 꾸밈 효과 +STR_CONFIG_SETTING_VIDEO_8BPP : {BLACK}8비트 +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :그래픽 색상 심도를 픽셀당 8비트로 설정합니다. 이 그래픽 모드는 물이 흐르는 애니메이션 효과를 표현할 수 있습니다. +STR_CONFIG_SETTING_VIDEO_16BPP : {BLACK}16비트 +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :{BLACK}그래픽 색상 심도를 픽셀당 16비트로 설정합니다. 이 그래픽 모드는 물이 흐르는 애니메이션 효과를 표현할 수 있습니다. +STR_CONFIG_SETTING_VIDEO_24BPP :{BLACK}24비트 +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :그래픽 색상 심도를 픽셀당 24비트로 설정합니다. 이 그래픽 모드는 물이 흐르는 애니메이션 효과를 표현할 수 있습니다. +STR_TABLET_CLOSE_TOOLTIP :{BLACK}열려있는 모든 창 닫기 (고정된 창 제외) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}이 행동을 하기 위한 예상 비용을 알아보려면 누르세요. +STR_TABLET_CTRL_TOOLTIP :{BLACK}"컨트롤"키를 이용하는 명령을 위해 사용 +STR_TUTORIAL_WINDOW_TITLE :{BLACK}튜토리얼 영상 +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}튜토리얼 영상을 보기 위해 비디오 플레이어를 열기 +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}도로, 역 건설 및 차량 구입 +STR_TUTORIAL_RAILWAYS :{BLACK}선로 및 열차 +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}차량 +STR_TUTORIAL_SHIPS :{BLACK}선박과 항구 +STR_TUTORIAL_CARGO :{BLACK}화물 종류 +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}네트워크에서 불러오기 +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}네트워크 저장소에서 불러오기 +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}네트워크에 저장 +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}네트워크 저장소로 게임을 백업 diff --git a/src/lang/latin.txt b/src/lang/latin.txt index 77ff4614cc..6c082af525 100644 --- a/src/lang/latin.txt +++ b/src/lang/latin.txt @@ -5345,3 +5345,35 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL :Rudimentum +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}Monstrare formulam graphicam / descriptionem tabulae +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :Arca instrumentorum directa: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :Si vis, arca instrumentorum prima dividitur in partes duas apud margines scrinii +STR_CONFIG_SETTING_BUTTON_SIZE :Magnitudo globulorum +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :Magnitudo omnium elementorum interfaciei +STR_CONFIG_SETTING_FONT_SIZE :Magnitudo fontis typographici +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :Magnitudo omnium fontium typographicorum in ludo +STR_CONFIG_SETTING_BUILD_CONFIRMATION :Confirmare: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :Monstrare confirmationem dum struuntur stationes viaeque +STR_CONFIG_SETTING_VIDEO_8BPP :8bpp +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :Eligere modum coloris 8bpp; hic sinit colores aquae moventes +STR_CONFIG_SETTING_VIDEO_16BPP :16bpp +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :Eligere modum coloris 16bpp (necesse erit programma exire et resumere); hic NON sinit colores aquae moventes +STR_CONFIG_SETTING_VIDEO_24BPP :24bpp +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :Eligere modum coloris 24bpp; hic sinit colores aquae moventes +STR_TABLET_CLOSE_TOOLTIP :{BLACK}Claudere omnes fenestras (sed non glutinosas) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}Preme ut aestimatio actionis monstretur +STR_TABLET_CTRL_TOOLTIP :{BLACK}Utendum est ad actiones cum "CTRL" +STR_TUTORIAL_WINDOW_TITLE :{BLACK}Rudimenta visifica +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Aperire programma visificum ad rudimenta videnda +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}Viae stationesque, emptio vehiculorum +STR_TUTORIAL_RAILWAYS :{BLACK}Ferriviae traminaque +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}Vehicula viaria +STR_TUTORIAL_SHIPS :{BLACK}Naves navaliaque +STR_TUTORIAL_CARGO :{BLACK}Genera onerum +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}Legere e nebula +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}Arcessere ludum "e nebula" (i.e. ex Interreti) +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}Servare in nebula +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}Conservare ludum "in nebula" (i.e. in Interreti) diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt index 9ab4dd48cc..56839cf783 100644 --- a/src/lang/latvian.txt +++ b/src/lang/latvian.txt @@ -4878,3 +4878,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/lithuanian.txt b/src/lang/lithuanian.txt index f030ba2b4f..b04f991d6f 100644 --- a/src/lang/lithuanian.txt +++ b/src/lang/lithuanian.txt @@ -5489,3 +5489,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt index b52b60dde5..58fb597536 100644 --- a/src/lang/luxembourgish.txt +++ b/src/lang/luxembourgish.txt @@ -5027,3 +5027,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/malay.txt b/src/lang/malay.txt index 0a0c8eb026..1e0f962f3a 100644 --- a/src/lang/malay.txt +++ b/src/lang/malay.txt @@ -4620,3 +4620,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 1d63e6fb0e..6abb6441db 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -5073,3 +5073,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/norwegian_nynorsk.txt b/src/lang/norwegian_nynorsk.txt index 757ffe25ee..937b4923e0 100644 --- a/src/lang/norwegian_nynorsk.txt +++ b/src/lang/norwegian_nynorsk.txt @@ -4865,3 +4865,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/polish.txt b/src/lang/polish.txt index 637b5ab6ea..7d61bb7a44 100644 --- a/src/lang/polish.txt +++ b/src/lang/polish.txt @@ -5454,3 +5454,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 74b40844d9..91b0ff2f3f 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -5069,3 +5069,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index 4c67771203..0852d415e6 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -4935,3 +4935,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 21542eb5f5..65f0cf92c1 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -5295,3 +5295,35 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL :Учебник +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}Показывать миникарту / легенду +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :Вертикальное меню: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :Меню разделено на два вертикальных меню по краям экрата +STR_CONFIG_SETTING_BUTTON_SIZE :Размер кнопок +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :Размер элементов интерфейса +STR_CONFIG_SETTING_FONT_SIZE :Размер шрифта +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :Размер всех шрифтов в игре +STR_CONFIG_SETTING_BUILD_CONFIRMATION :Подтверждать действия: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :Показывать окно подтверждения при постройки дорог и станций +STR_CONFIG_SETTING_VIDEO_8BPP :8 бит +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :Установить глубину цвета в 16 бит на точку. Этот режим поддерживает анимацию воды +STR_CONFIG_SETTING_VIDEO_16BPP :16 бит +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :Установить глубину цвета в 16 бит на точку. Это потребует перезапуска программы. Этот режим не поддерживает анимацию воды +STR_CONFIG_SETTING_VIDEO_24BPP :24 бит +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :Установить глубину цвета в 24 бит на точку. Этот режим поддерживает анимацию воды +STR_TABLET_CLOSE_TOOLTIP :{BLACK}Закрыть все открытые окна (кроме закреплённых) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}Использовать в качестве кнопки "SHIFT" (оценка стоимости) +STR_TABLET_CTRL_TOOLTIP :{BLACK}Использовать в качестве кнопки "CTRL" +STR_TUTORIAL_WINDOW_TITLE :{BLACK}Учебные видео +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Открыть видеоплеер для просмотра учебного видео +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}Постройка дорог и терминалов, покупка автомобилей +STR_TUTORIAL_RAILWAYS :{BLACK}Железные дороги и поезда +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}Автомобили +STR_TUTORIAL_SHIPS :{BLACK}Корабли и пристани +STR_TUTORIAL_CARGO :{BLACK}Грузы +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}Загрузка из сети +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}Загрузить игру из сетевого хранилища +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}Сохранение в сети +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}Сохранить игру в сетевое хранилище diff --git a/src/lang/serbian.txt b/src/lang/serbian.txt index 20a813b38a..be40e5b828 100644 --- a/src/lang/serbian.txt +++ b/src/lang/serbian.txt @@ -5194,3 +5194,29 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL :Priručnik +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}Prikaži legendu mape / opis simbola na mapi +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :Vertikalna alatna traka: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :Glavna alatna traka je podeljena na dve okomite alatne trake na rubovima ekrana +STR_CONFIG_SETTING_BUTTON_SIZE :Veličina dugmeta +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :Veličina svih elemenata korisničkog interfejsa +STR_CONFIG_SETTING_FONT_SIZE :Veličina slova +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :Veličina svih slova u igri +STR_CONFIG_SETTING_BUILD_CONFIRMATION :Potvrdi akcije: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :Prikaži dijalog potvrde pri gradnji drumova i stanica +STR_TABLET_CLOSE_TOOLTIP :{BLACK}Zatvori sve otvorene prozore (osim zakačenih) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}Pritisnite za dobivanje procene troškova odabrane akcije +STR_TABLET_CTRL_TOOLTIP :{BLACK}Koristite za sve akcije za koje se koristi tipka "CTRL" +STR_TUTORIAL_WINDOW_TITLE :{BLACK}Video za učenje +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Otvori video plejer za gledanje videa za učenje +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}Gradnja cesta i stanica, kupovina vozila +STR_TUTORIAL_RAILWAYS :{BLACK}Šine i vozovi +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}Drumska vozila +STR_TUTORIAL_SHIPS :{BLACK}Brodovi i dokovi +STR_TUTORIAL_CARGO :{BLACK}Tip tereta +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}Učitaj igru sa mreže +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}Učitaj igru sa mrežne pohrane podataka +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}Spremi igru na mrežu +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}Spremi igru na mrežu diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index 27c35cdabd..0aaf8f824a 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -4989,3 +4989,41 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL :教程 +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}在地图上显示图例/描述 +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :垂直工具栏: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :将主工具栏分为屏幕两侧的两个垂直工具栏 +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR :紧凑型垂直工具栏: {STRING} +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR_HELPTEXT :隐藏垂直工具栏中的“切换工具栏”按钮,以显示更多子菜单 +STR_CONFIG_SETTING_BUTTON_SIZE :按键大小 +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :用户界面大小 +STR_CONFIG_SETTING_FONT_SIZE :字体大小 +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :游戏字体大小 +STR_CONFIG_SETTING_BUILD_CONFIRMATION :确认操作: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :建立道路和车站时显示确认对话框 +STR_CONFIG_SETTING_WINDOWS_TITLEBARS :{BLACK}标题栏 +STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT :{BLACK}显示所有窗口的标题栏,或者隐藏它们以节省屏幕空间 +STR_CONFIG_SETTING_WINDOWS_DECORATIONS :窗口装饰: {STRING} +STR_CONFIG_SETTING_WINDOWS_DECORATIONS_HELPTEXT :窗口边缘装饰 +STR_CONFIG_SETTING_VIDEO_8BPP :8 bit +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :将视频颜色深度设置为8位像素,此模式支持水面动态涟漪 +STR_CONFIG_SETTING_VIDEO_16BPP :16 bit +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :将视频颜色深度设置为16位像素,这需要重新启动,此模式不支持水面动态涟漪 +STR_CONFIG_SETTING_VIDEO_24BPP :24 bit +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :将视频颜色深度设置为24位像素,此模式支持水面动态涟漪 +STR_TABLET_CLOSE_TOOLTIP :{BLACK}关闭所有打开的窗口(已固定的窗口除外) +STR_TABLET_SHIFT_TOOLTIP :{BLACK}按住显示预计费用 +STR_TABLET_CTRL_TOOLTIP :{BLACK}将其用于“CTRL”键的操作 +STR_TUTORIAL_WINDOW_TITLE :{BLACK}教程视频 +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}使用视频播放器观看教程视频 +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}建设道路和车站,购买车辆 +STR_TUTORIAL_RAILWAYS :{BLACK}铁路和火车 +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}公路车辆 +STR_TUTORIAL_SHIPS :{BLACK}船只和码头 +STR_TUTORIAL_CARGO :{BLACK}货物类型 +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}读取云端存档 +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}从云端储存读取游戏 +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}保存到云端储存 +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}备份游戏到云端储存 diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index 4ba647de92..6135aa084c 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -5018,3 +5018,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/slovenian.txt b/src/lang/slovenian.txt index 4de468b497..bb4f651db5 100644 --- a/src/lang/slovenian.txt +++ b/src/lang/slovenian.txt @@ -5149,3 +5149,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 79a0dfac19..a2ad54b6af 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -5019,3 +5019,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 7ce9fb2d2f..e39254134e 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -5069,3 +5069,41 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings +STR_ABOUT_MENU_TUTORIAL :{BLACK}Guía de cómo jugar +STR_SMALLMAP_TOOLTIP_SHOW_LEGEND :{BLACK}Mostrar leyenda o descripción de símbolos del mapa +STR_CONFIG_SETTING_VERTICAL_TOOLBAR :Barra de herramientas vertical: {STRING} +STR_CONFIG_SETTING_VERTICAL_TOOLBAR_HELPTEXT :La barra de herramientas principal se divide en dos barras verticales laterales +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR :Compactar barra vertical: {STRING} +STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR_HELPTEXT :Más submenúes en la barra vertical en lugar de botón de "Cambiar barras" +STR_CONFIG_SETTING_BUTTON_SIZE :{BLACK}Tamaño de botones +STR_CONFIG_SETTING_BUTTON_SIZE_TOOLTIP :{BLACK}Tamaño de elementos de la interfaz +STR_CONFIG_SETTING_FONT_SIZE :{BLACK}Tamaño de letra +STR_CONFIG_SETTING_FONT_SIZE_TOOLTIP :{BLACK}Tamaño de letra general +STR_CONFIG_SETTING_BUILD_CONFIRMATION :Confirmar acciones: {STRING} +STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT :Mostrar diálogo de confirmación al construir carreteras y estaciones +STR_CONFIG_SETTING_WINDOWS_TITLEBARS :{BLACK}Barras de título +STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT :{BLACK}Mostrar títulos en todas las ventas u ocultarlos para reducir espacio +STR_CONFIG_SETTING_WINDOWS_DECORATIONS :Decoraciones de ventana: {STRING} +STR_CONFIG_SETTING_WINDOWS_DECORATIONS_HELPTEXT :Adornos en bordes de ventana +STR_CONFIG_SETTING_VIDEO_8BPP :{BLACK}8 bits +STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT :{BLACK}Establecer profundidad de color de video a 8 bits por pixel. Este modo de video soporta animación de agua +STR_CONFIG_SETTING_VIDEO_16BPP :{BLACK}16 bits +STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT :{BLACK}Establecer profundidad de color de video a 16 bits por pixel. Requiere reiniciar. Este modo de video no soporta animación de agua +STR_CONFIG_SETTING_VIDEO_24BPP :{BLACK}24 bits +STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT :{BLACK}Establecer profundidad de color de video a 24 bits por pixel. Este modo de video soporta animación de agua +STR_TABLET_CLOSE_TOOLTIP :{BLACK}Cerrar todas las ventanas abiertas, salvo las que estén fijas +STR_TABLET_SHIFT_TOOLTIP :{BLACK}Pulsar para ver una estimación del precio al realizar una acción +STR_TABLET_CTRL_TOOLTIP :{BLACK}Emplearlo para acciones que utilizan la tecla "Ctrl" +STR_TUTORIAL_WINDOW_TITLE :{BLACK}Videos de guías de juego +STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Abrir reproductor de video para ver guías de juego +STR_TUTORIAL_ROADS_AND_STATIONS :{BLACK}Construir carrerteras y estaciones; comprar vehículos +STR_TUTORIAL_RAILWAYS :{BLACK}Vías férreas y trenes +STR_TUTORIAL_ROAD_VEHICLES :{BLACK}Vehículos de carretera +STR_TUTORIAL_SHIPS :{BLACK}Barcos y muelles +STR_TUTORIAL_CARGO :{BLACK}Cargamentos +STR_SAVELOAD_LOAD_NETWORK_BUTTON :{BLACK}Cargar desde red +STR_SAVELOAD_LOAD_NETWORK_TOOLTIP :{BLACK}Cargar partida desde almacenamiento en red +STR_SAVELOAD_SAVE_NETWORK_BUTTON :{BLACK}Guardar en red +STR_SAVELOAD_SAVE_NETWORK_TOOLTIP :{BLACK}Realizar respaldo en almacenamiento de red diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 03df018123..5abaecf730 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -5052,3 +5052,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/tamil.txt b/src/lang/tamil.txt index 13e4772d5c..b429be2b85 100644 --- a/src/lang/tamil.txt +++ b/src/lang/tamil.txt @@ -4502,3 +4502,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/thai.txt b/src/lang/thai.txt index 1c5d4400d3..fb8f1126ce 100644 --- a/src/lang/thai.txt +++ b/src/lang/thai.txt @@ -4859,3 +4859,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt index 7ddf4fbd3e..2bef0de060 100644 --- a/src/lang/traditional_chinese.txt +++ b/src/lang/traditional_chinese.txt @@ -4949,3 +4949,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt index c9e17a9cce..a93c8ff15f 100644 --- a/src/lang/turkish.txt +++ b/src/lang/turkish.txt @@ -5071,3 +5071,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/ukrainian.txt b/src/lang/ukrainian.txt index ffd1d135c8..2a91c56fa9 100644 --- a/src/lang/ukrainian.txt +++ b/src/lang/ukrainian.txt @@ -5234,3 +5234,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/vietnamese.txt b/src/lang/vietnamese.txt index 6b3c288342..75808fb5e3 100644 --- a/src/lang/vietnamese.txt +++ b/src/lang/vietnamese.txt @@ -5030,3 +5030,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/lang/welsh.txt b/src/lang/welsh.txt index 4e8e0b14fb..6f16e5b3d7 100644 --- a/src/lang/welsh.txt +++ b/src/lang/welsh.txt @@ -4968,3 +4968,5 @@ STR_PLANE :{BLACK}{PLANE} STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) + +# Android strings diff --git a/src/linkgraph/linkgraph_gui.cpp b/src/linkgraph/linkgraph_gui.cpp index 6844092c2e..dbf134ce28 100644 --- a/src/linkgraph/linkgraph_gui.cpp +++ b/src/linkgraph/linkgraph_gui.cpp @@ -406,6 +406,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 cdd3831576..8b02a55775 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -33,6 +33,8 @@ #include "tilehighlight_func.h" #include "hotkeys.h" #include "guitimer_func.h" +#include "tutorial_gui.h" +#include "gui.h" #include "saveload/saveload.h" @@ -343,7 +345,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_DELETE_ALL_MESSAGES: DeleteAllMessages(); break; @@ -467,6 +469,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; @@ -567,6 +570,15 @@ void SetupColoursAndInitialWindow() default: NOT_REACHED(); case GM_MENU: ShowSelectGameWindow(); + ShowTutorialWindowOnceAfterInstall(); + if (getenv("SDL_RESTART_PARAMS") != NULL) { + static int counter = 5; // This part of code is called several times during startup, which closes all windows, so we need to put random hacks here + counter--; + ShowGameOptions(); +#ifndef WIN32 + if (counter == 0) unsetenv("SDL_RESTART_PARAMS"); +#endif + } break; case GM_NORMAL: diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 061070a2b5..9a055c2de2 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -27,6 +27,7 @@ #include "newgrf_debug.h" #include "zoom_func.h" #include "guitimer_func.h" +#include "build_confirmation_func.h" #include "widgets/misc_widget.h" @@ -34,6 +35,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. @@ -42,6 +47,8 @@ enum OskActivation { OSKA_IMMEDIATELY, ///< Focusing click already opens OSK. }; +static char _android_text_input[512]; + static const NWidgetPart _nested_land_info_widgets[] = { NWidget(NWID_HORIZONTAL), @@ -533,6 +540,10 @@ void ShowAboutWindow() */ void ShowEstimatedCostOrIncome(Money cost, int x, int y) { + if (ConfirmationWindowEstimatingCost()) { + ConfirmationWindowSetEstimatedCost(cost); + return; + } StringID msg = STR_MESSAGE_ESTIMATED_COST; if (cost < 0) { @@ -680,10 +691,18 @@ struct TooltipsWindow : public Window /* Correctly position the tooltip position, watch out for window and cursor size * Clamp value to below main toolbar and above statusbar. If tooltip would * go below window, flip it so it is shown above the cursor */ - pt.y = Clamp(_cursor.pos.y + _cursor.total_size.y + _cursor.total_offs.y + 5, scr_top, scr_bot); - if (pt.y + sm_height > scr_bot) pt.y = min(_cursor.pos.y + _cursor.total_offs.y - 5, scr_bot) - sm_height; + pt.y = min(_cursor.pos.y + _cursor.total_offs.y - 5, scr_bot) - sm_height - GetMinSizing(NWST_STEP); + if (pt.y < scr_top) pt.y = Clamp(_cursor.pos.y + _cursor.total_size.y + _cursor.total_offs.y + 5, scr_top, scr_bot) + GetMinSizing(NWST_STEP); pt.x = sm_width >= _screen.width ? 0 : Clamp(_cursor.pos.x - (sm_width >> 1), 0, _screen.width - sm_width); + if (_settings_client.gui.windows_titlebars) { + // Move it to the top of the screen, away from mouse cursor, so it won't steal screen taps on Android + pt.y = GetMainViewTop(); + if (_cursor.pos.y < pt.y + GetMinSizing(NWST_STEP)) { + pt.x = _cursor.pos.x > _screen.width / 2 ? GetMinSizing(NWST_STEP) : _screen.width - sm_width - GetMinSizing(NWST_STEP); + } + } + return pt; } @@ -692,7 +711,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, ScaleGUITrad(250)); size->height = GetStringHeight(this->string_id, size->width); /* Increase slightly to have some space around the box. */ @@ -755,6 +774,14 @@ void QueryString::HandleEditBox(Window *w, int wid) /* For the OSK also invalidate the parent window */ if (w->window_class == WC_OSK) w->InvalidateData(); } +#ifdef __ANDROID__ + if (SDL_IsScreenKeyboardShown(NULL)) { + if (SDL_ANDROID_GetScreenKeyboardTextInputAsync(_android_text_input, sizeof(_android_text_input)) == SDL_ANDROID_TEXTINPUT_ASYNC_FINISHED) { + this->text.Assign(_android_text_input); + w->OnEditboxChanged(wid); + } + } +#endif } void QueryString::DrawEditBox(const Window *w, int wid) const @@ -765,7 +792,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; @@ -776,7 +803,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); @@ -799,11 +826,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; @@ -934,6 +962,11 @@ void QueryString::ClickEditBox(Window *w, Point pt, int wid, int click_count, bo /* Open the OSK window */ ShowOnScreenKeyboard(w, wid); } +#ifdef __ANDROID__ + strecpy(_android_text_input, this->text.buf, lastof(_android_text_input)); + this->text.DeleteAll(); + SDL_ANDROID_GetScreenKeyboardTextInputAsync(_android_text_input, sizeof(_android_text_input)); +#endif } /** Class for the string query window. */ @@ -1115,6 +1148,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 42c1e3c155..b32850b33f 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 "midifile.hpp" #include "../base_media_base.h" @@ -24,6 +25,7 @@ #include #include #include +#include #include "../safeguards.h" @@ -43,13 +45,34 @@ static struct { uint32 song_position; } _midi; ///< Metadata about the midi we're playing. +#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. @@ -97,6 +120,7 @@ void MusicDriver_LibTimidity::PlaySong(const MusicSongInfo &song) return; } + mid_song_set_volume(_midi.song, volume); mid_song_start(_midi.song); _midi.status = MIDI_PLAYING; } @@ -124,5 +148,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 badb05bab2..34dcc887da 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 885647427f..b0f88a3f8a 100644 --- a/src/music_gui.cpp +++ b/src/music_gui.cpp @@ -450,13 +450,32 @@ void InitializeMusic() 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 @@ -483,6 +502,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(); } @@ -502,19 +522,19 @@ 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 (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) { SetDParam(0, song->tracknr); SetDParam(1, 2); SetDParamStr(2, song->songname); - 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; } @@ -528,12 +548,14 @@ 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 (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) { + 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++) { SetDParam(0, song->tracknr); SetDParam(1, 2); SetDParamStr(2, song->songname); - 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; } @@ -542,12 +564,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 (MusicSystem::Playlist::const_iterator song = _music.active_playlist.begin(); song != _music.active_playlist.end(); ++song) { + 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, song->tracknr); SetDParam(1, 2); SetDParamStr(2, song->songname); - 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; } @@ -558,13 +583,13 @@ 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); + int y = this->left_sb->GetScrolledRowFromWidget(pt.y, this, WID_MTS_LIST_LEFT, WD_FRAMERECT_TOP, this->resize.step_height); _music.PlaylistAdd(y); break; } case WID_MTS_LIST_RIGHT: { // remove from playlist - int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL); + int y = this->right_sb->GetScrolledRowFromWidget(pt.y, this, WID_MTS_LIST_RIGHT, WD_FRAMERECT_TOP, this->resize.step_height); _music.PlaylistRemove(y); break; } @@ -597,6 +622,12 @@ struct MusicTrackSelectionWindow : public Window { NOT_REACHED(); } } + + 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[] = { @@ -604,36 +635,42 @@ static const NWidgetPart _nested_music_track_selection_widgets[] = { NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_MTS_CAPTION), SetDataTip(STR_PLAYLIST_MUSIC_SELECTION_SETNAME, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_MTS_MUSICSET), SetDataTip(STR_PLAYLIST_CHANGE_SET, STR_PLAYLIST_TOOLTIP_CHANGE_SET), + 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( @@ -728,7 +765,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; } @@ -741,7 +778,7 @@ struct MusicWindow : public Window { str = STR_MUSIC_TITLE_NAME; SetDParamStr(0, _music.GetCurrentSong().songname); } - 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; } @@ -806,7 +843,11 @@ struct MusicWindow : public Window { if (new_vol < 3) new_vol = 0; if (new_vol != *vol) { *vol = new_vol; +<<<<<<< HEAD if (widget == WID_M_MUSIC_VOL) MusicDriver::GetInstance()->SetVolume(new_vol); +======= + if (widget == WID_M_MUSIC_VOL) MusicVolumeChanged((new_vol * new_vol) / 127); // Kinda logarithmic scale +>>>>>>> origin/master this->SetDirty(); } @@ -895,11 +936,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 32c6cffff2..f9e66e6637 100644 --- a/src/network/core/os_abstraction.h +++ b/src/network/core/os_abstraction.h @@ -75,7 +75,7 @@ typedef unsigned long in_addr_t; # 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 68e1489874..45c2aa90b3 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -109,7 +109,7 @@ void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *m /** Initialize all font-dependent chat box sizes. */ void NetworkReInitChatBoxSize() { - _chatmsg_box.y = 3 * FONT_HEIGHT_NORMAL; + _chatmsg_box.y = GetMinSizing(NWST_STEP, 10) + 5; _chatmsg_box.height = MAX_CHAT_MESSAGES * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING) + 4; _chatmessage_backup = ReallocT(_chatmessage_backup, _chatmsg_box.width * _chatmsg_box.height * BlitterFactory::GetCurrentBlitter()->GetBytesPerPixel()); } @@ -120,7 +120,7 @@ void NetworkInitChatMessage() MAX_CHAT_MESSAGES = _settings_client.gui.network_chat_box_height; _chatmsg_list = ReallocT(_chatmsg_list, _settings_client.gui.network_chat_box_height); - _chatmsg_box.x = 10; + _chatmsg_box.x = GetMinSizing(NWST_STEP, 10) + 5; _chatmsg_box.width = _settings_client.gui.network_chat_box_width_pct * _screen.width / 100; NetworkReInitChatBoxSize(); _chatmessage_visible = false; @@ -462,7 +462,7 @@ struct NetworkChatWindow : public Window { virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) { - Point pt = { 0, _screen.height - sm_height - FindWindowById(WC_STATUS_BAR, 0)->height }; + Point pt = { (int)GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL) * 2, _screen.height - sm_height - FindWindowById(WC_STATUS_BAR, 0)->height }; return pt; } @@ -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 877dea9786..306bf9e39f 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -23,6 +23,8 @@ #include "../querystring_gui.h" #include "../core/geometry_func.hpp" #include "../textfile_gui.h" +#include "../settings_type.h" +#include "../settings_gui.h" #include "network_content_gui.h" @@ -584,8 +586,8 @@ 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; + resize->height = SETTING_BUTTON_HEIGHT; + size->height = 6 * resize->height; break; } } @@ -595,7 +597,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: @@ -638,14 +640,14 @@ public: int line_height = max(this->checkbox_size.height, (uint)FONT_HEIGHT_NORMAL); /* Fill the matrix with the information */ - int sprite_y_offset = WD_MATRIX_TOP + (line_height - this->checkbox_size.height) / 2 - 1; - int text_y_offset = WD_MATRIX_TOP + (line_height - FONT_HEIGHT_NORMAL) / 2; + int sprite_y_offset = WD_MATRIX_TOP + (line_height - this->checkbox_size.height) / 2 - 1 + (this->resize.step_height - line_height) / 2; + int text_y_offset = WD_MATRIX_TOP + (line_height - FONT_HEIGHT_NORMAL) / 2 + (this->resize.step_height - line_height) / 2; uint y = r.top; int cnt = 0; 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; @@ -1057,14 +1059,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), @@ -1094,6 +1089,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 93cd3d9733..ce41e187da 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -32,6 +32,7 @@ #include "../genworld.h" #include "../map_type.h" #include "../guitimer_func.h" +#include "../settings_gui.h" #include "../widgets/network_widget.h" @@ -509,17 +510,17 @@ 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; + resize->height = SETTING_BUTTON_HEIGHT; + size->height = 5 * resize->height; break; case WID_NG_LASTJOINED: - size->height = WD_MATRIX_TOP + max(GetSpriteSize(SPR_BLOT).height, (uint)FONT_HEIGHT_NORMAL) + WD_MATRIX_BOTTOM; + size->height = SETTING_BUTTON_HEIGHT; break; case WID_NG_LASTJOINED_SPACER: @@ -554,7 +555,7 @@ public: break; case WID_NG_DETAILS_SPACER: - size->height = 20 + 12 * FONT_HEIGHT_NORMAL; + size->height = 20 + 10 * FONT_HEIGHT_NORMAL; break; } } @@ -949,12 +950,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), @@ -1098,8 +1096,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; } } @@ -1282,15 +1280,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(), @@ -1393,8 +1391,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: @@ -1461,7 +1459,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) { @@ -1726,7 +1724,7 @@ struct NetworkClientListPopupWindow : Window { ClientList_Action_Proc *proc; ///< Action to execute }; - uint sel_index; + int sel_index; ClientID client_id; Point desired_location; SmallVector actions; ///< Actions to execute @@ -1745,10 +1743,10 @@ struct NetworkClientListPopupWindow : Window { NetworkClientListPopupWindow(WindowDesc *desc, int x, int y, ClientID client_id) : Window(desc), - sel_index(0), client_id(client_id) + sel_index(-1), client_id(client_id) { - this->desired_location.x = x; - this->desired_location.y = y; + this->desired_location.x = x - GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL); + this->desired_location.y = y + GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL) / 2; const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); @@ -1790,6 +1788,7 @@ struct NetworkClientListPopupWindow : Window { d = maxdim(GetStringBoundingBox(action->name), d); } + d.height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL); d.height *= this->actions.Length(); d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; @@ -1801,37 +1800,29 @@ struct NetworkClientListPopupWindow : Window { /* Draw the actions */ int sel = this->sel_index; int y = r.top + WD_FRAMERECT_TOP; - for (const ClientListAction *action = this->actions.Begin(); action != this->actions.End(); action++, y += FONT_HEIGHT_NORMAL) { + for (const ClientListAction *action = this->actions.Begin(); action != this->actions.End(); action++, y += GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL)) { TextColour colour; if (sel-- == 0) { // Selected item, highlight it - GfxFillRect(r.left + 1, y, r.right - 1, y + FONT_HEIGHT_NORMAL - 1, PC_BLACK); + GfxFillRect(r.left + 1, y, r.right - 1, y + GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL) - 1, PC_BLACK); colour = TC_WHITE; } else { colour = TC_BLACK; } - DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, action->name, colour); + DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, Center(y, GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL)), action->name, colour); } } - virtual void OnMouseLoop() + virtual void OnClick(Point pt, int widget, int click_count) { - /* We selected an action */ - uint index = (_cursor.pos.y - this->top - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL; + int index = (pt.y - WD_FRAMERECT_TOP) / GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL); - if (_left_button_down) { - if (index == this->sel_index || index >= this->actions.Length()) return; - - this->sel_index = index; - this->SetDirty(); - } else { - if (index < this->actions.Length() && _cursor.pos.y >= this->top) { - const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(this->client_id); - if (ci != NULL) this->actions[index].proc(ci); - } - - DeleteWindowByClass(WC_CLIENT_LIST_POPUP); + if (index >= 0 && index < (int)this->actions.Length()) { + const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(this->client_id); + if (ci != NULL) this->actions[index].proc(ci); } + + DeleteWindowByClass(WC_CLIENT_LIST_POPUP); } }; @@ -1853,7 +1844,7 @@ static const NWidgetPart _nested_client_list_widgets[] = { NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_STICKYBOX, COLOUR_GREY), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_CL_PANEL), SetMinimalSize(250, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM), SetResize(1, 1), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_CL_PANEL), SetMinimalSize(100, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM), SetResize(1, 1), EndContainer(), }; static WindowDesc _client_list_desc( @@ -1871,6 +1862,8 @@ struct NetworkClientListWindow : Window { uint server_client_width; uint line_height; + uint line_width; + enum { MAX_ROWS = 6 }; // Split the list in two if it does not fit the screen Dimension icon_size; @@ -1894,12 +1887,16 @@ struct NetworkClientListWindow : Window { if (ci->client_playas != COMPANY_INACTIVE_CLIENT) num++; } + int cols = 1 + (num - 1) / MAX_ROWS; + cols *= this->line_width; + num = min(num, MAX_ROWS); num *= this->line_height; - int diff = (num + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM) - (this->GetWidget(WID_CL_PANEL)->current_y); + int diffx = (cols + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT) - (this->GetWidget(WID_CL_PANEL)->current_x); + int diffy = (num + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM) - (this->GetWidget(WID_CL_PANEL)->current_y); /* If height is changed */ - if (diff != 0) { - ResizeWindow(this, 0, diff, false); + if (diffx > 0 || diffy != 0) { // Width can only grow, also title bar can be wider than content + ResizeWindow(this, diffx, diffy, false); return false; } return true; @@ -1912,6 +1909,7 @@ struct NetworkClientListWindow : Window { this->server_client_width = max(GetStringBoundingBox(STR_NETWORK_SERVER).width, GetStringBoundingBox(STR_NETWORK_CLIENT).width) + WD_FRAMERECT_RIGHT; this->icon_size = GetSpriteSize(SPR_COMPANY_ICON); this->line_height = max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL); + this->line_height = GetMinSizing(NWST_STEP, this->line_height); uint width = 100; // Default width const NetworkClientInfo *ci; @@ -1919,7 +1917,7 @@ struct NetworkClientListWindow : Window { width = max(width, GetStringBoundingBox(ci->client_name).width); } - size->width = WD_FRAMERECT_LEFT + this->server_client_width + this->icon_size.width + WD_FRAMERECT_LEFT + width + WD_FRAMERECT_RIGHT; + this->line_width = this->server_client_width + this->icon_size.width + WD_FRAMERECT_LEFT + width + WD_FRAMERECT_RIGHT; } virtual void OnPaint() @@ -1943,19 +1941,21 @@ struct NetworkClientListWindow : Window { uint right = r.right - WD_FRAMERECT_RIGHT; uint type_icon_width = this->server_client_width + this->icon_size.width + WD_FRAMERECT_LEFT; - - uint type_left = rtl ? right - this->server_client_width : left; - uint type_right = rtl ? right : left + this->server_client_width - 1; - uint icon_left = rtl ? right - type_icon_width + WD_FRAMERECT_LEFT : left + this->server_client_width; - uint name_left = rtl ? left : left + type_icon_width; - uint name_right = rtl ? right - type_icon_width : right; - int i = 0; const NetworkClientInfo *ci; FOR_ALL_CLIENT_INFOS(ci) { + uint type_left = rtl ? right - this->server_client_width : left; + uint type_right = rtl ? right : left + this->server_client_width - 1; + uint icon_left = rtl ? right - type_icon_width + WD_FRAMERECT_LEFT : left + this->server_client_width; + uint name_left = rtl ? right - this->line_width : left + type_icon_width; + uint name_right = rtl ? right - type_icon_width : left + this->line_width; TextColour colour; if (this->selected_item == i++) { // Selected item, highlight it - GfxFillRect(r.left + 1, y, r.right - 1, y + this->line_height - 1, PC_BLACK); + if (rtl) { + GfxFillRect(right - this->line_width, y, right + WD_FRAMERECT_RIGHT - 1, y + this->line_height - 1, PC_BLACK); + } else { + GfxFillRect(left - WD_FRAMERECT_LEFT + 1, y, left + this->line_width, y + this->line_height - 1, PC_BLACK); + } colour = TC_WHITE; } else { colour = TC_BLACK; @@ -1973,6 +1973,14 @@ struct NetworkClientListWindow : Window { DrawString(name_left, name_right, y + text_offset, ci->client_name, colour); y += line_height; + if (i % MAX_ROWS == 0 && i > 1) { + y = r.top + WD_FRAMERECT_TOP; + if (rtl) { + right -= this->line_width; + } else { + left += this->line_width; + } + } } } @@ -2005,7 +2013,7 @@ struct NetworkClientListWindow : Window { pt.y -= this->GetWidget(WID_CL_PANEL)->pos_y; int item = -1; if (IsInsideMM(pt.y, WD_FRAMERECT_TOP, this->GetWidget(WID_CL_PANEL)->current_y - WD_FRAMERECT_BOTTOM)) { - item = (pt.y - WD_FRAMERECT_TOP) / this->line_height; + item = (pt.y - WD_FRAMERECT_TOP) / this->line_height + ((pt.x - WD_FRAMERECT_LEFT) / this->line_width) * MAX_ROWS; } /* It did not change.. no update! */ diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 2fc546d4eb..1741b73295 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -204,7 +204,7 @@ static inline bool IsValidNewGRFImageIndex(uint8 image_index) return image_index == 0xFD || IsValidImageIndex(image_index); } -class OTTDByteReaderSignal { }; +class OTTDByteReaderSignal: public std::runtime_error { public: OTTDByteReaderSignal():std::runtime_error("OTTDByteReaderSignal: NewGRF byte data invalid") {} }; /** Class to read from a NewGRF file */ class ByteReader { diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index 75b06967f7..faa9b1f62b 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -437,7 +437,7 @@ 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; + 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, INVALID_VEHICLE, EIT_IN_DETAILS, skip); /* Highlight the articulated part (this is different to the whole-vehicle highlighting of DrawVehicleImage */ @@ -660,13 +660,13 @@ static const NWidgetPart _nested_newgrf_inspect_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_NGRFI_CAPTION), SetDataTip(STR_NEWGRF_INSPECT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NGRFI_PARENT), SetDataTip(STR_NEWGRF_INSPECT_PARENT_BUTTON, STR_NEWGRF_INSPECT_PARENT_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(WWT_PANEL, COLOUR_GREY, WID_NGRFI_MAINPANEL), SetMinimalSize(300, 0), SetScrollbar(WID_NGRFI_SCROLLBAR), EndContainer(), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NGRFI_PARENT), SetDataTip(STR_NEWGRF_INSPECT_PARENT_BUTTON, STR_NEWGRF_INSPECT_PARENT_TOOLTIP), NWidget(NWID_VERTICAL), NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_NGRFI_SCROLLBAR), NWidget(WWT_RESIZEBOX, COLOUR_GREY), @@ -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 5f32b5bad5..400b2332b6 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -654,10 +654,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 @@ -1308,8 +1309,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; @@ -1510,7 +1513,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 } /** @@ -1647,8 +1650,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); @@ -1685,7 +1688,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; @@ -1793,7 +1796,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; @@ -1801,7 +1804,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); } @@ -1917,33 +1920,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); @@ -2021,6 +2102,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); } @@ -2183,6 +2265,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 b79418c899..47922d8fc3 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -166,7 +166,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(), }; @@ -188,7 +188,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(), @@ -332,6 +332,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; @@ -374,7 +375,7 @@ struct NewsWindow : Window { { switch (widget) { case WID_N_CAPTION: - DrawCaption(r, COLOUR_LIGHT_BLUE, this->owner, STR_NEWS_MESSAGE_CAPTION); + DrawCaption(r, COLOUR_LIGHT_BLUE, this->owner, STR_NEWS_MESSAGE_CAPTION, this->GetWidget(WID_N_CAPTION), this); break; case WID_N_PANEL: @@ -1027,7 +1028,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 @@ -1058,7 +1059,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 6265b96849..cf2172c464 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -70,6 +70,12 @@ #include #include "safeguards.h" +#ifdef __ANDROID__ +#include +#include +#endif +#include +#include void CallLandscapeTick(); void IncreaseDate(); @@ -82,6 +88,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. @@ -492,6 +500,24 @@ struct AfterNewGRFScan : NewGRFScanCallback { } #endif /* ENABLE_NETWORK */ + // TODO: remove this hack in one year + // Check if OpenTTD config is broken by blitter changing code + static bool checked = false; + DEBUG(misc, 0, "========= Limits for vehicles: %d %d %d %d", _settings_newgame.vehicle.max_trains, _settings_newgame.vehicle.max_roadveh, _settings_newgame.vehicle.max_aircraft, _settings_newgame.vehicle.max_ships); + if (!checked && + _settings_newgame.vehicle.max_trains == 0 && _settings_newgame.vehicle.max_roadveh == 0 && + _settings_newgame.vehicle.max_aircraft == 0 && _settings_newgame.vehicle.max_ships == 0) { + if (access(".openttd/openttd-backup.cfg", F_OK) == 0) { + system("mv -f .openttd/openttd-backup.cfg .openttd/openttd.cfg"); + } else { + unlink("libsdl-DownloadFinished-1.flag"); + } + //_exit_game = true; + //_restart_game = true; + _exit(0); // kill(getpid(), SIG_KILL); //abort(); // Kill myself with contempt, user will restart the app, because otherwise we enter infinite restart loop + } + checked = true; + /* After the scan we're not used anymore. */ delete this; } @@ -732,6 +758,16 @@ int openttd_main(int argc, char *argv[]) * just be out of the bounds of the window. */ _cursor.in_window = true; + { +#ifndef WIN32 + // Configure local font path on Android + //char curdir[PATH_MAX]; + //getcwd(curdir, sizeof(curdir)); + //setenv("FONTCONFIG_FONTS", (std::string(curdir) + "/fonts").c_str(), 1); + setenv("FONTCONFIG_FONTS", "fonts", 1); + DEBUG(misc, 1, "Set FONTCONFIG_FONTS to %s", getenv("FONTCONFIG_FONTS")); +#endif + } /* enumerate language files */ InitializeLanguagePacks(); @@ -758,7 +794,7 @@ int openttd_main(int argc, char *argv[]) GfxInitPalettes(); DEBUG(misc, 1, "Loading blitter..."); - if (blitter == NULL && _ini_blitter != NULL) blitter = stredup(_ini_blitter); + if (_ini_blitter != NULL) blitter = stredup(_ini_blitter); _blitter_autodetected = StrEmpty(blitter); /* Activate the initial blitter. * This is only some initial guess, after NewGRFs have been loaded SwitchNewGRFBlitter may switch to a different one. @@ -863,7 +899,15 @@ int openttd_main(int argc, char *argv[]) ScanNewGRFFiles(scanner); scanner = NULL; - VideoDriver::GetInstance()->MainLoop(); + try { + VideoDriver::GetInstance()->MainLoop(); + } catch (const std::exception & e) { + DEBUG(misc, 0, "Main thread got exception: %s", e.what()); + throw; + } catch (...) { + DEBUG(misc, 0, "Main thread got unknown exception"); + throw; + } WaitTillSaved(); @@ -893,6 +937,14 @@ exit_bootstrap: free(sounddriver); exit_normal: + + if (_restart_game) { +#ifdef __ANDROID__ + // This makes OpenTTD reset all it's settings for some reason, because the process is not killed and shared libraries are not unloaded. + exit(0); +#endif + } + free(BaseGraphics::ini_set); free(BaseSounds::ini_set); free(BaseMusic::ini_set); @@ -1173,6 +1225,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, lastof(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/openttd.h b/src/openttd.h index 5e360d6fcd..0a92475f51 100644 --- a/src/openttd.h +++ b/src/openttd.h @@ -52,6 +52,7 @@ enum DisplayOptions { extern GameMode _game_mode; extern SwitchMode _switch_mode; extern bool _exit_game; +extern bool _restart_game; /** Modes of pausing we've got */ enum PauseMode { diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 81350deb74..91ca244d4d 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -556,13 +556,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(); + } } /** @@ -800,8 +803,8 @@ public: { switch (widget) { case WID_O_ORDER_LIST: - resize->height = FONT_HEIGHT_NORMAL; - size->height = 6 * resize->height + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; + resize->height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL); + size->height = 4 * resize->height + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; break; case WID_O_COND_VARIABLE: { @@ -1087,8 +1090,8 @@ public: int index_column_width = GetStringBoundingBox(STR_ORDER_INDEX).width + 2 * GetSpriteSize(rtl ? SPR_ARROW_RIGHT : SPR_ARROW_LEFT).width + 3; int middle = rtl ? r.right - WD_FRAMETEXT_RIGHT - index_column_width : r.left + WD_FRAMETEXT_LEFT + index_column_width; - int y = r.top + WD_FRAMERECT_TOP; int line_height = this->GetWidget(WID_O_ORDER_LIST)->resize_y; + int y = Center(r.top + WD_FRAMERECT_TOP, line_height); int i = this->vscroll->GetPosition(); const Order *order = this->vehicle->GetOrder(i); @@ -1113,7 +1116,7 @@ public: } /* Reset counters for drawing the orders. */ - y = r.top + WD_FRAMERECT_TOP; + y = Center(r.top + WD_FRAMERECT_TOP, line_height); i = this->vscroll->GetPosition(); order = this->vehicle->GetOrder(i); } @@ -1535,7 +1538,6 @@ static const NWidgetPart _nested_orders_train_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetDataTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), @@ -1585,6 +1587,7 @@ static const NWidgetPart _nested_orders_train_widgets[] = { /* Second button row. */ NWidget(NWID_HORIZONTAL), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_SKIP), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_ORDERS_SKIP_BUTTON, STR_ORDERS_SKIP_TOOLTIP), SetResize(1, 0), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_BOTTOM_MIDDLE), @@ -1613,7 +1616,6 @@ static const NWidgetPart _nested_orders_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetDataTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), @@ -1659,6 +1661,7 @@ static const NWidgetPart _nested_orders_widgets[] = { /* Second button row. */ NWidget(NWID_HORIZONTAL), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_SKIP), SetMinimalSize(124, 12), SetFill(1, 0), SetDataTip(STR_ORDERS_SKIP_BUTTON, STR_ORDERS_SKIP_TOOLTIP), SetResize(1, 0), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_BOTTOM_MIDDLE), @@ -1686,13 +1689,15 @@ static const NWidgetPart _nested_other_orders_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetDataTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), EndContainer(), NWidget(NWID_HORIZONTAL), - NWidget(WWT_PANEL, COLOUR_GREY, WID_O_ORDER_LIST), SetMinimalSize(372, 72), SetDataTip(0x0, STR_ORDERS_LIST_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_O_SCROLLBAR), EndContainer(), + NWidget(NWID_VERTICAL), + NWidget(WWT_PANEL, COLOUR_GREY, WID_O_ORDER_LIST), SetMinimalSize(372, 72), SetDataTip(0x0, STR_ORDERS_LIST_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_O_SCROLLBAR), EndContainer(), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP), + EndContainer(), NWidget(NWID_VERTICAL), NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_O_SCROLLBAR), NWidget(WWT_RESIZEBOX, COLOUR_GREY), 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 bea69ec931..6a25d9444e 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -27,7 +27,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 @@ -65,6 +65,10 @@ ULONG __stack = (1024*1024)*2; // maybe not that much is needed actually ;) #endif #endif +#ifdef __ANDROID__ + #include "android/log.h" +#endif + #include "../../safeguards.h" bool FiosIsRoot(const char *path) @@ -244,6 +248,9 @@ void ShowInfo(const char *str) #if !defined(__APPLE__) void ShowOSErrorBox(const char *buf, bool system) { +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_FATAL, "OpenTTD", "[ERROR] %s", buf); +#endif /* All unix systems, except OSX. Only use escape codes on a TTY. */ if (isatty(fileno(stderr))) { fprintf(stderr, "\033[1;31mError: %s\033[0;39m\n", buf); @@ -258,6 +265,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[]) { /* Make sure our arguments contain only valid UTF-8 characters. */ @@ -367,10 +379,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 dc069d1686..4ef27f7561 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 234edbf22f..ae07245e8c 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -37,6 +37,7 @@ #include "station_map.h" #include "tunnelbridge_map.h" +#include "build_confirmation_func.h" #include "widgets/rail_widget.h" @@ -192,15 +193,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 << 6 | _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); } } @@ -255,22 +248,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) { @@ -305,12 +282,15 @@ static bool RailToolbar_CtrlChanged(Window *w) if (w->IsWidgetDisabled(WID_RAT_REMOVE)) return false; /* allow ctrl to switch remove mode only for these widgets */ + // This breaks joining rail stations functionality on Android + /* for (uint i = WID_RAT_BUILD_NS; i <= WID_RAT_BUILD_STATION; i++) { if ((i <= WID_RAT_AUTORAIL || i >= WID_RAT_BUILD_WAYPOINT) && w->IsWidgetLowered(i)) { ToggleRailButton_Remove(w); return true; } } + */ return false; } @@ -419,6 +399,7 @@ static void HandleAutoSignalPlacement() struct BuildRailToolbarWindow : Window { RailType railtype; ///< Rail type to build. int last_user_action; ///< Last started user action. + bool last_user_action_remove; ///< Use bulldozer button with last action BuildRailToolbarWindow(WindowDesc *desc, RailType railtype) : Window(desc) { @@ -426,12 +407,14 @@ struct BuildRailToolbarWindow : Window { this->SetupRailToolbar(railtype); this->DisableWidget(WID_RAT_REMOVE); this->last_user_action = WIDGET_LIST_END; + this->last_user_action_remove = false; - if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this); + if (_settings_client.gui.link_terraform_toolbar || _settings_client.gui.compact_vertical_toolbar) ShowTerraformToolbar(); } ~BuildRailToolbarWindow() { + if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort(); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); } @@ -558,7 +541,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; } @@ -567,7 +550,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; @@ -647,9 +630,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: @@ -665,11 +646,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: @@ -678,6 +659,7 @@ struct BuildRailToolbarWindow : Window { default: NOT_REACHED(); } + MoveAllWindowsOffScreen(); } virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) @@ -685,17 +667,38 @@ 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); } virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) { if (pt.x != -1) { + this->last_user_action_remove = _remove_button_clicked; 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: @@ -721,7 +724,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), CcPlaySound_SPLAT_RAIL); } else { - HandleStationPlacement(start_tile, end_tile); + if (!_settings_client.gui.station_dragdrop) { + uint32 p1 = _cur_railtype | _railstation.orientation << 6 | _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 */ @@ -737,16 +752,27 @@ 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; } + MoveAllHiddenWindowsBackToScreen(); } } virtual void OnPlaceObjectAbort() { + MoveAllHiddenWindowsBackToScreen(); this->RaiseButtons(); this->DisableWidget(WID_RAT_REMOVE); this->SetWidgetDirty(WID_RAT_REMOVE); + if (ConfirmationWindowShown() && (this->last_user_action == WID_RAT_BUILD_BRIDGE || _ctrl_pressed)) return; DeleteWindowById(WC_BUILD_SIGNAL, TRANSPORT_RAIL); DeleteWindowById(WC_BUILD_STATION, TRANSPORT_RAIL); DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_RAIL); @@ -755,10 +781,30 @@ 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); + if (this->last_user_action_remove) BuildRailClick_Remove(this); + } + + 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() @@ -869,7 +915,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); @@ -1056,8 +1102,8 @@ public: d = maxdim(d, GetStringBoundingBox(StationClass::Get((StationClassID)i)->name)); } size->width = max(size->width, d.width + padding.width); - this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM; - size->height = 5 * this->line_height; + this->line_height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM); + size->height = 3 * this->line_height; resize->height = this->line_height; break; } @@ -1100,6 +1146,13 @@ public: fill->height = 1; resize->height = 1; break; + + case WID_BRAS_NEWST_SPACER: + size->height = 0; + if (_railstation.newstations) { + size->height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL); + } + break; } } @@ -1142,7 +1195,8 @@ public: for (uint i = 0; i < StationClass::GetClassCount(); i++) { if (i == STAT_CLASS_WAYP) continue; if (this->vscroll->IsVisible(statclass)) { - DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, row * this->line_height + r.top + WD_MATRIX_TOP, + DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, + Center(row * this->line_height + r.top, this->line_height), StationClass::Get((StationClassID)i)->name, (StationClassID)i == _railstation.station_class ? TC_WHITE : TC_BLACK); row++; @@ -1392,12 +1446,22 @@ static const NWidgetPart _nested_station_builder_widgets[] = { NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_BRAS_NEWST_SCROLL), EndContainer(), EndContainer(), - 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_VERTICAL), + 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), 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), + 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(), + EndContainer(), 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(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(NWID_VERTICAL), + NWidget(NWID_SPACER), SetMinimalSize(1, 0), SetFill(0, 1), + 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), + 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), @@ -1427,31 +1491,36 @@ 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_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. */ - NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetScrollbar(WID_BRAS_MATRIX_SCROLL), - NWidget(NWID_HORIZONTAL), - NWidget(NWID_MATRIX, COLOUR_DARK_GREEN, WID_BRAS_MATRIX), SetScrollbar(WID_BRAS_MATRIX_SCROLL), SetPIP(0, 2, 0), SetPadding(2, 0, 0, 0), - NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BRAS_IMAGE), SetMinimalSize(66, 60), - SetFill(0, 0), SetResize(0, 0), SetDataTip(0x0, STR_STATION_BUILD_STATION_TYPE_TOOLTIP), SetScrollbar(WID_BRAS_MATRIX_SCROLL), + NWidget(NWID_VERTICAL), + NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetScrollbar(WID_BRAS_MATRIX_SCROLL), + NWidget(NWID_HORIZONTAL), + NWidget(NWID_MATRIX, COLOUR_DARK_GREEN, WID_BRAS_MATRIX), SetScrollbar(WID_BRAS_MATRIX_SCROLL), SetPIP(0, 2, 0), SetPadding(2, 0, 0, 0), + NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BRAS_IMAGE), SetMinimalSize(66, 60), + SetFill(0, 0), SetResize(0, 0), SetDataTip(0x0, STR_STATION_BUILD_STATION_TYPE_TOOLTIP), SetScrollbar(WID_BRAS_MATRIX_SCROLL), + EndContainer(), EndContainer(), + NWidget(NWID_VSCROLLBAR, COLOUR_DARK_GREEN, WID_BRAS_MATRIX_SCROLL), EndContainer(), - NWidget(NWID_VSCROLLBAR, COLOUR_DARK_GREEN, WID_BRAS_MATRIX_SCROLL), EndContainer(), + NWidget(WWT_LABEL, COLOUR_DARK_GREEN, WID_BRAS_NEWST_SPACER), SetDataTip(STR_EMPTY, STR_NULL), + NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetDataTip(STR_EMPTY, STR_NULL), + NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetDataTip(STR_EMPTY, STR_NULL), EndContainer(), EndContainer(), EndContainer(), @@ -1469,7 +1538,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) @@ -1657,6 +1726,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), @@ -1666,14 +1738,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(), @@ -1745,18 +1813,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/road_gui.cpp b/src/road_gui.cpp index e3091ec8af..b11bb8e871 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -29,6 +29,7 @@ #include "hotkeys.h" #include "road_gui.h" #include "zoom_func.h" +#include "build_confirmation_func.h" #include "widgets/road_widget.h" @@ -69,21 +70,6 @@ void CcPlaySound_SPLAT_OTHER(const CommandCost &result, TileIndex tile, uint32 p 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. * @@ -297,12 +283,15 @@ static bool RoadToolbar_CtrlChanged(Window *w) if (w->IsWidgetDisabled(WID_ROT_REMOVE)) return false; /* allow ctrl to switch remove mode only for these widgets */ + // This breaks joining stations functionality on Android + /* for (uint i = WID_ROT_ROAD_X; i <= WID_ROT_AUTOROAD; i++) { if (w->IsWidgetLowered(i)) { ToggleRoadButton_Remove(w); return true; } } + */ return false; } @@ -310,6 +299,8 @@ static bool RoadToolbar_CtrlChanged(Window *w) /** Road toolbar window handler. */ struct BuildRoadToolbarWindow : Window { int last_started_action; ///< Last started user action. + bool last_started_action_remove; ///< Use bulldozer button with last action + bool last_started_action_oneway; ///< Use 'one way road' button with last action BuildRoadToolbarWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc) { @@ -321,12 +312,15 @@ struct BuildRoadToolbarWindow : Window { this->OnInvalidateData(); this->last_started_action = WIDGET_LIST_END; + this->last_started_action_remove = false; + this->last_started_action_oneway = false; - if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this); + if (_settings_client.gui.link_terraform_toolbar || _settings_client.gui.compact_vertical_toolbar) ShowTerraformToolbar(); } ~BuildRoadToolbarWindow() { + if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort(); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); } @@ -430,7 +424,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 +512,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,20 +524,21 @@ 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(); } + MoveAllWindowsOffScreen(); } virtual void OnPlaceObjectAbort() { + MoveAllHiddenWindowsBackToScreen(); this->RaiseButtons(); this->SetWidgetsDisabledState(true, WID_ROT_REMOVE, @@ -553,6 +547,7 @@ struct BuildRoadToolbarWindow : Window { this->SetWidgetDirty(WID_ROT_REMOVE); this->SetWidgetDirty(WID_ROT_ONE_WAY); + if (ConfirmationWindowShown() && (this->last_started_action == WID_ROT_BUILD_BRIDGE || _ctrl_pressed)) return; DeleteWindowById(WC_BUS_STATION, TRANSPORT_ROAD); DeleteWindowById(WC_TRUCK_STATION, TRANSPORT_ROAD); DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_ROAD); @@ -560,8 +555,26 @@ 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); + if (this->last_started_action_remove) ToggleRoadButton_Remove(this); + if (this->last_started_action_oneway) this->LowerWidget(WID_ROT_ONE_WAY); + _one_way_button_clicked = this->last_started_action_oneway; + } + 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 +606,6 @@ struct BuildRoadToolbarWindow : Window { /* Set dir = Y */ _place_road_flag |= RF_DIR_Y; } - break; default: @@ -606,11 +618,24 @@ struct BuildRoadToolbarWindow : Window { virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) { if (pt.x != -1) { + this->last_started_action_remove = _remove_button_clicked; + this->last_started_action_oneway = _one_way_button_clicked; 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: @@ -655,7 +680,16 @@ struct BuildRoadToolbarWindow : Window { } } 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; } + MoveAllHiddenWindowsBackToScreen(); } } @@ -811,7 +845,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); } @@ -843,7 +877,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), @@ -856,6 +890,7 @@ static WindowDesc _build_road_scen_desc( */ Window *ShowBuildRoadScenToolbar() { + DeleteToolbarLinkedWindows(); _cur_roadtype = ROADTYPE_ROAD; return AllocateWindowDescFront(&_build_road_scen_desc, TRANSPORT_ROAD); } @@ -919,18 +954,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), @@ -1069,17 +1104,17 @@ static const NWidgetPart _nested_road_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), SetFill(0, 0), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_NE), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_X), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_NW), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_NE), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_X), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetFill(0, 0), 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), SetFill(0, 0), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_SE), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_SW), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_SE), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), NWidget(NWID_SPACER), SetFill(1, 0), EndContainer(), NWidget(NWID_SPACER), SetMinimalSize(0, 1), @@ -1116,8 +1151,8 @@ static const NWidgetPart _nested_tram_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_X), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_X), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetFill(0, 0), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y), SetSizingType(NWST_BUTTON), SetMinimalSize(66, 50), SetFill(0, 0), 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 700a065669..f413ec149c 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. /** @@ -265,7 +266,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; @@ -379,6 +381,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++) { @@ -851,7 +864,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 ce2b37bb53..6d03b460ad 100644 --- a/src/script/api/game/game_window.hpp.sq +++ b/src/script/api/game/game_window.hpp.sq @@ -650,9 +650,11 @@ void SQGSWindow_Register(Squirrel *engine) SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TF_HSCROLLBAR, "WID_TF_HSCROLLBAR"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_MTS_CAPTION, "WID_MTS_CAPTION"); 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_MUSICSET, "WID_MTS_MUSICSET"); + 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"); @@ -1218,6 +1220,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 fa584693af..ad34ccd471 100644 --- a/src/script/api/script_window.hpp +++ b/src/script/api/script_window.hpp @@ -136,6 +136,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 @@ -1625,8 +1632,10 @@ public: enum MusicTrackSelectionWidgets { WID_MTS_CAPTION = ::WID_MTS_CAPTION, ///< Window caption. WID_MTS_LIST_LEFT = ::WID_MTS_LIST_LEFT, ///< Left button. + WID_MTS_LEFT_SCROLLBAR = ::WID_MTS_LEFT_SCROLLBAR, ///< Scrollbar of left list. WID_MTS_PLAYLIST = ::WID_MTS_PLAYLIST, ///< Playlist. WID_MTS_LIST_RIGHT = ::WID_MTS_LIST_RIGHT, ///< Right button. + WID_MTS_RIGHT_SCROLLBAR = ::WID_MTS_RIGHT_SCROLLBAR, ///< Scrollbar of right list. WID_MTS_MUSICSET = ::WID_MTS_MUSICSET, ///< Music set selection. WID_MTS_ALL = ::WID_MTS_ALL, ///< All button. WID_MTS_OLD = ::WID_MTS_OLD, ///< Old button. @@ -2439,6 +2448,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 b93f4d7066..dc11a37635 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" @@ -1078,6 +1080,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 c3a38b4081..ea6842b609 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -37,11 +37,17 @@ #include "stringfilter_type.h" #include "querystring_gui.h" #include "fontcache.h" +#include "settings_func.h" #include #include "safeguards.h" +#ifdef __ANDROID__ +#include +#endif + +enum { MIN_BUTTON_SIZE = 10, MAX_BUTTON_SIZE = 100 }; static const StringID _driveside_dropdown[] = { STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT, @@ -121,6 +127,8 @@ static int GetCurRes() static void ShowCustCurrency(); +static void ReconstructUserInterface(); + template static DropDownList *BuildSetDropDownList(int *selected_index, bool allow_selection) { @@ -192,6 +200,7 @@ struct GameOptionsWindow : Window { DeleteWindowById(WC_CUSTOM_CURRENCY, 0); DeleteWindowByClass(WC_TEXTFILE); if (this->reload) _switch_mode = SM_MENU; + if (!_exit_game) SaveToConfig(); // Save all settings immediately on Android, because users tend to kill the app instead of pressing 'Quit' button } /** @@ -300,6 +309,19 @@ struct GameOptionsWindow : Window { } break; + case WID_GO_BUTTON_SIZE_DROPDOWN: // Dropdowns for size of all GUI elements and fonts + case WID_GO_TEXT_SIZE_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_GUI_ZOOM_DROPDOWN: { list = new DropDownList(); *selected_index = ZOOM_LVL_OUT_4X - _gui_zoom; @@ -348,6 +370,8 @@ struct GameOptionsWindow : Window { case WID_GO_AUTOSAVE_DROPDOWN: SetDParam(0, _autosave_dropdown[_settings_client.gui.autosave]); break; 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_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_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[ZOOM_LVL_OUT_4X - _gui_zoom]); break; case WID_GO_FONT_ZOOM_DROPDOWN: SetDParam(0, _font_zoom_dropdown[ZOOM_LVL_OUT_4X - _font_zoom]); break; case WID_GO_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->name); break; @@ -363,17 +387,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; } } @@ -384,7 +408,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; @@ -403,7 +427,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; @@ -411,7 +435,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; @@ -475,6 +499,54 @@ struct GameOptionsWindow : Window { this->SetDirty(); break; + case WID_GO_WINDOWS_TITLEBARS: + _settings_client.gui.windows_titlebars = !_settings_client.gui.windows_titlebars; + this->SetWidgetLoweredState(WID_GO_WINDOWS_TITLEBARS, _settings_client.gui.windows_titlebars); + this->SetDirty(); + if (_settings_client.gui.min_button == 48 && _settings_client.gui.windows_titlebars) { + _settings_client.gui.min_button = 40; + _settings_client.gui.min_step = 40; + } + if (_settings_client.gui.min_button == 40 && !_settings_client.gui.windows_titlebars) { + _settings_client.gui.min_button = 48; + _settings_client.gui.min_step = 48; + } + ReconstructUserInterface(); + break; + + case WID_GO_8BPP_BUTTON: + if (this->IsWidgetLowered(WID_GO_8BPP_BUTTON)) break; + free(_ini_blitter); + _ini_blitter = stredup("8bpp-optimized"); + _exit_game = true; + _restart_game = true; + #ifdef __ANDROID__ + SDL_ANDROID_SetConfigOption(SDL_ANDROID_CONFIG_VIDEO_DEPTH_BPP, 16); + #endif + break; + + case WID_GO_16BPP_BUTTON: + if (this->IsWidgetLowered(WID_GO_16BPP_BUTTON)) break; + free(_ini_blitter); + _ini_blitter = stredup("16bpp-simple"); + _exit_game = true; + _restart_game = true; + #ifdef __ANDROID__ + SDL_ANDROID_SetConfigOption(SDL_ANDROID_CONFIG_VIDEO_DEPTH_BPP, 16); + #endif + break; + + case WID_GO_32BPP_BUTTON: + if (this->IsWidgetLowered(WID_GO_32BPP_BUTTON)) break; + free(_ini_blitter); + _ini_blitter = stredup("32bpp-anim"); + _exit_game = true; + _restart_game = true; + #ifdef __ANDROID__ + SDL_ANDROID_SetConfigOption(SDL_ANDROID_CONFIG_VIDEO_DEPTH_BPP, 24); + #endif + break; + default: { int selected; DropDownList *list = this->BuildDropDownList(widget, &selected); @@ -548,13 +620,34 @@ 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; + 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_GUI_ZOOM_DROPDOWN: GfxClearSpriteCache(); _gui_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index); + switch (_gui_zoom) { + case ZOOM_LVL_OUT_4X - ZOOM_LVL_NORMAL: ChangeResInGame(854, 480); break; + case ZOOM_LVL_OUT_4X - ZOOM_LVL_OUT_2X: ChangeResInGame(1280, 720); break; + case ZOOM_LVL_OUT_4X - ZOOM_LVL_OUT_4X: ChangeResInGame(1920, 1080); break; + default: break; + } UpdateCursorSize(); UpdateAllVirtCoords(); ReInitAllWindows(); @@ -565,6 +658,7 @@ struct GameOptionsWindow : Window { _font_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index); ClearFontCache(); LoadStringWidthTable(); + ReconstructUserInterface(); UpdateAllVirtCoords(); break; @@ -590,7 +684,14 @@ struct GameOptionsWindow : Window { virtual void OnInvalidateData(int data = 0, bool gui_scope = true) { if (!gui_scope) return; + this->SetWidgetLoweredState(WID_GO_WINDOWS_TITLEBARS, _settings_client.gui.windows_titlebars); +#ifdef WIN32 this->SetWidgetLoweredState(WID_GO_FULLSCREEN_BUTTON, _fullscreen); +#else + this->SetWidgetLoweredState(WID_GO_8BPP_BUTTON, _ini_blitter != NULL && strcmp(_ini_blitter, "8bpp-optimized") == 0); + this->SetWidgetLoweredState(WID_GO_16BPP_BUTTON, _ini_blitter == NULL || strcmp(_ini_blitter, "16bpp-simple") == 0); + this->SetWidgetLoweredState(WID_GO_32BPP_BUTTON, _ini_blitter != NULL && strcmp(_ini_blitter, "32bpp-anim") == 0); +#endif 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); @@ -623,13 +724,24 @@ static const NWidgetPart _nested_game_options_widgets[] = { NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_RESOLUTION_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_RESOLUTION_TOOLTIP), SetFill(1, 0), SetPadding(0, 0, 3, 0), NWidget(NWID_HORIZONTAL), +#ifdef WIN32 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP), +#else + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_8BPP_BUTTON), SetMinimalSize(9, 9), SetDataTip(STR_CONFIG_SETTING_VIDEO_8BPP, STR_CONFIG_SETTING_VIDEO_8BPP_HELPTEXT), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_16BPP_BUTTON), SetMinimalSize(9, 9), SetDataTip(STR_CONFIG_SETTING_VIDEO_16BPP, STR_CONFIG_SETTING_VIDEO_16BPP_HELPTEXT), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_32BPP_BUTTON), SetMinimalSize(9, 9), SetDataTip(STR_CONFIG_SETTING_VIDEO_24BPP, STR_CONFIG_SETTING_VIDEO_24BPP_HELPTEXT), +#endif EndContainer(), EndContainer(), NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_GUI_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0), EndContainer(), + NWidget(WWT_FRAME, COLOUR_GREY), + NWidget(NWID_HORIZONTAL), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_WINDOWS_TITLEBARS), SetMinimalSize(21, 9), SetDataTip(STR_CONFIG_SETTING_WINDOWS_TITLEBARS, STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT), SetFill(1, 0), + EndContainer(), + EndContainer(), EndContainer(), NWidget(NWID_VERTICAL), SetPIP(0, 6, 0), @@ -642,49 +754,53 @@ static const NWidgetPart _nested_game_options_widgets[] = { 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), - NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_FONT_ZOOM, STR_NULL), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_FONT_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0), + 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(), 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(), @@ -1099,7 +1215,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) { @@ -1574,6 +1689,11 @@ static SettingsContainer &GetSettingsTree() } interface->Add(new SettingEntry("gui.autosave")); + interface->Add(new SettingEntry("gui.vertical_toolbar")); + interface->Add(new SettingEntry("gui.compact_vertical_toolbar")); + interface->Add(new SettingEntry("gui.build_confirmation")); + interface->Add(new SettingEntry("gui.windows_titlebars")); + interface->Add(new SettingEntry("gui.windows_decorations")); interface->Add(new SettingEntry("gui.toolbar_pos")); interface->Add(new SettingEntry("gui.statusbar_pos")); interface->Add(new SettingEntry("gui.prefer_teamchat")); @@ -1856,11 +1976,16 @@ struct GameSettingsWindow : Window { this->InvalidateData(); } + ~GameSettingsWindow() + { + SaveToConfig(); // save all settins immediately on Android, because users tend to kill the app instead of pressing 'Quit' button + } + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) { switch (widget) { case WID_GS_OPTIONSPANEL: - resize->height = SETTING_HEIGHT = max(max(_circle_size.height, SETTING_BUTTON_HEIGHT), FONT_HEIGHT_NORMAL) + 1; + resize->height = SETTING_HEIGHT = GetMinSizing(NWST_STEP, max(max(_circle_size.height, SETTING_BUTTON_HEIGHT), FONT_HEIGHT_NORMAL) + 1); resize->width = 1; size->height = 5 * resize->height + SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET; @@ -2371,10 +2496,10 @@ static const NWidgetPart _nested_settings_selection_widgets[] = { NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_CATEGORY), SetDataTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY, STR_NULL), NWidget(WWT_DROPDOWN, COLOUR_MAUVE, WID_GS_RESTRICT_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_BLACK_STRING, STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0), EndContainer(), - NWidget(NWID_HORIZONTAL), SetPIP(WD_FRAMETEXT_LEFT, WD_FRAMETEXT_RIGHT, WD_FRAMETEXT_RIGHT), - NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_TYPE), SetDataTip(STR_CONFIG_SETTING_RESTRICT_TYPE, STR_NULL), - NWidget(WWT_DROPDOWN, COLOUR_MAUVE, WID_GS_TYPE_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_BLACK_STRING, STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0), - EndContainer(), + //NWidget(NWID_HORIZONTAL), SetPIP(WD_FRAMETEXT_LEFT, WD_FRAMETEXT_RIGHT, WD_FRAMETEXT_RIGHT), + // NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_TYPE), SetDataTip(STR_CONFIG_SETTING_RESTRICT_TYPE, STR_NULL), + // NWidget(WWT_DROPDOWN, COLOUR_MAUVE, WID_GS_TYPE_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_BLACK_STRING, STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0), + //EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), SetPadding(0, 0, WD_TEXTPANEL_BOTTOM, 0), SetPIP(WD_FRAMETEXT_LEFT, WD_FRAMETEXT_RIGHT, WD_FRAMETEXT_RIGHT), @@ -2431,8 +2556,8 @@ void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clic DrawFrameRect(x, y, x + dim.width - 1, y + dim.height - 1, button_colour, (state == 1) ? FR_LOWERED : FR_NONE); DrawFrameRect(x + dim.width, y, x + dim.width + dim.width - 1, y + dim.height - 1, button_colour, (state == 2) ? FR_LOWERED : FR_NONE); - DrawSprite(SPR_ARROW_LEFT, PAL_NONE, x + WD_IMGBTN_LEFT, y + WD_IMGBTN_TOP); - DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, x + WD_IMGBTN_LEFT + dim.width, y + WD_IMGBTN_TOP); + DrawSprite(SPR_ARROW_LEFT, PAL_NONE, Center(x + WD_IMGBTN_LEFT, dim.width - 1), Center(y + WD_IMGBTN_TOP, dim.height - 1)); + DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, Center(x + WD_IMGBTN_LEFT + dim.width, dim.width - 1), Center(y + WD_IMGBTN_TOP, dim.height - 1)); /* Grey out the buttons that aren't clickable */ bool rtl = _current_text_dir == TD_RTL; @@ -2457,7 +2582,7 @@ void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool cl int colour = _colour_gradient[button_colour][2]; DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, button_colour, state ? FR_LOWERED : FR_NONE); - DrawSprite(SPR_ARROW_DOWN, PAL_NONE, x + (SETTING_BUTTON_WIDTH - NWidgetScrollbar::GetVerticalDimension().width) / 2 + state, y + 2 + state); + DrawSpriteCentered(SPR_ARROW_DOWN, PAL_NONE, x + (SETTING_BUTTON_WIDTH - NWidgetScrollbar::GetVerticalDimension().width) + state, y + state + SETTING_BUTTON_HEIGHT / 2); if (!clickable) { GfxFillRect(x + 1, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 2, colour, FILLRECT_CHECKER); @@ -2705,3 +2830,35 @@ 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(); + if (_settings_client.gui.windows_titlebars) { + // Hack to prevent second click on the same button via button-up event + ShowGameOptions(); + } +} diff --git a/src/settings_gui.h b/src/settings_gui.h index 23a343219f..8cc507ddd1 100644 --- a/src/settings_gui.h +++ b/src/settings_gui.h @@ -15,10 +15,8 @@ #include "gfx_type.h" #include "widgets/dropdown_type.h" -/** Width of setting buttons */ -#define SETTING_BUTTON_WIDTH ((int)NWidgetScrollbar::GetHorizontalDimension().width * 2) -/** Height of setting buttons */ -#define SETTING_BUTTON_HEIGHT ((int)NWidgetScrollbar::GetHorizontalDimension().height) +extern int SETTING_BUTTON_WIDTH; ///< Width of setting buttons +extern int SETTING_BUTTON_HEIGHT; ///< Height of setting buttons void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right); void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable); diff --git a/src/settings_type.h b/src/settings_type.h index 8f03b1dc15..5756c6e4e9 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -86,6 +86,13 @@ 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 + bool compact_vertical_toolbar; ///< compact mode for vertical toolbars, with more sub-menus + bool build_confirmation; ///< show confirmation dialog when building roads and stations + bool windows_titlebars; ///< show or hide titlebars for all windows to increase scrren space + bool windows_decorations; ///< draw ornament on all window edges + 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 @@ -111,6 +118,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 56af6e6655..7d64c33589 100644 --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -24,6 +24,7 @@ #include "sortlist_type.h" #include "stringfilter_type.h" #include "string_func.h" +#include "settings_type.h" #include "core/geometry_func.hpp" #include "hotkeys.h" #include "transparency.h" @@ -200,7 +201,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); @@ -271,13 +272,14 @@ struct SignListWindow : Window, SignList { case WID_SIL_LIST: { 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 = max(GetMinSizing(NWST_STEP), spr_dim.height); Dimension d = {(uint)(this->text_offset + WD_FRAMETEXT_RIGHT), WD_FRAMERECT_TOP + 5 * resize->height + WD_FRAMERECT_BOTTOM}; *size = maxdim(*size, d); break; } case WID_SIL_CAPTION: + if (!_settings_client.gui.windows_titlebars) break; SetDParamMaxValue(0, Sign::GetPoolSize(), 3); *size = GetStringBoundingBox(STR_SIGN_LIST_CAPTION); size->height += padding.height; diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 97d01325a0..3d1604385a 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -38,7 +38,7 @@ static int _smallmap_company_count; ///< Number of entries in the owner legend. static int _smallmap_cargo_count; ///< Number of cargos in the link stats legend. /** Link stat colours shown in legenda. */ -static uint8 _linkstat_colours_in_legenda[] = {0, 1, 3, 5, 7, 9, 11}; +static uint8 _linkstat_colours_in_legenda[] = {0, 1, 3, 5, 7}; static const int NUM_NO_COMPANY_ENTRIES = 4; ///< Number of entries in the owner legend that are not companies. @@ -86,12 +86,12 @@ static LegendAndColour _legend_land_contours[] = { MC(false), MC(false), MC(false), - MC(false), MC(true), MC(false), MC(false), MC(false), MC(false), + MC(true), MC(false), MKEND() }; @@ -126,12 +126,13 @@ static const LegendAndColour _legend_vegetation[] = { MK(PC_BARE_LAND, STR_SMALLMAP_LEGENDA_BARE_LAND), MK(PC_FIELDS, STR_SMALLMAP_LEGENDA_FIELDS), MK(PC_TREES, STR_SMALLMAP_LEGENDA_TREES), - MK(PC_GREEN, STR_SMALLMAP_LEGENDA_FOREST), - MS(PC_GREY, STR_SMALLMAP_LEGENDA_ROCKS), + MS(PC_GREEN, STR_SMALLMAP_LEGENDA_FOREST), + MK(PC_GREY, STR_SMALLMAP_LEGENDA_ROCKS), MK(PC_ORANGE, STR_SMALLMAP_LEGENDA_DESERT), MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_SNOW), - MK(PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES), + + MS(PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES), MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES), MKEND() }; @@ -146,6 +147,7 @@ static LegendAndColour _legend_land_owners[NUM_NO_COMPANY_ENTRIES + MAX_COMPANIE }; #undef MK +#undef MKB #undef MC #undef MS #undef MO @@ -186,7 +188,7 @@ void BuildIndustriesLegend() _legend_from_industries[j].colour = indsp->map_colour; _legend_from_industries[j].type = ind; _legend_from_industries[j].show_on_map = true; - _legend_from_industries[j].col_break = false; + _legend_from_industries[j].col_break = j > 0 && j % lengthof(_linkstat_colours_in_legenda) == 0; _legend_from_industries[j].end = false; /* Store widget number for this industry type. */ @@ -217,6 +219,7 @@ void BuildLinkStatsLegend() _legend_linkstats[i].colour = cs->legend_colour; _legend_linkstats[i].type = cs->Index(); _legend_linkstats[i].show_on_map = true; + _legend_linkstats[i].col_break = i > 0 && i % lengthof(_linkstat_colours_in_legenda) == 0; } _legend_linkstats[i].col_break = true; @@ -313,7 +316,7 @@ void BuildLandLegend() uint delta = deltas[i][1]; int total_entries = (_settings_game.construction.max_heightlevel / delta) + 1; - int rows = CeilDiv(total_entries, 2); + int rows = lengthof(_linkstat_colours_in_legenda); int j = 0; for (i = 0; i < lengthof(_legend_land_contours) - 1 && j < total_entries; i++) { @@ -341,7 +344,7 @@ void BuildOwnerLegend() _legend_land_owners[i].colour = _colour_gradient[c->colour][5]; _legend_land_owners[i].company = c->index; _legend_land_owners[i].show_on_map = true; - _legend_land_owners[i].col_break = false; + _legend_land_owners[i].col_break = i > 0 && i % lengthof(_linkstat_colours_in_legenda) == 0; _legend_land_owners[i].end = false; _company_to_list_pos[c->index] = i; i++; @@ -1051,12 +1054,18 @@ void SmallMapWindow::SetupWidgetData() } this->GetWidget(WID_SM_LEGEND)->SetDataTip(STR_NULL, legend_tooltip); +/* this->GetWidget(WID_SM_ENABLE_ALL)->SetDataTip(STR_SMALLMAP_ENABLE_ALL, enable_all_tooltip); this->GetWidget(WID_SM_DISABLE_ALL)->SetDataTip(STR_SMALLMAP_DISABLE_ALL, disable_all_tooltip); this->GetWidget(WID_SM_SELECT_BUTTONS)->SetDisplayedPlane(plane); +*/ } -SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(desc), refresh(GUITimer(FORCE_REFRESH_PERIOD)) +SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : + Window(desc), + show_legend(true), + 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(GUITimer(FORCE_REFRESH_PERIOD)) { _smallmap_industry_highlight = INVALID_INDUSTRYTYPE; this->overlay = new LinkGraphOverlay(this, WID_SM_MAP, 0, this->GetOverlayCompanyMask(), 1); @@ -1065,9 +1074,10 @@ SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(des this->RebuildColourIndexIfNecessary(); - this->SetWidgetLoweredState(WID_SM_SHOW_HEIGHT, _smallmap_show_heightmap); + //this->SetWidgetLoweredState(WID_SM_SHOW_HEIGHT, _smallmap_show_heightmap); this->SetWidgetLoweredState(WID_SM_TOGGLETOWNNAME, this->show_towns); + //this->SetWidgetLoweredState(WID_SM_SHOW_LEGEND, this->show_legend); this->SetupWidgetData(); @@ -1149,7 +1159,7 @@ void SmallMapWindow::RebuildColourIndexIfNecessary() } } else { if (tbl->col_break) { - this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height); + //this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height); height = 0; num_columns++; } @@ -1158,7 +1168,7 @@ void SmallMapWindow::RebuildColourIndexIfNecessary() } min_width = max(GetStringBoundingBox(str).width, min_width); } - this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height); + //this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height); this->min_number_of_columns = max(this->min_number_of_columns, num_columns); } @@ -1198,9 +1208,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); @@ -1227,7 +1236,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; } @@ -1257,7 +1266,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; } @@ -1266,13 +1275,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; } } } @@ -1367,9 +1376,10 @@ 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); + number_of_rows = this->min_number_of_fixed_rows; if (line >= number_of_rows) return -1; bool rtl = _current_text_dir == TD_RTL; @@ -1402,6 +1412,7 @@ int SmallMapWindow::GetPositionOnLegend(Point pt) switch (widget) { case WID_SM_MAP: { // Map window if (click_count > 0) this->mouse_capture_widget = widget; + _scrolling_viewport = true; const NWidgetBase *wid = this->GetWidget(WID_SM_MAP); Window *w = FindWindowById(WC_MAIN_WINDOW, 0); @@ -1447,6 +1458,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); @@ -1665,6 +1684,14 @@ Point SmallMapWindow::GetStationMiddle(const Station *st) const return ret; } +/* virtual */ void SmallMapWindow::UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) +{ + if (widget != WID_SM_LEGEND) return; + + size->width = this->GetMinLegendWidth(); + size->height = this->GetLegendHeight(this->min_number_of_columns); +} + SmallMapWindow::SmallMapType SmallMapWindow::map_type = SMT_CONTOUR; bool SmallMapWindow::show_towns = true; int SmallMapWindow::max_heightlevel = -1; @@ -1694,8 +1721,9 @@ public: bar->SetupSmallestSize(w, init_array); 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); @@ -1746,7 +1774,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(), }; @@ -1754,27 +1782,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), @@ -1785,10 +1809,12 @@ static const NWidgetPart _nested_smallmap_bar[] = { SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP), SetFill(1, 1), NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_OWNERS), SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP), SetFill(1, 1), + NWidget(NWID_SPACER), SetResize(1, 0), SetMinimalSize(0, 1), + NWidget(WWT_RESIZEBOX, COLOUR_BROWN), EndContainer(), - NWidget(NWID_SPACER), SetResize(0, 1), EndContainer(), EndContainer(), + NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SM_LEGEND), SetResize(1, 1), EndContainer(), }; @@ -1812,6 +1838,7 @@ static const NWidgetPart _nested_smallmap_widgets[] = { EndContainer(), NWidgetFunction(SmallMapDisplay), // Smallmap display and legend bar + image buttons. /* Bottom button row and resize box. */ +/* NWidget(NWID_HORIZONTAL), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SM_SELECT_BUTTONS), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), @@ -1826,10 +1853,11 @@ static const NWidgetPart _nested_smallmap_widgets[] = { EndContainer(), NWidget(WWT_RESIZEBOX, COLOUR_BROWN), EndContainer(), +*/ }; 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 486f2a6524..b0e1a83249 100644 --- a/src/smallmap_gui.h +++ b/src/smallmap_gui.h @@ -71,9 +71,11 @@ protected: static const uint FORCE_REFRESH_PERIOD = 930; ///< map is redrawn after that many milliseconds. static const uint BLINK_PERIOD = 450; ///< highlight blinking interval in milliseconds. + 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. @@ -116,7 +118,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; } /** @@ -135,8 +137,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->min_number_of_fixed_rows * this->row_height : 0; } /** @@ -191,6 +193,7 @@ public: virtual void OnRealtimeTick(uint delta_ms); virtual void OnScroll(Point delta); virtual void OnMouseOver(Point pt, int widget); + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize); }; #endif /* SMALLMAP_GUI_H */ diff --git a/src/sound/sdl_s.cpp b/src/sound/sdl_s.cpp index b37016c24e..e4c89b0f20 100644 --- a/src/sound/sdl_s.cpp +++ b/src/sound/sdl_s.cpp @@ -22,6 +22,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. @@ -31,6 +35,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 8a5a25ac00..2f9e243d46 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -419,6 +419,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 bf860538d1..7b349a39e7 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 5c2e06070b..b64942d479 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]; @@ -721,7 +724,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(), @@ -762,12 +765,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(), @@ -802,7 +805,7 @@ static const NWidgetPart _nested_station_view_widgets[] = { * @param right right most coordinate to draw on * @param y y coordinate */ -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 y) { int width = ScaleGUITrad(10); uint num = min((waiting + (width / 2)) / width, (right - left) / width); // maximum is width / 10 icons so it won't overflow @@ -1382,6 +1385,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; } } @@ -1731,7 +1740,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(); @@ -2262,8 +2271,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; @@ -2273,7 +2282,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 88ba495f34..278f85d8b3 100644 --- a/src/statusbar_gui.cpp +++ b/src/statusbar_gui.cpp @@ -27,6 +27,7 @@ #include "toolbar_gui.h" #include "core/geometry_func.hpp" #include "guitimer_func.h" +#include "settings_gui.h" #include "widgets/statusbar_widget.h" @@ -71,7 +72,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); @@ -107,27 +108,37 @@ struct StatusBarWindow : Window { virtual void FindWindowPlacementAndResize(int def_width, int def_height) { - Window::FindWindowPlacementAndResize(_toolbar_width, def_height); + Window::FindWindowPlacementAndResize(min(_toolbar_width, _screen.width - GetMinSizing(NWST_STEP) * 2), def_height); } virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) { 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; } @@ -139,11 +150,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: { @@ -151,7 +164,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; } @@ -159,11 +172,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)) { @@ -171,23 +184,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.HasElapsed()) { - 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.HasElapsed()) { + 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); + } } /** diff --git a/src/strings.cpp b/src/strings.cpp index a3ece9830e..34b923830b 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -2010,7 +2010,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]; @@ -2020,6 +2020,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; @@ -2028,11 +2029,11 @@ bool MissingGlyphSearcher::FindMissingGlyphs(const char **str) size = (FontSize)(c - SCC_FIRST_FONT); } 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 0da711bc4d..41ecc305eb 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -278,7 +278,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/subsidy_gui.cpp b/src/subsidy_gui.cpp index 04e5ae262b..0e7c35d0e5 100644 --- a/src/subsidy_gui.cpp +++ b/src/subsidy_gui.cpp @@ -133,6 +133,7 @@ struct SubsidyListWindow : Window { { if (widget != WID_SUL_PANEL) return; Dimension d = maxdim(GetStringBoundingBox(STR_SUBSIDIES_OFFERED_TITLE), GetStringBoundingBox(STR_SUBSIDIES_SUBSIDISED_TITLE)); + d.height = GetMinSizing(NWST_STEP, d.height); resize->height = d.height; @@ -152,12 +153,13 @@ struct SubsidyListWindow : Window { int right = r.right - WD_FRAMERECT_RIGHT; int y = r.top + WD_FRAMERECT_TOP; int x = r.left + WD_FRAMERECT_LEFT; + y = Center(y, GetMinSizing(NWST_STEP)); int pos = -this->vscroll->GetPosition(); const int cap = this->vscroll->GetCapacity(); /* Section for drawing the offered subsidies */ - if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_SUBSIDIES_OFFERED_TITLE); + if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * GetMinSizing(NWST_STEP), STR_SUBSIDIES_OFFERED_TITLE); pos++; uint num = 0; @@ -168,7 +170,7 @@ struct SubsidyListWindow : Window { /* Displays the two offered towns */ SetupSubsidyDecodeParam(s, true); SetDParam(7, _date - ymd.day + s->remaining * 32); - DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_SUBSIDIES_OFFERED_FROM_TO); + DrawString(x, right, y + pos * GetMinSizing(NWST_STEP), STR_SUBSIDIES_OFFERED_FROM_TO); } pos++; num++; @@ -176,13 +178,13 @@ struct SubsidyListWindow : Window { } if (num == 0) { - if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_SUBSIDIES_NONE); + if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * GetMinSizing(NWST_STEP), STR_SUBSIDIES_NONE); pos++; } /* Section for drawing the already granted subsidies */ pos++; - if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_SUBSIDIES_SUBSIDISED_TITLE); + if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * GetMinSizing(NWST_STEP), STR_SUBSIDIES_SUBSIDISED_TITLE); pos++; num = 0; @@ -194,7 +196,7 @@ struct SubsidyListWindow : Window { SetDParam(8, _date - ymd.day + s->remaining * 32); /* Displays the two connected stations */ - DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_SUBSIDIES_SUBSIDISED_FROM_TO); + DrawString(x, right, y + pos * GetMinSizing(NWST_STEP), STR_SUBSIDIES_SUBSIDISED_FROM_TO); } pos++; num++; @@ -202,7 +204,7 @@ struct SubsidyListWindow : Window { } if (num == 0) { - if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_SUBSIDIES_NONE); + if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * GetMinSizing(NWST_STEP), STR_SUBSIDIES_NONE); pos++; } } diff --git a/src/table/gameopt_settings.ini b/src/table/gameopt_settings.ini index 624d475c31..6152dfb2f6 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 787a82dd86..1ee03faf00 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -121,7 +121,7 @@ name = ""resolution"" type = SLE_INT length = 2 var = _cur_resolution -def = ""640,480"" +def = ""854,480"" cat = SC_BASIC [SDTG_STR] @@ -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 = 40 +min = 0 +max = 100 +cat = SC_EXPERT + +[SDTG_VAR] +name = ""min_step_size"" +type = SLE_UINT +var = _settings_client.gui.min_step +def = 40 +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 5bb2c73aad..3493097551 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -41,6 +41,7 @@ static bool RedrawTownAuthority(int32 p1); static bool InvalidateCompanyInfrastructureWindow(int32 p1); static bool InvalidateCompanyWindow(int32 p1); static bool ZoomMinMaxChanged(int32 p1); +static bool VerticalToolbarChanged(int32 p1); static bool MaxVehiclesChanged(int32 p1); static bool InvalidateShipPathCache(int32 p1); @@ -2524,6 +2525,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 @@ -2542,6 +2552,47 @@ 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.compact_vertical_toolbar +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +def = true +str = STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR +strhelp = STR_CONFIG_SETTING_COMPACT_VERTICAL_TOOLBAR_HELPTEXT +cat = SC_BASIC + +[SDTC_BOOL] +var = gui.build_confirmation +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +def = true +str = STR_CONFIG_SETTING_BUILD_CONFIRMATION +strhelp = STR_CONFIG_SETTING_BUILD_CONFIRMATION_HELPTEXT +cat = SC_BASIC + +[SDTC_BOOL] +var = gui.windows_titlebars +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +def = true +str = STR_CONFIG_SETTING_WINDOWS_TITLEBARS +strhelp = STR_CONFIG_SETTING_WINDOWS_TITLEBARS_HELPTEXT +cat = SC_BASIC + +[SDTC_BOOL] +var = gui.windows_decorations +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +def = true +str = STR_CONFIG_SETTING_WINDOWS_DECORATIONS +strhelp = STR_CONFIG_SETTING_WINDOWS_DECORATIONS_HELPTEXT +cat = SC_BASIC + [SDTC_BOOL] var = gui.show_finances flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC @@ -2568,7 +2619,7 @@ var = gui.scroll_mode type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_MULTISTRING -def = 0 +def = 3 min = 0 max = 3 str = STR_CONFIG_SETTING_SCROLLMODE @@ -3722,7 +3773,7 @@ ifdef = ENABLE_NETWORK var = network.server_advertise flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NETWORK_ONLY -def = false +def = true [SDTC_VAR] ifdef = ENABLE_NETWORK diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp index 97749a8dcc..122096ec05 100644 --- a/src/terraform_gui.cpp +++ b/src/terraform_gui.cpp @@ -224,18 +224,22 @@ struct TerraformToolbarWindow : Window { switch (this->last_user_action) { case WID_TT_LOWER_LAND: // Lower land button VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LOWER_AND_LEVEL_AREA); + MoveAllWindowsOffScreen(); break; case WID_TT_RAISE_LAND: // Raise land button VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_RAISE_AND_LEVEL_AREA); + MoveAllWindowsOffScreen(); break; case WID_TT_LEVEL_LAND: // Level land button VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LEVEL_AREA); + MoveAllWindowsOffScreen(); break; case WID_TT_DEMOLISH: // Demolish aka dynamite button PlaceProc_DemolishArea(tile); + MoveAllWindowsOffScreen(); break; case WID_TT_BUY_LAND: // Buy land button @@ -274,14 +278,26 @@ struct TerraformToolbarWindow : Window { GUIPlaceProcDragXY(select_proc, start_tile, end_tile); break; } + MoveAllHiddenWindowsBackToScreen(); } } virtual void OnPlaceObjectAbort() { + MoveAllHiddenWindowsBackToScreen(); this->RaiseButtons(); } + 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; }; diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index ff5226c2b5..6a1d975c66 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -36,7 +36,6 @@ static const NWidgetPart _nested_textfile_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_TF_CAPTION), SetDataTip(STR_NULL, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_TEXTBTN, COLOUR_MAUVE, WID_TF_WRAPTEXT), SetDataTip(STR_TEXTFILE_WRAP_TEXT, STR_TEXTFILE_WRAP_TEXT_TOOLTIP), NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE), EndContainer(), NWidget(NWID_HORIZONTAL), @@ -47,6 +46,7 @@ static const NWidgetPart _nested_textfile_widgets[] = { EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), + NWidget(WWT_TEXTBTN, COLOUR_MAUVE, WID_TF_WRAPTEXT), SetDataTip(STR_TEXTFILE_WRAP_TEXT, STR_TEXTFILE_WRAP_TEXT_TOOLTIP), NWidget(NWID_HSCROLLBAR, COLOUR_MAUVE, WID_TF_HSCROLLBAR), NWidget(WWT_RESIZEBOX, COLOUR_MAUVE), EndContainer(), diff --git a/src/tilehighlight_func.h b/src/tilehighlight_func.h index 3edef509a2..c9c7ea809f 100644 --- a/src/tilehighlight_func.h +++ b/src/tilehighlight_func.h @@ -22,13 +22,17 @@ bool HandlePlacePushButton(Window *w, int widget, CursorID cursor, HighLightStyl void SetObjectToPlaceWnd(CursorID icon, PaletteID pal, HighLightStyle mode, Window *w); void SetObjectToPlace(CursorID icon, PaletteID pal, HighLightStyle mode, WindowClass window_class, WindowNumber window_num); void ResetObjectToPlace(); +void ConfirmPlacingObject(); + 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/timetable_gui.cpp b/src/timetable_gui.cpp index 5dd45561f3..e3e9660d19 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -201,8 +201,8 @@ struct TimetableWindow : Window { case WID_VT_ARRIVAL_DEPARTURE_SELECTION: case WID_VT_TIMETABLE_PANEL: - resize->height = FONT_HEIGHT_NORMAL; - size->height = WD_FRAMERECT_TOP + 8 * resize->height + WD_FRAMERECT_BOTTOM; + resize->height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL); + size->height = WD_FRAMERECT_TOP + 4 * resize->height + WD_FRAMERECT_BOTTOM; break; case WID_VT_SUMMARY_PANEL: @@ -213,7 +213,8 @@ struct TimetableWindow : Window { int GetOrderFromTimetableWndPt(int y, const Vehicle *v) { - int sel = (y - this->GetWidget(WID_VT_TIMETABLE_PANEL)->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL; + int line_height = this->GetWidget(WID_VT_TIMETABLE_PANEL)->resize_y; + int sel = (y - this->GetWidget(WID_VT_TIMETABLE_PANEL)->pos_y - WD_FRAMERECT_TOP) / line_height; if ((uint)sel >= this->vscroll->GetCapacity()) return INVALID_ORDER; @@ -356,7 +357,8 @@ struct TimetableWindow : Window { switch (widget) { case WID_VT_TIMETABLE_PANEL: { - int y = r.top + WD_FRAMERECT_TOP; + int line_height = this->GetWidget(WID_VT_TIMETABLE_PANEL)->resize_y; + int y = Center(r.top + WD_FRAMERECT_TOP, line_height); int i = this->vscroll->GetPosition(); VehicleOrderID order_id = (i + 1) / 2; bool final_order = false; @@ -414,7 +416,7 @@ struct TimetableWindow : Window { } i++; - y += FONT_HEIGHT_NORMAL; + y += line_height; } break; } @@ -432,7 +434,8 @@ struct TimetableWindow : Window { VehicleOrderID earlyID = BuildArrivalDepartureList(v, arr_dep) ? cur_order : (VehicleOrderID)INVALID_VEH_ORDER_ID; - int y = r.top + WD_FRAMERECT_TOP; + int line_height = this->GetWidget(WID_VT_TIMETABLE_PANEL)->resize_y; + int y = Center(r.top + WD_FRAMERECT_TOP, line_height); bool show_late = this->show_expected && v->lateness_counter > DAY_TICKS; Ticks offset = show_late ? 0 : -v->lateness_counter; @@ -467,7 +470,7 @@ struct TimetableWindow : Window { show_late ? TC_RED : i == selected ? TC_WHITE : TC_BLACK); } } - y += FONT_HEIGHT_NORMAL; + y += line_height; } break; } @@ -654,7 +657,6 @@ static const NWidgetPart _nested_timetable_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_VT_CAPTION), SetDataTip(STR_TIMETABLE_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_ORDER_VIEW), SetMinimalSize(61, 14), SetDataTip( STR_TIMETABLE_ORDER_VIEW, STR_TIMETABLE_ORDER_VIEW_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), @@ -669,6 +671,7 @@ static const NWidgetPart _nested_timetable_widgets[] = { NWidget(WWT_PANEL, COLOUR_GREY, WID_VT_SUMMARY_PANEL), SetMinimalSize(400, 22), SetResize(1, 0), EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_ORDER_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_TIMETABLE_ORDER_VIEW, STR_TIMETABLE_ORDER_VIEW_TOOLTIP), NWidget(NWID_VERTICAL, NC_EQUALSIZE), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_CHANGE_TIME), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_CHANGE_TIME, STR_TIMETABLE_WAIT_TIME_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_CLEAR_TIME), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_CLEAR_TIME, STR_TIMETABLE_CLEAR_TIME_TOOLTIP), diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 5567c55800..5b68d67fbb 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -46,6 +46,7 @@ #include "game/game.hpp" #include "goal_base.h" #include "story_base.h" +#include "tutorial_gui.h" #include "toolbar_gui.h" #include "framerate_type.h" #include "guitimer_func.h" @@ -66,6 +67,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 { @@ -108,9 +110,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); } }; @@ -146,7 +148,7 @@ public: uint Height(uint width) const { - return max(max(this->icon_size.height, this->lock_size.height) + 2U, (uint)FONT_HEIGHT_NORMAL); + return GetMinSizing(NWST_STEP, max(max(this->icon_size.height, this->lock_size.height) + 2U, (uint)FONT_HEIGHT_NORMAL)); } void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const @@ -189,7 +191,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); } @@ -214,6 +226,7 @@ static const int CTMN_CLIENT_LIST = -1; ///< Show the client list static const int CTMN_NEW_COMPANY = -2; ///< Create a new company static const int CTMN_SPECTATE = -3; ///< Become spectator static const int CTMN_SPECTATOR = -4; ///< Show a company window as spectator +static const int CTMN_SPEAK_ALL = -5; ///< Send message to public chat /** * Pop up a generic company list menu. @@ -232,6 +245,7 @@ static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0) /* Add the client list button for the companies menu */ *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false); + *list->Append() = new DropDownListStringItem(STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, CTMN_SPEAK_ALL, false); if (_local_company == COMPANY_SPECTATOR) { *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached()); @@ -345,7 +359,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; } @@ -515,7 +529,7 @@ static CallBackFunction MenuClickMap(int index) static CallBackFunction ToolbarTownClick(Window *w) { - PopupMainToolbMenu(w, WID_TN_TOWNS, STR_TOWN_MENU_TOWN_DIRECTORY, (_settings_game.economy.found_town == TF_FORBIDDEN) ? 1 : 2); + PopupMainToolbMenu(w, WID_TN_TOWNS, STR_TOWN_MENU_TOWN_DIRECTORY, (_settings_game.economy.found_town == TF_FORBIDDEN) ? 5 : 6); return CBF_NONE; } @@ -529,7 +543,11 @@ static CallBackFunction MenuClickTown(int index) { switch (index) { case 0: ShowTownDirectory(); break; - case 1: // setting could be changed when the dropdown was open + case 1: ShowSubsidiesList(); break; + case 2: ShowIndustryDirectory(); break; + case 3: ShowIndustryCargoesWindow(); break; + case 4: if (_local_company != COMPANY_SPECTATOR) ShowBuildIndustryWindow(); break; + case 5: // setting could be changed when the dropdown was open if (_settings_game.economy.found_town != TF_FORBIDDEN) ShowFoundTownWindow(); break; } @@ -637,6 +655,10 @@ static CallBackFunction MenuClickCompany(int index) NetworkClientRequestMove(COMPANY_SPECTATOR); } return CBF_NONE; + + case CTMN_SPEAK_ALL: + ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0); + return CBF_NONE; } } #endif /* ENABLE_NETWORK */ @@ -688,7 +710,8 @@ static CallBackFunction MenuClickGoal(int index) static CallBackFunction ToolbarGraphsClick(Window *w) { - PopupMainToolbMenu(w, WID_TN_GRAPHS, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8); + PopupMainToolbMenu(w, WID_TN_GRAPHS, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, + (_toolbar_mode == TB_NORMAL && !_settings_client.gui.compact_vertical_toolbar) ? 6 : (_networking ? 8 : 9)); return CBF_NONE; } @@ -710,6 +733,7 @@ static CallBackFunction MenuClickGraphs(int index) /* functions for combined graphs/league button */ case 6: ShowCompanyLeagueTable(); break; case 7: ShowPerformanceRatingDetail(); break; + case 8: ShowHighscoreTable(); break; } return CBF_NONE; } @@ -881,11 +905,23 @@ static CallBackFunction ToolbarZoomOutClick(Window *w) static CallBackFunction ToolbarBuildRailClick(Window *w) { - ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, true, true); + DropDownList *list = GetRailTypeDropDownList(); + if (_settings_client.gui.compact_vertical_toolbar) { + const Company *c = Company::Get(_local_company); + *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION, RAILTYPE_END + ROADTYPE_ROAD, false); + *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION, RAILTYPE_END + ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM)); + *list->Append() = new DropDownListStringItem(STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, RAILTYPE_END + WID_TN_WATER, false); + *list->Append() = new DropDownListStringItem(STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, RAILTYPE_END + WID_TN_AIR, false); + } + ShowDropDownList(w, list, _last_built_railtype, WID_TN_RAILS, 140, true); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } +static CallBackFunction MenuClickBuildRoad(int index); +static CallBackFunction MenuClickBuildWater(int index); +static CallBackFunction MenuClickBuildAir(int index); + /** * Handle click on the entry in the Build Rail menu. * @@ -894,6 +930,16 @@ static CallBackFunction ToolbarBuildRailClick(Window *w) */ static CallBackFunction MenuClickBuildRail(int index) { + switch (index) { + case RAILTYPE_END + ROADTYPE_ROAD: + return MenuClickBuildRoad(ROADTYPE_ROAD); + case RAILTYPE_END + ROADTYPE_TRAM: + return MenuClickBuildRoad(ROADTYPE_TRAM); + case RAILTYPE_END + WID_TN_WATER: + return MenuClickBuildWater(0); + case RAILTYPE_END + WID_TN_AIR: + return MenuClickBuildAir(0); + } _last_built_railtype = (RailType)index; ShowBuildRailToolbar(_last_built_railtype); return CBF_NONE; @@ -918,7 +964,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; } @@ -1052,14 +1098,34 @@ 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; } } static CallBackFunction ToolbarHelpClick(Window *w) { - PopupMainToolbMenu(w, WID_TN_HELP, STR_ABOUT_MENU_LAND_BLOCK_INFO, _settings_client.gui.newgrf_developer_tools ? 13 : 10); + DropDownList *list = new DropDownList(); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_LAND_BLOCK_INFO, 0, false); + *list->Append() = new DropDownListStringItem(STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT, 1, false); + *list->Append() = new DropDownListStringItem(STR_NEWS_MENU_MESSAGE_HISTORY_MENU, 2, false); + *list->Append() = new DropDownListStringItem(STR_TOOLBAR_SOUND_MUSIC, 3, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_TUTORIAL, 4, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_TOGGLE_CONSOLE, 5, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_AI_DEBUG, 6, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_SCREENSHOT, 7, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_ZOOMIN_SCREENSHOT, 8, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_DEFAULTZOOM_SCREENSHOT, 9, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_GIANT_SCREENSHOT, 10, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_SHOW_FRAMERATE, 11, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_ABOUT_OPENTTD, 12, false); + if (_settings_client.gui.newgrf_developer_tools) { + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_SPRITE_ALIGNER, 13, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES, 14, false); + *list->Append() = new DropDownListStringItem(STR_ABOUT_MENU_TOGGLE_DIRTY_BLOCKS, 15, false); + } + ShowDropDownList(w, list, 0, WID_TN_HELP, 140, true); + if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -1155,17 +1221,21 @@ static CallBackFunction MenuClickHelp(int index) { switch (index) { case 0: return PlaceLandBlockInfo(); - case 2: IConsoleSwitch(); break; - case 3: ShowAIDebugWindow(); break; - case 4: MenuClickSmallScreenshot(); break; - case 5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break; - case 6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break; - case 7: MenuClickLargeWorldScreenshot(SC_WORLD); break; - case 8: ShowFramerateWindow(); break; - case 9: ShowAboutWindow(); break; - case 10: ShowSpriteAlignerWindow(); break; - case 11: ToggleBoundingBoxes(); break; - case 12: ToggleDirtyBlocks(); break; + case 1: ShowLastNewsMessage(); break; + case 2: ShowMessageHistory(); break; + case 3: ShowMusicWindow(); break; + case 4: ShowTutorialWindow(); break; + case 5: IConsoleSwitch(); break; + case 6: ShowAIDebugWindow(); break; + case 7: MenuClickSmallScreenshot(); break; + case 8: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break; + case 9: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break; + case 10: MenuClickLargeWorldScreenshot(SC_WORLD); break; + case 11: ShowFramerateWindow(); break; + case 12: ShowAboutWindow(); break; + case 13: ShowSpriteAlignerWindow(); break; + case 14: ToggleBoundingBoxes(); break; + case 15: ToggleDirtyBlocks(); break; } return CBF_NONE; } @@ -1186,6 +1256,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. */ /** @@ -1328,7 +1432,7 @@ protected: uint spacers; ///< Number of spacer widgets in this toolbar public: - NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL) + NWidgetToolbarContainer(WidgetType widgetType = NWID_HORIZONTAL) : NWidgetContainer(widgetType) { } @@ -1339,27 +1443,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++; } @@ -1367,11 +1479,25 @@ 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; + } } } + if (type == NWID_HORIZONTAL) { + //w->window_desc->default_width_trad = nbuttons * this->smallest_x; + w->window_desc->pref_width = nbuttons * this->smallest_x; + } else { + //w->window_desc->default_height_trad = nbuttons * this->smallest_y; + w->window_desc->pref_height = nbuttons * this->smallest_y; + } _toolbar_width = nbuttons * this->smallest_x; } @@ -1403,6 +1529,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; @@ -1423,12 +1553,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--; @@ -1482,8 +1622,8 @@ 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; + uint SMALLEST_ARRANGEMENT = 14 + (_settings_client.gui.build_confirmation ? 1 : 2); + uint BIGGEST_ARRANGEMENT = 20 + (_settings_client.gui.build_confirmation ? 1 : 2); /* The number of buttons of each row of the toolbar should match the number of items which we want to be visible. * The total number of buttons should be equal to arrangable_count * 2. @@ -1505,6 +1645,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_WATER, WID_TN_AIR, WID_TN_LANDSCAPE, + WID_TN_CTRL, WID_TN_SWITCH_BAR, // lower toolbar WID_TN_SETTINGS, @@ -1520,6 +1661,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_MUSIC_SOUND, WID_TN_MESSAGES, WID_TN_HELP, + WID_TN_CTRL, WID_TN_SWITCH_BAR, }; static const byte arrange15[] = { @@ -1537,6 +1679,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_LANDSCAPE, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, // lower toolbar WID_TN_PAUSE, @@ -1553,6 +1696,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_MUSIC_SOUND, WID_TN_MESSAGES, WID_TN_HELP, + WID_TN_CTRL, WID_TN_SWITCH_BAR, }; static const byte arrange16[] = { @@ -1571,6 +1715,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_LANDSCAPE, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, // lower toolbar WID_TN_PAUSE, @@ -1588,6 +1733,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_HELP, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, }; static const byte arrange17[] = { @@ -1607,6 +1753,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_LANDSCAPE, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, // lower toolbar WID_TN_PAUSE, @@ -1625,6 +1772,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_HELP, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, }; static const byte arrange18[] = { @@ -1645,6 +1793,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_LANDSCAPE, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, // lower toolbar WID_TN_PAUSE, @@ -1664,6 +1813,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_HELP, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, }; static const byte arrange19[] = { @@ -1685,6 +1835,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_MUSIC_SOUND, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, // lower toolbar WID_TN_PAUSE, @@ -1705,6 +1856,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_HELP, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, }; static const byte arrange20[] = { @@ -1727,6 +1879,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_GOAL, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, // lower toolbar WID_TN_PAUSE, @@ -1748,6 +1901,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_HELP, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT, + WID_TN_CTRL, WID_TN_SWITCH_BAR, }; static const byte arrange_all[] = { @@ -1779,19 +1933,345 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { WID_TN_LANDSCAPE, WID_TN_MUSIC_SOUND, WID_TN_MESSAGES, + WID_TN_CTRL, WID_TN_HELP }; + /* With 'Shift' button included */ + static const byte arrange14shift[] = { + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + // lower toolbar + WID_TN_SETTINGS, + WID_TN_SAVE, + WID_TN_SMALL_MAP, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_GRAPHS, + WID_TN_INDUSTRIES, + WID_TN_MUSIC_SOUND, + WID_TN_MESSAGES, + WID_TN_HELP, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + }; + static const byte arrange15shift[] = { + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SMALL_MAP, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + // lower toolbar + WID_TN_PAUSE, + WID_TN_SETTINGS, + WID_TN_SMALL_MAP, + WID_TN_SAVE, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_GRAPHS, + WID_TN_INDUSTRIES, + WID_TN_MUSIC_SOUND, + WID_TN_MESSAGES, + WID_TN_HELP, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + }; + static const byte arrange16shift[] = { + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SETTINGS, + WID_TN_SMALL_MAP, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + // lower toolbar + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SAVE, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_GRAPHS, + WID_TN_INDUSTRIES, + WID_TN_MUSIC_SOUND, + WID_TN_MESSAGES, + WID_TN_HELP, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + }; + static const byte arrange17shift[] = { + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SETTINGS, + WID_TN_SMALL_MAP, + WID_TN_SUBSIDIES, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + // lower toolbar + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SAVE, + WID_TN_SMALL_MAP, + WID_TN_SUBSIDIES, + WID_TN_TOWNS, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_GRAPHS, + WID_TN_INDUSTRIES, + WID_TN_MUSIC_SOUND, + WID_TN_MESSAGES, + WID_TN_HELP, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + }; + static const byte arrange18shift[] = { + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SETTINGS, + WID_TN_SMALL_MAP, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_INDUSTRIES, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + // lower toolbar + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SAVE, + WID_TN_SMALL_MAP, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_STATIONS, + WID_TN_GRAPHS, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_MUSIC_SOUND, + WID_TN_MESSAGES, + WID_TN_HELP, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + }; + static const byte arrange19shift[] = { + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SETTINGS, + WID_TN_SMALL_MAP, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_MUSIC_SOUND, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + // lower toolbar + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SAVE, + WID_TN_SMALL_MAP, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_GRAPHS, + WID_TN_INDUSTRIES, + WID_TN_MESSAGES, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_HELP, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + }; + static const byte arrange20shift[] = { + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SETTINGS, + WID_TN_SMALL_MAP, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_MUSIC_SOUND, + WID_TN_GOAL, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + // lower toolbar + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SAVE, + WID_TN_SMALL_MAP, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_GRAPHS, + WID_TN_INDUSTRIES, + WID_TN_MESSAGES, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_STORY, + WID_TN_HELP, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_SWITCH_BAR, + }; + static const byte arrange_all_shift[] = { + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SETTINGS, + WID_TN_SAVE, + WID_TN_SMALL_MAP, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_STORY, + WID_TN_GOAL, + WID_TN_GRAPHS, + WID_TN_LEAGUE, + WID_TN_INDUSTRIES, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_MUSIC_SOUND, + WID_TN_MESSAGES, + WID_TN_HELP, + WID_TN_CTRL, + WID_TN_SHIFT, + }; /* 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); + button_count = arrangable_count = _settings_client.gui.build_confirmation ? lengthof(arrange_all) : lengthof(arrange_all_shift); spacer_count = this->spacers; - return arrange_all; + return _settings_client.gui.build_confirmation ? arrange_all : arrange_all_shift; } /* Introduce the split toolbar */ - static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20 }; + static const byte * const arrangements_noshift[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20 }; + + static const byte * const arrangements_shift[] = { arrange14shift, arrange15shift, arrange16shift, arrange17shift, arrange18shift, arrange19shift, arrange20shift }; + + const byte * const * arrangements = _settings_client.gui.build_confirmation ? arrangements_noshift : arrangements_shift; button_count = arrangable_count = full_buttons; spacer_count = this->spacers; @@ -1799,6 +2279,228 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer { } }; +/** 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 + { + // Ultra-compact arrangement, ultra-huge buttons. + // No WID_TN_SHIFT, WID_TN_STORY, WID_TN_GOAL, and WID_TN_LEAGUE buttons. + static const byte arrange_left_compact[] = { + WID_TN_DELETE, + WID_TN_CTRL, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SETTINGS, + WID_TN_SAVE, + WID_TN_SMALL_MAP, + WID_TN_STATIONS, + }; + static const byte arrange_right_compact[] = { + WID_TN_SWITCH_BAR, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_FINANCES, + WID_TN_COMPANIES, + + WID_TN_SWITCH_BAR, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_GRAPHS, + WID_TN_INDUSTRIES, + WID_TN_MUSIC_SOUND, + WID_TN_MESSAGES, + WID_TN_HELP, + }; + static const byte arrange_right_compact_noswitch[] = { + WID_TN_RAILS, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_TOWNS, + WID_TN_GRAPHS, + WID_TN_HELP, + }; + + // Some rather artistic button arrangement, I'm proud of myself + static const byte arrange_left_classic[] = { + WID_TN_DELETE, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SETTINGS, + WID_TN_SAVE, + WID_TN_SMALL_MAP, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + }; + static const byte arrange_right_classic[] = { + WID_TN_SWITCH_BAR, + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_LANDSCAPE, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_GRAPHS, + WID_TN_INDUSTRIES, + WID_TN_HELP, + + WID_TN_SWITCH_BAR, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_LEAGUE, + WID_TN_STATIONS, + WID_TN_STORY, + WID_TN_GOAL, + WID_TN_MUSIC_SOUND, + WID_TN_MESSAGES, + WID_TN_HELP, + }; + static const byte arrange_right_classic_noswitch[] = { + WID_TN_RAILS, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_GRAPHS, + WID_TN_LEAGUE, + WID_TN_GOAL, + WID_TN_HELP, + }; + + // Full-length toolbar without switch button. + // No WID_TN_SHIFT, WID_TN_STORY, WID_TN_GOAL, and WID_TN_LEAGUE buttons. + static const byte arrange_left_almost_all[] = { + WID_TN_DELETE, + WID_TN_CTRL, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SETTINGS, + WID_TN_SAVE, + WID_TN_SMALL_MAP, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + }; + static const byte arrange_right_almost_all[] = { + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_LANDSCAPE, + WID_TN_GRAPHS, + WID_TN_INDUSTRIES, + WID_TN_MUSIC_SOUND, + WID_TN_MESSAGES, + WID_TN_HELP + }; + + // Full-length toolbar without switch button, all buttons are included. + static const byte arrange_left_all[] = { + WID_TN_DELETE, + WID_TN_CTRL, + WID_TN_SHIFT, + WID_TN_ZOOM_IN, + WID_TN_ZOOM_OUT, + WID_TN_PAUSE, + WID_TN_FAST_FORWARD, + WID_TN_SETTINGS, + WID_TN_SAVE, + WID_TN_SMALL_MAP, + WID_TN_TOWNS, + WID_TN_SUBSIDIES, + WID_TN_STATIONS, + WID_TN_FINANCES, + WID_TN_COMPANIES, + WID_TN_STORY, + }; + static const byte arrange_right_all[] = { + WID_TN_RAILS, + WID_TN_ROADS, + WID_TN_WATER, + WID_TN_AIR, + WID_TN_TRAINS, + WID_TN_ROADVEHS, + WID_TN_SHIPS, + WID_TN_AIRCRAFTS, + WID_TN_LANDSCAPE, + WID_TN_GOAL, + WID_TN_GRAPHS, + WID_TN_LEAGUE, + WID_TN_INDUSTRIES, + WID_TN_MUSIC_SOUND, + WID_TN_MESSAGES, + WID_TN_HELP + }; + + 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; + } + + if (_screen.height / this->smallest_y >= lengthof(arrange_left_almost_all)) + { + button_count = arrangable_count = lengthof(arrange_left_almost_all); + if (side == 0) return arrange_left_almost_all; + return arrange_right_almost_all; + } + + if (_screen.height / this->smallest_y >= lengthof(arrange_left_classic)) + { + button_count = arrangable_count = lengthof(arrange_left_classic); + if (side == 0) return arrange_left_classic; + if (_settings_client.gui.compact_vertical_toolbar) return arrange_right_classic_noswitch; + return &arrange_right_classic[((_toolbar_mode == TB_LOWER) ? button_count : 0)]; + } + + button_count = arrangable_count = lengthof(arrange_left_compact); + if (side == 0) return arrange_left_compact; + if (_settings_client.gui.compact_vertical_toolbar) return arrange_right_compact_noswitch; + return &arrange_right_compact[((_toolbar_mode == TB_LOWER) ? button_count : 0)]; + } +}; + /** Container for the scenario editor's toolbar */ class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer { uint panel_widths[2]; ///< The width of the two panels (the text panel and date panel) @@ -1946,6 +2648,9 @@ static ToolbarButtonProc * const _toolbar_button_procs[] = { ToolbarNewspaperClick, ToolbarHelpClick, ToolbarSwitchClick, + ToolbarCtrlClick, + ToolbarShiftClick, + ToolbarDeleteClick, }; enum MainToolbarHotkeys { @@ -1992,8 +2697,10 @@ enum MainToolbarHotkeys { /** Main toolbar. */ struct MainToolbarWindow : Window { GUITimer timer; + 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); @@ -2032,11 +2739,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) _last_started_action = cbf; } @@ -2100,7 +2811,7 @@ struct MainToolbarWindow : Window { ShowLandInfo(tile); break; - default: NOT_REACHED(); + default: return; //NOT_REACHED(); } } @@ -2201,44 +2912,44 @@ 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 WID_TN_SMALL_MAP: case WID_TN_FINANCES: @@ -2249,10 +2960,15 @@ static NWidgetBase *MakeMainToolbar(int *biggest_index) 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; } @@ -2268,6 +2984,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 */ @@ -2603,6 +3372,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..69cb3bba6d 100644 --- a/src/toolbar_gui.h +++ b/src/toolbar_gui.h @@ -16,6 +16,7 @@ void AllocateToolbar(); void ToggleBoundingBoxes(); void ToggleDirtyBlocks(); +extern int _last_clicked_toolbar_idx; extern uint _toolbar_width; #endif /* TOOLBAR_GUI_H */ diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 17449854d6..dae8696a72 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); @@ -568,7 +571,6 @@ static const NWidgetPart _nested_town_editor_view_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TV_CAPTION), SetDataTip(STR_TOWN_VIEW_TOWN_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_CHANGE_NAME), SetMinimalSize(76, 14), SetDataTip(STR_BUTTON_RENAME, STR_TOWN_VIEW_RENAME_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_BROWN), NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN), NWidget(WWT_STICKYBOX, COLOUR_BROWN), @@ -581,6 +583,7 @@ static const NWidgetPart _nested_town_editor_view_widgets[] = { NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_INFO), SetMinimalSize(260, 32), SetResize(1, 0), SetFill(1, 0), EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), + NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_CHANGE_NAME), SetMinimalSize(76, 14), SetDataTip(STR_BUTTON_RENAME, STR_TOWN_VIEW_RENAME_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_CENTER_VIEW), SetMinimalSize(80, 12), SetFill(1, 1), SetResize(1, 0), SetDataTip(STR_BUTTON_LOCATION, STR_TOWN_VIEW_CENTER_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_EXPAND), SetMinimalSize(80, 12), SetFill(1, 1), SetResize(1, 0), SetDataTip(STR_TOWN_VIEW_EXPAND_BUTTON, STR_TOWN_VIEW_EXPAND_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_DELETE), SetMinimalSize(80, 12), SetFill(1, 1), SetResize(1, 0), SetDataTip(STR_TOWN_VIEW_DELETE_BUTTON, STR_TOWN_VIEW_DELETE_TOOLTIP), @@ -616,7 +619,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(), @@ -838,7 +841,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; @@ -990,61 +993,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(), }; @@ -1073,6 +1080,10 @@ public: this->UpdateButtons(true); } + ~FoundTownWindow() { + if (_thd.GetCallbackWnd() == this) this->OnPlaceObjectAbort(); + } + void RandomTownName() { this->townnamevalid = GenerateTownName(&this->townnameparts); @@ -1177,11 +1188,25 @@ 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); + MoveAllWindowsOffScreen(); + } + + 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); + MoveAllHiddenWindowsBackToScreen(); } virtual void OnPlaceObjectAbort() { + MoveAllHiddenWindowsBackToScreen(); this->RaiseButtons(); this->UpdateButtons(false); } @@ -1199,7 +1224,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) @@ -1208,5 +1233,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..e444745220 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 @@ -141,6 +147,7 @@ public: virtual void OnPlaceObject(Point pt, TileIndex tile) { VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_PLANT_TREES); + MoveAllWindowsOffScreen(); } virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) @@ -153,6 +160,7 @@ public: if (pt.x != -1 && select_proc == DDSP_PLANT_TREES) { DoCommandP(end_tile, this->tree_to_plant, start_tile, CMD_PLANT_TREE | CMD_MSG(STR_ERROR_CAN_T_PLANT_TREE_HERE)); + MoveAllHiddenWindowsBackToScreen(); } } @@ -167,7 +175,10 @@ public: virtual void OnPlaceObjectAbort() { + MoveAllHiddenWindowsBackToScreen(); this->RaiseButtons(); + + ResetObjectToPlace(); } }; diff --git a/src/tutorial_gui.cpp b/src/tutorial_gui.cpp new file mode 100644 index 0000000000..575d63514e --- /dev/null +++ b/src/tutorial_gui.cpp @@ -0,0 +1,227 @@ +/* $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" + +#ifdef __ANDROID__ +#include +#endif + +#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 } +}; + +static VideoLink_t trainTutorial[] = { + { "en", "https://www.youtube.com/watch?v=VdMdL2qyZ6s" }, + { ANY_LANG, "https://www.youtube.com/watch?v=VdMdL2qyZ6s" }, + { NULL, NULL } +}; + +static VideoLink_t truckTutorial[] = { + { "en", "https://www.youtube.com/watch?v=B-CL-XFGNtw" }, + { ANY_LANG, "https://www.youtube.com/watch?v=B-CL-XFGNtw" }, + { NULL, NULL } +}; + +static VideoLink_t shipTutorial[] = { + { "en", "https://www.youtube.com/watch?v=a5JHlWtIg3A" }, + { ANY_LANG, "https://www.youtube.com/watch?v=a5JHlWtIg3A" }, + { NULL, NULL } +}; + +static VideoLink_t cargoTutorial[] = { + { "en", "https://www.youtube.com/watch?v=GwjiQYsu3xg" }, + { ANY_LANG, "https://www.youtube.com/watch?v=GwjiQYsu3xg" }, + { 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; + } +#ifdef __ANDROID__ + SDL_ANDROID_OpenExternalWebBrowser(link); +#else + char cmd[PATH_MAX] = +#ifdef WIN32 + "start "; +#else + "xdg-open "; +#endif + strcat(cmd, link); + system(cmd); +#endif +} + +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(WWT_TEXTBTN, COLOUR_GREY, WID_STL_BUS), SetMinimalSize(120, 20), SetDataTip(STR_TUTORIAL_ROADS_AND_STATIONS, STR_TUTORIAL_ROADS_AND_STATIONS), SetFill(1, 1), + NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetFill(1, 0), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_TRAIN), SetMinimalSize(120, 20), SetDataTip(STR_TUTORIAL_RAILWAYS, STR_TUTORIAL_RAILWAYS), SetFill(1, 1), + NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetFill(1, 0), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_TRUCK), SetMinimalSize(120, 20), SetDataTip(STR_TUTORIAL_ROAD_VEHICLES, STR_TUTORIAL_ROAD_VEHICLES), SetFill(1, 1), + NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetFill(1, 0), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_SHIP), SetMinimalSize(120, 20), SetDataTip(STR_TUTORIAL_SHIPS, STR_TUTORIAL_SHIPS), SetFill(1, 1), + NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetFill(1, 0), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_STL_FACILALL), SetMinimalSize(120, 20), SetDataTip(STR_TUTORIAL_CARGO, STR_TUTORIAL_CARGO), SetFill(1, 1), + 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->video = NULL; + this->counter = 0; + } + + virtual void OnClick(Point pt, int widget, int click_count) + { + showTutorialMainMenu = false; + this->counter = 5; + this->LowerWidget(widget); + this->SetDirty(); + switch (widget) { + case WID_STL_BUS: + this->video = busTutorial; + break; + case WID_STL_TRUCK: + this->video = truckTutorial; + break; + case WID_STL_TRAIN: + this->video = trainTutorial; + break; + case WID_STL_SHIP: + this->video = shipTutorial; + break; + //case WID_STL_AIRPLANE: + // this->video = planeTutorial; + // break; + case WID_STL_FACILALL: + this->video = cargoTutorial; + 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 (this->counter > 0) { + this->counter--; + if (this->counter == 1) { + 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(); + } + if (this->counter == 0) { + if (this->video) { + OpenExternTutorialVideo(this->video); + this->video = NULL; + } + } + } + } +}; + +void ShowTutorialWindow() +{ + DeleteWindowByClass(WC_GAME_OPTIONS); + new TutorialWindow(); +} + +void ShowTutorialWindowOnceAfterInstall() +{ + // Close button on tutorial window is gone, so don't show that windows on first run, it's confusing +#if 0 + static const char * TUTORIAL_SHOWN_FLAG = ".tutorial-shown-3.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(); +#endif +} 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 777716c646..4036744599 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,16 +660,17 @@ 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 * 5; break; case WID_VR_VEHICLE_PANEL_DISPLAY: - size->height = ScaleGUITrad(GetVehicleHeight(Vehicle::Get(this->window_number)->type)); + size->height = max((int)GetMinSizing(NWST_STEP), ScaleGUITrad(GetVehicleHeight(Vehicle::Get(this->window_number)->type))); break; case WID_VR_INFO: size->width = WD_FRAMERECT_LEFT + this->information_width + WD_FRAMERECT_RIGHT; + size->height = GetMinSizing(NWST_STEP, FONT_HEIGHT_NORMAL); break; } } @@ -732,7 +733,7 @@ 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, INVALID_VEHICLE, EIT_IN_DETAILS, this->hscroll != NULL ? this->hscroll->GetPosition() : 0); /* Highlight selected vehicles. */ if (this->order != INVALID_VEH_ORDER_ID) break; @@ -1791,7 +1792,6 @@ static const NWidgetPart _nested_nontrain_vehicle_details_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetDataTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_RENAME_VEHICLE), SetMinimalSize(40, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_VEHICLE_NAME_BUTTON, STR_NULL /* filled in later */), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), @@ -1799,6 +1799,7 @@ static const NWidgetPart _nested_nontrain_vehicle_details_widgets[] = { NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_TOP_DETAILS), SetMinimalSize(405, 42), SetResize(1, 0), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_MIDDLE_DETAILS), SetMinimalSize(405, 45), SetResize(1, 0), EndContainer(), NWidget(NWID_HORIZONTAL), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_RENAME_VEHICLE), SetMinimalSize(40, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_VEHICLE_NAME_BUTTON, STR_NULL /* filled in later */), NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_VD_DECREASE_SERVICING_INTERVAL), SetFill(0, 1), SetDataTip(AWV_DECREASE, STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP), NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_VD_INCREASE_SERVICING_INTERVAL), SetFill(0, 1), @@ -1815,7 +1816,6 @@ static const NWidgetPart _nested_train_vehicle_details_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetDataTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_RENAME_VEHICLE), SetMinimalSize(40, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_VEHICLE_NAME_BUTTON, STR_NULL /* filled in later */), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY), @@ -1835,6 +1835,7 @@ static const NWidgetPart _nested_train_vehicle_details_widgets[] = { NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_SERVICING_INTERVAL), SetFill(1, 1), SetResize(1, 0), EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_RENAME_VEHICLE), SetMinimalSize(40, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_VEHICLE_NAME_BUTTON, STR_NULL /* filled in later */), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_DETAILS_CARGO_CARRIED), SetMinimalSize(96, 12), SetDataTip(STR_VEHICLE_DETAIL_TAB_CARGO, STR_VEHICLE_DETAILS_TRAIN_CARGO_TOOLTIP), SetFill(1, 0), SetResize(1, 0), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_DETAILS_TRAIN_VEHICLES), SetMinimalSize(99, 12), @@ -2659,8 +2660,8 @@ public: 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, r.bottom - r.top) + WD_IMGBTN_TOP + lowered); + DrawString(text_left + lowered, text_right + lowered, Center(r.top, r.bottom - r.top) + lowered, str, TC_FROMSTRING, SA_HOR_CENTER); } virtual void OnClick(Point pt, int widget, int click_count) diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp index 8493ae89fc..eb35240364 100644 --- a/src/video/sdl_v.cpp +++ b/src/video/sdl_v.cpp @@ -23,8 +23,15 @@ #include "../core/math_func.hpp" #include "../fileio_func.h" #include "../framerate_type.h" +#include "../settings_type.h" +#include "../tilehighlight_func.h" +#include "../viewport_func.h" #include "sdl_v.h" #include +#ifdef __ANDROID__ +#include +#include +#endif #include "../safeguards.h" @@ -50,6 +57,9 @@ static int _num_dirty_rects; static int _use_hwpalette; static int _requested_hwpalette; /* Did we request a HWPALETTE for the current video mode? */ +static SDL_Joystick * _multitouch_device = NULL; +static Point _multitouch_second_point; + void VideoDriver_SDL::MakeDirty(int left, int top, int width, int height) { if (_num_dirty_rects < MAX_DIRTY_RECTS) { @@ -151,7 +161,11 @@ static void DrawSurfaceToScreen() PerformanceMeasurer framerate(PFE_VIDEO); int n = _num_dirty_rects; +#ifdef __ANDROID__ + if (n == 0 && !_left_button_down) return; // We have to update the screen regularly to receive mouse_up event on Android +#else if (n == 0) return; +#endif _num_dirty_rects = 0; if (n > MAX_DIRTY_RECTS) { @@ -165,7 +179,9 @@ static void DrawSurfaceToScreen() SDL_BlitSurface(_sdl_screen, &_dirty_rects[i], _sdl_realscreen, &_dirty_rects[i]); } } - SDL_UpdateRects(_sdl_realscreen, n, _dirty_rects); + static SDL_Rect dummy_rect = { 0, 0, 8, 8 }; + if (n > 0) SDL_UpdateRects(_sdl_realscreen, n, _dirty_rects); + else SDL_UpdateRects(_sdl_realscreen, 1, &dummy_rect); } } @@ -405,6 +421,14 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h) GameSizeChanged(); +#ifdef __ANDROID__ + if (!_multitouch_device) { + SDL_InitSubSystem(SDL_INIT_JOYSTICK); + _multitouch_device = SDL_JoystickOpen(0); + } + SDL_ANDROID_SetSystemMousePointerVisible(0); // We have our own cursor, only works on Android N +#endif + return true; } @@ -505,6 +529,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 @@ -528,7 +554,9 @@ int VideoDriver_SDL::PollEvent() switch (ev.type) { case SDL_MOUSEMOTION: if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) { +#ifndef __ANDROID__ // No mouse warping on Android, mouse strictly follows finger SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y); +#endif } HandleMouseEvents(); break; @@ -546,10 +574,30 @@ 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; +#ifdef __ANDROID__ + case SDL_BUTTON_WHEELUP: + case SDL_BUTTON_WHEELDOWN: + _cursor.wheel += (ev.button.button == SDL_BUTTON_WHEELDOWN) ? 1 : -1; + _right_button_down = false; + // Center the mouse cursor between touch points + SDL_GetMouseState(&_cursor.pos.x, &_cursor.pos.y); + _cursor.pos.x = (_cursor.pos.x + _multitouch_second_point.x) / 2; + _cursor.pos.y = (_cursor.pos.y + _multitouch_second_point.y) / 2; + //_cursor.UpdateCursorPosition(_cursor.pos.x, _cursor.pos.y, false); + break; +#else case SDL_BUTTON_WHEELUP: _cursor.wheel--; break; case SDL_BUTTON_WHEELDOWN: _cursor.wheel++; break; +#endif default: break; } @@ -564,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; @@ -580,7 +636,7 @@ int VideoDriver_SDL::PollEvent() _cursor.in_window = false; } break; - +#endif /* not __ANDROID__ */ case SDL_QUIT: HandleExitGameRequest(); break; @@ -593,15 +649,42 @@ 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; +#ifdef __ANDROID__ + case SDL_JOYBALLMOTION: + if (ev.jball.which == 0 && ev.jball.ball == 1) { + _multitouch_second_point.x = ev.jball.xrel; + _multitouch_second_point.y = ev.jball.yrel; + } + break; +#endif /* not __ANDROID__ */ +#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 @@ -641,6 +724,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; } @@ -734,8 +820,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 = @@ -756,7 +844,9 @@ void VideoDriver_SDL::MainLoop() * except sleeping can't. */ if (_draw_mutex != NULL) _draw_mutex->EndCritical(); - GameLoop(); + for (int i = (_fast_forward ? 5 : 1); i > 0; i--) { + GameLoop(); + } if (_draw_mutex != NULL) _draw_mutex->BeginCritical(); diff --git a/src/viewport.cpp b/src/viewport.cpp index 07cecb556e..3f6619490e 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -88,6 +88,7 @@ #include "command_func.h" #include "network/network_func.h" #include "framerate_type.h" +#include "build_confirmation_func.h" #include @@ -1799,7 +1800,7 @@ void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_heigh * * @ingroup dirty */ -static void SetSelectionTilesDirty() +void SetSelectionTilesDirty() { int x_size = _thd.size.x; int y_size = _thd.size.y; @@ -2015,6 +2016,8 @@ static void PlaceObject() Point pt; Window *w; + if (BuildConfirmationWindowProcessViewportClick()) return; + pt = GetTileBelowCursor(); if (pt.x == -1) return; @@ -2033,6 +2036,22 @@ 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) { @@ -2285,8 +2304,10 @@ void UpdateTileSelection() default: NOT_REACHED(); } - _thd.selstart.x = x1 & ~TILE_UNIT_MASK; - _thd.selstart.y = y1 & ~TILE_UNIT_MASK; + if (!ConfirmationWindowShown()) { + _thd.selstart.x = x1 & ~TILE_UNIT_MASK; + _thd.selstart.y = y1 & ~TILE_UNIT_MASK; + } break; default: NOT_REACHED(); @@ -2296,6 +2317,8 @@ void UpdateTileSelection() } } + if (ConfirmationWindowShown()) return; + /* redraw selection */ if (_thd.drawstyle != new_drawstyle || _thd.pos.x != _thd.new_pos.x || _thd.pos.y != _thd.new_pos.y || @@ -2357,7 +2380,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)) { @@ -2398,7 +2423,7 @@ void VpSetPresizeRange(TileIndex from, TileIndex to) } } -static void VpStartPreSizing() +void VpStartPreSizing() { _thd.selend.x = -1; _special_mouse_mode = WSM_PRESIZE; @@ -2840,6 +2865,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; @@ -2990,15 +3020,20 @@ EventState VpHandlePlaceSizingDrag() /* while dragging execute the drag procedure of the corresponding window (mostly VpSelectTilesWithMethod() ) */ if (_left_button_down) { + HideBuildConfirmationWindow(); w->OnPlaceDrag(_thd.select_method, _thd.select_proc, GetTileBelowCursor()); return ES_HANDLED; } + ShowBuildConfirmationWindow(); // This will also remember tile selection, so it's okay for the code below to change selection + /* mouse button released.. * 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; @@ -3009,9 +3044,7 @@ EventState VpHandlePlaceSizingDrag() } SetTileSelectSize(1, 1); - HideMeasurementTooltips(); - w->OnPlaceMouseUp(_thd.select_method, _thd.select_proc, _thd.selend, TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y)); - +place_mouseup: return ES_HANDLED; } @@ -3029,6 +3062,24 @@ 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; + +/** Place object from the build confirmation dialog */ +void ConfirmPlacingObject() +{ + Window *w = _thd.GetCallbackWnd(); + if (w == NULL) { + ResetObjectToPlace(); + return; + } + + _last_selected_window_class = _thd.window_class; + _last_selected_window_number = _thd.window_number; + HideMeasurementTooltips(); + w->OnPlaceMouseUp(_thd.select_method, _thd.select_proc, _thd.selend, TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y)); +} + /** * Change the cursor and mouse click/drag handling to a mode for performing special operations like tile area selection, object placement, etc. * @param icon New shape of the mouse cursor. @@ -3087,7 +3138,20 @@ void SetObjectToPlace(CursorID icon, PaletteID pal, HighLightStyle mode, WindowC /** Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows). */ 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); + HideBuildConfirmationWindow(); + 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 319d4efd60..1ae5e20a0b 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); @@ -93,4 +94,6 @@ static inline void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset = 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 9c89a85f84..3f08fccc36 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), @@ -45,9 +45,6 @@ static const NWidgetPart _nested_extra_view_port_widgets[] = { NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_EV_VIEW_TO_MAIN), SetFill(1, 1), SetResize(1, 0), SetDataTip(STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN, STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT), EndContainer(), - EndContainer(), - NWidget(NWID_HORIZONTAL), - NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(), NWidget(WWT_RESIZEBOX, COLOUR_GREY), EndContainer(), }; diff --git a/src/viewport_type.h b/src/viewport_type.h index 74cd88d95d..d2adff8a63 100644 --- a/src/viewport_type.h +++ b/src/viewport_type.h @@ -85,6 +85,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 }; @@ -121,6 +122,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.) }; diff --git a/src/widget.cpp b/src/widget.cpp index 5ec539a496..afe5d0ad13 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -18,7 +18,10 @@ #include "transparency.h" #include "core/geometry_func.hpp" #include "settings_type.h" +#include "settings_gui.h" #include "querystring_gui.h" +#include "blitter/factory.hpp" + #include "table/sprites.h" #include "table/strings.h" @@ -47,6 +50,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 +65,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 +105,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->mouse_capture_widget = sb->index; @@ -105,7 +114,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->mouse_capture_widget = sb->index; @@ -119,7 +128,10 @@ 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->mouse_capture_widget = sb->index; + w->scrolling_scrollbar = sb->index; _cursorpos_drag_start = _cursor.pos; } } @@ -342,10 +354,10 @@ static inline void DrawVerticalScrollbar(const Rect &r, Colours colour, bool up_ /* draw up/down buttons */ DrawFrameRect(r.left, r.top, r.right, r.top + height - 1, colour, (up_clicked) ? FR_LOWERED : FR_NONE); - DrawSprite(SPR_ARROW_UP, PAL_NONE, r.left + 1 + up_clicked, r.top + 1 + up_clicked); + DrawSpriteCenteredRect(SPR_ARROW_UP, PAL_NONE, r.left + 2 + up_clicked * 2, r.top + 2 + up_clicked * 2, r.right, r.top + height); DrawFrameRect(r.left, r.bottom - (height - 1), r.right, r.bottom, colour, (down_clicked) ? FR_LOWERED : FR_NONE); - DrawSprite(SPR_ARROW_DOWN, PAL_NONE, r.left + 1 + down_clicked, r.bottom - (height - 2) + down_clicked); + DrawSpriteCenteredRect(SPR_ARROW_DOWN, PAL_NONE, r.left + 2 + down_clicked * 2, r.bottom - height + 2 + down_clicked, r.right, r.bottom); int c1 = _colour_gradient[colour & 0xF][3]; int c2 = _colour_gradient[colour & 0xF][7]; @@ -377,12 +389,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); + DrawSpriteCenteredRect(SPR_ARROW_LEFT, PAL_NONE, r.left + left_clicked * 2, r.top + 2 + left_clicked * 2, r.left + height, r.bottom); 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); + DrawSpriteCenteredRect(SPR_ARROW_RIGHT, PAL_NONE, r.right - width + right_clicked * 2, r.top + 2 + right_clicked * 2, r.right, r.bottom); int c1 = _colour_gradient[colour & 0xF][3]; int c2 = _colour_gradient[colour & 0xF][7]; @@ -537,16 +550,14 @@ static inline void DrawCloseBox(const Rect &r, Colours colour) * @param owner 'Owner' of the window. * @param str Text to draw in the bar. */ -void DrawCaption(const Rect &r, Colours colour, Owner owner, StringID str) +void DrawCaption(const Rect &r, Colours colour, Owner owner, StringID str, const NWidgetCore *widget, const Window *window) { bool company_owned = owner < MAX_COMPANIES; + GfxFillRect(r.left + 2, r.top + 2, r.right - 2, r.bottom - 2, company_owned ? _colour_gradient[_company_colours[owner]][4] : _colour_gradient[colour][5]); + if (widget != NULL && window != NULL) widget->DrawEdgeOrnament(window); DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, FR_BORDERONLY); - DrawFrameRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, colour, company_owned ? FR_LOWERED | FR_DARKENED | FR_BORDERONLY : FR_LOWERED | FR_DARKENED); - - if (company_owned) { - GfxFillRect(r.left + 2, r.top + 2, r.right - 2, r.bottom - 2, _colour_gradient[_company_colours[owner]][4]); - } + DrawFrameRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, colour, FR_LOWERED | FR_DARKENED | FR_BORDERONLY); if (str != STR_NULL) { Dimension d = GetStringBoundingBox(str); @@ -569,19 +580,19 @@ 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) { DrawFrameRect(r.left, r.top, r.right - dd_width, r.bottom, colour, clicked_button ? FR_LOWERED : FR_NONE); DrawFrameRect(r.right + 1 - dd_width, r.top, r.right, r.bottom, colour, clicked_dropdown ? FR_LOWERED : FR_NONE); - DrawSprite(SPR_ARROW_DOWN, PAL_NONE, r.right - (dd_width - 2) + clicked_dropdown, r.top + image_offset + clicked_dropdown); + DrawSpriteCenteredRect(SPR_ARROW_DOWN, PAL_NONE, r.right - (dd_width - 2) + clicked_dropdown * 2, r.top + image_offset + clicked_dropdown * 2, r.right, r.bottom); if (str != STR_NULL) DrawString(r.left + WD_DROPDOWNTEXT_LEFT + clicked_button, r.right - dd_width - WD_DROPDOWNTEXT_RIGHT + clicked_button, r.top + text_offset + clicked_button, str, TC_BLACK); } else { DrawFrameRect(r.left + dd_width, r.top, r.right, r.bottom, colour, clicked_button ? FR_LOWERED : FR_NONE); DrawFrameRect(r.left, r.top, r.left + dd_width - 1, r.bottom, colour, clicked_dropdown ? FR_LOWERED : FR_NONE); - DrawSprite(SPR_ARROW_DOWN, PAL_NONE, r.left + 1 + clicked_dropdown, r.top + image_offset + clicked_dropdown); + DrawSpriteCenteredRect(SPR_ARROW_DOWN, PAL_NONE, r.left + 1 + clicked_dropdown * 2, r.top + image_offset + clicked_dropdown * 2, r.left + dd_width, r.bottom); if (str != STR_NULL) DrawString(r.left + dd_width + WD_DROPDOWNTEXT_LEFT + clicked_button, r.right - WD_DROPDOWNTEXT_RIGHT + clicked_button, r.top + text_offset + clicked_button, str, TC_BLACK); } } @@ -628,6 +639,11 @@ void Window::DrawWidgets() const GfxFillRect(left, bottom, right, bottom, colour); } } + + /* Dim the window if it's about to close */ + if ((this->flags & WF_DRAGGING) && !_settings_client.gui.windows_titlebars && GetWindowDraggedOffScreen(this)) { + GfxFillRect(2, 2, this->width - 3, this->height - 3, PALETTE_TO_TRANSPARENT, FILLRECT_RECOLOUR); + } } /** @@ -643,12 +659,11 @@ void Window::DrawSortButtonState(int widget, SortButtonState state) const const NWidgetBase *nwid = this->GetWidget(widget); /* Sort button uses the same sprites as vertical scrollbar */ - Dimension dim = NWidgetScrollbar::GetVerticalDimension(); int offset = this->IsWidgetLowered(widget) ? 1 : 0; - int x = offset + nwid->pos_x + (_current_text_dir == TD_LTR ? nwid->current_x - dim.width : 0); - int y = offset + nwid->pos_y + (nwid->current_y - dim.height) / 2; + int x = offset + nwid->pos_x + (_current_text_dir == TD_LTR ? nwid->current_x - SETTING_BUTTON_HEIGHT / 2 : SETTING_BUTTON_HEIGHT / 2); + int y = offset + Center(nwid->pos_y, nwid->current_y, FONT_HEIGHT_NORMAL / 4); - DrawSprite(state == SBS_DOWN ? SPR_ARROW_DOWN : SPR_ARROW_UP, PAL_NONE, x, y); + DrawSpriteCentered(state == SBS_DOWN ? SPR_ARROW_DOWN : SPR_ARROW_UP, PAL_NONE, x, y); } /** @@ -805,6 +820,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; } @@ -818,6 +834,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); } /** @@ -869,6 +906,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; @@ -907,6 +945,192 @@ NWidgetCore *NWidgetCore::GetWidgetFromPos(int x, int y) return (IsInsideBS(x, this->pos_x, this->current_x) && IsInsideBS(y, this->pos_y, this->current_y)) ? this : NULL; } +void NWidgetCore::DrawEdgeOrnament(const Window *w) const +{ + if (!_settings_client.gui.windows_decorations) return; + if (w->window_class == WC_MAIN_TOOLBAR || + w->window_class == WC_MAIN_TOOLBAR_RIGHT || + w->window_class == WC_BUILD_CONFIRMATION || + w->window_class == WC_STATUS_BAR || + w->window_class == WC_TOOLTIPS || + w->window_class == WC_DROPDOWN_MENU) { + return; + } + if (this->pos_x == 0) { + DrawEdgeOrnamentL(); + } + if (int(this->pos_x + this->current_x) == w->width) { + DrawEdgeOrnamentR(); + } + if (this->pos_y == 0) { + DrawEdgeOrnamentT(); + } + if (int(this->pos_y + this->current_y) == w->height) { + DrawEdgeOrnamentB(); + } +} + +/* + Ornament image + + - - - - - - - - - - - - - - - - 0 + - - - - - - - + + + - - - + + + 1 + + - - - - - + - - - + - + - - - 2 + - + - - - + - - - - - + - - - - 3 + - - + - + - - - - - - + - - - - 4 + - - - + - - - + - - + - + - - + 5 + - - - - - - - - + + - - - + + - 6 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +*/ + +static const unsigned char ornamentImg[][2] = { + { 0, 2, }, + { 1, 3, }, + { 2, 4, }, + { 3, 5, }, + { 4, 4, }, + { 5, 3, }, + { 6, 2, }, + { 7, 1, }, + { 7, 5, }, + { 8, 1, }, + { 8, 6, }, + { 9, 1, }, + { 9, 6, }, + { 10, 2, }, + { 10, 5, }, + { 11, 3, }, + { 11, 4, }, + { 12, 2, }, + { 12, 5, }, + { 13, 1, }, + { 13, 6, }, + { 14, 1, }, + { 14, 6, }, + { 15, 1, }, + { 15, 5, }, +}; + + +enum { + ORNAMENT_STEP = 16, + ORNAMENT_HEIGHT = 4, + ORNAMENT_IMG_LEN = sizeof(ornamentImg) / sizeof(ornamentImg[0]) +}; + + +void NWidgetCore::DrawEdgeOrnamentL() const +{ + if (_cur_dpi == NULL || _cur_dpi->zoom != ZOOM_LVL_NORMAL) return; + + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + + void *dst = _cur_dpi->dst_ptr; + int left = _cur_dpi->left; + int width = _cur_dpi->width; + int top = _cur_dpi->top; + int height = _cur_dpi->height; + + int edge = this->pos_y + this->current_y - top - 1 - ORNAMENT_HEIGHT; + + int x = this->pos_x - left; + + for (int y = this->pos_y - top + 1 + ORNAMENT_HEIGHT; y < edge + ORNAMENT_STEP; y += ORNAMENT_STEP) { + for (int i = 0; i < ORNAMENT_IMG_LEN; i++) { + int xx = x + ornamentImg[i][1]; + int yy = y + ornamentImg[i][0]; + if (yy >= height || yy >= edge) break; + if (xx >= 0 && xx < width && yy >= 0) { + blitter->SetPixel(dst, xx, yy, PC_DARK_GREY); + } + } + } +} + +void NWidgetCore::DrawEdgeOrnamentR() const +{ + if (_cur_dpi == NULL || _cur_dpi->zoom != ZOOM_LVL_NORMAL) return; + + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + + void *dst = _cur_dpi->dst_ptr; + int left = _cur_dpi->left; + int width = _cur_dpi->width; + int top = _cur_dpi->top; + int height = _cur_dpi->height; + + int edge = this->pos_y + this->current_y - top - 1 - ORNAMENT_HEIGHT; + + int x = this->pos_x + this->current_x - left - 1; + + for (int y = this->pos_y - top + 1 + ORNAMENT_HEIGHT; y < edge + ORNAMENT_STEP; y += ORNAMENT_STEP) { + for (int i = 0; i < ORNAMENT_IMG_LEN; i++) { + int xx = x - ornamentImg[i][1]; + int yy = y + ornamentImg[i][0]; + if (yy >= height || yy >= edge) break; + if (xx >= 0 && xx < width && yy >= 0) { + blitter->SetPixel(dst, xx, yy, PC_DARK_GREY); + } + } + } +} + +void NWidgetCore::DrawEdgeOrnamentT() const +{ + if (_cur_dpi == NULL || _cur_dpi->zoom != ZOOM_LVL_NORMAL) return; + + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + + void *dst = _cur_dpi->dst_ptr; + int left = _cur_dpi->left; + int width = _cur_dpi->width; + int top = _cur_dpi->top; + int height = _cur_dpi->height; + + int edge = this->pos_x + this->current_x - left - 1 - ORNAMENT_HEIGHT; + + int y = this->pos_y - top; + + for (int x = this->pos_x - left + 1 + ORNAMENT_HEIGHT; x < edge + ORNAMENT_STEP; x += ORNAMENT_STEP) { + for (int i = 0; i < ORNAMENT_IMG_LEN; i++) { + int xx = x + ornamentImg[i][0]; + int yy = y + ornamentImg[i][1]; + if (xx >= width || xx >= edge) break; + if (yy >= 0 && yy < height && xx >= 0) { + blitter->SetPixel(dst, xx, yy, PC_DARK_GREY); + } + } + } +} + +void NWidgetCore::DrawEdgeOrnamentB() const +{ + if (_cur_dpi == NULL || _cur_dpi->zoom != ZOOM_LVL_NORMAL) return; + + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + + void *dst = _cur_dpi->dst_ptr; + int left = _cur_dpi->left; + int width = _cur_dpi->width; + int top = _cur_dpi->top; + int height = _cur_dpi->height; + + int edge = this->pos_x + this->current_x - left - 1 - ORNAMENT_HEIGHT; + + int y = this->pos_y + this->current_y - top - 1; + + for (int x = this->pos_x - left + 1 + ORNAMENT_HEIGHT; x < edge + ORNAMENT_STEP; x += ORNAMENT_STEP) { + for (int i = 0; i < ORNAMENT_IMG_LEN; i++) { + int xx = x + ornamentImg[i][0]; + int yy = y - ornamentImg[i][1]; + if (xx >= width || xx >= edge) break; + if (yy >= 0 && yy < height && xx >= 0) { + blitter->SetPixel(dst, xx, yy, PC_DARK_GREY); + } + } + } +} + /** * Constructor container baseclass. * @param tp Type of the container. @@ -1859,6 +2083,8 @@ void NWidgetBackground::Draw(const Window *w) NOT_REACHED(); } + DrawEdgeOrnament(w); + if (this->index >= 0) w->DrawWidget(r, this->index); if (this->child != NULL) this->child->Draw(w); @@ -1867,6 +2093,7 @@ void NWidgetBackground::Draw(const Window *w) } } + NWidgetCore *NWidgetBackground::GetWidgetFromPos(int x, int y) { NWidgetCore *nwid = NULL; @@ -1989,6 +2216,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); } @@ -2063,7 +2291,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; } @@ -2074,7 +2304,9 @@ 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; } @@ -2112,12 +2344,46 @@ 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; this->SetResize(0, 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; + this->SetMinimalSize(8, 8); + break; + case NWID_PUSHBUTTON_DROPDOWN: + case NWID_BUTTON_DROPDOWN: + case WWT_DROPDOWN: + case WWT_ARROWBTN: + this->sizing_type = NWST_STEP; + this->SetMinimalSize(8, 8); + break; + default: + this->sizing_type = NWST_OVERRIDE; + } + } + switch (tp) { case WWT_EMPTY: break; @@ -2146,7 +2412,7 @@ NWidgetLeaf::NWidgetLeaf(WidgetType tp, Colours colour, int index, uint32 data, case WWT_CAPTION: this->SetFill(1, 0); this->SetResize(1, 0); - this->min_y = WD_CAPTION_HEIGHT; + //this->min_y = WD_CAPTION_HEIGHT; this->SetDataTip(data, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS); break; @@ -2188,7 +2454,7 @@ NWidgetLeaf::NWidgetLeaf(WidgetType tp, Colours colour, int index, uint32 data, case WWT_DROPDOWN: this->SetFill(0, 0); - this->min_y = WD_DROPDOWN_HEIGHT; + //this->min_y = WD_DROPDOWN_HEIGHT; break; default: @@ -2208,7 +2474,20 @@ void NWidgetLeaf::SetupSmallestSize(Window *w, bool init_array) Dimension resize = {this->resize_x, this->resize_y}; /* Get padding, and update size with the real content size if appropriate. */ const Dimension *padding = NULL; - switch (this->type) { + if (!_settings_client.gui.windows_titlebars && w->window_class != WC_NEWS_WINDOW && + (this->type == WWT_CAPTION || this->type == WWT_STICKYBOX || this->type == WWT_SHADEBOX || + this->type == WWT_DEFSIZEBOX || this->type == WWT_CLOSEBOX || this->type == WWT_DEBUGBOX)) { + static const Dimension extra = {0, 0}; + padding = &extra; + this->sizing_type = NWST_OVERRIDE; + size = extra; + fill = extra; + resize = extra; + if (this->type == WWT_CAPTION) { + fill.width = 1; + resize.width = 1; + } + } else switch (this->type) { case WWT_EMPTY: { static const Dimension extra = {0, 0}; padding = &extra; @@ -2287,6 +2566,7 @@ void NWidgetLeaf::SetupSmallestSize(Window *w, bool init_array) Dimension sprite_size = GetSpriteSize(_current_text_dir == TD_RTL ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT); size.width = max(size.width, 30 + sprite_size.width); size.height = max(sprite_size.height, GetStringBoundingBox("_").height + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM); + size.height = GetMinSizing(NWST_BUTTON, size.height); } FALLTHROUGH; case WWT_PUSHBTN: { @@ -2353,7 +2633,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; @@ -2365,7 +2645,8 @@ void NWidgetLeaf::SetupSmallestSize(Window *w, bool init_array) padding = &extra; if (NWidgetLeaf::dropdown_dimension.width == 0) { NWidgetLeaf::dropdown_dimension = GetSpriteSize(SPR_ARROW_DOWN); - NWidgetLeaf::dropdown_dimension.width += WD_DROPDOWNTEXT_LEFT + WD_DROPDOWNTEXT_RIGHT; + NWidgetLeaf::dropdown_dimension.width = SETTING_BUTTON_HEIGHT; + //NWidgetLeaf::dropdown_dimension.width += WD_DROPDOWNTEXT_LEFT + WD_DROPDOWNTEXT_RIGHT; NWidgetLeaf::dropdown_dimension.height += WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM; extra.width = WD_DROPDOWNTEXT_LEFT + WD_DROPDOWNTEXT_RIGHT + NWidgetLeaf::dropdown_dimension.width; } @@ -2470,26 +2751,28 @@ void NWidgetLeaf::Draw(const Window *w) case WWT_CAPTION: if (this->index >= 0) w->SetStringParameters(this->index); - DrawCaption(r, this->colour, w->owner, this->widget_data); + DrawCaption(r, this->colour, w->owner, this->widget_data, this, w); break; 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: @@ -2533,11 +2816,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 - NWidgetLeaf::dropdown_dimension.width; + int button_width = this->pos_x + this->current_x - button_size; return pt.x < button_width; } else { - int button_left = this->pos_x + NWidgetLeaf::dropdown_dimension.width; + int button_left = this->pos_x + button_size; return pt.x >= button_left; } } @@ -2630,6 +2914,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) { @@ -2886,6 +3180,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); @@ -2906,3 +3201,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 33fb8bce08..3edd25f6e6 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(). */ @@ -293,6 +309,12 @@ public: inline void SetDisabled(bool disabled); inline bool IsDisabled() const; + inline void DrawEdgeOrnament(const Window *w) const; + inline void DrawEdgeOrnamentL() const; + inline void DrawEdgeOrnamentR() const; + inline void DrawEdgeOrnamentT() const; + inline void DrawEdgeOrnamentB() const; + /* virtual */ void FillNestedArray(NWidgetBase **array, uint length); /* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y); /* virtual */ bool IsHighlighted() const; @@ -918,6 +940,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 +961,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/build_confirmation_widget.h b/src/widgets/build_confirmation_widget.h new file mode 100644 index 0000000000..9244ef204e --- /dev/null +++ b/src/widgets/build_confirmation_widget.h @@ -0,0 +1,23 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file build_confirmation_widget.h Types related to the build_confirmation widgets. */ + +#ifndef WIDGETS_BUILD_CONFIRMATION_WIDGET_H +#define WIDGETS_BUILD_CONFIRMATION_WIDGET_H + +/** Widgets of the #BuildVehicleWindow class. */ +enum BuildConfirmationWidgets { + WID_BC_PRICE, ///< Estimated price. + WID_BC_OK, ///< Confirm action. + WID_BC_CANCEL, ///< Cancel action. + WID_BC_PANEL, ///< Cancel action. +}; + +#endif /* WIDGETS_BUILD_CONFIRMATION_WIDGET_H */ diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index 61656c020e..3646d18a27 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -41,7 +41,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); } /** @@ -97,6 +97,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). GUITimer scrolling_timer; ///< Timer for auto-scroll of the item list. Point position; ///< Position of the topleft corner of the window. @@ -155,9 +156,10 @@ 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->scrolling_timer = GUITimer(MILLISECONDS_PER_TICK); + this->left_button_state = _left_button_down; } ~DropdownWindow() @@ -265,8 +267,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(); @@ -322,6 +327,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; + } } }; @@ -368,7 +383,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b bool above = false; /* Available height below (or above, if the dropdown is placed above the widget). */ - uint available_height = (uint)max(GetMainViewBottom() - top - 4, 0); + uint available_height = (uint)max(_screen.height - top - 4, 0); /* If the dropdown doesn't fully fit below the widget... */ if (height > available_height) { 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/error_widget.h b/src/widgets/error_widget.h index 8693575a75..b1fcb1b01c 100644 --- a/src/widgets/error_widget.h +++ b/src/widgets/error_widget.h @@ -17,6 +17,7 @@ enum ErrorMessageWidgets { WID_EM_CAPTION, ///< Caption of the window. WID_EM_FACE, ///< Error title. WID_EM_MESSAGE, ///< Error message. + WID_EM_CLOSE, ///< Close button. }; #endif /* WIDGETS_ERROR_WIDGET_H */ diff --git a/src/widgets/fios_widget.h b/src/widgets/fios_widget.h index 2351f8035e..1199fdaa9a 100644 --- a/src/widgets/fios_widget.h +++ b/src/widgets/fios_widget.h @@ -32,6 +32,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 ae48827ed1..4b772852e5 100644 --- a/src/widgets/intro_widget.h +++ b/src/widgets/intro_widget.h @@ -34,6 +34,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/rail_widget.h b/src/widgets/rail_widget.h index f977f44803..d334f02c5a 100644 --- a/src/widgets/rail_widget.h +++ b/src/widgets/rail_widget.h @@ -71,6 +71,7 @@ enum BuildRailStationWidgets { WID_BRAS_SHOW_NEWST_TYPE, ///< Display of selected station type. WID_BRAS_NEWST_LIST, ///< List with available newstation classes. WID_BRAS_NEWST_SCROLL, ///< Scrollbar of the #WID_BRAS_NEWST_LIST. + WID_BRAS_NEWST_SPACER, ///< Spacer to make newst list fit the screen WID_BRAS_PLATFORM_NUM_BEGIN = WID_BRAS_PLATFORM_NUM_1 - 1, ///< Helper for determining the chosen platform width. WID_BRAS_PLATFORM_LEN_BEGIN = WID_BRAS_PLATFORM_LEN_1 - 1, ///< Helper for determining the chosen platform length. diff --git a/src/widgets/settings_widget.h b/src/widgets/settings_widget.h index ac64ac80ae..48ee83c933 100644 --- a/src/widgets/settings_widget.h +++ b/src/widgets/settings_widget.h @@ -23,6 +23,14 @@ enum GameOptionsWidgets { WID_GO_LANG_DROPDOWN, ///< Language dropdown. WID_GO_RESOLUTION_DROPDOWN, ///< Dropdown for the resolution. WID_GO_FULLSCREEN_BUTTON, ///< Toggle fullscreen. + WID_GO_8BPP_BUTTON, ///< 8 bits per pixel video mode + WID_GO_16BPP_BUTTON, ///< 16 bits per pixel video mode + WID_GO_32BPP_BUTTON, ///< 32 bits per pixel video mode + 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_BUILD_CONFIRMATION, ///< Enable build confirmation dialog. + WID_GO_WINDOWS_TITLEBARS, ///< Titlebars for all windows. WID_GO_GUI_ZOOM_DROPDOWN, ///< Dropdown for the GUI zoom level. WID_GO_BASE_GRF_DROPDOWN, ///< Use to select a base GRF. WID_GO_BASE_GRF_STATUS, ///< Info about missing files etc. 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 c317fc9574..1692a9505e 100644 --- a/src/widgets/toolbar_widget.h +++ b/src/widgets/toolbar_widget.h @@ -46,6 +46,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 faae96187c..4b72264c0d 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -40,6 +40,7 @@ #include "network/network_func.h" #include "guitimer_func.h" #include "news_func.h" +#include "build_confirmation_func.h" #include "safeguards.h" @@ -51,8 +52,11 @@ enum ViewportAutoscrolling { VA_EVERY_VIEWPORT, //!< Scroll all viewports at their edges. }; +static bool _dragging_window; ///< A window is being dragged or resized. static Point _drag_delta; ///< delta between mouse cursor and upper left corner of dragged window static Window *_mouseover_last_w = NULL; ///< Window of the last OnMouseOver event. +static Point _left_button_down_pos; ///< Position of left mouse button down event, to handle the difference between click and drag +static bool _dragging_widget; ///< A widget inside the window is being dragged, prevent the window itself from being dragged static Window *_last_scroll_window = NULL; ///< Window of the last scroll event. /** List of windows opened at the screen sorted from the front. */ @@ -78,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. @@ -627,13 +632,14 @@ static void StartWindowDrag(Window *w); static void StartWindowSizing(Window *w, bool to_left); /** - * Dispatch left mouse-button (possibly double) click in window. + * Mouse left button down+up events trigger OnClick event for a window. * @param w Window to dispatch event in * @param x X coordinate of the click * @param y Y coordinate of the click * @param click_count Number of fast consecutive clicks at same position + * @param mouse_down Event generated on mouse button press */ -static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) +static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count, bool mouse_down) { NWidgetCore *nw = w->nested_root->GetWidgetFromPos(x, y); WidgetType widget_type = (nw != NULL) ? nw->type : WWT_EMPTY; @@ -670,18 +676,35 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) focused_widget_changed |= w->SetFocusedWidget(widget_index); } + Point pt = { x, y }; + + if (!_settings_client.gui.windows_titlebars && mouse_down) { + // TODO: this should be handled inside window or widget methods, not here + if (widget_type == NWID_VSCROLLBAR || widget_type == NWID_HSCROLLBAR) { + ScrollbarClickHandler(w, nw, x, y); + _dragging_widget = true; + } + if (widget_type == WWT_RESIZEBOX) { + StartWindowSizing(w, (int)nw->pos_x < (w->width / 2)); + nw->SetDirty(w); + } + if (w->window_class == WC_SMALLMAP && widget_index == WID_SM_MAP) { + w->OnClick(pt, widget_index, click_count); + _dragging_widget = true; + } + return; + } + /* Close any child drop down menus. If the button pressed was the drop down * list's own button, then we should not process the click any further. */ if (HideDropDownMenu(w) == widget_index && widget_index >= 0) return; if ((widget_type & ~WWB_PUSHBUTTON) < WWT_LAST && (widget_type & WWB_PUSHBUTTON)) w->HandleButtonClick(widget_index); - Point pt = { x, y }; - switch (widget_type) { case NWID_VSCROLLBAR: case NWID_HSCROLLBAR: - ScrollbarClickHandler(w, nw, x, y); + if (mouse_down) ScrollbarClickHandler(w, nw, x, y); break; case WWT_EDITBOX: { @@ -759,6 +782,33 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) w->OnClick(pt, widget_index, click_count); } +static int _left_button_click_count = 0; +/** + * Dispatch left mouse-button (possibly double) press in window. + * @param w Window to dispatch event in + * @param x X coordinate of the click + * @param y Y coordinate of the click + * @param click_count Number of fast consecutive clicks at same position + */ +static void DispatchLeftButtonDownEvent(Window *w, int x, int y, int click_count) +{ + _left_button_click_count = click_count; + DispatchLeftClickEvent(w, x, y, click_count, true); +} + +/** + * Dispatch left mouse-button (possibly double) release in window. + * @param w Window to dispatch event in + * @param x X coordinate of the click + * @param y Y coordinate of the click + */ +static void DispatchLeftButtonUpEvent(Window *w, int x, int y) +{ + _dragging_widget = false; + if (_settings_client.gui.windows_titlebars || _dragging_window) return; + DispatchLeftClickEvent(w, x, y, _left_button_click_count, false); +} + /** * Dispatch right mouse-button click in window. * @param w Window to dispatch event in @@ -1259,6 +1309,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: @@ -1301,7 +1352,7 @@ static uint GetWindowZPriority(WindowClass wc) FALLTHROUGH; case WC_MAIN_TOOLBAR: - case WC_STATUS_BAR: + case WC_MAIN_TOOLBAR_RIGHT: ++z_priority; FALLTHROUGH; @@ -1338,11 +1389,14 @@ static uint GetWindowZPriority(WindowClass wc) ++z_priority; FALLTHROUGH; - case WC_NEWS_WINDOW: + default: ++z_priority; FALLTHROUGH; - default: + case WC_STATUS_BAR: + ++z_priority; + + case WC_NEWS_WINDOW: ++z_priority; FALLTHROUGH; @@ -1453,6 +1507,14 @@ void Window::InitializeData(WindowNumber window_number) this->nested_focus = NULL; this->window_number = window_number; + if (this->window_class != WC_BUILD_CONFIRMATION && + this->window_class != WC_TOOLTIPS && + this->window_class != WC_NEWS_WINDOW && + this->window_class != WC_BUILD_BRIDGE && + this->window_class != WC_SELECT_STATION) { + HideBuildConfirmationWindow(); + } + this->OnInit(); /* Initialize nested widget tree. */ if (this->nested_array == NULL) { @@ -1507,6 +1569,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; @@ -1518,10 +1581,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 @@ -1542,8 +1608,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; @@ -1572,7 +1643,13 @@ static bool IsGoodAutoPlace1(int left, int top, int width, int height, int toolb int right = width + left; int bottom = height + top; - if (left < 0 || top < toolbar_y || right > _screen.width || bottom > _screen.height) return false; + const Window *main_toolbar = FindWindowByClass(WC_MAIN_TOOLBAR); + bool vertical_toolbar = _settings_client.gui.vertical_toolbar && _game_mode != GM_EDITOR; + if (!vertical_toolbar || !main_toolbar) { + if (left < 0 || top < toolbar_y || right > _screen.width || bottom > _screen.height) return false; + } else { + if (left < main_toolbar->width || top < 0 || right > _screen.width - main_toolbar->width || bottom > _screen.height) return false; + } /* Make sure it is not obscured by any window. */ const Window *w; @@ -1647,13 +1724,18 @@ static bool IsGoodAutoPlace2(int left, int top, int width, int height, int toolb static Point GetAutoPlacePosition(int width, int height) { Point pt; + bool vertical_toolbar = _settings_client.gui.vertical_toolbar && _game_mode != GM_EDITOR; bool rtl = _current_text_dir == TD_RTL; /* First attempt, try top-left of the screen */ const Window *main_toolbar = FindWindowByClass(WC_MAIN_TOOLBAR); - const int toolbar_y = main_toolbar != NULL ? main_toolbar->height : 0; - if (IsGoodAutoPlace1(rtl ? _screen.width - width : 0, toolbar_y, width, height, toolbar_y, pt)) return pt; + const int toolbar_y = !vertical_toolbar && main_toolbar != NULL ? main_toolbar->height : 0; + if (vertical_toolbar) { + if (IsGoodAutoPlace1(main_toolbar != NULL ? main_toolbar->width : 0, 0, width, height, toolbar_y, pt)) return pt; + } else { + if (IsGoodAutoPlace1(rtl ? _screen.width - width : 0, toolbar_y, width, height, toolbar_y, pt)) return pt; + } /* Second attempt, try around all existing windows. * The new window must be entirely on-screen, and not overlap with an existing window. @@ -1690,6 +1772,10 @@ static Point GetAutoPlacePosition(int width, int height) * of the closebox */ int left = rtl ? _screen.width - width : 0, top = toolbar_y; + if (vertical_toolbar) { + left = main_toolbar != NULL ? (rtl ? _screen.width - width - main_toolbar->width : main_toolbar->width) : 0; + top = 0; + } int offset_x = rtl ? -(int)NWidgetLeaf::closebox_dimension.width : (int)NWidgetLeaf::closebox_dimension.width; int offset_y = max(NWidgetLeaf::closebox_dimension.height, FONT_HEIGHT_NORMAL + WD_CAPTIONTEXT_TOP + WD_CAPTIONTEXT_BOTTOM); @@ -1717,7 +1803,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; } @@ -1746,11 +1840,20 @@ 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 != WC_NONE && (w = FindWindowById(desc->parent_cls, window_number)) != NULL) { + 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) { bool rtl = _current_text_dir == TD_RTL; if (desc->parent_cls == WC_BUILD_TOOLBAR || desc->parent_cls == WC_SCEN_LAND_GEN) { pt.x = w->left + (rtl ? w->width - default_width : 0); pt.y = w->top + w->height; + if (pt.x > _screen.width + 10 - default_width) { + pt.x = _screen.width + 10 - default_width; + } + const Window *wt = FindWindowById(WC_MAIN_TOOLBAR_RIGHT, 0); + if (wt) { + // 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; + } return pt; } else { /* Position child window with offset of closebox, but make sure that either closebox or resizebox is visible @@ -1758,7 +1861,7 @@ static Point LocalGetWindowPlacement(const WindowDesc *desc, int16 sm_width, int * - X position: closebox on left/right, resizebox on right/left (depending on ltr/rtl) */ int indent_y = max(NWidgetLeaf::closebox_dimension.height, FONT_HEIGHT_NORMAL + WD_CAPTIONTEXT_TOP + WD_CAPTIONTEXT_BOTTOM); - if (w->top + 3 * indent_y < _screen.height) { + if (w->top + 3 * indent_y < _screen.height && _settings_client.gui.windows_titlebars) { pt.y = w->top + indent_y; int indent_close = NWidgetLeaf::closebox_dimension.width; int indent_resize = NWidgetLeaf::resizebox_dimension.width; @@ -1794,6 +1897,8 @@ static Point LocalGetWindowPlacement(const WindowDesc *desc, int16 sm_width, int NOT_REACHED(); } + // try to put it to + return pt; } @@ -1871,6 +1976,21 @@ Window *FindWindowFromPt(int x, int y) return NULL; } +int SETTING_BUTTON_WIDTH = 20; +int SETTING_BUTTON_HEIGHT = 10; + +/** + * 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 CheckWindowMinSizings() +{ + SETTING_BUTTON_HEIGHT = GetMinSizing(NWST_STEP); + SETTING_BUTTON_WIDTH = 2 * SETTING_BUTTON_HEIGHT; +} + /** * (re)initialize the windowing system */ @@ -1977,6 +2097,27 @@ static void HandlePlacePresize() w->OnPlacePresize(pt, TileVirtXY(pt.x, pt.y)); } +/** + * Handle dragging mouse while left button is pressed in no-titlebars mode. + */ +static void HandleMouseDragNoTitlebars() +{ + if (_settings_client.gui.windows_titlebars || _dragging_window || + !_left_button_down || _focused_window == NULL || _dragging_widget) return; + unsigned distance = abs(_cursor.pos.x - _left_button_down_pos.x) + abs(_cursor.pos.y - _left_button_down_pos.y); + if (distance * 2 > GetMinSizing(NWST_STEP) && + _focused_window->window_class != WC_SELECT_GAME && + _focused_window->window_class != WC_STATUS_BAR && + _focused_window->window_class != WC_MAIN_TOOLBAR && + _focused_window->window_class != WC_MAIN_TOOLBAR_RIGHT && + _focused_window->window_class != WC_BUILD_CONFIRMATION) { + //SendLeftClickEventToWindow(_focused_window, _left_button_down_pos.x, _left_button_down_pos.y, 1); + StartWindowDrag(_focused_window); + _drag_delta.x += _cursor.pos.x - _left_button_down_pos.x; + _drag_delta.y += _cursor.pos.y - _left_button_down_pos.y; + } +} + /** * Handle dragging and dropping in mouse dragging mode (#WSM_DRAGDROP). * @return State of handling the event. @@ -1985,7 +2126,14 @@ static EventState HandleMouseDragDrop() { if (_special_mouse_mode != WSM_DRAGDROP) return ES_NOT_HANDLED; - if (_left_button_down && _cursor.delta.x == 0 && _cursor.delta.y == 0) return ES_HANDLED; // Dragging, but the mouse did not move. + bool button = _left_button_down; + static bool button_second_click = false; + if (!_settings_client.gui.windows_titlebars) { + if (_left_button_down) button_second_click = true; + button = _left_button_down || !button_second_click; + } + + if (button && _cursor.delta.x == 0 && _cursor.delta.y == 0) return ES_HANDLED; // Dragging, but the mouse did not move. Window *w = _thd.GetCallbackWnd(); if (w != NULL) { @@ -1993,14 +2141,18 @@ static EventState HandleMouseDragDrop() Point pt; pt.x = _cursor.pos.x - w->left; pt.y = _cursor.pos.y - w->top; - if (_left_button_down) { + if (button) { w->OnMouseDrag(pt, GetWidgetFromPos(w, pt.x, pt.y)); } else { w->OnDragDrop(pt, GetWidgetFromPos(w, pt.x, pt.y)); } } - if (!_left_button_down) ResetObjectToPlace(); // Button released, finished dragging. + if (!button) { + ResetObjectToPlace(); // Button released, finished dragging. + button_second_click = false; + } + return ES_HANDLED; } @@ -2089,7 +2241,7 @@ static void EnsureVisibleCaption(Window *w, int nx, int ny) /* Search for the title bar rectangle. */ Rect caption_rect; const NWidgetBase *caption = w->nested_root->GetWidgetOfType(WWT_CAPTION); - if (caption != NULL) { + if (caption != NULL && _settings_client.gui.windows_titlebars) { caption_rect.left = caption->pos_x; caption_rect.right = caption->pos_x + caption->current_x; caption_rect.top = caption->pos_y; @@ -2098,9 +2250,11 @@ static void EnsureVisibleCaption(Window *w, int nx, int ny) /* Make sure the window doesn't leave the screen */ nx = Clamp(nx, MIN_VISIBLE_TITLE_BAR - caption_rect.right, _screen.width - MIN_VISIBLE_TITLE_BAR - caption_rect.left); ny = Clamp(ny, 0, _screen.height - MIN_VISIBLE_TITLE_BAR); - /* 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); + if (!_settings_client.gui.vertical_toolbar || _game_mode == GM_EDITOR) { + // This call hides the window totally with vertical toolbar if you move it slightly off-screen to the left + PreventHiding(&nx, &ny, caption_rect, FindWindowById(WC_MAIN_TOOLBAR, 0), w->left, PHD_DOWN); + } PreventHiding(&nx, &ny, caption_rect, FindWindowById(WC_STATUS_BAR, 0), w->left, PHD_UP); } @@ -2161,6 +2315,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; } @@ -2176,7 +2331,31 @@ int GetMainViewBottom() return (w == NULL) ? _screen.height : w->top; } -static bool _dragging_window; ///< A window is being dragged or resized. +bool GetWindowDraggedOffScreen(const Window *w) +{ + if (_settings_client.gui.windows_titlebars) return false; + Rect edge = { 0, GetMainViewTop(), _screen.width, _screen.height }; + if (_settings_client.gui.vertical_toolbar && _game_mode != GM_EDITOR && _game_mode != GM_MENU) { + edge.left += GetMinSizing(NWST_BUTTON); + edge.right -= GetMinSizing(NWST_BUTTON); + } + Rect visible = { edge.left + (int)GetMinSizing(NWST_BUTTON) * 4, edge.top + (int)GetMinSizing(NWST_BUTTON) * 2, + edge.right - (int)GetMinSizing(NWST_BUTTON) * 4, edge.bottom - (int)GetMinSizing(NWST_BUTTON) * 2 }; + // 1/4 of the window must be hidden to close it when flicking it off to the left/right + if (w->width >= (int)GetMinSizing(NWST_BUTTON) * 4) { + edge.left -= GetMinSizing(NWST_BUTTON) * 2; + edge.right += GetMinSizing(NWST_BUTTON) * 2; + } + if (w->height >= (int)GetMinSizing(NWST_BUTTON) * 4) { + edge.top -= GetMinSizing(NWST_BUTTON); + edge.bottom += GetMinSizing(NWST_BUTTON); + } + if (w->left < edge.left && w->left + w->width < visible.right) return true; + if (w->left + w->width > edge.right && w->left > visible.left) return true; + if (w->top < edge.top && w->top + w->height < visible.bottom) return true; + if (w->top + w->height > edge.bottom && w->top > visible.top) return true; + return false; +} /** * Handle dragging/resizing of a window. @@ -2197,6 +2376,9 @@ static EventState HandleWindowDragging() /* Stop the dragging if the left mouse button was released */ if (!_left_button_down) { w->flags &= ~WF_DRAGGING; + if (GetWindowDraggedOffScreen(w)) { + delete w; + } break; } @@ -2286,6 +2468,12 @@ static EventState HandleWindowDragging() EnsureVisibleCaption(w, nx, ny); w->SetDirty(); + if (GetWindowDraggedOffScreen(w)) { + GuiShowTooltips(w, STR_TOOLTIP_CLOSE_WINDOW, 0, NULL, TCC_LEFT_CLICK); + } else { + GuiShowTooltips(w, STR_NULL, 0, NULL, TCC_LEFT_CLICK); // Hide tooltip + } + return ES_HANDLED; } else if (w->flags & WF_SIZING) { /* Stop the sizing if the left mouse button was released */ @@ -2406,7 +2594,7 @@ static void HandleScrollbarScrolling(Window *w) 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(); } @@ -2464,6 +2652,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.scroll_mode == VSM_MAP_LMB) { + // 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)) * 2 > (int)GetMinSizing(NWST_STEP, 10)) { + _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. @@ -2471,7 +2674,7 @@ 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 || !((_settings_client.gui.scroll_mode != VSM_MAP_LMB && _right_button_down) || scrollwheel_scrolling || (_settings_client.gui.scroll_mode == VSM_MAP_LMB && _left_button_down))) { + if (_last_scroll_window == NULL || !((_settings_client.gui.scroll_mode != VSM_MAP_LMB && _right_button_down) || scrollwheel_scrolling || ((_move_pressed || _settings_client.gui.scroll_mode == VSM_MAP_LMB) && _left_button_down))) { _cursor.fix_at = false; _scrolling_viewport = false; _last_scroll_window = NULL; @@ -2760,12 +2963,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; @@ -2777,22 +2982,44 @@ static void HandleAutoscroll() y -= vp->top; /* here allows scrolling in both x and y axis */ - static const int 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); + static const int SCROLLSPEED = 15; + if (x - border < 0) { + _move_pressed = true; + w->viewport->dest_scrollpos_x += ScaleByZoom((x - border) * SCROLLSPEED, vp->zoom); + } else if (border - (vp->width - x) > 0) { + _move_pressed = true; + w->viewport->dest_scrollpos_x += ScaleByZoom((border - (vp->width - x)) * 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((y - border * 2) * SCROLLSPEED, vp->zoom); + } else if (border - (vp->height - y) > 0) { + _move_pressed = true; + w->viewport->dest_scrollpos_y += ScaleByZoom((border - (vp->height - y)) * SCROLLSPEED, vp->zoom); + } +} + +/** + * Perform small continuous scrolling with right button press and drag. + */ +static void HandleContinuousScroll() +{ + static const float 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); } } enum MouseClick { MC_NONE = 0, MC_LEFT, + MC_LEFT_UP, MC_RIGHT, MC_DOUBLE_LEFT, MC_HOVER, @@ -2860,8 +3087,21 @@ 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; + + if (click == MC_LEFT) _left_button_down_pos = Point { x, y }; + HandlePlacePresize(); UpdateTileSelection(); + if (!mouse_down_on_viewport) HandleMouseDragNoTitlebars(); if (VpHandlePlaceSizingDrag() == ES_HANDLED) return; if (HandleMouseDragDrop() == ES_HANDLED) return; @@ -2874,16 +3114,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, unless we're scrolling a viewport or the map */ @@ -2903,14 +3136,32 @@ static void MouseLoop(MouseClick click, int mousewheel) switch (click) { case MC_DOUBLE_LEFT: case MC_LEFT: - if (HandleViewportClicked(vp, x, y)) return; - if (!(w->flags & WF_DISABLE_VP_SCROLL) && - _settings_client.gui.scroll_mode == VSM_MAP_LMB) { - _scrolling_viewport = true; - _cursor.fix_at = false; + mouse_down_on_viewport = true; + if (HandleViewportClicked(vp, x, y)) { + // Viewport already clicked, prevent sending same event on mouse-up + _left_button_dragged = true; return; } - break; + if (!(w->flags & WF_DISABLE_VP_SCROLL) && + (_settings_client.gui.scroll_mode == VSM_MAP_LMB || _move_pressed)) { + _scrolling_viewport = true; + _cursor.fix_at = false; + } else { + // Viewport already clicked, prevent sending same event on mouse-up + _left_button_dragged = true; + } + return; + + case MC_LEFT_UP: + if (!_left_button_dragged && mouse_down_on_viewport) { + HandleViewportMouseUp(vp, x, y); + MoveAllHiddenWindowsBackToScreen(); + } else if (_left_button_dragged && mouse_down_on_viewport) { + BuildConfirmationWindowProcessViewportClick(); + } + _left_button_dragged = false; + mouse_down_on_viewport = false; + return; case MC_RIGHT: if (!(w->flags & WF_DISABLE_VP_SCROLL) && @@ -2929,9 +3180,14 @@ static void MouseLoop(MouseClick click, int mousewheel) if (vp == NULL || (w->flags & WF_DISABLE_VP_SCROLL)) { switch (click) { + case MC_LEFT_UP: + DispatchLeftButtonUpEvent(w, x - w->left, y - w->top); + mouse_down_on_viewport = false; + break; + case MC_LEFT: case MC_DOUBLE_LEFT: - DispatchLeftClickEvent(w, x - w->left, y - w->top, click == MC_DOUBLE_LEFT ? 2 : 1); + DispatchLeftButtonDownEvent(w, x - w->left, y - w->top, click == MC_DOUBLE_LEFT ? 2 : 1); return; default: @@ -2966,6 +3222,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; @@ -2979,11 +3236,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; @@ -3093,6 +3356,8 @@ void InputLoop() /* HandleMouseEvents was already called for this tick */ HandleMouseEvents(); + HandleAutoscroll(); + HandleContinuousScroll(); } /** @@ -3356,6 +3621,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' @@ -3425,10 +3691,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); } @@ -3487,6 +3776,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); } @@ -3569,13 +3859,20 @@ void RelocateAllWindows(int neww, int newh) left = PositionMainToolbar(w); // changes toolbar orientation break; + case WC_MAIN_TOOLBAR_RIGHT: + ResizeWindow(w, min(neww, _toolbar_width) - w->width, 0, false); + + top = w->top; + left = neww - w->width; + break; + case WC_NEWS_WINDOW: top = newh - w->height; left = PositionNewsMessage(w); break; case WC_STATUS_BAR: - ResizeWindow(w, min(neww, _toolbar_width) - w->width, 0, false); + ResizeWindow(w, min(neww, min(_toolbar_width, _screen.width - SETTING_BUTTON_HEIGHT * 2)) - w->width, 0, false); top = newh - w->height; left = PositionStatusbar(w); @@ -3613,6 +3910,65 @@ 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_BUILD_CONFIRMATION: + 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 45e2d71eca..821b695fd7 100644 --- a/src/window_func.h +++ b/src/window_func.h @@ -29,6 +29,7 @@ int PositionNetworkChatWindow(Window *w); int GetMainViewTop(); int GetMainViewBottom(); +void CheckWindowMinSizings(); void InitWindowSystem(); void UnInitWindowSystem(); void ResetWindowSystem(); @@ -42,6 +43,7 @@ void DeleteNonVitalWindows(); void DeleteAllNonVitalWindows(); void DeleteAllMessages(); void DeleteConstructionWindows(); +void DeleteToolbarLinkedWindows(); void HideVitalWindows(); void ShowVitalWindows(); diff --git a/src/window_gui.h b/src/window_gui.h index b2bba675b2..e9e4f6b4a0 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -142,7 +142,7 @@ enum WidgetDrawDistances { /* widget.cpp */ void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags); -void DrawCaption(const Rect &r, Colours colour, Owner owner, StringID str); +void DrawCaption(const Rect &r, Colours colour, Owner owner, StringID str, const NWidgetCore *widget, const Window *window); /* window.cpp */ extern Window *_z_front_window; @@ -767,6 +767,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 @@ -884,6 +888,8 @@ Wcls *AllocateWindowDescFront(WindowDesc *desc, int window_number, bool return_e } void RelocateAllWindows(int neww, int newh); +void MoveAllWindowsOffScreen(); +void MoveAllHiddenWindowsBackToScreen(); void GuiShowTooltips(Window *parent, StringID str, uint paramcount = 0, const uint64 params[] = NULL, TooltipCloseCondition close_tooltip = TCC_HOVER); @@ -901,6 +907,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; @@ -918,4 +927,6 @@ void SetFocusedWindow(Window *w); void ScrollbarClickHandler(Window *w, NWidgetCore *nw, int x, int y); +bool GetWindowDraggedOffScreen(const Window *w); ///< Return whether window is dragged off screen edge and about to close, for no-titlebars mode + #endif /* WINDOW_GUI_H */ diff --git a/src/window_type.h b/src/window_type.h index 7185bfcb4f..c3d0b059dc 100644 --- a/src/window_type.h +++ b/src/window_type.h @@ -52,6 +52,19 @@ enum WindowClass { */ WC_MAIN_TOOLBAR, + /** + * Right part of split main toolbar; %Window numbers: + * - 0 = #ToolbarNormalWidgets + * - 0 = #ToolbarEditorWidgets + */ + WC_MAIN_TOOLBAR_RIGHT, + + /** + * Confirmation window for building anything; %Window numbers: + * - 0 = #BuildConfirmationWidgets + */ + WC_BUILD_CONFIRMATION, + /** * 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..b711feb80a --- /dev/null +++ b/todo.txt @@ -0,0 +1,12 @@ + +- 'Place Sign' does not work. Landscaping - Place Sign works. + +- Smallmap UI won't fit all FIRS industries. + +- Add 'Goal' menu item somewhere to compact toolbar. + +- Misclicking station from orders dialog should hide the dialog for 3 times. + +- Draggable combo boxes. + +- Create auto-save when the app is put to background, and load it on the next start.