# bootstrap_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: bootstrap_gui.cpp 26544 2014-04-29 18:41:19Z frosch $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "base_media_base.h"
    00014 #include "blitter/factory.hpp"
    00015
    00016 #if defined(ENABLE_NETWORK) && defined(WITH_FREETYPE)
    00017
    00018 #include "core/geometry_func.hpp"
    00019 #include "fontcache.h"
    00020 #include "gfx_func.h"
    00021 #include "network/network.h"
    00022 #include "network/network_content_gui.h"
    00023 #include "openttd.h"
    00024 #include "strings_func.h"
    00025 #include "video/video_driver.hpp"
    00026 #include "window_func.h"
    00027
    00028 #include "widgets/bootstrap_widget.h"
    00029
    00030 #include "table/strings.h"
    00031
    00033 static const struct NWidgetPart _background_widgets[] = {
    00034   NWidget(WWT_PANEL, COLOUR_DARK_BLUE, WID_BB_BACKGROUND), SetResize(1, 1),
    00035 };
    00036
    00040 static WindowDesc _background_desc(
    00041   WDP_MANUAL, NULL, 0, 0,
    00042   WC_BOOTSTRAP, WC_NONE,
    00043   0,
    00044   _background_widgets, lengthof(_background_widgets)
    00045 );
    00046
    00048 class BootstrapBackground : public Window {
    00049 public:
    00050   BootstrapBackground() : Window(&_background_desc)
    00051   {
    00052     this->InitNested(0);
    00053     CLRBITS(this->flags, WF_WHITE_BORDER);
    00054     ResizeWindow(this, _screen.width, _screen.height);
    00055   }
    00056
    00057   virtual void DrawWidget(const Rect &r, int widget) const
    00058   {
    00059     GfxFillRect(r.left, r.top, r.right, r.bottom, 4, FILLRECT_OPAQUE);
    00060     GfxFillRect(r.left, r.top, r.right, r.bottom, 0, FILLRECT_CHECKER);
    00061   }
    00062 };
    00063
    00065 static const NWidgetPart _nested_boostrap_download_status_window_widgets[] = {
    00066   NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00067   NWidget(WWT_PANEL, COLOUR_GREY, WID_NCDS_BACKGROUND),
    00068     NWidget(NWID_SPACER), SetMinimalSize(350, 0), SetMinimalTextLines(3, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 30),
    00069   EndContainer(),
    00070 };
    00071
    00073 static WindowDesc _bootstrap_download_status_window_desc(
    00074   WDP_CENTER, NULL, 0, 0,
    00075   WC_NETWORK_STATUS_WINDOW, WC_NONE,
    00076   WDF_MODAL,
    00077   _nested_boostrap_download_status_window_widgets, lengthof(_nested_boostrap_download_status_window_widgets)
    00078 );
    00079
    00080
    00082 struct BootstrapContentDownloadStatusWindow : public BaseNetworkContentDownloadStatusWindow {
    00083 public:
    00085   BootstrapContentDownloadStatusWindow() : BaseNetworkContentDownloadStatusWindow(&_bootstrap_download_status_window_desc)
    00086   {
    00087   }
    00088
    00089   virtual void OnDownloadComplete(ContentID cid)
    00090   {
    00091     /* We have completed downloading. We can trigger finding the right set now. */
    00092     BaseGraphics::FindSets();
    00093
    00094     /* And continue going into the menu. */
    00095     _game_mode = GM_MENU;
    00096
    00097     /* _exit_game is used to break out of the outer video driver's MainLoop. */
    00098     _exit_game = true;
    00099     delete this;
    00100   }
    00101 };
    00102
    00104 static const NWidgetPart _bootstrap_query_widgets[] = {
    00105   NWidget(NWID_HORIZONTAL),
    00106     NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_MISSING_GRAPHICS_SET_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00107   EndContainer(),
    00108   NWidget(WWT_PANEL, COLOUR_GREY),
    00109     NWidget(WWT_PANEL, COLOUR_GREY, WID_BAFD_QUESTION), EndContainer(),
    00110     NWidget(NWID_HORIZONTAL),
    00111       NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BAFD_YES), SetDataTip(STR_MISSING_GRAPHICS_YES_DOWNLOAD, STR_NULL),
    00112       NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BAFD_NO), SetDataTip(STR_MISSING_GRAPHICS_NO_QUIT, STR_NULL),
    00113     EndContainer(),
    00114   EndContainer(),
    00115 };
    00116
    00118 static WindowDesc _bootstrap_query_desc(
    00119   WDP_CENTER, NULL, 0, 0,
    00120   WC_CONFIRM_POPUP_QUERY, WC_NONE,
    00121   0,
    00122   _bootstrap_query_widgets, lengthof(_bootstrap_query_widgets)
    00123 );
    00124
    00126 class BootstrapAskForDownloadWindow : public Window, ContentCallback {
    00127   Dimension button_size;
    00128
    00129 public:
    00131   BootstrapAskForDownloadWindow() : Window(&_bootstrap_query_desc)
    00132   {
    00133     this->InitNested(WN_CONFIRM_POPUP_QUERY_BOOTSTRAP);
    00134     _network_content_client.AddCallback(this);
    00135   }
    00136
    00138   ~BootstrapAskForDownloadWindow()
    00139   {
    00140     _network_content_client.RemoveCallback(this);
    00141   }
    00142
    00143   virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
    00144   {
    00145     /* We cache the button size. This is safe as no reinit can happen here. */
    00146     if (this->button_size.width == 0) {
    00147       this->button_size = maxdim(GetStringBoundingBox(STR_MISSING_GRAPHICS_YES_DOWNLOAD), GetStringBoundingBox(STR_MISSING_GRAPHICS_NO_QUIT));
    00148       this->button_size.width += WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
    00149       this->button_size.height += WD_FRAMETEXT_TOP + WD_FRAMETEXT_BOTTOM;
    00150     }
    00151
    00152     switch (widget) {
    00153       case WID_BAFD_QUESTION:
    00154         /* The question is twice as wide as the buttons, and determine the height based on the width. */
    00155         size->width = this->button_size.width * 2;
    00156         size->height = GetStringHeight(STR_MISSING_GRAPHICS_SET_MESSAGE, size->width - WD_FRAMETEXT_LEFT - WD_FRAMETEXT_RIGHT) + WD_FRAMETEXT_BOTTOM + WD_FRAMETEXT_TOP;
    00157         break;
    00158
    00159       case WID_BAFD_YES:
    00160       case WID_BAFD_NO:
    00161         *size = this->button_size;
    00162         break;
    00163     }
    00164   }
    00165
    00166   virtual void DrawWidget(const Rect &r, int widget) const
    00167   {
    00168     if (widget != 0) return;
    00169
    00170     DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, r.top + WD_FRAMETEXT_TOP, r.bottom - WD_FRAMETEXT_BOTTOM, STR_MISSING_GRAPHICS_SET_MESSAGE, TC_FROMSTRING, SA_CENTER);
    00171   }
    00172
    00173   virtual void OnClick(Point pt, int widget, int click_count)
    00174   {
    00175     switch (widget) {
    00176       case WID_BAFD_YES:
    00177         /* We got permission to connect! Yay! */
    00178         _network_content_client.Connect();
    00179         break;
    00180
    00181       case WID_BAFD_NO:
    00182         _exit_game = true;
    00183         break;
    00184
    00185       default:
    00186         break;
    00187     }
    00188   }
    00189
    00190   virtual void OnConnect(bool success)
    00191   {
    00192     /* Once connected, request the metadata. */
    00193     _network_content_client.RequestContentList(CONTENT_TYPE_BASE_GRAPHICS);
    00194   }
    00195
    00196   virtual void OnReceiveContentInfo(const ContentInfo *ci)
    00197   {
    00198     /* And once the meta data is received, start downloading it. */
    00199     _network_content_client.Select(ci->id);
    00200     new BootstrapContentDownloadStatusWindow();
    00201     delete this;
    00202   }
    00203 };
    00204
    00205 #endif /* defined(ENABLE_NETWORK) && defined(WITH_FREETYPE) */
    00206
    00213 bool HandleBootstrap()
    00214 {
    00215   if (BaseGraphics::GetUsedSet() != NULL) return true;
    00216
    00217   /* No user interface, bail out with an error. */
    00218   if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) goto failure;
    00219
    00220   /* If there is no network or no freetype, then there is nothing we can do. Go straight to failure. */
    00221 #if defined(ENABLE_NETWORK) && defined(WITH_FREETYPE) && (defined(WITH_FONTCONFIG) || defined(WIN32) || defined(__APPLE__))
    00222   if (!_network_available) goto failure;
    00223
    00224   /* First tell the game we're bootstrapping. */
    00225   _game_mode = GM_BOOTSTRAP;
    00226
    00227   /* Initialise the freetype font code. */
    00228   InitializeUnicodeGlyphMap();
    00229   /* Next "force" finding a suitable freetype font as the local font is missing. */
    00230   CheckForMissingGlyphs(false);
    00231
    00232   /* Initialise the palette. The biggest step is 'faking' some recolour sprites.
    00233    * This way the mauve and gray colours work and we can show the user interface. */
    00234   GfxInitPalettes();
    00235   static const int offsets[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0x04, 0x08 };
    00236   for (uint i = 0; i != 16; i++) {
    00237     for (int j = 0; j < 8; j++) {
    00238       _colour_gradient[i][j] = offsets[i] + j;
    00239     }
    00240   }
    00241
    00242   /* Finally ask the question. */
    00243   new BootstrapBackground();
    00244   new BootstrapAskForDownloadWindow();
    00245
    00246   /* Process the user events. */
    00247   VideoDriver::GetInstance()->MainLoop();
    00248
    00249   /* _exit_game is used to get out of the video driver's main loop.
    00250    * In case GM_BOOTSTRAP is still set we did not exit it via the
    00251    * "download complete" event, so it was a manual exit. Obey it. */
    00252   _exit_game = _game_mode == GM_BOOTSTRAP;
    00253   if (_exit_game) return false;
    00254
    00255   /* Try to probe the graphics. Should work this time. */
    00256   if (!BaseGraphics::SetSet(NULL)) goto failure;
    00257
    00258   /* Finally we can continue heading for the menu. */
    00259   _game_mode = GM_MENU;
    00260   return true;
    00261 #endif
    00262
    00263   /* Failure to get enough working to get a graphics set. */
    00264 failure:
    00265   usererror("Failed to find a graphics set. Please acquire a graphics set for OpenTTD. See section 4.1 of readme.txt.");
    00266   return false;
    00267 }