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 "C4Version.h"
22 #include "c4group/C4Components.h"
23 #include "game/C4Application.h"
24 #include "graphics/C4Draw.h"
26 #include "gui/C4Startup.h"
27 #include "gui/C4StartupAboutDlg.h"
28 #include "gui/C4StartupNetDlg.h"
30 #include "gui/C4StartupPlrSelDlg.h"
32 #include "gui/C4UpdateDlg.h"
33 
34 #ifdef _WIN32
35 #include <shellapi.h>
36 #endif
37 
38 
39 C4StartupMainDlg::C4StartupMainDlg() : C4StartupDlg(nullptr) // create w/o title; it is drawn in custom draw proc
40 {
41  // ctor
42  fFirstShown = true;
43  // screen calculations
44  int iButtonPadding = 2;
45  int iButtonHeight = C4GUI_BigButtonHgt;
46  C4GUI::ComponentAligner caMain(rcBounds, 0,0,true);
47  C4GUI::ComponentAligner caRightPanel(caMain.GetFromLeft(rcBounds.Wdt*2/5), rcBounds.Wdt/26, 40+rcBounds.Hgt/5);
48  C4GUI::ComponentAligner caButtons(caRightPanel.GetAll(), 0, iButtonPadding);
49  // main menu buttons
51  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_BTN_LOCALGAME"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnStartBtn));
52  btn->SetToolTip(LoadResStr("IDS_DLGTIP_STARTGAME"));
53  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
54  pStartButton = btn;
55  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_BTN_NETWORKGAME"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnNetJoinBtn));
56  btn->SetToolTip(LoadResStr("IDS_DLGTIP_NETWORKGAME"));
57  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
58  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_PLAYERSELECTION"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnPlayerSelectionBtn));
59  btn->SetToolTip(LoadResStr("IDS_DLGTIP_PLAYERSELECTION"));
60  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
61  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_OPTIONS"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnOptionsBtn));
62  btn->SetToolTip(LoadResStr("IDS_DLGTIP_OPTIONS"));
63  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
64 #ifdef WITH_QT_EDITOR
65  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_EDITOR"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnEditorBtn));
66  btn->SetToolTip(LoadResStr("IDS_DLGTIP_EDITOR"));
67  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
68 #endif
69  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_ABOUT"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnAboutBtn));
70  btn->SetToolTip(LoadResStr("IDS_DLGTIP_ABOUT"));
71  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
72  AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_EXIT"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnExitBtn));
73  btn->SetToolTip(LoadResStr("IDS_DLGTIP_EXIT"));
74  btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
75  // list of selected players
76  AddElement(pParticipantsLbl = new C4GUI::Label("test", GetClientRect().Wdt*39/40, GetClientRect().Hgt*9/10, ARight, 0xffffffff, &::GraphicsResource.TitleFont, false));
77  pParticipantsLbl->SetToolTip(LoadResStr("IDS_DLGTIP_SELECTEDPLAYERS"));
78  // player selection shortcut - to be made optional
81  // key bindings
83  keys.emplace_back(K_DOWN); keys.emplace_back(K_RIGHT);
85  {
86  ControllerKeys::Down(keys); // right will be done by Dialog already
87  }
88  pKeyDown = new C4KeyBinding(keys, "StartupMainCtrlNext", KEYSCOPE_Gui,
90  keys.clear(); keys.emplace_back(K_UP); keys.emplace_back(K_LEFT);
92  {
93  ControllerKeys::Up(keys); // left will be done by Dialog already
94  }
95  pKeyUp = new C4KeyBinding(keys, "StartupMainCtrlPrev", KEYSCOPE_Gui,
97  keys.clear(); keys.emplace_back(K_RETURN);
98  pKeyEnter = new C4KeyBinding(keys, "StartupMainOK", KEYSCOPE_Gui,
100 }
101 
103 {
104  // dtor
105  delete pKeyEnter;
106  delete pKeyUp;
107  delete pKeyDown;
108 }
109 
111 {
112  // inherited
113  typedef C4GUI::FullscreenDialog Base;
114  Base::DrawElement(cgo);
115  // draw logo
116  C4FacetID * fctStartupLogo = &C4Startup::Get()->Graphics.fctStartupLogo;
117  float fLogoZoom = 1.0f;
118  fctStartupLogo->DrawX(cgo.Surface, rcBounds.Wdt *1/21, rcBounds.Hgt/28, int32_t(fLogoZoom*fctStartupLogo->Wdt), int32_t(fLogoZoom*fctStartupLogo->Hgt));
119  // draw version info
120  StdStrBuf sVer;
121  sVer.Format(LoadResStr("IDS_DLG_VERSION"), C4VERSION);
122  pDraw->TextOut(sVer.getData(), ::GraphicsResource.TextFont, 1.0f, cgo.Surface, rcBounds.Wdt*1/40, rcBounds.Hgt*38/40, 0xffffffff, ALeft, true);
123 }
124 
126 {
127  // preliminary player selection via simple context menu
130  pCtx->AddItem("Remove", "Remove participant", C4GUI::Ico_None, nullptr, new C4GUI::CBContextHandler<C4StartupMainDlg>(this, &C4StartupMainDlg::OnPlayerSelContextRemove));
131  return pCtx;
132 }
133 
135 {
137  const char *szFn;
138  StdStrBuf sSearchPath(Config.General.UserDataPath);
139 // sSearchPath.Format("%s%s", (const char *) Config.General.ExePath, (const char *) Config.General.PlayerPath);
140  for (DirectoryIterator i(sSearchPath.getData()); (szFn=*i); i++)
141  {
142  szFn = Config.AtRelativePath(szFn);
143  if (*GetFilename(szFn) == '.') continue;
144  if (!WildcardMatch(C4CFN_PlayerFiles, GetFilename(szFn))) continue;
145  if (!SIsModule(Config.General.Participants, szFn, nullptr, false))
146  pCtx->AddItem(GetFilenameOnly(szFn), "Let this player join in next game", C4GUI::Ico_Player,
148  }
149  return pCtx;
150 }
151 
153 {
155  char szPlayer[1024+1];
156  for (int i = 0; SCopySegment(Config.General.Participants, i, szPlayer, ';', 1024, true); i++)
157  if (*szPlayer)
158  pCtx->AddItem(GetFilenameOnly(szPlayer), "Remove this player from participation list", C4GUI::Ico_Player, new C4GUI::CBMenuHandlerEx<C4StartupMainDlg, int>(this, &C4StartupMainDlg::OnPlayerSelContextRemovePlr, i), nullptr);
159  return pCtx;
160 }
161 
163 {
164  // De-select all other players for now (see #1529)
165  SCopy(rsFilename.getData(), Config.General.Participants);
166  //SAddModule(Config.General.Participants, rsFilename.getData());
168 }
169 
171 {
172  char szPlayer[1024+1];
173  if (SCopySegment(Config.General.Participants, iIndex, szPlayer, ';', 1024, true))
174  SRemoveModule(Config.General.Participants, szPlayer, false);
176 }
177 
179 {
180  // First validate all participants (files must exist)
181  std::string strPlayers(Config.General.Participants);
182  std::vector<char> strPlayer(1025);
184  for (int i = 0; SCopySegment(strPlayers.c_str(), i, &strPlayer[0], ';', strPlayer.size() - 1, true); i++)
185  {
186  const char *szPlayer = &strPlayer[0];
187  std::string strPlayerFile(Config.General.UserDataPath);
188  strPlayerFile.append(szPlayer);
189  if (!szPlayer || !*szPlayer) continue;
190  if (!FileExists(strPlayerFile.c_str())) continue;
191  if (!SEqualNoCase(GetExtension(szPlayer), "ocp")) continue; // additional sanity check to clear strange exe-path-only entries in player list?
193  }
194  // Draw selected players - we are currently displaying the players stored in Config.General.Participants.
195  // Existence of the player files is not validated and player filenames are displayed directly
196  // (names are not loaded from the player core).
197  strPlayers = LoadResStr("IDS_DESC_PLRS");
198  if (!Config.General.Participants[0])
199  strPlayers.append(LoadResStr("IDS_DLG_NOPLAYERSSELECTED"));
200  else
201  for (int i = 0; SCopySegment(Config.General.Participants, i, &strPlayer[0], ';', 1024, true); i++)
202  {
203  if (i > 0) strPlayers.append(", ");
204  strPlayers.append(GetFilenameOnly(&strPlayer[0]));
205  }
206  pParticipantsLbl->SetText(strPlayers.c_str());
207 }
208 
210 {
211  // if dlg got aborted (by user), quit startup
212  // if it got closed with OK, the user pressed one of the buttons and dialog switching has been done already
213  if (!fOK) Application.Quit();
214 }
215 
217 {
218  // advance to scenario selection screen
220 }
221 
223 {
224  // advance to player selection screen
226 }
227 
229 {
230  // advanced net join and host dlg!
232 }
233 
234 void C4StartupMainDlg::OnNetJoin(const StdStrBuf &rsHostAddress)
235 {
236  // no IP given: No join
237  if (!rsHostAddress || !*rsHostAddress.getData()) return;
238  // set default startup parameters
240  SCopy("Objects.ocd", Game.DefinitionFilenames);
241  Game.NetworkActive = true;
242  Game.fLobby = true;
243  Game.fObserve = false;
244  SCopy(rsHostAddress.getData(), Game.DirectJoinAddress, sizeof(Game.DirectJoinAddress)-1);
245  // start with this set!
247 }
248 
250 {
251  // advance to options screen
253 }
254 
256 {
257  if (!RestartApplication({"--editor"}))
258  {
259  C4GUI::TheScreen.ShowErrorMessage(LoadResStr("IDS_ERR_STARTEDITOR"));
260  }
261 }
262 
264 {
265  // advance to about screen
267 }
268 
270 {
271  // callback: exit button pressed
272  Application.Quit();
273 }
274 
276 {
277  GetScreen()->ShowMessage("not yet implemented", "2do", C4GUI::Ico_Error);
278 }
279 
281 {
282  // just execute selected button: Re-Send as space
283  return Game.DoKeyboardInput(K_SPACE, KEYEV_Down, false, false, false, false, this);
284 }
285 
287 {
288  // just execute selected button: Re-Send as space
289  return Game.DoKeyboardInput(K_SPACE, KEYEV_Up, false, false, false, false, this);
290 }
291 
293 {
294 #ifdef WITH_AUTOMATIC_UPDATE
295  // Incoming update
296  if (!Application.IncomingUpdate.empty())
297  {
298  C4UpdateDlg::ApplyUpdate(Application.IncomingUpdate.c_str(), false, GetScreen());
299  Application.IncomingUpdate.clear();
300  }
301  // Manual update by command line or url
303  {
304  C4UpdateDlg::CheckForUpdates(GetScreen(), false);
306  }
307  // Automatic update
308  else
309  {
310  if (Config.Network.AutomaticUpdate)
311  C4UpdateDlg::CheckForUpdates(GetScreen(), true);
312  }
313 #endif
314 
315  // first start evaluation
317  {
318  Config.General.FirstStart = false;
319  }
320  // first thing that's needed is a new player, if there's none - independent of first start
321  bool fHasPlayer = false;
322  StdStrBuf sSearchPath(Config.General.UserDataPath);
323  const char *szFn;
324 // sSearchPath.Format("%s%s", (const char *) Config.General.ExePath, (const char *) Config.General.PlayerPath);
325  for (DirectoryIterator i(sSearchPath.getData()); (szFn=*i); i++)
326  {
327  szFn = Config.AtRelativePath(szFn);
328  if (*GetFilename(szFn) == '.') continue; // ignore ".", ".." and private files (".*")
329  if (!WildcardMatch(C4CFN_PlayerFiles, GetFilename(szFn))) continue;
330  fHasPlayer = true;
331  break;
332  }
333  if (!fHasPlayer)
334  {
335  // no player created yet: Create one
336  C4GUI::Dialog *pDlg;
337  GetScreen()->ShowModalDlg(pDlg=new C4StartupPlrPropertiesDlg(nullptr, nullptr), true);
338  }
339  // make sure participants are updated after switching back from player selection
341 
342  // First show
343  if (fFirstShown)
344  {
345  // Activate the application (trying to prevent flickering half-focus in win32...)
347  // Set the focus to the start button (we might still not have the focus after the update-check sometimes... :/)
348  SetFocus(pStartButton, false);
349  }
350  fFirstShown = false;
351 }
char * GetFilename(char *szPath)
Definition: StdFile.cpp:45
const char * getData() const
Definition: StdBuf.h:442
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
void OpenGame(const char *scenario=nullptr)
C4GUI::DynBarFacet barMainButtonsDown
Definition: C4Startup.h:51
char ScenarioFilename[_MAX_PATH+1]
Definition: C4Game.h:102
C4Config Config
Definition: C4Config.cpp:833
void Up(T &keys)
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:152
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:251
void OnEditorBtn(C4GUI::Control *btn)
bool SCopySegment(const char *szString, int iSegment, char *sTarget, char cSeparator, int iMaxL, bool fSkipWhitespace)
Definition: Standard.cpp:273
void SetToolTip(const char *szNewTooltip, bool is_immediate=false)
Definition: C4Gui.cpp:409
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:567
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:207
#define C4GUI_BigButtonHgt
Definition: C4Gui.h:112
const int ARight
Definition: C4Surface.h:41
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:174
void AddElement(Element *pChild)
bool SIsModule(const char *szList, const char *szString, int *ipIndex, bool fCaseSensitive)
Definition: Standard.cpp:541
const char * GetFilenameOnly(const char *strFilename)
Definition: StdFile.cpp:60
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:1865
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
void OnTODO(C4GUI::Control *btn)
#define C4CFN_PlayerFiles
Definition: C4Components.h:168
void OnShown() override
int32_t Wdt
Definition: C4Rect.h:30
std::vector< C4KeyCodeEx > CodeList
void OnNetJoinBtn(C4GUI::Control *btn)
void OnExitBtn(C4GUI::Control *btn)
char Participants[CFG_MaxString+1]
Definition: C4Config.h:38
char UserDataPath[CFG_MaxString+1]
Definition: C4Config.h:54
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:582
std::string IncomingUpdate
Definition: C4Application.h:77
C4Rect rcBounds
Definition: C4Gui.h:385
C4Rect & GetClientRect() override
Definition: C4Gui.h:864
void OnAboutBtn(C4GUI::Control *btn)
C4ConfigNetwork Network
Definition: C4Config.h:255
class C4StartupDlg * SwitchDialog(DialogID eToDlg, bool fFade=true, const char *szSubDialog=nullptr)
Definition: C4Startup.cpp:137
C4Draw * pDraw
Definition: C4Draw.cpp:42
void SetContextHandler(ContextHandler *pNewHd)
Definition: C4Gui.h:465
void DrawElement(C4TargetFacet &cgo) override
char * GetExtension(char *szFilename)
Definition: StdFile.cpp:121
bool KeyAdvanceFocus(bool fBackwards)
Definition: C4Gui.h:2138
bool NetworkActive
Definition: C4Game.h:122
bool FirstStart
Definition: C4Config.h:59
bool fObserve
Definition: C4Game.h:120
void Quit() override
bool FileExists(const char *szFileName)
bool ShowMessage(const char *szMessage, const char *szCaption, Icons icoIcon, int32_t *piConfigDontShowAgainSetting=nullptr)
int32_t GamepadGuiControl
Definition: C4Config.h:229
void SetFocus(Control *pCtrl, bool fByMouse)
C4ConfigControls Controls
Definition: C4Config.h:259
float Hgt
Definition: C4Facet.h:118
void OnPlayerSelectionBtn(C4GUI::Control *btn)
const int ALeft
Definition: C4Surface.h:41
bool WildcardMatch(const char *szWildcard, const char *szString)
Definition: StdFile.cpp:374
static C4Startup * Get()
Definition: C4Startup.h:133
bool RestartApplication(std::vector< const char * > parameters)
char DefinitionFilenames[20 *_MAX_PATH+1]
Definition: C4Game.h:105
void OnOptionsBtn(C4GUI::Control *btn)
bool ShowModalDlg(Dialog *pDlg, bool fDestruct=true)
virtual Screen * GetScreen()
Definition: C4Gui.cpp:289
int32_t Hgt
Definition: C4Rect.h:30
const char * AtRelativePath(const char *szFilename)
Definition: C4Config.cpp:656
char DirectJoinAddress[_MAX_PATH+1]
Definition: C4Game.h:106
C4GUI::ContextMenu * OnPlayerSelContextRemove(C4GUI::Element *pBtn, int32_t iX, int32_t iY)
C4Surface * Surface
Definition: C4Facet.h:117
bool GetFromLeft(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1076
~C4StartupMainDlg() override
Screen TheScreen
Definition: C4Gui.cpp:1054
bool fLobby
Definition: C4Game.h:118
float Wdt
Definition: C4Facet.h:118
C4StartupGraphics Graphics
Definition: C4Startup.h:100
bool SAddModule(char *szList, const char *szModule, bool fCaseSensitive)
Definition: Standard.cpp:557
C4Application Application
Definition: C4Globals.cpp:44
void OnNetJoin(const StdStrBuf &rsHostAddress)
void SetText(const char *szToText, bool fAllowHotkey=true)
Definition: C4GuiLabels.cpp:74
void OnClosed(bool fOK) override