config file/directory at first ever start of supertuxkart. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk@760 178a84e3-b1eb-0310-8ba1-8eac791a3b58
443 lines
16 KiB
C++
443 lines
16 KiB
C++
// $Id$
|
|
//
|
|
// SuperTuxKart - a fun racing game with go-kart
|
|
// Copyright (C) 2006 SuperTuxKart-Team
|
|
// Modelled after Supertux's configfile.cpp
|
|
//
|
|
// 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 2
|
|
// 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, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
#include <stdio.h>
|
|
#include <stdexcept>
|
|
|
|
// for mkdir:
|
|
#if !defined(WIN32) || defined(__CYGWIN__)
|
|
# include <sys/stat.h>
|
|
# include <sys/types.h>
|
|
#else
|
|
# include <direct.h>
|
|
#endif
|
|
|
|
#include <plib/pw.h>
|
|
#include <plib/ul.h>
|
|
|
|
#include "config.hpp"
|
|
#include "lisp/lisp.hpp"
|
|
#include "lisp/parser.hpp"
|
|
#include "lisp/writer.hpp"
|
|
|
|
Config *config;
|
|
|
|
Config::Config() {
|
|
setDefaults();
|
|
loadConfig();
|
|
} // Config
|
|
|
|
// -----------------------------------------------------------------------------
|
|
Config::Config(const std::string& filename) {
|
|
setDefaults();
|
|
loadConfig(filename);
|
|
} // Config
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
Config::~Config() {
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
std::string Config::getConfigDir() {
|
|
std::string dirname;
|
|
#ifdef WIN32
|
|
// For now the old windows config way is used: store a config file
|
|
// in the current directory (in other OS a special subdirectory is created)
|
|
dirname=".";
|
|
#else
|
|
if(getenv("HOME")!=NULL) {
|
|
dirname = getenv("HOME");
|
|
} else{
|
|
dirname = ".";
|
|
}
|
|
dirname += "/";
|
|
dirname += CONFIGDIR;
|
|
#endif
|
|
return dirname;
|
|
} // getConfigDir
|
|
|
|
// -----------------------------------------------------------------------------
|
|
/*set the config filename for this platform*/
|
|
void Config::setFilename() {
|
|
filename = getConfigDir();
|
|
filename += "/";
|
|
#ifdef WIN32
|
|
filename += "supertuxkart.cfg";
|
|
#else
|
|
filename += "config";
|
|
#endif
|
|
} // setFilename
|
|
|
|
// -----------------------------------------------------------------------------
|
|
/*load default values for options*/
|
|
void Config::setDefaults() {
|
|
setFilename();
|
|
fullscreen = false;
|
|
noStartScreen = false;
|
|
sfx = true;
|
|
music = true;
|
|
smoke = false;
|
|
displayFPS = false;
|
|
singleWindowMenu = false;
|
|
oldStatusDisplay = false;
|
|
herringStyle = "new";
|
|
disableMagnet = true;
|
|
profile = 0;
|
|
useKPH = false;
|
|
improvedPhysics = false;
|
|
newKeyboardStyle = true;
|
|
replayHistory = false;
|
|
width = 800;
|
|
height = 600;
|
|
karts = 4;
|
|
|
|
player[0].setName("Player 1");
|
|
player[1].setName("Player 2");
|
|
player[2].setName("Player 3");
|
|
player[3].setName("Player 4");
|
|
|
|
player[0].setUseJoystick(true);
|
|
player[1].setUseJoystick(false);
|
|
player[2].setUseJoystick(false);
|
|
player[3].setUseJoystick(false);
|
|
|
|
/*player 1 default keyboard settings*/
|
|
player[0].setKey(KC_LEFT, PW_KEY_LEFT);
|
|
player[0].setKey(KC_RIGHT, PW_KEY_RIGHT);
|
|
player[0].setKey(KC_ACCEL, PW_KEY_UP);
|
|
player[0].setKey(KC_BRAKE, PW_KEY_DOWN);
|
|
player[0].setKey(KC_WHEELIE, 'a');
|
|
player[0].setKey(KC_JUMP, 's');
|
|
player[0].setKey(KC_RESCUE, 'd');
|
|
player[0].setKey(KC_FIRE, 'f');
|
|
/*player 1 default joystick settings*/
|
|
player[0].setButton(KC_BRAKE, 1);
|
|
player[0].setButton(KC_WHEELIE, 0x20);
|
|
player[0].setButton(KC_JUMP, 0x10);
|
|
player[0].setButton(KC_RESCUE, 0x04);
|
|
player[0].setButton(KC_FIRE, 0x08);
|
|
|
|
/*player 2 default keyboard settings*/
|
|
player[1].setKey(KC_LEFT, 'j');
|
|
player[1].setKey(KC_RIGHT, 'l');
|
|
player[1].setKey(KC_ACCEL, 'i');
|
|
player[1].setKey(KC_BRAKE, 'k');
|
|
player[1].setKey(KC_WHEELIE, 'q');
|
|
player[1].setKey(KC_JUMP, 'w');
|
|
player[1].setKey(KC_RESCUE, 'e');
|
|
player[1].setKey(KC_FIRE, 'r');
|
|
/*player 2 default joystick settings*/
|
|
player[1].setButton(KC_ACCEL, 0);
|
|
player[1].setButton(KC_BRAKE, 1);
|
|
player[1].setButton(KC_WHEELIE, 2);
|
|
player[1].setButton(KC_JUMP, 3);
|
|
player[1].setButton(KC_RESCUE, 4);
|
|
player[1].setButton(KC_FIRE, 5);
|
|
|
|
/*player 3 default joystick settings*/
|
|
player[2].setButton(KC_ACCEL, 0);
|
|
player[2].setButton(KC_BRAKE, 1);
|
|
player[2].setButton(KC_WHEELIE, 2);
|
|
player[2].setButton(KC_JUMP, 3);
|
|
player[2].setButton(KC_RESCUE, 4);
|
|
player[2].setButton(KC_FIRE, 5);
|
|
/*player 4 default joystick settings*/
|
|
player[3].setButton(KC_ACCEL, 0);
|
|
player[3].setButton(KC_BRAKE, 1);
|
|
player[3].setButton(KC_WHEELIE, 2);
|
|
player[3].setButton(KC_JUMP, 3);
|
|
player[3].setButton(KC_RESCUE, 4);
|
|
player[3].setButton(KC_FIRE, 5);
|
|
} // setDefaults
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
/*load default configuration file for this platform*/
|
|
void Config::loadConfig() {
|
|
loadConfig(filename);
|
|
} // loadConfig
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Checks for existance of the tuxkart configuration directory. If the
|
|
// directory does not exist, it will be created. Return values:
|
|
// 1: config dir exists
|
|
// 2: does not exist, but was created
|
|
// 0: does not exist, and could not be created.
|
|
int Config::CheckAndCreateDir() {
|
|
std::string dirname = getConfigDir();
|
|
ulDir* u = ulOpenDir(dirname.c_str());
|
|
if(u) { // OK, directory exists
|
|
ulCloseDir(u);
|
|
return 1;
|
|
}
|
|
// The directory does not exist, try to create it
|
|
int bError;
|
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
|
bError = _mkdir(dirname.c_str() ) != 0;
|
|
#else
|
|
bError = mkdir(dirname.c_str(), 0755) != 0;
|
|
#endif
|
|
if(bError) {
|
|
fprintf(stderr, "Couldn't create '%s', config files will not be saved.\n",
|
|
dirname.c_str());
|
|
return 0;
|
|
} else {
|
|
printf("Config directory '%s' successfully created.\n",dirname.c_str());
|
|
return 2;
|
|
}
|
|
|
|
} // CheckAndCreateDir
|
|
|
|
// -----------------------------------------------------------------------------
|
|
/*load configuration values from file*/
|
|
void Config::loadConfig(const std::string& filename) {
|
|
std::string temp;
|
|
const lisp::Lisp* root = 0;
|
|
int i;
|
|
int dirExist = CheckAndCreateDir();
|
|
// Check if the config directory exists. If not, exit without an error
|
|
// message, an appropriate message was printed by CheckAndCreateDir
|
|
if (dirExist != 1) return;
|
|
|
|
try {
|
|
lisp::Parser parser;
|
|
root = parser.parse(filename);
|
|
} catch(std::exception& e) {
|
|
std::cout << "Config file '"<<filename<<"' does not exist, it will be created.\n";
|
|
delete root;
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const lisp::Lisp* lisp = root->getLisp("tuxkart-config");
|
|
if(!lisp)
|
|
throw std::runtime_error("No tuxkart-config node");
|
|
|
|
/*get toggles*/
|
|
lisp->get("fullscreen", fullscreen);
|
|
lisp->get("sfx" , sfx);
|
|
lisp->get("nostartscreen", noStartScreen);
|
|
lisp->get("music", music);
|
|
lisp->get("smoke", smoke);
|
|
lisp->get("displayFPS", displayFPS);
|
|
lisp->get("singlewindowmenu", singleWindowMenu);
|
|
lisp->get("oldStatusDisplay", oldStatusDisplay);
|
|
lisp->get("herringStyle", herringStyle);
|
|
lisp->get("disableMagnet", disableMagnet);
|
|
lisp->get("newKeyboardStyle", newKeyboardStyle);
|
|
lisp->get("useKPH", useKPH);
|
|
lisp->get("improvedPhysics", improvedPhysics);
|
|
|
|
/*get resolution width/height*/
|
|
lisp->get("width", width);
|
|
lisp->get("height", height);
|
|
|
|
/*get number of karts*/
|
|
lisp->get("karts", karts);
|
|
|
|
/*get player configurations*/
|
|
for(i=0; i<PLAYERS; ++i) {
|
|
temp = "player-";
|
|
temp += i+'1';
|
|
|
|
const lisp::Lisp* reader = lisp->getLisp(temp);
|
|
if(!reader) {
|
|
temp = "No " + temp + " node";
|
|
throw std::runtime_error(temp);
|
|
}
|
|
std::string name;
|
|
reader->get("name", name);
|
|
player[i].setName(name);
|
|
|
|
int tmp= 0;
|
|
/*get keyboard configuration*/
|
|
reader->get("left", tmp); player[i].setKey(KC_LEFT, tmp);
|
|
reader->get("right", tmp); player[i].setKey(KC_RIGHT, tmp);
|
|
reader->get("up", tmp); player[i].setKey(KC_ACCEL, tmp);
|
|
reader->get("down", tmp); player[i].setKey(KC_BRAKE, tmp);
|
|
reader->get("wheelie", tmp); player[i].setKey(KC_WHEELIE, tmp);
|
|
reader->get("jump", tmp); player[i].setKey(KC_JUMP, tmp);
|
|
reader->get("rescue", tmp); player[i].setKey(KC_RESCUE, tmp);
|
|
reader->get("fire", tmp); player[i].setKey(KC_FIRE, tmp);
|
|
|
|
/*get joystick configuration*/
|
|
reader->get("joy-up", tmp); player[i].setButton(KC_ACCEL, tmp);
|
|
reader->get("joy-down", tmp); player[i].setButton(KC_BRAKE, tmp);
|
|
reader->get("joy-wheelie", tmp); player[i].setButton(KC_WHEELIE, tmp);
|
|
reader->get("joy-jump", tmp); player[i].setButton(KC_JUMP, tmp);
|
|
reader->get("joy-rescue", tmp); player[i].setButton(KC_RESCUE, tmp);
|
|
reader->get("joy-fire", tmp); player[i].setButton(KC_FIRE, tmp);
|
|
}
|
|
} catch(std::exception& e) {
|
|
std::cout << "Error while parsing config '" << filename << "': " << e.what() << "\n";
|
|
}
|
|
delete root;
|
|
} // loadConfig
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
/*call saveConfig w/ the default filename for this platform*/
|
|
void Config::saveConfig() {
|
|
saveConfig(filename);
|
|
} // saveConfig
|
|
|
|
// -----------------------------------------------------------------------------
|
|
/*write settings to config file*/
|
|
void Config::saveConfig(const std::string& filename) {
|
|
std::string temp;
|
|
int i;
|
|
|
|
int dirExist = CheckAndCreateDir();
|
|
// Check if the config directory exists (again, since it was already checked
|
|
// when reading the config file - this is done in case that the problem was
|
|
// fixed while tuxkart is running). If the directory does not exist and
|
|
// can not be created, an error message was already printed to stderr,
|
|
// and we can exit here without any further messages.
|
|
if (dirExist == 0) return;
|
|
|
|
try {
|
|
lisp::Writer writer(filename);
|
|
|
|
writer.beginList("tuxkart-config");
|
|
writer.writeComment("the following options can be set to #t or #f:");
|
|
writer.write("fullscreen\t", fullscreen);
|
|
writer.write("sfx\t", sfx);
|
|
writer.write("music\t", music);
|
|
writer.write("smoke\t", smoke);
|
|
writer.writeComment("Display frame per seconds");
|
|
writer.write("displayFPS\t", displayFPS);
|
|
writer.writeComment("Use the old, one-window style menu at startup");
|
|
writer.write("singleWindowMenu\t", singleWindowMenu);
|
|
writer.writeComment("Display kart icons in bottom row instead of at the left");
|
|
writer.write("oldStatusDisplay\t", oldStatusDisplay);
|
|
writer.writeComment("Name of the .herring file to use.");
|
|
writer.write("herringStyle\t", herringStyle);
|
|
writer.writeComment("Allow players to disable a magnet");
|
|
writer.write("disableMagnet\t", disableMagnet);
|
|
writer.writeComment("Use of kilometers per hours (km/h) instead of mph");
|
|
writer.write("useKPH\t", useKPH);
|
|
writer.writeComment("With improved physics the gravity on a non-horizontal");
|
|
writer.writeComment("plane will add an accelerating force on the kart");
|
|
writer.write("improvedPhysics\t", improvedPhysics);
|
|
writer.writeComment("#f: old 'digital' style, #t:new analog style, allows for better turning");
|
|
writer.write("newKeyboardStyle\t", newKeyboardStyle);
|
|
|
|
writer.writeComment("screen resolution");
|
|
writer.write("width\t", width);
|
|
writer.write("height\t", height);
|
|
|
|
writer.writeComment("number of karts. -1 means use all");
|
|
writer.write("karts\t", karts);
|
|
|
|
/*write player configurations*/
|
|
for(i=0; i<PLAYERS; ++i) {
|
|
temp = "player ";
|
|
temp += i+'1';
|
|
temp += " settings";
|
|
writer.writeComment(temp);
|
|
temp = "player-";
|
|
temp += i+'1';
|
|
writer.beginList(temp);
|
|
|
|
writer.write("name\t", player[i].getName());
|
|
|
|
writer.writeComment("keyboard layout");
|
|
writer.write("left\t", player[i].getKey(KC_LEFT));
|
|
writer.write("right\t", player[i].getKey(KC_RIGHT));
|
|
writer.write("up\t\t", player[i].getKey(KC_ACCEL));
|
|
writer.write("down\t", player[i].getKey(KC_BRAKE));
|
|
writer.write("wheelie\t", player[i].getKey(KC_WHEELIE));
|
|
writer.write("jump\t", player[i].getKey(KC_JUMP));
|
|
writer.write("rescue\t", player[i].getKey(KC_RESCUE));
|
|
writer.write("fire\t", player[i].getKey(KC_FIRE));
|
|
|
|
writer.writeComment("joystick layout");
|
|
writer.write("joy-up", player[i].getButton(KC_ACCEL));
|
|
writer.write("joy-down", player[i].getButton(KC_BRAKE));
|
|
writer.write("joy-wheelie\t", player[i].getButton(KC_WHEELIE));
|
|
writer.write("joy-jump\t", player[i].getButton(KC_JUMP));
|
|
writer.write("joy-rescue\t", player[i].getButton(KC_RESCUE));
|
|
writer.write("joy-fire\t", player[i].getButton(KC_FIRE));
|
|
|
|
writer.endList(temp);
|
|
} // for i
|
|
|
|
writer.endList("tuxkart-config");
|
|
} catch(std::exception& e) {
|
|
std::cout << "Couldn't write config: " << e.what() << "\n";
|
|
}
|
|
} // saveConfig
|
|
// -----------------------------------------------------------------------------
|
|
std::string Config::GetKeyAsString(int player_index, KartActions control) {
|
|
int key = player[player_index].getKey(control);
|
|
int useJoystick = player[player_index].IsUsingJoystick();
|
|
std::string ret;
|
|
switch (key) {
|
|
case PW_KEY_RIGHT : ret="right" ; break;
|
|
case PW_KEY_LEFT : ret="left" ; break;
|
|
case PW_KEY_UP : ret="up" ; break;
|
|
case PW_KEY_DOWN : ret="down" ; break;
|
|
case PW_KEY_F1 : ret="F1" ; break;
|
|
case PW_KEY_F2 : ret="F2" ; break;
|
|
case PW_KEY_F3 : ret="F3" ; break;
|
|
case PW_KEY_F4 : ret="F4" ; break;
|
|
case PW_KEY_F5 : ret="F5" ; break;
|
|
case PW_KEY_F6 : ret="F6" ; break;
|
|
case PW_KEY_F7 : ret="F7" ; break;
|
|
case PW_KEY_F8 : ret="F8" ; break;
|
|
case PW_KEY_F9 : ret="F9" ; break;
|
|
case PW_KEY_F10 : ret="F10" ; break;
|
|
case PW_KEY_F11 : ret="F11" ; break;
|
|
case PW_KEY_F12 : ret="F12" ; break;
|
|
case PW_KEY_PAGE_UP : ret="pg up" ; break;
|
|
case PW_KEY_PAGE_DOWN : ret="pg down"; break;
|
|
case PW_KEY_HOME : ret="home" ; break;
|
|
case PW_KEY_END : ret="end" ; break;
|
|
case PW_KEY_INSERT : ret="insert" ; break;
|
|
case 13 : ret="enter" ; break;
|
|
case 32 : ret="space" ; break;
|
|
default: ret=" ";
|
|
ret[0]=key;
|
|
}
|
|
if (useJoystick) {
|
|
char joyInfo[60];
|
|
if (control == KC_LEFT) sprintf(joyInfo, " or stick left");
|
|
else if (control == KC_RIGHT) sprintf(joyInfo, " or stick right");
|
|
else if (control == KC_ACCEL) sprintf(joyInfo, " or stick up");
|
|
else
|
|
{
|
|
const int TARGET_BUTTON = config->player[player_index].getButton(control);
|
|
int button_number = 0;
|
|
while((1 << button_number != TARGET_BUTTON) && (button_number < 16))
|
|
++button_number;
|
|
|
|
if(button_number < 16)
|
|
sprintf(joyInfo, " or joybutton %d", button_number + 1 );
|
|
else
|
|
sprintf(joyInfo, " or unassigned" );
|
|
|
|
}
|
|
ret += joyInfo;
|
|
}
|
|
return ret;
|
|
} // GetKeyAsString
|
|
|
|
/*EOF*/
|