OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4StartupMainDlg.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // Startup screen for non-parameterized engine start (stub)
17 
18 #include "C4Include.h"
19 #include "gui/C4StartupMainDlg.h"
20 
21 #include "game/C4Application.h"
22 #include "c4group/C4Components.h"
23 #include "gui/C4UpdateDlg.h"
24 #include "C4Version.h"
25 #include "gui/C4StartupNetDlg.h"
28 #include "gui/C4StartupAboutDlg.h"
29 #include "gui/C4StartupPlrSelDlg.h"
30 #include "gui/C4Startup.h"
31 #include "game/C4Game.h"
32 #include "lib/C4Log.h"
33 #include "c4group/C4Language.h"
35 #include "graphics/C4Draw.h"
36 
37 #ifdef _WIN32
38 #include <shellapi.h>
39 #else
40 #include <unistd.h>
41 #include <stdio.h>
42 #endif
43 
44 
45 C4StartupMainDlg::C4StartupMainDlg() : C4StartupDlg(nullptr) // create w/o title; it is drawn in custom draw proc
46 {
47  // ctor
48  fFirstShown = true;
49  // screen calculations
50  int iButtonPadding = 2;
51  int iButtonHeight = C4GUI_BigButtonHgt;
52  C4GUI::ComponentAligner caMain(rcBounds, 0,0,true);
53  C4GUI::ComponentAligner caRightPanel(caMain.GetFromLeft(rcBounds.Wdt*2/5), rcBounds.Wdt/26, 40+rcBounds.Hgt/5);
54  C4GUI::ComponentAligner caButtons(caRightPanel.GetAll(), 0, iButtonPadding);
55  // main menu buttons
57  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_BTN_LOCALGAME"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnStartBtn));
58  btn->SetToolTip(LoadResStr("IDS_DLGTIP_STARTGAME"));
59  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
60  pStartButton = btn;
61  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_BTN_NETWORKGAME"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnNetJoinBtn));
62  btn->SetToolTip(LoadResStr("IDS_DLGTIP_NETWORKGAME"));
63  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
64  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_PLAYERSELECTION"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnPlayerSelectionBtn));
65  btn->SetToolTip(LoadResStr("IDS_DLGTIP_PLAYERSELECTION"));
66  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
67  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_OPTIONS"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnOptionsBtn));
68  btn->SetToolTip(LoadResStr("IDS_DLGTIP_OPTIONS"));
69  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
70 #ifdef WITH_QT_EDITOR
71  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_EDITOR"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnEditorBtn));
72  btn->SetToolTip(LoadResStr("IDS_DLGTIP_EDITOR"));
73  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
74 #endif
75  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_ABOUT"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnAboutBtn));
76  btn->SetToolTip(LoadResStr("IDS_DLGTIP_ABOUT"));
77  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
78  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_EXIT"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnExitBtn));
79  btn->SetToolTip(LoadResStr("IDS_DLGTIP_EXIT"));
80  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
81  // list of selected players
82  AddElement(pParticipantsLbl = new C4GUI::Label("test", GetClientRect().Wdt*39/40, GetClientRect().Hgt*9/10, ARight, 0xffffffff, &::GraphicsResource.TitleFont, false));
83  pParticipantsLbl->SetToolTip(LoadResStr("IDS_DLGTIP_SELECTEDPLAYERS"));
84  // player selection shortcut - to be made optional
87  // key bindings
89  keys.push_back(C4KeyCodeEx(K_DOWN)); keys.push_back(C4KeyCodeEx(K_RIGHT));
91  {
92  ControllerKeys::Down(keys); // right will be done by Dialog already
93  }
94  pKeyDown = new C4KeyBinding(keys, "StartupMainCtrlNext", KEYSCOPE_Gui,
96  keys.clear(); keys.push_back(C4KeyCodeEx(K_UP)); keys.push_back(C4KeyCodeEx(K_LEFT));
98  {
99  ControllerKeys::Up(keys); // left will be done by Dialog already
100  }
101  pKeyUp = new C4KeyBinding(keys, "StartupMainCtrlPrev", KEYSCOPE_Gui,
103  keys.clear(); keys.push_back(C4KeyCodeEx(K_RETURN));
104  pKeyEnter = new C4KeyBinding(keys, "StartupMainOK", KEYSCOPE_Gui,
106 }
107 
109 {
110  // dtor
111  delete pKeyEnter;
112  delete pKeyUp;
113  delete pKeyDown;
114 }
115 
117 {
118  // inherited
119  typedef C4GUI::FullscreenDialog Base;
120  Base::DrawElement(cgo);
121  // draw logo
122  C4FacetID * fctStartupLogo = &C4Startup::Get()->Graphics.fctStartupLogo;
123  float fLogoZoom = 1.0f;
124  fctStartupLogo->DrawX(cgo.Surface, rcBounds.Wdt *1/21, rcBounds.Hgt/28, int32_t(fLogoZoom*fctStartupLogo->Wdt), int32_t(fLogoZoom*fctStartupLogo->Hgt));
125  // draw version info
126  StdStrBuf sVer;
127  sVer.Format(LoadResStr("IDS_DLG_VERSION"), C4VERSION);
128  pDraw->TextOut(sVer.getData(), ::GraphicsResource.TextFont, 1.0f, cgo.Surface, rcBounds.Wdt*1/40, rcBounds.Hgt*38/40, 0xffffffff, ALeft, true);
129 }
130 
132 {
133  // preliminary player selection via simple context menu
136  pCtx->AddItem("Remove", "Remove participant", C4GUI::Ico_None, nullptr, new C4GUI::CBContextHandler<C4StartupMainDlg>(this, &C4StartupMainDlg::OnPlayerSelContextRemove));
137  return pCtx;
138 }
139 
141 {
143  const char *szFn;
144  StdStrBuf sSearchPath(Config.General.UserDataPath);
145 // sSearchPath.Format("%s%s", (const char *) Config.General.ExePath, (const char *) Config.General.PlayerPath);
146  for (DirectoryIterator i(sSearchPath.getData()); (szFn=*i); i++)
147  {
148  szFn = Config.AtRelativePath(szFn);
149  if (*GetFilename(szFn) == '.') continue;
150  if (!WildcardMatch(C4CFN_PlayerFiles, GetFilename(szFn))) continue;
151  if (!SIsModule(Config.General.Participants, szFn, nullptr, false))
152  pCtx->AddItem(GetFilenameOnly(szFn), "Let this player join in next game", C4GUI::Ico_Player,
154  }
155  return pCtx;
156 }
157 
159 {
161  char szPlayer[1024+1];
162  for (int i = 0; SCopySegment(Config.General.Participants, i, szPlayer, ';', 1024, true); i++)
163  if (*szPlayer)
164  pCtx->AddItem(GetFilenameOnly(szPlayer), "Remove this player from participation list", C4GUI::Ico_Player, new C4GUI::CBMenuHandlerEx<C4StartupMainDlg, int>(this, &C4StartupMainDlg::OnPlayerSelContextRemovePlr, i), nullptr);
165  return pCtx;
166 }
167 
169 {
170  // De-select all other players for now (see #1529)
171  SCopy(rsFilename.getData(), Config.General.Participants);
172  //SAddModule(Config.General.Participants, rsFilename.getData());
174 }
175 
177 {
178  char szPlayer[1024+1];
179  if (SCopySegment(Config.General.Participants, iIndex, szPlayer, ';', 1024, true))
180  SRemoveModule(Config.General.Participants, szPlayer, false);
182 }
183 
185 {
186  // First validate all participants (files must exist)
187  std::string strPlayers(Config.General.Participants);
188  std::vector<char> strPlayer(1025);
190  for (int i = 0; SCopySegment(strPlayers.c_str(), i, &strPlayer[0], ';', strPlayer.size() - 1, true); i++)
191  {
192  const char *szPlayer = &strPlayer[0];
193  std::string strPlayerFile(Config.General.UserDataPath);
194  strPlayerFile.append(szPlayer);
195  if (!szPlayer || !*szPlayer) continue;
196  if (!FileExists(strPlayerFile.c_str())) continue;
197  if (!SEqualNoCase(GetExtension(szPlayer), "ocp")) continue; // additional sanity check to clear strange exe-path-only entries in player list?
199  }
200  // Draw selected players - we are currently displaying the players stored in Config.General.Participants.
201  // Existence of the player files is not validated and player filenames are displayed directly
202  // (names are not loaded from the player core).
203  strPlayers = LoadResStr("IDS_DESC_PLRS");
204  if (!Config.General.Participants[0])
205  strPlayers.append(LoadResStr("IDS_DLG_NOPLAYERSSELECTED"));
206  else
207  for (int i = 0; SCopySegment(Config.General.Participants, i, &strPlayer[0], ';', 1024, true); i++)
208  {
209  if (i > 0) strPlayers.append(", ");
210  strPlayers.append(GetFilenameOnly(&strPlayer[0]));
211  }
212  pParticipantsLbl->SetText(strPlayers.c_str());
213 }
214 
216 {
217  // if dlg got aborted (by user), quit startup
218  // if it got closed with OK, the user pressed one of the buttons and dialog switching has been done already
219  if (!fOK) Application.Quit();
220 }
221 
223 {
224  // advance to scenario selection screen
226 }
227 
229 {
230  // advance to player selection screen
232 }
233 
235 {
236  // advanced net join and host dlg!
238 }
239 
240 void C4StartupMainDlg::OnNetJoin(const StdStrBuf &rsHostAddress)
241 {
242  // no IP given: No join
243  if (!rsHostAddress || !*rsHostAddress.getData()) return;
244  // set default startup parameters
246  SCopy("Objects.ocd", Game.DefinitionFilenames);
247  Game.NetworkActive = true;
248  Game.fLobby = true;
249  Game.fObserve = false;
250  SCopy(rsHostAddress.getData(), Game.DirectJoinAddress, sizeof(Game.DirectJoinAddress)-1);
251  // start with this set!
253 }
254 
256 {
257  // advance to options screen
259 }
260 
262 {
263  if (!RestartApplication({"--editor"}))
264  {
265  C4GUI::TheScreen.ShowErrorMessage(LoadResStr("IDS_ERR_STARTEDITOR"));
266  }
267 }
268 
270 {
271  // advance to about screen
273 }
274 
276 {
277  // callback: exit button pressed
278  Application.Quit();
279 }
280 
282 {
283  GetScreen()->ShowMessage("not yet implemented", "2do", C4GUI::Ico_Error);
284 }
285 
287 {
288  // just execute selected button: Re-Send as space
289  return Game.DoKeyboardInput(K_SPACE, KEYEV_Down, false, false, false, false, this);
290 }
291 
293 {
294  // just execute selected button: Re-Send as space
295  return Game.DoKeyboardInput(K_SPACE, KEYEV_Up, false, false, false, false, this);
296 }
297 
299 {
300 #ifdef WITH_AUTOMATIC_UPDATE
301  // Incoming update
302  if (!Application.IncomingUpdate.empty())
303  {
304  C4UpdateDlg::ApplyUpdate(Application.IncomingUpdate.c_str(), false, GetScreen());
305  Application.IncomingUpdate.clear();
306  }
307  // Manual update by command line or url
309  {
310  C4UpdateDlg::CheckForUpdates(GetScreen(), false);
312  }
313  // Automatic update
314  else
315  {
316  if (Config.Network.AutomaticUpdate)
317  C4UpdateDlg::CheckForUpdates(GetScreen(), true);
318  }
319 #endif
320 
321  // first start evaluation
323  {
324  Config.General.FirstStart = false;
325  }
326  // first thing that's needed is a new player, if there's none - independent of first start
327  bool fHasPlayer = false;
328  StdStrBuf sSearchPath(Config.General.UserDataPath);
329  const char *szFn;
330 // sSearchPath.Format("%s%s", (const char *) Config.General.ExePath, (const char *) Config.General.PlayerPath);
331  for (DirectoryIterator i(sSearchPath.getData()); (szFn=*i); i++)
332  {
333  szFn = Config.AtRelativePath(szFn);
334  if (*GetFilename(szFn) == '.') continue; // ignore ".", ".." and private files (".*")
335  if (!WildcardMatch(C4CFN_PlayerFiles, GetFilename(szFn))) continue;
336  fHasPlayer = true;
337  break;
338  }
339  if (!fHasPlayer)
340  {
341  // no player created yet: Create one
342  C4GUI::Dialog *pDlg;
343  GetScreen()->ShowModalDlg(pDlg=new C4StartupPlrPropertiesDlg(nullptr, nullptr), true);
344  }
345  // make sure participants are updated after switching back from player selection
347 
348  // First show
349  if (fFirstShown)
350  {
351  // Activate the application (trying to prevent flickering half-focus in win32...)
353  // Set the focus to the start button (we might still not have the focus after the update-check sometimes... :/)
354  SetFocus(pStartButton, false);
355  }
356  fFirstShown = false;
357 }
char * GetFilename(char *szPath)
Definition: StdFile.cpp:55
const char * getData() const
Definition: StdBuf.h:450
C4FacetID fctStartupLogo
Definition: C4Startup.h:47
void AddItem(const char *szText, const char *szToolTip=nullptr, Icons icoIcon=Ico_None, MenuHandler *pMenuHandler=nullptr, ContextHandler *pSubmenuHandler=nullptr)
Definition: C4Gui.h:1873
C4GUI::DynBarFacet barMainButtonsDown
Definition: C4Startup.h:51
char ScenarioFilename[_MAX_PATH+1]
Definition: C4Game.h:104
C4Config Config
Definition: C4Config.cpp:837
void Up(T &keys)
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:129
C4Game Game
Definition: C4Globals.cpp:52
void OnStartBtn(C4GUI::Control *btn)
void Down(T &keys)
void OnPlayerSelContextAddPlr(C4GUI::Element *pTarget, const StdCopyStrBuf &rsFilename)
C4ConfigGeneral General
Definition: C4Config.h:252
void OnEditorBtn(C4GUI::Control *btn)
bool SCopySegment(const char *szString, int iSegment, char *sTarget, char cSeparator, int iMaxL, bool fSkipWhitespace)
Definition: Standard.cpp:250
void SetToolTip(const char *szNewTooltip, bool is_immediate=false)
Definition: C4Gui.cpp:410
void OnPlayerSelContextRemovePlr(C4GUI::Element *pTarget, const int &iIndex)
bool TextOut(const char *szText, CStdFont &rFont, float fZoom, C4Surface *sfcDest, float iTx, float iTy, DWORD dwFCol=0xffffffff, BYTE byForm=ALeft, bool fDoMarkup=true)
Definition: C4Draw.cpp:570
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:184
#define C4GUI_BigButtonHgt
Definition: C4Gui.h:112
const int ARight
Definition: C4Surface.h:43
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:181
virtual C4Rect & GetClientRect()
Definition: C4Gui.h:864
void AddElement(Element *pChild)
bool SIsModule(const char *szList, const char *szString, int *ipIndex, bool fCaseSensitive)
Definition: Standard.cpp:518
const char * GetFilenameOnly(const char *strFilename)
Definition: StdFile.cpp:70
C4GUI::ContextMenu * OnPlayerSelContextAdd(C4GUI::Element *pBtn, int32_t iX, int32_t iY)
C4GraphicsResource GraphicsResource
C4GUI::ContextMenu * OnPlayerSelContext(C4GUI::Element *pBtn, int32_t iX, int32_t iY)
bool DoKeyboardInput(C4KeyCode vk_code, C4KeyEventType eEventType, bool fAlt, bool fCtrl, bool fShift, bool fRepeated, class C4GUI::Dialog *pForDialog=nullptr, bool fPlrCtrlOnly=false, int32_t iStrength=-1)
Definition: C4Game.cpp:1869
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
void OnTODO(C4GUI::Control *btn)
#define C4CFN_PlayerFiles
Definition: C4Components.h:167
int32_t Wdt
Definition: C4Rect.h:32
std::vector< C4KeyCodeEx > CodeList
void OnNetJoinBtn(C4GUI::Control *btn)
virtual void Quit()
void OnExitBtn(C4GUI::Control *btn)
char Participants[CFG_MaxString+1]
Definition: C4Config.h:39
char UserDataPath[CFG_MaxString+1]
Definition: C4Config.h:55
void DrawX(C4Surface *sfcTarget, float iX, float iY, float iWdt, float iHgt, int32_t iPhaseX=0, int32_t iPhaseY=0) const
Definition: C4Facet.cpp:358
bool ShowErrorMessage(const char *szMessage)
bool SRemoveModule(char *szList, const char *szModule, bool fCaseSensitive)
Definition: Standard.cpp:559
std::string IncomingUpdate
Definition: C4Application.h:77
C4Rect rcBounds
Definition: C4Gui.h:385
void OnAboutBtn(C4GUI::Control *btn)
C4ConfigNetwork Network
Definition: C4Config.h:256
class C4StartupDlg * SwitchDialog(DialogID eToDlg, bool fFade=true, const char *szSubDialog=nullptr)
Definition: C4Startup.cpp:139
C4Draw * pDraw
Definition: C4Draw.cpp:45
void SetContextHandler(ContextHandler *pNewHd)
Definition: C4Gui.h:465
char * GetExtension(char *szFilename)
Definition: StdFile.cpp:131
bool KeyAdvanceFocus(bool fBackwards)
Definition: C4Gui.h:2138
bool NetworkActive
Definition: C4Game.h:124
bool FirstStart
Definition: C4Config.h:60
bool fObserve
Definition: C4Game.h:122
bool ShowMessage(const char *szMessage, const char *szCaption, Icons icoIcon, int32_t *piConfigDontShowAgainSetting=nullptr)
int32_t GamepadGuiControl
Definition: C4Config.h:230
virtual void OnShown()
void SetFocus(Control *pCtrl, bool fByMouse)
C4ConfigControls Controls
Definition: C4Config.h:260
float Hgt
Definition: C4Facet.h:120
void OnPlayerSelectionBtn(C4GUI::Control *btn)
const int ALeft
Definition: C4Surface.h:43
bool WildcardMatch(const char *szWildcard, const char *szString)
Definition: StdFile.cpp:384
bool FileExists(const char *szFilename)
Definition: StdFile.cpp:439
static C4Startup * Get()
Definition: C4Startup.h:133
bool RestartApplication(std::vector< const char * > parameters)
char DefinitionFilenames[20 *_MAX_PATH+1]
Definition: C4Game.h:107
void OnOptionsBtn(C4GUI::Control *btn)
bool ShowModalDlg(Dialog *pDlg, bool fDestruct=true)
virtual Screen * GetScreen()
Definition: C4Gui.cpp:290
int32_t Hgt
Definition: C4Rect.h:32
const char * AtRelativePath(const char *szFilename)
Definition: C4Config.cpp:660
virtual void DrawElement(C4TargetFacet &cgo)
char DirectJoinAddress[_MAX_PATH+1]
Definition: C4Game.h:108
C4GUI::ContextMenu * OnPlayerSelContextRemove(C4GUI::Element *pBtn, int32_t iX, int32_t iY)
C4Surface * Surface
Definition: C4Facet.h:119
bool GetFromLeft(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1079
virtual void OnClosed(bool fOK)
Screen TheScreen
Definition: C4Gui.cpp:1057
bool fLobby
Definition: C4Game.h:120
float Wdt
Definition: C4Facet.h:120
C4StartupGraphics Graphics
Definition: C4Startup.h:100
bool SAddModule(char *szList, const char *szModule, bool fCaseSensitive)
Definition: Standard.cpp:534
C4Application Application
Definition: C4Globals.cpp:44
void OpenGame(const char *scenario=0)
void OnNetJoin(const StdStrBuf &rsHostAddress)
void SetText(const char *szToText, bool fAllowHotkey=true)
Definition: C4GuiLabels.cpp:74