/* * Copyright (c) 2020-2021 The reone project contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "frame.h" #include #include #include #include #include #include #include "../src/common/types.h" using namespace std; namespace fs = boost::filesystem; namespace po = boost::program_options; namespace reone { static const char kIconName[] = "reone"; static const char kConfigFilename[] = "reone.cfg"; static const wxSize g_windowSize { 400, 400 }; LauncherFrame::LauncherFrame() : wxFrame(nullptr, wxID_ANY, "reone", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX)) { // Configure this frame #ifdef _WIN32 SetIcon(wxIcon(kIconName)); #endif SetSize(g_windowSize); LoadConfiguration(); // Setup controls _textCtrlGameDir = new wxTextCtrl(this, WindowID::gameDir, _config.gameDir, wxDefaultPosition, wxDefaultSize, wxTE_READONLY); _textCtrlGameDir->Bind(wxEVT_LEFT_DOWN, &LauncherFrame::OnGameDirLeftDown, this, WindowID::gameDir); auto gameSizer = new wxBoxSizer(wxHORIZONTAL); gameSizer->Add(new wxStaticText(this, wxID_ANY, "Game Directory", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL), 1, wxEXPAND | wxALL, 3); gameSizer->Add(_textCtrlGameDir, 1, wxEXPAND | wxALL, 3); _checkBoxDev = new wxCheckBox(this, WindowID::devMode, "Developer Mode", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); _checkBoxDev->SetValue(_config.devMode); wxArrayString resChoices; set uniqueRes; wxArrayVideoModes modes(wxDisplay(wxDisplay::GetFromWindow(this)).GetModes()); for (size_t i = 0; i < modes.GetCount(); ++i) { wxVideoMode mode = modes[i]; string res(str(boost::format("%dx%d") % mode.GetWidth() % mode.GetHeight())); if (uniqueRes.count(res) == 0) { resChoices.Add(res); uniqueRes.insert(res); } } string configResolution(str(boost::format("%dx%d") % _config.width % _config.height)); int resSelection = resChoices.Index(configResolution); if (resSelection == wxNOT_FOUND) { resSelection = 1; } _choiceResolution = new wxChoice(this, WindowID::resolution, wxDefaultPosition, wxDefaultSize, resChoices); _choiceResolution->SetSelection(resSelection); auto resSizer = new wxBoxSizer(wxHORIZONTAL); resSizer->Add(new wxStaticText(this, wxID_ANY, "Screen Resolution", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL), 1, wxEXPAND | wxALL, 3); resSizer->Add(_choiceResolution, 1, wxEXPAND | wxALL, 3); _checkBoxFullscreen = new wxCheckBox(this, WindowID::fullscreen, "Fullscreen", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); _checkBoxFullscreen->SetValue(_config.fullscreen); _checkBoxEnhancedGfx = new wxCheckBox(this, WindowID::enhancedGfx, "Enhanced Graphics", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); _checkBoxEnhancedGfx->SetValue(_config.pbr); auto graphicsSizer = new wxStaticBoxSizer(wxVERTICAL, this, "Graphics"); graphicsSizer->Add(resSizer, 0, wxEXPAND, 0); graphicsSizer->Add(_checkBoxFullscreen, 0, wxEXPAND | wxALL, 3); graphicsSizer->Add(_checkBoxEnhancedGfx, 0, wxEXPAND | wxALL, 3); wxArrayString debugChoices; debugChoices.Add("0"); debugChoices.Add("1"); debugChoices.Add("2"); debugChoices.Add("3"); int debugLevelSelection = _config.debug >= 0 && _config.debug <= 3 ? _config.debug : 0; _choiceDebugLevel = new wxChoice(this, WindowID::debug, wxDefaultPosition, wxDefaultSize, debugChoices); _choiceDebugLevel->SetSelection(debugLevelSelection); auto debugLevelSizer = new wxBoxSizer(wxHORIZONTAL); debugLevelSizer->Add(new wxStaticText(this, wxID_ANY, "Log Level", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL), 1, wxEXPAND | wxALL, 3); debugLevelSizer->Add(_choiceDebugLevel, 1, wxEXPAND | wxALL, 3); wxArrayString debugChannelsChoices; debugChannelsChoices.Add("All"); debugChannelsChoices.Add("General"); debugChannelsChoices.Add("GUI"); debugChannelsChoices.Add("Script"); debugChannelsChoices.Add("Conversation"); debugChannelsChoices.Add("Combat"); int debugChannelsSelection; switch (_config.debugch) { case DebugChannels::general: debugChannelsSelection = 1; break; case DebugChannels::gui: debugChannelsSelection = 2; break; case DebugChannels::script: debugChannelsSelection = 3; break; case DebugChannels::conversation: debugChannelsSelection = 4; break; case DebugChannels::combat: debugChannelsSelection = 5; break; default: debugChannelsSelection = 0; break; } _choiceDebugChannels = new wxChoice(this, WindowID::debugChannels, wxDefaultPosition, wxDefaultSize, debugChannelsChoices); _choiceDebugChannels->SetSelection(debugChannelsSelection); auto debugChannelsSizer = new wxBoxSizer(wxHORIZONTAL); debugChannelsSizer->Add(new wxStaticText(this, wxID_ANY, "Channels", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL), 1, wxEXPAND | wxALL, 3); debugChannelsSizer->Add(_choiceDebugChannels, 1, wxEXPAND | wxALL, 3); _checkBoxLogFile = new wxCheckBox(this, WindowID::logFile, "Log to File", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); _checkBoxLogFile->SetValue(_config.logfile); auto debugSizer = new wxStaticBoxSizer(wxVERTICAL, this, "Debug"); debugSizer->Add(debugLevelSizer, 0, wxEXPAND, 0); debugSizer->Add(debugChannelsSizer, 0, wxEXPAND, 0); debugSizer->Add(_checkBoxLogFile, 0, wxEXPAND, 0); auto topSizer = new wxBoxSizer(wxVERTICAL); topSizer->Add(gameSizer, 0, wxEXPAND, 0); topSizer->Add(_checkBoxDev, 0, wxEXPAND | wxALL, 3); topSizer->Add(graphicsSizer, 0, wxEXPAND | wxALL, 3); topSizer->Add(debugSizer, 0, wxEXPAND | wxALL, 3); topSizer->Add(new wxButton(this, WindowID::launch, "Launch"), 0, wxEXPAND | wxALL, 3); topSizer->Add(new wxButton(this, WindowID::saveConfig, "Save Configuration"), 0, wxEXPAND | wxALL, 3); SetSizer(topSizer); } void LauncherFrame::LoadConfiguration() { po::options_description options; options.add_options() ("game", po::value()) ("dev", po::value()) ("width", po::value()) ("height", po::value()) ("fullscreen", po::value()) ("pbr", po::value()) ("debug", po::value()) ("debugch", po::value()) ("logfile", po::value()); po::variables_map vars; if (fs::exists(kConfigFilename)) { po::store(po::parse_config_file(kConfigFilename, options, true), vars); } po::notify(vars); _config.gameDir = vars.count("game") > 0 ? vars["game"].as() : ""; _config.devMode = vars.count("dev") > 0 ? vars["dev"].as() : false; _config.width = vars.count("width") > 0 ? vars["width"].as() : 1024; _config.height = vars.count("height") > 0 ? vars["height"].as() : 768; _config.fullscreen = vars.count("fullscreen") > 0 ? vars["fullscreen"].as() : false; _config.pbr = vars.count("pbr") > 0 ? vars["pbr"].as() : false; _config.debug = vars.count("debug") > 0 ? vars["debug"].as() : 0; _config.debugch = vars.count("debugch") > 0 ? vars["debugch"].as() : DebugChannels::all; _config.logfile = vars.count("logfile") > 0 ? vars["logfile"].as() : false; } void LauncherFrame::OnLaunch(wxCommandEvent &event) { SaveConfiguration(); string exe("reone"); #ifndef _WIN32 exe.insert(0, "./"); #endif system(exe.c_str()); Close(true); } void LauncherFrame::SaveConfiguration() { static set recognized { "game=", "width=", "height=", "fullscreen=", "pbr=", "dev=", "debug=", "debugch=", "logfile=" }; string resolution(_choiceResolution->GetStringSelection()); vector tokens; boost::split(tokens, resolution, boost::is_any_of("x"), boost::token_compress_on); int debugch = 0; switch (_choiceDebugChannels->GetSelection()) { case 1: debugch = DebugChannels::general; break; case 2: debugch = DebugChannels::gui; break; case 3: debugch = DebugChannels::script; break; case 4: debugch = DebugChannels::conversation; break; case 5: debugch = DebugChannels::combat; break; default: debugch = DebugChannels::all; break; } _config.gameDir = _textCtrlGameDir->GetValue(); _config.devMode = _checkBoxDev->IsChecked(); _config.width = stoi(tokens[0]); _config.height = stoi(tokens[1]); _config.fullscreen = _checkBoxFullscreen->IsChecked(); _config.pbr = _checkBoxEnhancedGfx->IsChecked(); _config.debug = stoi(string(_choiceDebugLevel->GetStringSelection())); _config.debugch = debugch; _config.logfile = _checkBoxLogFile->IsChecked(); vector lines; fs::ifstream in(kConfigFilename); for (string line; getline(in, line); ) { bool add = true; for (auto &opt : recognized) { if (boost::starts_with(line, opt)) { add = false; break; } } if (add) { lines.push_back(line); } } fs::ofstream config(kConfigFilename); config << "game=" << _config.gameDir << endl; config << "dev=" << (_config.devMode ? 1 : 0) << endl; config << "width=" << _config.width << endl; config << "height=" << _config.height << endl; config << "fullscreen=" << (_config.fullscreen ? 1 : 0) << endl; config << "pbr=" << (_config.pbr ? 1 : 0) << endl; config << "debug=" << _config.debug << endl; config << "debugch=" << _config.debugch << endl; config << "logfile=" << (_config.logfile ? 1 : 0) << endl; for (auto &line : lines) { config << line << endl; } } void LauncherFrame::OnSaveConfig(wxCommandEvent &event) { SaveConfiguration(); } void LauncherFrame::OnGameDirLeftDown(wxMouseEvent &event) { wxDirDialog dlg(nullptr, "Choose game directory", _textCtrlGameDir->GetValue(), wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST); if (dlg.ShowModal() == wxID_OK) { _textCtrlGameDir->SetValue(dlg.GetPath()); } } wxBEGIN_EVENT_TABLE(LauncherFrame, wxFrame) EVT_BUTTON(WindowID::launch, LauncherFrame::OnLaunch) EVT_BUTTON(WindowID::saveConfig, LauncherFrame::OnSaveConfig) wxEND_EVENT_TABLE() } // namespace reone