diff --git a/source.list b/source.list
index 63a8060709..3c3fa2e6f0 100644
--- a/source.list
+++ b/source.list
@@ -92,6 +92,7 @@ tgp.cpp
tile_map.cpp
tilearea.cpp
townname.cpp
+tutorial_gui.cpp
#if WIN32
#else
#if WINCE
diff --git a/src/intro_gui.cpp b/src/intro_gui.cpp
index 3d07096d6b..4ef7a84476 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"
@@ -139,6 +140,7 @@ struct SelectGameWindow : public Window {
}
break;
case WID_SGI_AI_SETTINGS: ShowAIConfigWindow(); break;
+ case WID_SGI_TUTORIAL: ShowTutorialWindow(); break;
case WID_SGI_EXIT: HandleExitGameRequest(); break;
}
}
@@ -234,11 +236,11 @@ static const NWidgetPart _nested_select_game_widgets[] = {
NWidget(NWID_SPACER), SetMinimalSize(0, 6),
/* 'exit program' button */
- NWidget(NWID_HORIZONTAL),
- NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_EXIT), SetMinimalSize(128, 12),
- SetDataTip(STR_INTRO_QUIT, STR_INTRO_TOOLTIP_QUIT),
- NWidget(NWID_SPACER), SetFill(1, 0),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_TUTORIAL), SetMinimalSize(158, 12),
+ SetDataTip(STR_ABOUT_MENU_TUTORIAL, STR_TUTORIAL_WINDOW_TOOLTIP), SetPadding(0, 0, 0, 10), SetFill(1, 0),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_EXIT), SetMinimalSize(158, 12),
+ SetDataTip(STR_INTRO_QUIT, STR_INTRO_TOOLTIP_QUIT), SetPadding(0, 10, 0, 0), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 8),
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 5490fb75e8..9d785fe953 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -460,7 +460,7 @@ STR_NEWS_MENU_MESSAGE_HISTORY_MENU :Message history
############ range for about menu starts
STR_ABOUT_MENU_LAND_BLOCK_INFO :Land area information
-STR_ABOUT_MENU_SEPARATOR :
+STR_ABOUT_MENU_TUTORIAL :{BLACK}Tutorial
STR_ABOUT_MENU_TOGGLE_CONSOLE :Toggle console
STR_ABOUT_MENU_AI_DEBUG :AI/Game script debug
STR_ABOUT_MENU_SCREENSHOT :Screenshot
@@ -471,6 +471,7 @@ STR_ABOUT_MENU_ABOUT_OPENTTD :About 'OpenTTD'
STR_ABOUT_MENU_SPRITE_ALIGNER :Sprite aligner
STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES :Toggle bounding boxes
STR_ABOUT_MENU_TOGGLE_DIRTY_BLOCKS :Toggle colouring of dirty blocks
+STR_ABOUT_MENU_SEPARATOR :
############ range ends here
############ range for ordinal numbers used for the place in the highscore window
@@ -2701,6 +2702,10 @@ STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Original
STR_ABOUT_VERSION :{BLACK}OpenTTD version {REV}
STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-2014 The OpenTTD team
+#Tutorial window
+STR_TUTORIAL_WINDOW_TITLE :{BLACK}Tutorial videos
+STR_TUTORIAL_WINDOW_TOOLTIP :{BLACK}Open a video player to watch tutorial videos
+
# Save/load game/scenario
STR_SAVELOAD_SAVE_CAPTION :{WHITE}Save Game
STR_SAVELOAD_LOAD_CAPTION :{WHITE}Load Game
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index 9b987dcaf1..815f99f187 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -32,6 +32,7 @@
#include "linkgraph/linkgraph_gui.h"
#include "tilehighlight_func.h"
#include "hotkeys.h"
+#include "tutorial_gui.h"
#include "saveload/saveload.h"
@@ -561,6 +562,7 @@ void SetupColoursAndInitialWindow()
default: NOT_REACHED();
case GM_MENU:
ShowSelectGameWindow();
+ ShowTutorialWindowOnceAfterInstall();
break;
case GM_NORMAL:
diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp
index fa085d6dfc..31afc842b3 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 "widgets/toolbar_widget.h"
@@ -1143,6 +1144,7 @@ static CallBackFunction MenuClickHelp(int index)
{
switch (index) {
case 0: return PlaceLandBlockInfo();
+ case 1: ShowTutorialWindow(); break;
case 2: IConsoleSwitch(); break;
case 3: ShowAIDebugWindow(); break;
case 4: MenuClickSmallScreenshot(); break;
diff --git a/src/tutorial_gui.cpp b/src/tutorial_gui.cpp
new file mode 100644
index 0000000000..530a600737
--- /dev/null
+++ b/src/tutorial_gui.cpp
@@ -0,0 +1,191 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see .
+ */
+
+/**
+ * @file tutorial_gui.cpp
+ * Links to video tutorials on Youtube.
+ */
+
+#include "stdafx.h"
+
+#include
+
+#include "tutorial_gui.h"
+#include "debug.h"
+#include "strings_func.h"
+#include "window_func.h"
+#include "fios.h"
+#include "string_func.h"
+#include "language.h"
+#include "widget_type.h"
+#include "window_type.h"
+#include "window_func.h"
+#include "window_gui.h"
+#include "widgets/station_widget.h"
+#include "table/strings.h"
+#include "table/sprites.h"
+
+
+static const char * ANY_LANG = "ANY_LANG";
+
+struct VideoLink_t {
+ const char *lang;
+ const char *video;
+};
+
+static VideoLink_t busTutorial[] = {
+ { "en", "https://www.youtube.com/watch?v=EULXRMR4PyE" },
+ { ANY_LANG, "https://www.youtube.com/watch?v=EULXRMR4PyE" },
+ { NULL, NULL }
+};
+
+void OpenExternTutorialVideo(VideoLink_t *tutorial)
+{
+ const char *link = NULL;
+ for (; tutorial->lang != NULL; tutorial++) {
+ if (strcmp(tutorial->lang, _current_language->isocode) == 0) {
+ link = tutorial->video;
+ break;
+ }
+ if (strcmp(tutorial->lang, ANY_LANG) == 0) {
+ link = tutorial->video;
+ break;
+ }
+ }
+ if (!link) {
+ return;
+ }
+ SDL_ANDROID_OpenExternalWebBrowser(link);
+}
+
+static const NWidgetPart _nested_tutorial_widgets[] = {
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_CLOSEBOX, COLOUR_GREY),
+ NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_TUTORIAL_WINDOW_TITLE, STR_TUTORIAL_WINDOW_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL), SetPIP(6, 0, 6),
+ NWidget(WWT_PANEL, COLOUR_GREY), SetPIP(8, 2, 6),
+ // TODO: make different button IDs
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_BUS_STATION, STR_SMALLMAP_LEGENDA_BUS_STATION), SetFill(1, 1),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_ROAD_VEHICLES, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY), SetFill(1, 1),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_BUS), SetMinimalSize(120, 20), SetDataTip(SPR_VEH_BUS_SW_VIEW, STR_SMALLMAP_LEGENDA_BUS_STATION), SetFill(1, 1),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_TRUCK), SetMinimalSize(120, 20), SetDataTip(SPR_IMG_TRUCKLIST, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY), SetFill(1, 1),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetFill(1, 0),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_RAILROADS, STR_SMALLMAP_LEGENDA_RAILROAD_STATION), SetFill(1, 1),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_SHIPS, STR_SMALLMAP_LEGENDA_DOCK), SetFill(1, 1),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_TRAIN), SetMinimalSize(120, 20), SetDataTip(SPR_IMG_TRAINLIST, STR_SMALLMAP_LEGENDA_RAILROAD_STATION), SetFill(0, 1),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_SHIP), SetMinimalSize(120, 20), SetDataTip(SPR_IMG_SHIPLIST, STR_SMALLMAP_LEGENDA_DOCK), SetFill(0, 1),
+ EndContainer(),
+ NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetFill(1, 0),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_AIRCRAFT, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT), SetFill(1, 1),
+ NWidget(WWT_LABEL, COLOUR_GREY), SetMinimalSize(120, 12), SetDataTip(STR_SMALLMAP_LEGENDA_INDUSTRIES, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES), SetFill(1, 1),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_AIRPLANE), SetMinimalSize(120, 20), SetDataTip(SPR_IMG_AIRPLANESLIST, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT), SetFill(0, 1),
+ NWidget(WWT_IMGBTN, COLOUR_GREY, WID_STL_FACILALL), SetMinimalSize(120, 20), SetDataTip(SPR_IMG_COMPANY_FINANCE, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES), SetFill(0, 1),
+ EndContainer(),
+ EndContainer(),
+ EndContainer(),
+};
+
+static WindowDesc _tutorial_desc(
+ WDP_CENTER, NULL, 0, 0,
+ WC_GAME_OPTIONS, WC_NONE,
+ 0,
+ _nested_tutorial_widgets, lengthof(_nested_tutorial_widgets)
+);
+
+
+struct TutorialWindow : public Window {
+ VideoLink_t *video;
+ int counter;
+ TutorialWindow() : Window(&_tutorial_desc)
+ {
+ this->InitNested(WN_GAME_OPTIONS_ABOUT);
+ this->SetWidgetDisabledState(WID_STL_TRUCK, true);
+ this->SetWidgetDisabledState(WID_STL_TRAIN, true);
+ this->SetWidgetDisabledState(WID_STL_SHIP, true);
+ this->SetWidgetDisabledState(WID_STL_AIRPLANE, true);
+ this->SetWidgetDisabledState(WID_STL_FACILALL, true);
+ video = NULL;
+ counter = 0;
+ }
+
+ virtual void OnClick(Point pt, int widget, int click_count)
+ {
+ counter = 5;
+ this->LowerWidget(widget);
+ this->SetDirty();
+ switch (widget) {
+ case WID_STL_BUS:
+ video = busTutorial;
+ break;
+ case WID_STL_TRUCK:
+ break;
+ case WID_STL_TRAIN:
+ break;
+ case WID_STL_SHIP:
+ break;
+ case WID_STL_AIRPLANE:
+ break;
+ case WID_STL_FACILALL:
+ break;
+ }
+ }
+
+ virtual void OnTick()
+ {
+ // Open video with delay, to make visual feedback of button pressing,
+ // because youtube app freezes a screen for a second before launching.
+ if (counter > 0) {
+ counter--;
+ if (counter == 0) {
+ if (video) {
+ OpenExternTutorialVideo(video);
+ }
+ video = NULL;
+ this->RaiseWidget(WID_STL_BUS);
+ this->RaiseWidget(WID_STL_TRUCK);
+ this->RaiseWidget(WID_STL_TRAIN);
+ this->RaiseWidget(WID_STL_SHIP);
+ this->RaiseWidget(WID_STL_AIRPLANE);
+ this->RaiseWidget(WID_STL_FACILALL);
+ this->SetDirty();
+ }
+ }
+ }
+};
+
+void ShowTutorialWindow()
+{
+ DeleteWindowByClass(WC_GAME_OPTIONS);
+ new TutorialWindow();
+}
+
+void ShowTutorialWindowOnceAfterInstall()
+{
+ static const char * TUTORIAL_SHOWN_FLAG = ".tutorial-shown-1.flag";
+ FILE *ff = fopen(TUTORIAL_SHOWN_FLAG, "r");
+ if (ff) {
+ fclose(ff);
+ return;
+ }
+ ff = fopen(TUTORIAL_SHOWN_FLAG, "w");
+ fprintf(ff, "Tutorial shown");
+ fclose(ff);
+ ShowTutorialWindow();
+}
diff --git a/src/tutorial_gui.h b/src/tutorial_gui.h
new file mode 100644
index 0000000000..04840ee2c6
--- /dev/null
+++ b/src/tutorial_gui.h
@@ -0,0 +1,18 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see .
+ */
+
+/** @file tutorial_gui.h Links to video tutorials. */
+
+#ifndef TUTORIAL_GUI_H
+#define TUTORIAL_GUI_H
+
+void ShowTutorialWindow();
+void ShowTutorialWindowOnceAfterInstall();
+
+#endif /* TUTORIAL_GUI_H */
diff --git a/src/widgets/intro_widget.h b/src/widgets/intro_widget.h
index 6a67fe64ca..7447fbdb5f 100644
--- a/src/widgets/intro_widget.h
+++ b/src/widgets/intro_widget.h
@@ -32,6 +32,7 @@ enum SelectGameIntroWidgets {
WID_SGI_GRF_SETTINGS, ///< NewGRF button.
WID_SGI_CONTENT_DOWNLOAD, ///< Content Download button.
WID_SGI_AI_SETTINGS, ///< AI button.
+ WID_SGI_TUTORIAL, ///< Tutorial button.
WID_SGI_EXIT, ///< Exit button.
};