root/cafu/trunk/Ca3DE/AppCafu.cpp

Revision 455, 20.2 KB (checked in by Carsten, 4 months ago)

Updated copyright banners (in C++ files).

Line 
1/*
2=================================================================================
3This file is part of Cafu, the open-source game engine and graphics engine
4for multiplayer, cross-platform, real-time 3D action.
5Copyright (C) 2002-2012 Carsten Fuchs Software.
6
7Cafu is free software: you can redistribute it and/or modify it under the terms
8of the GNU General Public License as published by the Free Software Foundation,
9either version 3 of the License, or (at your option) any later version.
10
11Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13PURPOSE. See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with Cafu. If not, see <http://www.gnu.org/licenses/>.
17
18For support and more information about Cafu, visit us at <http://www.cafu.de>.
19=================================================================================
20*/
21
22#include "AppCafu.hpp"
23#include "MainFrame.hpp"
24
25#include "ClipSys/CollisionModelMan_impl.hpp"
26#include "ConsoleCommands/ConsoleInterpreterImpl.hpp"
27#include "ConsoleCommands/ConsoleComposite.hpp"
28#include "ConsoleCommands/ConsoleFile.hpp"
29#include "ConsoleCommands/ConsoleStdout.hpp"
30#include "ConsoleCommands/ConsoleStringBuffer.hpp"
31#include "ConsoleCommands/ConVar.hpp"
32#include "ConsoleCommands/ConFunc.hpp"
33#include "FileSys/FileManImpl.hpp"
34#include "GuiSys/GuiMan.hpp"
35#include "GuiSys/Window.hpp"
36#include "MaterialSystem/MaterialManagerImpl.hpp"
37#include "Network/Network.hpp"
38#include "SoundSystem/SoundShaderManagerImpl.hpp"
39#include "SoundSystem/SoundSys.hpp"
40#include "TypeSys.hpp"
41#include "../Games/Game.hpp"
42
43#include "wx/cmdline.h"
44#include "wx/filename.h"
45#include "wx/msgdlg.h"
46#include "wx/stdpaths.h"
47
48
49// For each interface that is globally available to the application,
50// provide a definition for the pointer instance and have it point to an implementation.
51static cf::CompositeConsoleT s_CompositeConsole;
52cf::ConsoleI* Console=&s_CompositeConsole;
53
54static cf::FileSys::FileManImplT s_FileManImpl;
55cf::FileSys::FileManI* cf::FileSys::FileMan=&s_FileManImpl;
56
57static cf::ClipSys::CollModelManImplT s_CCM;
58cf::ClipSys::CollModelManI* cf::ClipSys::CollModelMan=&s_CCM;
59
60static ConsoleInterpreterImplT s_ConInterpreterImpl;
61ConsoleInterpreterI* ConsoleInterpreter=&s_ConInterpreterImpl;      // TODO: Put it into a proper namespace.
62
63static MaterialManagerImplT s_MaterialManagerImpl;
64MaterialManagerI* MaterialManager=&s_MaterialManagerImpl;           // TODO: Put it into a proper namespace.
65
66static SoundShaderManagerImplT s_SoundShaderManagerImpl;
67SoundShaderManagerI* SoundShaderManager=&s_SoundShaderManagerImpl;  // TODO: Put it into a proper namespace.
68
69// static WinSockT WinSock;     // This unfortunately can throw.
70WinSockT* g_WinSock=NULL;
71
72
73// Implementations for these interfaces are obtained later at run-time.
74// MatSys::RendererI* MatSys::Renderer=NULL;                    // TODO: Don't have it predefine the global pointer instance.
75// MatSys::TextureMapManagerI* MatSys::TextureMapManager=NULL;  // TODO: Don't have it predefine the global pointer instance.
76SoundSysI* SoundSystem=NULL;
77cf::GuiSys::GuiManI* cf::GuiSys::GuiMan=NULL;
78cf::GameSys::GameI* cf::GameSys::Game=NULL;
79
80
81static bool CompareModes(const wxVideoMode& Mode1, const wxVideoMode& Mode2)
82{
83    // Compare the widths.
84    if (Mode1.w < Mode2.w) return true;
85    if (Mode1.w > Mode2.w) return false;
86
87    // The widths are equal, now compare the heights.
88    if (Mode1.h < Mode2.h) return true;
89    if (Mode1.h > Mode2.h) return false;
90
91    // The widths and heights are equal, now compare the BPP.
92    if (Mode1.bpp < Mode2.bpp) return true;
93    if (Mode1.bpp > Mode2.bpp) return false;
94
95    // The widths, heights and BPPs are equal, now compare the refresh rate.
96    if (Mode1.refresh < Mode2.refresh) return true;
97    if (Mode1.refresh > Mode2.refresh) return false;
98
99    // The modes are equal.
100    return false;
101}
102
103
104static std::string GetVideoModes()
105{
106    ArrayT<wxVideoMode> Modes;
107
108    {
109        wxDisplay         Display;
110        wxArrayVideoModes wxModes=Display.GetModes();
111
112        for (size_t ModeNr=0; ModeNr<wxModes.GetCount(); ModeNr++)
113            Modes.PushBack(wxModes[ModeNr]);
114    }
115
116    // Remove modes according to certain filter criteria, cutting excessively long mode lists.
117    for (unsigned long ModeNr=0; ModeNr<Modes.Size(); ModeNr++)
118    {
119        const wxVideoMode& Mode=Modes[ModeNr];
120
121        if (Mode.w==0 || Mode.h==0 || Mode.bpp<15)
122        {
123            Modes.RemoveAt(ModeNr);
124            ModeNr--;
125            continue;
126        }
127
128        for (unsigned long OtherNr=0; OtherNr<Modes.Size(); OtherNr++)
129        {
130            if (OtherNr==ModeNr) continue;
131
132            const wxVideoMode& Other=Modes[OtherNr];
133
134            if (Mode==Other || (Mode.w==Other.w && Mode.h==Other.h && Mode.bpp<32 && Mode.bpp<Other.bpp))
135            {
136                Modes.RemoveAt(ModeNr);
137                ModeNr--;
138                break;
139            }
140        }
141
142        // Note that the above loop is written in a way that allows no additional statements here.
143    }
144
145    // Sort the modes by increasing width, height, BPP and refresh rate.
146    Modes.QuickSort(CompareModes);
147
148    // Build the result string.
149    wxString List;
150
151    for (unsigned long ModeNr=0; ModeNr<Modes.Size(); ModeNr++)
152    {
153        const wxVideoMode& Mode=Modes[ModeNr];
154
155        List+=wxString::Format("%i x %i, %i bpp, %i Hz\n", Mode.w, Mode.h, Mode.bpp, Mode.refresh);
156    }
157
158    return List.ToStdString();
159}
160
161
162IMPLEMENT_APP(AppCafuT)
163
164
165AppCafuT::AppCafuT()
166    : wxApp(),
167      m_Locale(NULL),
168      m_ConBuffer(new cf::ConsoleStringBufferT()),
169      m_ConFile(NULL),
170      m_IsCustomVideoMode(false),
171      m_MainFrame(NULL)
172{
173    s_CompositeConsole.Attach(m_ConBuffer);
174
175    #ifdef __WXGTK__
176    {
177        static cf::ConsoleStdoutT s_ConStdout;
178        s_CompositeConsole.Attach(&s_ConStdout);
179    }
180    #endif
181
182    // All global convars and confuncs have registered themselves in linked lists.
183    // Register them with the console interpreter now.
184    ConFuncT::RegisterStaticList();
185    ConVarT ::RegisterStaticList();
186
187    // The one-time init of the GuiSys' windows type info manager.
188    cf::GuiSys::GetWindowTIM().Init();
189
190    SetAppName("Cafu");
191    SetAppDisplayName("Cafu Engine");
192    SetVendorName("Carsten Fuchs Software");
193    wxStandardPaths::Get().UseAppInfo(wxStandardPaths::AppInfo_VendorName | wxStandardPaths::AppInfo_AppName);
194
195    Console->Print("Cafu Engine, "__DATE__"\n");
196}
197
198
199AppCafuT::~AppCafuT()
200{
201    s_CompositeConsole.Detach(m_ConFile);
202    delete m_ConFile;
203
204    s_CompositeConsole.Detach(m_ConBuffer);
205    delete m_ConBuffer;
206}
207
208
209cf::CompositeConsoleT& AppCafuT::GetConComposite() const
210{
211    return s_CompositeConsole;
212}
213
214
215bool AppCafuT::OnInit()
216{
217    const wxString UserDataDir=wxStandardPaths::Get().GetUserDataDir();
218
219    if (!wxFileName::Mkdir(UserDataDir, 0777, wxPATH_MKDIR_FULL))
220        wxMessageBox(wxString("Config file storage path \n")+UserDataDir+"\n doesn't exist, and it could not be created, either.", "Warning!");
221
222    // Undo the wx locale initialization, as we want to be sure to use the same (default) locale "C" always and everywhere.
223    // Using other locales introduces a lot of subtle errors. E.g. reading floating point numbers from anywhere
224    // (like map files!) fails because e.g. "1.4" is no proper floating point string in the German locale (but "1,4" is).
225    // setlocale(LC_ALL, "C");      // This alone is not enough, see http://trac.wxwidgets.org/ticket/12970 for details.
226    for (int LangNr=wxLANGUAGE_ENGLISH; LangNr<=wxLANGUAGE_ENGLISH_ZIMBABWE; LangNr++)
227    {
228        if (wxLocale::IsAvailable(LangNr))
229        {
230            m_Locale=new wxLocale(LangNr, wxLOCALE_DONT_LOAD_DEFAULT);
231
232            wxLogDebug("Program locale set to %s (%s, %s).", m_Locale->GetName(), m_Locale->GetCanonicalName(), m_Locale->GetLocale());
233            break;
234        }
235    }
236
237    if (!m_Locale)
238    {
239        // If the above for some reason didn't work, set at least the CRT to the "C" locale.
240        setlocale(LC_ALL, "C");
241        wxLogDebug("Program locale set to \"C\".");
242    }
243
244    ConsoleInterpreter->RunCommand("dofile('config.lua');");
245
246    // Parse the command line.
247    if (!wxApp::OnInit()) { OnExit(); return false; }
248
249    // Insert legacy dialog here...
250
251    try
252    {
253        g_WinSock=new WinSockT;
254    }
255    catch (const WinSockT::InitFailure& /*E*/) { wxMessageBox("Unable to initialize WinSock 2.0." ); OnExit(); return false; }
256    catch (const WinSockT::BadVersion&  /*E*/) { wxMessageBox("WinSock version 2.0 not supported."); OnExit(); return false; }
257
258    cf::FileSys::FileMan->MountFileSystem(cf::FileSys::FS_TYPE_LOCAL_PATH, "./", "");
259 // cf::FileSys::FileMan->MountFileSystem(cf::FileSys::FS_TYPE_LOCAL_PATH, "Games/DeathMatch/", "");
260    cf::FileSys::FileMan->MountFileSystem(cf::FileSys::FS_TYPE_ZIP_ARCHIVE, "Games/DeathMatch/Textures/TechDemo.zip", "Games/DeathMatch/Textures/TechDemo/", "Ca3DE");
261    cf::FileSys::FileMan->MountFileSystem(cf::FileSys::FS_TYPE_ZIP_ARCHIVE, "Games/DeathMatch/Textures/SkyDomes.zip", "Games/DeathMatch/Textures/SkyDomes/", "Ca3DE");
262
263    extern ConVarT     Options_ServerGameName;
264    const std::string& GameName=Options_ServerGameName.GetValueString();
265
266    MaterialManager->RegisterMaterialScriptsInDir("Games/"+GameName+"/Materials", "Games/"+GameName+"/");
267    SoundShaderManager->RegisterSoundShaderScriptsInDir("Games/"+GameName+"/SoundShader", "Games/"+GameName+"/");
268
269
270    // The console variable VideoModes is initialized here, because under wxGTK, using wxDisplay requires
271    // that the wxWidgets library (and thus GTK) is initialized first.
272    // Note that the format of the VideoModes string is fixed - it is parsed by the Main Menu GUI in order to populate the choice box.
273    static ConVarT VideoModes("VideoModes", GetVideoModes(), ConVarT::FLAG_MAIN_EXE | ConVarT::FLAG_READ_ONLY, "The list of video modes that are available on your system.");
274
275
276    // Change the video mode. Although the two actions
277    //
278    //     (a) change the screen resolution (video mode) and
279    //     (b) show the Cafu window full-screen
280    //
281    // are theoretically independent of each other, case "(a) but not (b)" does not make sense at all;
282    // case "not (a) but (b)" makes more sense but is atypical as well, and is easily switched from case
283    // "neither (a) nor (b)" by pressing F11. Thus, we are effectively only concerned by two cases:
284    //
285    //     (1) windowed mode:    "neither (a) nor (b)"
286    //     (2) full-screen mode: "both (a) and (b)"
287    //
288    // For case (1), we simply open a normal application window with dimensions Options_ClientWindowSize[X/Y].
289    // For case (2), we change the video mode as specified by Options_Client* and show the application
290    // window full-screen.
291    wxDisplay      Display;
292    extern ConVarT Options_ClientFullScreen;
293
294    if (Options_ClientFullScreen.GetValueBool())
295    {
296        extern ConVarT Options_ClientWindowSizeX;
297        extern ConVarT Options_ClientWindowSizeY;
298        extern ConVarT Options_ClientDisplayBPP;
299        extern ConVarT Options_ClientDisplayRefresh;
300
301        const wxVideoMode VideoMode1(Options_ClientWindowSizeX.GetValueInt(),
302                                     Options_ClientWindowSizeY.GetValueInt(),
303                                     Options_ClientDisplayBPP.GetValueInt(),
304                                     Options_ClientDisplayRefresh.GetValueInt());
305
306        const wxVideoMode VideoMode2(Options_ClientWindowSizeX.GetValueInt(),
307                                     Options_ClientWindowSizeY.GetValueInt(),
308                                     Options_ClientDisplayBPP.GetValueInt(), 0);
309
310        const wxVideoMode VideoMode3(Options_ClientWindowSizeX.GetValueInt(),
311                                     Options_ClientWindowSizeY.GetValueInt(), 0, 0);
312
313        if (Display.ChangeMode(VideoMode1))
314        {
315            m_IsCustomVideoMode=true;
316        }
317        else if (Display.ChangeMode(VideoMode2))
318        {
319            Options_ClientDisplayRefresh.SetValue(Display.GetCurrentMode().refresh);
320            m_IsCustomVideoMode=true;
321        }
322        else if (Display.ChangeMode(VideoMode3))
323        {
324            Options_ClientDisplayBPP.SetValue(Display.GetCurrentMode().bpp);
325            Options_ClientDisplayRefresh.SetValue(Display.GetCurrentMode().refresh);
326            m_IsCustomVideoMode=true;
327        }
328        else
329        {
330            wxMessageBox("Cafu tried to change the video mode to\n"+
331                wxString::Format("        %i x %i, %i bpp at %i Hz,\n", VideoMode1.w, VideoMode1.h, VideoMode1.bpp, VideoMode1.refresh)+
332                wxString::Format("        %i x %i, %i bpp at any refresh rate,\n", VideoMode2.w, VideoMode2.h, VideoMode2.bpp)+
333                wxString::Format("        %i x %i at any color depth and refresh rate,\n", VideoMode3.w, VideoMode3.h)+
334                "but it didn't work out (zero values mean system defaults).\n"+
335                "We will continue with the currently active video mode instead, where you can press F11 to toggle full-screen mode.\n\n"+
336                "Alternatively, you can set a different video mode at the Options menu, or tweak the video mode details via the console variables.\n",
337                "Could not change the video mode", wxOK | wxICON_EXCLAMATION);
338
339            Options_ClientFullScreen.SetValue(false);
340        }
341    }
342
343    m_CurrentMode=Display.GetCurrentMode();
344
345    if (m_CurrentMode.w==0) { m_CurrentMode.w=wxGetDisplaySize().x; wxLogDebug("Set m_CurrentMode.w from 0 to %i", m_CurrentMode.w); }
346    if (m_CurrentMode.h==0) { m_CurrentMode.h=wxGetDisplaySize().y; wxLogDebug("Set m_CurrentMode.h from 0 to %i", m_CurrentMode.h); }
347
348    if (m_CurrentMode.w<200) { m_CurrentMode.w=1024; wxLogDebug("Set m_CurrentMode.w from <200 to %i", m_CurrentMode.w); }
349    if (m_CurrentMode.h<150) { m_CurrentMode.h= 768; wxLogDebug("Set m_CurrentMode.h from <150 to %i", m_CurrentMode.h); }
350
351
352    // Create the main frame.
353    m_MainFrame=new MainFrameT();
354    SetTopWindow(m_MainFrame);
355
356    return true;
357}
358
359
360int AppCafuT::OnExit()
361{
362    if (m_IsCustomVideoMode)
363    {
364        wxDisplay Display;
365
366        // Reset the display to default (desktop) video mode.
367        Display.ChangeMode();
368    }
369
370    delete g_WinSock;
371    g_WinSock=NULL;
372
373    // Setting the ConsoleInterpreter to NULL is very important, to make sure that no ConFuncT
374    // or ConVarT dtor accesses the ConsoleInterpreter that might already have been destroyed then.
375    ConsoleInterpreter=NULL;
376
377    delete m_Locale;
378    m_Locale=NULL;
379
380    return wxApp::OnExit();
381}
382
383
384extern ConVarT Options_ServerGameName;
385extern ConVarT Options_ServerWorldName;
386extern ConVarT Options_ServerPortNr;
387extern ConVarT Options_ClientPortNr;
388extern ConVarT Options_ClientRemoteName;
389extern ConVarT Options_ClientRemotePortNr;
390
391extern ConVarT Options_ClientWindowSizeX;
392extern ConVarT Options_ClientWindowSizeY;
393extern ConVarT Options_ClientDisplayBPP;        // TODO
394extern ConVarT Options_ClientDisplayRefresh;    // TODO
395extern ConVarT Options_ClientFullScreen;
396
397extern ConVarT Options_ClientDesiredRenderer;
398extern ConVarT Options_ClientDesiredSoundSystem;
399extern ConVarT Options_ClientTextureDetail;
400extern ConVarT Options_DeathMatchPlayerName;
401extern ConVarT Options_DeathMatchModelName;
402
403
404void AppCafuT::OnInitCmdLine(wxCmdLineParser& Parser)
405{
406    Parser.AddOption("con",            "", "Runs the given commands in the console. -con \"x=3;\" is equivalent to appending x=3; to the end of the config.lua file.", wxCMD_LINE_VAL_STRING);
407    Parser.AddOption("svGame",         "", "Name of the MOD / game the server should run ["+Options_ServerGameName.GetValueString()+"]. Case sensitive!", wxCMD_LINE_VAL_STRING);
408    Parser.AddOption("svWorld",        "", "Name of the world the server should run ["+Options_ServerWorldName.GetValueString()+"]. Case sensitive!", wxCMD_LINE_VAL_STRING);
409    Parser.AddOption("svPort",         "", wxString::Format("Server port number [%i].", Options_ServerPortNr.GetValueInt()), wxCMD_LINE_VAL_NUMBER);
410    Parser.AddSwitch("noFS", "clNoFullscreen", "Don't run full-screen, but rather in a window.");
411    Parser.AddOption("clPort",         "", wxString::Format("Client port number [%i].", Options_ClientPortNr.GetValueInt()), wxCMD_LINE_VAL_NUMBER);
412    Parser.AddOption("clRemoteName",   "", "Name or IP of the server we connect to ["+Options_ClientRemoteName.GetValueString()+"].", wxCMD_LINE_VAL_STRING);
413    Parser.AddOption("clRemotePort",   "", wxString::Format("Port number of the remote server [%i].", Options_ClientRemotePortNr.GetValueInt()), wxCMD_LINE_VAL_NUMBER);
414    Parser.AddOption("clTexDetail",    "", wxString::Format("0 high detail, 1 medium detail, 2 low detail [%i].", Options_ClientTextureDetail.GetValueInt()), wxCMD_LINE_VAL_NUMBER);
415    Parser.AddOption("clWinSizeX",     "", wxString::Format("If not full-screen, this is the width  of the window [%i].", Options_ClientWindowSizeX.GetValueInt()), wxCMD_LINE_VAL_NUMBER);
416    Parser.AddOption("clWinSizeY",     "", wxString::Format("If not full-screen, this is the height of the window [%i].", Options_ClientWindowSizeY.GetValueInt()), wxCMD_LINE_VAL_NUMBER);
417    Parser.AddOption("clRenderer",     "", "Override the auto-selection of the best available renderer [auto].", wxCMD_LINE_VAL_STRING);
418    Parser.AddOption("clSoundSystem",  "", "Override the auto-selection of the best available sound system [auto].", wxCMD_LINE_VAL_STRING);
419    Parser.AddOption("clPlayerName",   "", "Player name ["+Options_DeathMatchPlayerName.GetValueString()+"].", wxCMD_LINE_VAL_STRING);
420    Parser.AddOption("clModelName",    "", "Name of the players model ["+Options_DeathMatchModelName.GetValueString()+"].", wxCMD_LINE_VAL_STRING);
421    Parser.AddOption("log",            "", "Logs all console message into the specified file.");
422    Parser.AddParam("worldname", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
423
424    wxApp::OnInitCmdLine(Parser);
425    Parser.AddUsageText("\nDefault values are enclosed in [brackets].");
426    Parser.AddUsageText("It is also ok to omit the \"-svWorld\" option for specifying a world name: \"Cafu MyWorld\" is the same as \"Cafu -svWorld MyWorld\".\n");
427    Parser.SetSwitchChars("-");
428}
429
430
431bool AppCafuT::OnCmdLineParsed(wxCmdLineParser& Parser)
432{
433    long int i=0;
434    wxString s="";
435
436    if (Parser.Found("con",           &s)) ConsoleInterpreter->RunCommand(s.ToStdString());
437    if (Parser.Found("svGame",        &s)) Options_ServerGameName=s.ToStdString();
438    if (Parser.Found("svWorld",       &s)) Options_ServerWorldName=s.ToStdString();
439    if (Parser.Found("svPort",        &i)) Options_ServerPortNr=int(i);
440    if (Parser.Found("noFS")             ) Options_ClientFullScreen=false;
441    if (Parser.Found("clPort",        &i)) Options_ClientPortNr=int(i);
442    if (Parser.Found("clRemoteName",  &s)) Options_ClientRemoteName=s.ToStdString();
443    if (Parser.Found("clRemotePort",  &i)) Options_ClientRemotePortNr=int(i);
444    if (Parser.Found("clTexDetail",   &i)) Options_ClientTextureDetail=int(i % 3);
445    if (Parser.Found("clWinSizeX",    &i)) Options_ClientWindowSizeX=int(i);
446    if (Parser.Found("clWinSizeY",    &i)) Options_ClientWindowSizeY=int(i);
447    if (Parser.Found("clRenderer",    &s)) Options_ClientDesiredRenderer=s.ToStdString();
448    if (Parser.Found("clSoundSystem", &s)) Options_ClientDesiredSoundSystem=s.ToStdString();
449    if (Parser.Found("clPlayerName",  &s)) Options_DeathMatchPlayerName=s.ToStdString();
450    if (Parser.Found("clModelName",   &s)) Options_DeathMatchModelName=s.ToStdString();
451
452    if (Parser.Found("log", &s) && m_ConFile==NULL)
453    {
454        m_ConFile=new cf::ConsoleFileT(s.ToStdString());
455        m_ConFile->SetAutoFlush(true);
456        m_ConFile->Print(m_ConBuffer->GetBuffer());
457
458        s_CompositeConsole.Attach(m_ConFile);
459    }
460
461    if (!Parser.Found("svWorld") && Parser.GetParamCount()==1)
462        Options_ServerWorldName=Parser.GetParam(0).ToStdString();
463
464    return wxApp::OnCmdLineParsed(Parser);
465}
Note: See TracBrowser for help on using the browser.