git-svn-id: https://scorched3d.svn.sourceforge.net/svnroot/scorched3d/trunk/scorched...
[scorched3d/parasti.git] / src / launcher / wxdialogs / MainDialog.cpp
blob16d8eac127665dfe864a134b4046fd57ae757682
1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2003
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <stdlib.h>
22 #include <wx/wx.h>
23 #include <wx/image.h>
24 #include <wx/process.h>
25 #include <wx/txtstrm.h>
26 #include <wx/msgdlg.h>
27 #include <wx/dcbuffer.h>
28 #include <wx/splash.h>
29 #define WIN32_LEAN_AND_MEAN
30 #include <windows.h>
31 #include <SDL/SDL.h>
32 #include <wxdialogs/MainDialog.h>
33 #include <wxdialogs/DisplayDialog.h>
34 #include <wxdialogs/ServerSDialog.h>
35 #include <wxdialogs/TrueTypeFont.h>
36 #include <scorched/ScorchedParams.h>
37 #include <graph/OptionsDisplay.h>
38 #include <common/Defines.h>
40 extern char scorched3dAppName[128];
41 static wxFrame *mainDialog = 0;
42 bool wxWindowExit = false;
44 enum
46 ID_MAIN_TIMER
49 wxString convertString(const std::string &input)
51 wxString result(input.c_str(), wxConvUTF8);
52 return result;
55 void addTitleToWindow(
56 wxWindow *parent,
57 wxSizer *sizer,
58 const char *fileName,
59 int buttonId)
61 wxBitmap scorchedBitmap;
62 if (scorchedBitmap.LoadFile(wxString(fileName, wxConvUTF8),
63 wxBITMAP_TYPE_BMP) &&
64 scorchedBitmap.Ok())
66 wxBitmapButton *button = new wxBitmapButton(
67 parent, buttonId, scorchedBitmap);
68 wxBoxSizer *boxSizer = new wxBoxSizer(wxHORIZONTAL);
69 boxSizer->Add(button, 0, wxALL, 5);
70 sizer->Add(boxSizer, 0, wxALIGN_CENTER | wxALL, 5);
74 static SDL_mutex *messageMutex_ = 0;
75 static std::string messageString_;
76 static int exitCode_ = 0;
78 class ScorchedProcess : public wxProcess
80 public:
81 ScorchedProcess(bool server) :
82 wxProcess(!server?wxPROCESS_REDIRECT:0),
83 server_(server)
85 if (server_) serverProcessesRunning_++;
86 else clientProcessesRunning_++;
89 virtual void OnTerminate(int pid, int status)
91 if (server_) serverProcessesRunning_--;
92 else clientProcessesRunning_--;
94 if (status != 0)
96 SDL_LockMutex(messageMutex_);
97 if (server_) exitCode_ = 64; // So it doesn't say to load failsafe
98 else exitCode_ = status;
100 if (status != 64)
102 messageString_ = "The Scorched3d process "
103 "terminated unexpectedly.\n";
105 else
107 messageString_ = "The Scorched3d process "
108 "terminated due to configuration errors.\n";
110 while (IsInputAvailable())
112 wxTextInputStream tis(*GetInputStream());
113 wxString line = tis.ReadLine();
114 messageString_.append((const char *) line.mb_str(wxConvUTF8));
115 messageString_.append("\n");
117 SDL_UnlockMutex(messageMutex_);
119 Detach();
120 wxProcess::OnTerminate(pid, status);
123 static unsigned int getClientProcessesRunning()
125 return clientProcessesRunning_;
128 static unsigned int getServerProcessesRunning()
130 return serverProcessesRunning_;
133 protected:
134 bool server_;
135 static unsigned int clientProcessesRunning_;
136 static unsigned int serverProcessesRunning_;
139 unsigned int ScorchedProcess::clientProcessesRunning_(0);
140 unsigned int ScorchedProcess::serverProcessesRunning_(0);
142 void runScorched3D(const char *text, bool server)
144 if (!server &&
145 ScorchedProcess::getClientProcessesRunning() > 0)
147 if (::wxMessageBox(
148 wxT("You are already running the game, do you wish to run another copy?"),
149 wxT("Scorched3D"),
150 wxCANCEL | wxOK | wxICON_EXCLAMATION) == wxCANCEL)
152 return;
156 std::string exeName = S3D::getExeName();
157 const char *exePart = strstr(exeName.c_str(), ".exe");
158 if (exePart) ((char *)exePart)[0] = '\0';
159 exePart = strstr(exeName.c_str(), ".EXE");
160 if (exePart) ((char *)exePart)[0] = '\0';
162 char path[1024];
163 snprintf(path, 1024, "\"%s%s%s\" %s -settingsdir %s %s",
164 exeName.c_str(),
165 (server?"s":"c"),
166 (exePart?".exe":""),
167 (ScorchedParams::instance()->getAllowExceptions()?" -allowexceptions":""),
168 ScorchedParams::instance()->getSettingsDir(),
169 text);
171 ScorchedProcess *process = new ScorchedProcess(server);
172 long result = ::wxExecute(wxString(path, wxConvUTF8), wxEXEC_ASYNC, process);
173 if (result == 0)
175 delete process;
176 S3D::dialogMessage(scorched3dAppName, S3D::formatStringBuffer(
177 "Error: Failed to execute scorched3d using commandline :-\n"
178 "%s",
179 path));
183 wxButton *addButtonToWindow(
184 int id,
185 const char *text,
186 const char *bitmapName,
187 wxWindow *parent,
188 wxSizer *sizer,
189 wxObjectRefData *data)
191 wxButton *button = 0;
192 wxBitmap bitmap;
193 if (bitmap.LoadFile(wxString(bitmapName, wxConvUTF8), wxBITMAP_TYPE_BMP) &&
194 bitmap.Ok())
196 button = new wxBitmapButton(parent, id, bitmap);
198 else
200 button = new wxButton(parent, id, wxT("Select"));
202 if (data) button->SetRefData(data);
204 wxStaticText *staticText = new wxStaticText(
205 parent, -1,
206 wxString(text, wxConvUTF8));
208 sizer->Add(button, 0, wxRIGHT, 5);
209 sizer->Add(staticText, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5);
211 return button;
214 class MainFrame: public wxFrame
216 public:
217 MainFrame();
219 void onTimer(wxTimerEvent &event);
220 void onPaint(wxPaintEvent& event);
221 void onMotion(wxMouseEvent &event);
222 void onEraseBackground(wxEraseEvent &event);
224 void onDisplayButton();
225 void onQuitButton();
226 void onSingleButton();
227 void onServerButton();
228 void onDonateClick();
229 void onHelpButton();
231 private:
232 DECLARE_EVENT_TABLE()
234 struct ImageData
236 int x, y;
237 wxImage loadedImage;
238 wxImage descriptionImage;
239 wxBitmap cachedBitmap1;
240 wxBitmap cachedBitmap2;
241 wxBitmap cachedDescription;
244 wxTimer timer_;
245 wxBitmap backdropBitmap_;
246 wxImage backdropImage_;
247 std::list<ImageData *> images_;
248 long mouseX_, mouseY_;
249 int lastPos_;
251 void generateCachedImage(int x, int y,
252 wxImage &src, wxBitmap &destBitamp,
253 bool highlight = false);
256 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
257 EVT_TIMER(ID_MAIN_TIMER, MainFrame::onTimer)
258 EVT_PAINT(MainFrame::onPaint)
259 EVT_MOUSE_EVENTS(MainFrame::onMotion)
260 EVT_ERASE_BACKGROUND(MainFrame::onEraseBackground)
261 END_EVENT_TABLE()
263 MainFrame::MainFrame() :
264 wxFrame((wxFrame *)NULL, -1, wxString(scorched3dAppName, wxConvUTF8),
265 wxDefaultPosition, wxDefaultSize,
266 wxMINIMIZE_BOX | wxCAPTION | wxSYSTEM_MENU),
267 mouseX_(0), mouseY_(0), lastPos_(-1)
269 if (!messageMutex_) messageMutex_ = SDL_CreateMutex();
271 // Set the frame's icon
272 wxIcon icon(convertString(S3D::getDataFile("data/windows/tank2.ico")), wxBITMAP_TYPE_ICO);
273 SetIcon(icon);
275 #if wxCHECK_VERSION(2, 6, 0)
276 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
277 #endif
279 // Load the backdrop bitmaps
280 if (!backdropImage_.LoadFile(
281 convertString(S3D::getDataFile("data/windows/backdrop.gif")),
282 wxBITMAP_TYPE_GIF))
284 S3D::dialogMessage("Scorched", "Failed to load backdrop");
286 backdropBitmap_ = wxBitmap(backdropImage_, -1);
288 // Load all of the button bitmaps
289 struct ImageDefinition
291 const char *name;
292 const char *description;
293 int x, y;
294 } imageDefinitions[] = {
295 "Play", "- Play a game.", 30, 150,
296 "Start Server", "- Start a LAN or internet server.", 30, 180,
297 "Settings", "- Change the display, sound or other settings.", 30, 210,
298 "Help", "- View the online help.", 30, 260,
299 "Donate", "- Show support for Scorched3D.", 30, 290,
300 "Quit", "- Exit the game.", 30, 340
303 TrueTypeFont largeImageFont(S3D::getDataFile("data/fonts/vera.ttf"), 14);
304 TrueTypeFont smallImageFont(S3D::getDataFile("data/fonts/vera.ttf"), 12);
306 for (int i=0; i<sizeof(imageDefinitions) / sizeof(ImageDefinition); i++)
308 ImageData *image = new ImageData();
309 image->x = imageDefinitions[i].x;
310 image->y = imageDefinitions[i].y;
312 if (!largeImageFont.getImageForText(imageDefinitions[i].name, image->loadedImage) ||
313 !smallImageFont.getImageForText(imageDefinitions[i].description, image->descriptionImage))
315 S3D::dialogMessage("Scorched",
316 S3D::formatStringBuffer("Failed to load button %s", imageDefinitions[i].name));
318 else
320 images_.push_back(image);
324 // Setup timer
325 timer_.SetOwner(this, ID_MAIN_TIMER);
326 timer_.Start(1000, false);
328 // use the sizer for layout
329 // Create the positioning sizer
330 wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
331 topsizer->SetMinSize(533, 400);
332 SetSizer(topsizer);
333 topsizer->SetSizeHints(this); // set size hints to honour minimum size
335 CentreOnScreen();
338 void MainFrame::onMotion(wxMouseEvent &event)
340 mouseX_ = event.m_x;
341 mouseY_ = event.m_y;
343 int foundPos = -1;
344 int pos = 0;
345 std::list<ImageData *>::iterator itor;
346 for (itor = images_.begin();
347 itor != images_.end();
348 itor++, pos++)
350 ImageData *imageData = (*itor);
351 if (mouseX_ > imageData->x &&
352 mouseY_ > imageData->y &&
353 mouseX_ < imageData->x + imageData->cachedBitmap1.GetWidth() &&
354 mouseY_ < imageData->y + imageData->cachedBitmap1.GetHeight())
356 foundPos = pos;
360 if (event.ButtonDown() &&
361 foundPos != -1)
363 switch (foundPos)
365 case 0:
366 onSingleButton();
367 break;
368 case 1:
369 onServerButton();
370 break;
371 case 2:
372 onDisplayButton();
373 break;
374 case 3:
375 onHelpButton();
376 break;
377 case 4:
378 onDonateClick();
379 break;
380 case 5:
381 onQuitButton();
382 break;
386 if (lastPos_ != foundPos)
388 lastPos_ = foundPos;
389 Refresh();
393 void MainFrame::generateCachedImage(int x, int y,
394 wxImage &src, wxBitmap &destBitamp,
395 bool highlight)
397 wxImage dest(
398 src.GetWidth(),
399 src.GetHeight());
401 unsigned char *backdropdata = backdropImage_.GetData();
402 backdropdata +=
403 3 * x +
404 3 * y * backdropImage_.GetWidth();
406 unsigned char *srcdata = src.GetData();
407 unsigned char *destdata = dest.GetData();
408 for (int y=0; y<src.GetHeight(); y++)
410 unsigned char *backdropstart = backdropdata;
411 for (int x=0; x<src.GetWidth(); x++)
413 float alpha = srcdata[0] + srcdata[1] + srcdata[2];
414 alpha /= 255.0f + 255.0f + 255.0f;
416 float mult = (highlight?1.5f:1.0f);
417 float src0 = float(srcdata[0]) * mult; if (src0 > 255.0f) src0 = 255.0f;
418 float src1 = float(srcdata[1]) * mult; if (src1 > 255.0f) src1 = 255.0f;
419 float src2 = float(srcdata[2]) * mult; if (src2 > 255.0f) src2 = 255.0f;
420 destdata[0] = (unsigned char) ((1.0f - alpha) * float(backdropdata[0]) + alpha * float(src0));
421 destdata[1] = (unsigned char) ((1.0f - alpha) * float(backdropdata[1]) + alpha * float(src1));
422 destdata[2] = (unsigned char) ((1.0f - alpha) * float(backdropdata[2]) + alpha * float(src2));
424 srcdata += 3;
425 destdata += 3;
426 backdropdata += 3;
428 backdropdata = backdropstart + 3 * backdropImage_.GetWidth();
432 destBitamp = wxBitmap(dest, -1);
435 void MainFrame::onPaint(wxPaintEvent& event)
437 wxBufferedPaintDC dc(this);
439 dc.DrawBitmap(backdropBitmap_, 0, 0, false);
441 // So its easy to display an alpha blended bitmap in wxWindows then!!!
442 std::list<ImageData *>::iterator itor;
443 for (itor = images_.begin();
444 itor != images_.end();
445 itor++)
447 ImageData *imageData = (*itor);
449 if (!imageData->cachedBitmap1.Ok())
451 generateCachedImage(imageData->x, imageData->y,
452 imageData->loadedImage, imageData->cachedBitmap1, false);
453 generateCachedImage(imageData->x, imageData->y,
454 imageData->loadedImage, imageData->cachedBitmap2, true);
455 generateCachedImage(imageData->x + 135, imageData->y + 2,
456 imageData->descriptionImage, imageData->cachedDescription, true);
459 if (mouseX_ > imageData->x &&
460 mouseY_ > imageData->y &&
461 mouseX_ < imageData->x + imageData->cachedBitmap1.GetWidth() &&
462 mouseY_ < imageData->y + imageData->cachedBitmap1.GetHeight())
464 dc.DrawBitmap(imageData->cachedBitmap2, imageData->x, imageData->y, false);
465 dc.DrawBitmap(imageData->cachedDescription, imageData->x + 135, imageData->y + 2, false);
467 else
469 dc.DrawBitmap(imageData->cachedBitmap1, imageData->x, imageData->y, false);
474 void MainFrame::onEraseBackground(wxEraseEvent &event)
478 void MainFrame::onTimer(wxTimerEvent &event)
480 std::string newString;
481 SDL_LockMutex(messageMutex_);
482 if (!messageString_.empty())
484 newString = messageString_;
485 messageString_ = "";
487 SDL_UnlockMutex(messageMutex_);
489 if (!newString.empty())
491 if (exitCode_ != 64)
493 newString.append("\n"
494 "Would you like to load the failsafe "
495 "scorched3d settings?\n"
496 "This gives the best chance of working but "
497 "at the cost of graphical detail.\n"
498 "You can adjust this later in the Scorched3D "
499 "display settings dialog.\n"
500 "Note: Most problems can be fixed by using "
501 "the very latest drivers\n"
502 "for your graphics card.");
503 int answer = ::wxMessageBox(
504 wxString(newString.c_str(), wxConvUTF8),
505 wxT("Scorched3D Abnormal Termination"),
506 wxYES_NO | wxICON_ERROR);
507 if (answer == wxYES)
509 OptionsDisplay::instance()->loadSafeValues();
510 OptionsDisplay::instance()->writeOptionsToFile();
513 else
515 ::wxMessageBox(
516 wxString(newString.c_str(), wxConvUTF8),
517 wxT("Scorched3D Termination"),
518 wxICON_ERROR);
523 void MainFrame::onDonateClick()
525 const char *exec =
526 "\"https://www.paypal.com/xclick/business=donations%40"
527 "scorched3d.co.uk&item_name=Scorched3D&no_note=1&tax=0&currency_code=GBP\"";
528 S3D::showURL(exec);
531 void MainFrame::onDisplayButton()
533 showDisplayDialog();
536 void MainFrame::onSingleButton()
538 runScorched3D("", false);
541 void MainFrame::onServerButton()
543 showServerSDialog();
546 void MainFrame::onQuitButton()
548 wxWindowExit = true;
549 Close();
552 void MainFrame::onHelpButton()
554 S3D::showURL("http://www.scorched3d.co.uk/wiki");
557 extern bool newVersion;
558 void showMainDialog()
560 mainDialog = new MainFrame;
561 mainDialog->Show(TRUE);
563 if (newVersion)
565 wxBitmap bitmap;
566 if (bitmap.LoadFile(convertString(S3D::getDataFile("data/windows/splash.gif")),
567 wxBITMAP_TYPE_GIF))
569 wxSplashScreen* splash = new wxSplashScreen(bitmap,
570 wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_TIMEOUT,
571 9000, NULL, -1, wxDefaultPosition, wxDefaultSize,
572 wxSIMPLE_BORDER | wxSTAY_ON_TOP);
577 wxFrame *getMainDialog()
579 return mainDialog;