1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2003
4 // This file is part of Scorched3D.
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 ////////////////////////////////////////////////////////////////////////////////
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
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;
49 wxString
convertString(const std::string
&input
)
51 wxString
result(input
.c_str(), wxConvUTF8
);
55 void addTitleToWindow(
61 wxBitmap scorchedBitmap
;
62 if (scorchedBitmap
.LoadFile(wxString(fileName
, wxConvUTF8
),
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
81 ScorchedProcess(bool server
) :
82 wxProcess(!server
?wxPROCESS_REDIRECT
:0),
85 if (server_
) serverProcessesRunning_
++;
86 else clientProcessesRunning_
++;
89 virtual void OnTerminate(int pid
, int status
)
91 if (server_
) serverProcessesRunning_
--;
92 else clientProcessesRunning_
--;
96 SDL_LockMutex(messageMutex_
);
97 if (server_
) exitCode_
= 64; // So it doesn't say to load failsafe
98 else exitCode_
= status
;
102 messageString_
= "The Scorched3d process "
103 "terminated unexpectedly.\n";
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_
);
120 wxProcess::OnTerminate(pid
, status
);
123 static unsigned int getClientProcessesRunning()
125 return clientProcessesRunning_
;
128 static unsigned int getServerProcessesRunning()
130 return serverProcessesRunning_
;
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
)
145 ScorchedProcess::getClientProcessesRunning() > 0)
148 wxT("You are already running the game, do you wish to run another copy?"),
150 wxCANCEL
| wxOK
| wxICON_EXCLAMATION
) == wxCANCEL
)
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';
163 snprintf(path
, 1024, "\"%s%s%s\" %s -settingsdir %s %s",
167 (ScorchedParams::instance()->getAllowExceptions()?" -allowexceptions":""),
168 ScorchedParams::instance()->getSettingsDir(),
171 ScorchedProcess
*process
= new ScorchedProcess(server
);
172 long result
= ::wxExecute(wxString(path
, wxConvUTF8
), wxEXEC_ASYNC
, process
);
176 S3D::dialogMessage(scorched3dAppName
, S3D::formatStringBuffer(
177 "Error: Failed to execute scorched3d using commandline :-\n"
183 wxButton
*addButtonToWindow(
186 const char *bitmapName
,
189 wxObjectRefData
*data
)
191 wxButton
*button
= 0;
193 if (bitmap
.LoadFile(wxString(bitmapName
, wxConvUTF8
), wxBITMAP_TYPE_BMP
) &&
196 button
= new wxBitmapButton(parent
, id
, bitmap
);
200 button
= new wxButton(parent
, id
, wxT("Select"));
202 if (data
) button
->SetRefData(data
);
204 wxStaticText
*staticText
= new wxStaticText(
206 wxString(text
, wxConvUTF8
));
208 sizer
->Add(button
, 0, wxRIGHT
, 5);
209 sizer
->Add(staticText
, 0, wxALIGN_CENTER_VERTICAL
| wxLEFT
, 5);
214 class MainFrame
: public wxFrame
219 void onTimer(wxTimerEvent
&event
);
220 void onPaint(wxPaintEvent
& event
);
221 void onMotion(wxMouseEvent
&event
);
222 void onEraseBackground(wxEraseEvent
&event
);
224 void onDisplayButton();
226 void onSingleButton();
227 void onServerButton();
228 void onDonateClick();
232 DECLARE_EVENT_TABLE()
238 wxImage descriptionImage
;
239 wxBitmap cachedBitmap1
;
240 wxBitmap cachedBitmap2
;
241 wxBitmap cachedDescription
;
245 wxBitmap backdropBitmap_
;
246 wxImage backdropImage_
;
247 std::list
<ImageData
*> images_
;
248 long mouseX_
, mouseY_
;
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
)
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
);
275 #if wxCHECK_VERSION(2, 6, 0)
276 SetBackgroundStyle(wxBG_STYLE_CUSTOM
);
279 // Load the backdrop bitmaps
280 if (!backdropImage_
.LoadFile(
281 convertString(S3D::getDataFile("data/windows/backdrop.gif")),
284 S3D::dialogMessage("Scorched", "Failed to load backdrop");
286 backdropBitmap_
= wxBitmap(backdropImage_
, -1);
288 // Load all of the button bitmaps
289 struct ImageDefinition
292 const char *description
;
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
));
320 images_
.push_back(image
);
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);
333 topsizer
->SetSizeHints(this); // set size hints to honour minimum size
338 void MainFrame::onMotion(wxMouseEvent
&event
)
345 std::list
<ImageData
*>::iterator itor
;
346 for (itor
= images_
.begin();
347 itor
!= images_
.end();
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())
360 if (event
.ButtonDown() &&
386 if (lastPos_
!= foundPos
)
393 void MainFrame::generateCachedImage(int x
, int y
,
394 wxImage
&src
, wxBitmap
&destBitamp
,
401 unsigned char *backdropdata
= backdropImage_
.GetData();
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
));
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();
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);
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_
;
487 SDL_UnlockMutex(messageMutex_
);
489 if (!newString
.empty())
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
);
509 OptionsDisplay::instance()->loadSafeValues();
510 OptionsDisplay::instance()->writeOptionsToFile();
516 wxString(newString
.c_str(), wxConvUTF8
),
517 wxT("Scorched3D Termination"),
523 void MainFrame::onDonateClick()
526 "\"https://www.paypal.com/xclick/business=donations%40"
527 "scorched3d.co.uk&item_name=Scorched3D&no_note=1&tax=0¤cy_code=GBP\"";
531 void MainFrame::onDisplayButton()
536 void MainFrame::onSingleButton()
538 runScorched3D("", false);
541 void MainFrame::onServerButton()
546 void MainFrame::onQuitButton()
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
);
566 if (bitmap
.LoadFile(convertString(S3D::getDataFile("data/windows/splash.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()