Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 3280 for code/trunk/src/core


Ignore:
Timestamp:
Jul 12, 2009, 11:58:01 PM (16 years ago)
Author:
rgrieder
Message:

Merged most of the core4 revisions back to the trunk except for:

  • orxonox_cast
  • all the radical changes in the input library
Location:
code/trunk
Files:
38 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/core/ArgumentCompletionFunctions.cc

    r3196 r3280  
    3434
    3535#include "util/Convert.h"
    36 #include "util/String.h"
     36#include "util/StringUtils.h"
    3737#include "Identifier.h"
    3838#include "ConfigValueContainer.h"
     
    143143
    144144            for (std::list<unsigned int>::const_iterator it = threadnumbers.begin(); it != threadnumbers.end(); ++it)
    145                 threads.push_back(ArgumentCompletionListElement(getConvertedValue<unsigned int, std::string>(*it)));
     145                threads.push_back(ArgumentCompletionListElement(multi_cast<std::string>(*it)));
    146146
    147147            return threads;
  • code/trunk/src/core/BaseObject.cc

    r3196 r3280  
    3636#include <tinyxml/tinyxml.h>
    3737
    38 #include "util/String.h"
     38#include "util/StringUtils.h"
    3939#include "CoreIncludes.h"
    4040#include "Event.h"
  • code/trunk/src/core/CMakeLists.txt

    r3196 r3280  
    6868  TOLUA_FILES
    6969    CommandExecutor.h
    70     Game.h
    7170    LuaBind.h
    7271  DEFINE_SYMBOL
  • code/trunk/src/core/CommandEvaluation.cc

    r3196 r3280  
    3030
    3131#include "util/Debug.h"
    32 #include "util/String.h"
     32#include "util/StringUtils.h"
    3333#include "ConsoleCommand.h"
    3434#include "Identifier.h"
     
    3939    {
    4040        this->initialize("");
    41         this->state_ = CS_Uninitialized;
     41        this->state_ = CommandState::Uninitialized;
    4242    }
    4343
     
    6464
    6565        this->errorMessage_ = "";
    66         this->state_ = CS_Empty;
     66        this->state_ = CommandState::Empty;
    6767    }
    6868
     
    104104            switch (this->state_)
    105105            {
    106                 case CS_Uninitialized:
    107                     break;
    108                 case CS_Empty:
    109                     break;
    110                 case CS_ShortcutOrIdentifier:
     106                case CommandState::Uninitialized:
     107                    break;
     108                case CommandState::Empty:
     109                    break;
     110                case CommandState::ShortcutOrIdentifier:
    111111                    if (this->function_)
    112112                    {
     
    119119                        return (this->command_ = this->functionclass_->getName() + " ");
    120120                    break;
    121                 case CS_Function:
     121                case CommandState::Function:
    122122                    if (this->function_)
    123123                    {
     
    128128                    }
    129129                    break;
    130                 case CS_ParamPreparation:
    131                 case CS_Params:
     130                case CommandState::ParamPreparation:
     131                case CommandState::Params:
    132132                {
    133133                    if (this->argument_ == "" && this->possibleArgument_ == "")
     
    149149                    break;
    150150                }
    151                 case CS_Finished:
    152                     break;
    153                 case CS_Error:
     151                case CommandState::Finished:
     152                    break;
     153                case CommandState::Error:
    154154                    break;
    155155            }
     
    163163        switch (this->state_)
    164164        {
    165             case CS_Uninitialized:
    166                 break;
    167             case CS_Empty:
    168             case CS_ShortcutOrIdentifier:
     165            case CommandState::Uninitialized:
     166                break;
     167            case CommandState::Empty:
     168            case CommandState::ShortcutOrIdentifier:
    169169                if (this->listOfPossibleFunctions_.size() == 0)
    170170                    return CommandEvaluation::dump(this->listOfPossibleIdentifiers_);
     
    174174                    return (CommandEvaluation::dump(this->listOfPossibleFunctions_) + "\n" + CommandEvaluation::dump(this->listOfPossibleIdentifiers_));
    175175                break;
    176             case CS_Function:
     176            case CommandState::Function:
    177177                return CommandEvaluation::dump(this->listOfPossibleFunctions_);
    178178                break;
    179             case CS_ParamPreparation:
    180             case CS_Params:
     179            case CommandState::ParamPreparation:
     180            case CommandState::Params:
    181181                if (this->listOfPossibleArguments_.size() > 0)
    182182                    return CommandEvaluation::dump(this->listOfPossibleArguments_);
    183183                else
    184184                    return CommandEvaluation::dump(this->function_);
    185             case CS_Finished:
     185            case CommandState::Finished:
    186186                if (this->function_)
    187187                    return CommandEvaluation::dump(this->function_);
    188188                break;
    189             case CS_Error:
     189            case CommandState::Error:
    190190                return this->errorMessage_;
    191191                break;
     
    200200
    201201        for (unsigned int i = 0; i < MAX_FUNCTOR_ARGUMENTS; i++)
    202             this->param_[i] = MT_null;
     202            this->param_[i] = MT_Type::Null;
    203203
    204204        if (!this->isValid())
     
    230230            return this->param_[index];
    231231
    232         return MT_null;
     232        return MT_Type::Null;
    233233    }
    234234
     
    238238            return this->function_->hasReturnvalue();
    239239
    240         return MT_null;
     240        return MT_Type::Null;
    241241    }
    242242
  • code/trunk/src/core/CommandEvaluation.h

    r1747 r3280  
    4141namespace orxonox
    4242{
    43     enum CommandState
     43    namespace CommandState
    4444    {
    45         CS_Uninitialized,
    46         CS_Empty,
    47         CS_ShortcutOrIdentifier,
    48         CS_Function,
    49         CS_ParamPreparation,
    50         CS_Params,
    51         CS_Finished,
    52         CS_Error
    53     };
     45        enum Value
     46        {
     47            Uninitialized,
     48            Empty,
     49            ShortcutOrIdentifier,
     50            Function,
     51            ParamPreparation,
     52            Params,
     53            Finished,
     54            Error
     55        };
     56    }
    5457
    5558    class _CoreExport CommandEvaluation
     
    112115
    113116            std::string errorMessage_;
    114             CommandState state_;
     117            CommandState::Value state_;
    115118
    116119            bool bEvaluatedParams_;
  • code/trunk/src/core/CommandExecutor.cc

    r3196 r3280  
    3030
    3131#include "util/Debug.h"
    32 #include "util/String.h"
     32#include "util/StringUtils.h"
    3333#include "ConsoleCommand.h"
    3434#include "Identifier.h"
     
    141141    void CommandExecutor::parseIfNeeded(const std::string& command)
    142142    {
    143         if (CommandExecutor::getEvaluation().state_ == CS_Uninitialized)
     143        if (CommandExecutor::getEvaluation().state_ == CommandState::Uninitialized)
    144144        {
    145145            CommandExecutor::parse(command);
     
    169169        switch (CommandExecutor::getEvaluation().state_)
    170170        {
    171             case CS_Uninitialized:
     171            case CommandState::Uninitialized:
    172172            {
    173173                // Impossible
    174174                break;
    175175            }
    176             case CS_Empty:
     176            case CommandState::Empty:
    177177            {
    178178                if (CommandExecutor::argumentsGiven() == 0)
     
    184184                else
    185185                {
    186                     CommandExecutor::getEvaluation().state_ = CS_ShortcutOrIdentifier;
     186                    CommandExecutor::getEvaluation().state_ = CommandState::ShortcutOrIdentifier;
    187187                    // Move on to next case
    188188                }
    189189            }
    190             case CS_ShortcutOrIdentifier:
     190            case CommandState::ShortcutOrIdentifier:
    191191            {
    192192                if (CommandExecutor::argumentsGiven() > 1)
     
    199199                    {
    200200                        // It's a shortcut
    201                         CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
     201                        CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
    202202                        CommandExecutor::getEvaluation().functionclass_ = 0;
    203203                        // Move on to next case
     
    206206                    {
    207207                        // It's a functionname
    208                         CommandExecutor::getEvaluation().state_ = CS_Function;
     208                        CommandExecutor::getEvaluation().state_ = CommandState::Function;
    209209                        CommandExecutor::getEvaluation().function_ = 0;
    210210                        // Move on to next case
     
    213213                    {
    214214                        // The first argument is bad
    215                         CommandExecutor::getEvaluation().state_ = CS_Error;
     215                        CommandExecutor::getEvaluation().state_ = CommandState::Error;
    216216                        AddLanguageEntry("commandexecutorunknownfirstargument", "is not a shortcut nor a classname");
    217217                        CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(0) + " " + GetLocalisation("commandexecutorunknownfirstargument") + ".";
     
    238238                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
    239239                        }
    240                         CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
     240                        CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
    241241                        CommandExecutor::getEvaluation().functionclass_ = 0;
    242242                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().function_->getName();
     
    258258                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
    259259                        }
    260                         CommandExecutor::getEvaluation().state_ = CS_Function;
     260                        CommandExecutor::getEvaluation().state_ = CommandState::Function;
    261261                        CommandExecutor::getEvaluation().function_ = 0;
    262262                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " ";
     
    266266                    {
    267267                        // No possibilities
    268                         CommandExecutor::getEvaluation().state_ = CS_Error;
     268                        CommandExecutor::getEvaluation().state_ = CommandState::Error;
    269269                        AddLanguageEntry("commandexecutorunknownfirstargumentstart", "There is no command or classname starting with");
    270270                        CommandExecutor::getEvaluation().errorMessage_ = "Error: " + GetLocalisation("commandexecutorunknownfirstargumentstart") + " " + CommandExecutor::getArgument(0) + ".";
     
    285285                }
    286286            }
    287             case CS_Function:
     287            case CommandState::Function:
    288288            {
    289289                if (CommandExecutor::getEvaluation().functionclass_)
     
    298298                        {
    299299                            // It's a function
    300                             CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
     300                            CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
    301301                            // Move on to next case
    302302                        }
     
    304304                        {
    305305                            // The second argument is bad
    306                             CommandExecutor::getEvaluation().state_ = CS_Error;
     306                            CommandExecutor::getEvaluation().state_ = CommandState::Error;
    307307                            AddLanguageEntry("commandexecutorunknownsecondargument", "is not a function of");
    308308                            CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(1) + " " + GetLocalisation("commandexecutorunknownsecondargument") + " " + CommandExecutor::getEvaluation().functionclass_->getName() + ".";
     
    326326                                CommandExecutor::getEvaluation().bCommandChanged_ = true;
    327327                            }
    328                             CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
     328                            CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
    329329                            CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " " + CommandExecutor::getEvaluation().function_->getName();
    330330                            if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
     
    338338                        {
    339339                            // No possibilities
    340                             CommandExecutor::getEvaluation().state_ = CS_Error;
     340                            CommandExecutor::getEvaluation().state_ = CommandState::Error;
    341341                            AddLanguageEntry("commandexecutorunknownsecondargumentstart", "has no function starting with");
    342342                            CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getEvaluation().functionclass_->getName() + " " + GetLocalisation("commandexecutorunknownsecondargumentstart") + " " + CommandExecutor::getArgument(1) + ".";
     
    355355                else
    356356                {
    357                     // There is no classname - move on to CS_ParamPreparation
    358                 }
    359             }
    360             case CS_ParamPreparation:
     357                    // There is no classname - move on to CommandState::ParamPreparation
     358                }
     359            }
     360            case CommandState::ParamPreparation:
    361361            {
    362362                if (CommandExecutor::getEvaluation().function_->getParamCount() == 0 || CommandExecutor::enoughArgumentsGiven(CommandExecutor::getEvaluation().function_))
    363363                {
    364                     CommandExecutor::getEvaluation().state_ = CS_Finished;
     364                    CommandExecutor::getEvaluation().state_ = CommandState::Finished;
    365365                    return;
    366366                }
     
    372372
    373373                    CommandExecutor::createListOfPossibleArguments(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
    374                     CommandExecutor::getEvaluation().state_ = CS_Params;
     374                    CommandExecutor::getEvaluation().state_ = CommandState::Params;
    375375
    376376                    if (CommandExecutor::getEvaluation().bCommandChanged_)
     
    381381                }
    382382            }
    383             case CS_Params:
     383            case CommandState::Params:
    384384            {
    385385                if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 1)
     
    388388                    CommandExecutor::getEvaluation().argument_ = (*CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()).getString();
    389389                    CommandExecutor::getEvaluation().possibleArgument_ = (*CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()).getString();
    390                     CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
     390                    CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
    391391                    return;
    392392                }
     
    394394                {
    395395                    // The user tries something new - we let him do
    396                     CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
     396                    CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
    397397                    CommandExecutor::getEvaluation().argument_ = CommandExecutor::getLastArgument();
    398398                    return;
     
    409409                    CommandExecutor::getEvaluation().argument_ = CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleArguments_);
    410410                    CommandExecutor::getEvaluation().possibleArgument_ = CommandExecutor::getPossibleArgument(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
    411                     CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
     411                    CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
    412412                    return;
    413413                }
    414414            }
    415             case CS_Finished:
     415            case CommandState::Finished:
    416416            {
    417417                // Nothing more to do
    418418                break;
    419419            }
    420             case CS_Error:
     420            case CommandState::Error:
    421421            {
    422422                // Bad, very bad
  • code/trunk/src/core/CommandLine.cc

    r3196 r3280  
    2929#include "CommandLine.h"
    3030
     31#include <algorithm>
     32#include <sstream>
    3133#include <boost/filesystem.hpp>
    3234
     
    3436#include "util/Debug.h"
    3537#include "util/Exception.h"
    36 #include "util/String.h"
     38#include "util/StringUtils.h"
    3739#include "util/SubString.h"
    3840#include "Core.h"
     
    4042namespace orxonox
    4143{
    42     SetCommandLineArgument(optionsFile, "start.ini").shortcut("o");
     44    SetCommandLineOnlyArgument(optionsFile, "start.ini").shortcut("o");
    4345
    4446    /**
     
    4951        so that you can have simple command line switches.
    5052    */
    51     void CommandLineArgument::parse(const std::string& value)
    52     {
    53         if (value_.getType() == MT_bool)
     53    void CommandLineArgument::parse(const std::string& value, bool bParsingFile)
     54    {
     55        if (bParsingFile && this->bCommandLineOnly_)
     56            ThrowException(Argument, "Command line argument '" + getName() + "' is not allowed in files.");
     57        if (value_.getType() == MT_Type::Bool)
    5458        {
    5559            // simulate command line switch
     
    6670            }
    6771            else
    68             {
    6972                ThrowException(Argument, "Could not read command line argument '" + getName() + "'.");
    70             }
    7173        }
    7274        else
     
    126128        Vector of space separated strings.
    127129    */
    128     void CommandLine::_parse(const std::vector<std::string>& arguments)
    129     {
    130         // why this? See bFirstTimeParse_ declaration.
    131         if (bFirstTimeParse_)
    132         {
    133             // first shove all the shortcuts in a map
    134             for (std::map<std::string, CommandLineArgument*>::const_iterator it = cmdLineArgs_.begin();
    135                 it != cmdLineArgs_.end(); ++it)
    136             {
    137                 OrxAssert(cmdLineArgsShortcut_.find(it->second->getShortcut()) == cmdLineArgsShortcut_.end(),
    138                     "Cannot have two command line shortcut with the same name.");
    139                 if (it->second->getShortcut() != "")
    140                     cmdLineArgsShortcut_[it->second->getShortcut()] = it->second;
    141             }
    142             bFirstTimeParse_ = false;
    143         }
    144 
    145         std::string name;
    146         std::string shortcut;
    147         std::string value;
    148         for (unsigned int i = 0; i < arguments.size(); ++i)
    149         {
    150             if (arguments[i].size() != 0)
    151             {
    152                 // sure not ""
    153                 if (arguments[i][0] == '-')
     130    void CommandLine::_parse(const std::vector<std::string>& arguments, bool bParsingFile)
     131    {
     132        try
     133        {
     134            // why this? See bFirstTimeParse_ declaration.
     135            if (bFirstTimeParse_)
     136            {
     137                // first shove all the shortcuts in a map
     138                for (std::map<std::string, CommandLineArgument*>::const_iterator it = cmdLineArgs_.begin();
     139                    it != cmdLineArgs_.end(); ++it)
    154140                {
    155                     // start with "-"
    156                     if (arguments[i].size() == 1)
     141                    OrxAssert(cmdLineArgsShortcut_.find(it->second->getShortcut()) == cmdLineArgsShortcut_.end(),
     142                        "Cannot have two command line shortcut with the same name.");
     143                    if (it->second->getShortcut() != "")
     144                        cmdLineArgsShortcut_[it->second->getShortcut()] = it->second;
     145                }
     146                bFirstTimeParse_ = false;
     147            }
     148
     149            std::string name;
     150            std::string shortcut;
     151            std::string value;
     152            for (unsigned int i = 0; i < arguments.size(); ++i)
     153            {
     154                if (arguments[i].size() != 0)
     155                {
     156                    // sure not ""
     157                    if (arguments[i][0] == '-')
    157158                    {
    158                         // argument[i] is "-", probably a minus sign
    159                         value += "- ";
    160                     }
    161                     else if (arguments[i][1] <= 57 && arguments[i][1] >= 48)
    162                     {
    163                         // negative number as a value
    164                         value += arguments[i] + " ";
     159                        // start with "-"
     160                        if (arguments[i].size() == 1)
     161                        {
     162                            // argument[i] is "-", probably a minus sign
     163                            value += "- ";
     164                        }
     165                        else if (arguments[i][1] <= 57 && arguments[i][1] >= 48)
     166                        {
     167                            // negative number as a value
     168                            value += arguments[i] + " ";
     169                        }
     170                        else
     171                        {
     172                            // can be shortcut or full name argument
     173
     174                            // save old data first
     175                            value = removeTrailingWhitespaces(value);
     176                            if (name != "")
     177                            {
     178                                checkFullArgument(name, value, bParsingFile);
     179                                name = "";
     180                                assert(shortcut == "");
     181                            }
     182                            else if (shortcut != "")
     183                            {
     184                                checkShortcut(shortcut, value, bParsingFile);
     185                                shortcut = "";
     186                                assert(name == "");
     187                            }
     188
     189                            if (arguments[i][1] == '-')
     190                            {
     191                                // full name argument with "--name"
     192                                name = arguments[i].substr(2);
     193                            }
     194                            else
     195                            {
     196                                // shortcut with "-s"
     197                                shortcut = arguments[i].substr(1);
     198                            }
     199
     200                            // reset value string
     201                            value = "";
     202                        }
    165203                    }
    166204                    else
    167205                    {
    168                         // can be shortcut or full name argument
    169 
    170                         // save old data first
    171                         value = removeTrailingWhitespaces(value);
    172                         if (name != "")
     206                        // value string
     207
     208                        if (name == "" && shortcut == "")
    173209                        {
    174                             checkFullArgument(name, value);
    175                             name = "";
    176                             assert(shortcut == "");
     210                            ThrowException(Argument, "Expected \"-\" or \"-\" in command line arguments.\n");
    177211                        }
    178                         else if (shortcut != "")
    179                         {
    180                             checkShortcut(shortcut, value);
    181                             shortcut = "";
    182                             assert(name == "");
    183                         }
    184 
    185                         if (arguments[i][1] == '-')
    186                         {
    187                             // full name argument with "--name"
    188                             name = arguments[i].substr(2);
    189                         }
    190                         else
    191                         {
    192                             // shortcut with "-s"
    193                             shortcut = arguments[i].substr(1);
    194                         }
    195 
    196                         // reset value string
    197                         value = "";
     212
     213                        // Concatenate strings as long as there's no new argument by "-" or "--"
     214                        value += arguments[i] + ' ';
    198215                    }
    199216                }
    200                 else
    201                 {
    202                     // value string
    203 
    204                     if (name == "" && shortcut == "")
    205                     {
    206                         ThrowException(Argument, "Expected \"-\" or \"-\" in command line arguments.\n");
    207                     }
    208 
    209                     // Concatenate strings as long as there's no new argument by "-" or "--"
    210                     value += arguments[i] + ' ';
    211                 }
    212             }
    213         }
    214 
    215         // parse last argument
    216         value = removeTrailingWhitespaces(value);
    217         if (name != "")
    218         {
    219             checkFullArgument(name, value);
    220             assert(shortcut == "");
    221         }
    222         else if (shortcut != "")
    223         {
    224             checkShortcut(shortcut, value);
    225             assert(name == "");
     217            }
     218
     219            // parse last argument
     220            value = removeTrailingWhitespaces(value);
     221            if (name != "")
     222            {
     223                checkFullArgument(name, value, bParsingFile);
     224                assert(shortcut == "");
     225            }
     226            else if (shortcut != "")
     227            {
     228                checkShortcut(shortcut, value, bParsingFile);
     229                assert(name == "");
     230            }
     231        }
     232        catch (const ArgumentException& ex)
     233        {
     234            COUT(0) << "Could not parse command line (including additional files): " << ex.what() << std::endl;
     235            COUT(0) << CommandLine::getUsageInformation() << std::endl;
     236            throw GeneralException("");
    226237        }
    227238    }
     
    235246        String containing the value
    236247    */
    237     void CommandLine::checkFullArgument(const std::string& name, const std::string& value)
     248    void CommandLine::checkFullArgument(const std::string& name, const std::string& value, bool bParsingFile)
    238249    {
    239250        std::map<std::string, CommandLineArgument*>::const_iterator it = cmdLineArgs_.find(name);
     
    241252            ThrowException(Argument, "Command line argument '" + name + "' does not exist.");
    242253
    243         it->second->parse(value);
     254        it->second->parse(value, bParsingFile);
    244255    }
    245256
     
    252263        String containing the value
    253264    */
    254     void CommandLine::checkShortcut(const std::string& shortcut, const std::string& value)
     265    void CommandLine::checkShortcut(const std::string& shortcut, const std::string& value, bool bParsingFile)
    255266    {
    256267        std::map<std::string, CommandLineArgument*>::const_iterator it = cmdLineArgsShortcut_.find(shortcut);
     
    258269            ThrowException(Argument, "Command line shortcut '" + shortcut + "' does not exist.");
    259270
    260         it->second->parse(value);
     271        it->second->parse(value, bParsingFile);
    261272    }
    262273
    263274    std::string CommandLine::getUsageInformation()
    264275    {
    265         CommandLine* inst = &_getInstance();
    266         std::string infoStr;
    267         for (std::map<std::string, CommandLineArgument*>::const_iterator it = inst->cmdLineArgs_.begin();
    268             it != inst->cmdLineArgs_.end(); ++it)
    269         {
    270             infoStr += "[--" + it->second->getName() + " " + it->second->getInformation() + "] ";
    271         }
    272         return infoStr;
     276        CommandLine& inst = _getInstance();
     277        std::ostringstream infoStr;
     278
     279        // determine maximum name size
     280        size_t maxNameSize = 0;
     281        for (std::map<std::string, CommandLineArgument*>::const_iterator it = inst.cmdLineArgs_.begin();
     282            it != inst.cmdLineArgs_.end(); ++it)
     283        {
     284            maxNameSize = std::max(it->second->getName().size(), maxNameSize);
     285        }
     286
     287        infoStr << "Usage: orxonox [options]" << std::endl;
     288        infoStr << "Available options:" << std::endl;
     289
     290        for (std::map<std::string, CommandLineArgument*>::const_iterator it = inst.cmdLineArgs_.begin();
     291            it != inst.cmdLineArgs_.end(); ++it)
     292        {
     293            if (it->second->getShortcut() != "")
     294                infoStr << " [-" << it->second->getShortcut() << "] ";
     295            else
     296                infoStr << "      ";
     297            infoStr << "--" << it->second->getName() << " ";
     298            if (it->second->getValue().getType() != MT_Type::Bool)
     299                infoStr << "ARG ";
     300            else
     301                infoStr << "    ";
     302            // fill with the necessary amount of blanks
     303            infoStr << std::string(maxNameSize - it->second->getName().size(), ' ');
     304            infoStr << ": " << it->second->getInformation();
     305            infoStr << std::endl;
     306        }
     307        return infoStr.str();
    273308    }
    274309
     
    295330    /**
    296331    @brief
    297         Parses both command line and start.ini for CommandLineArguments.
    298     */
    299     void CommandLine::_parseAll(int argc, char** argv)
    300     {
    301         // parse command line first
     332        Parses only the command line for CommandLineArguments.
     333    */
     334    void CommandLine::_parseCommandLine(int argc, char** argv)
     335    {
    302336        std::vector<std::string> args;
    303337        for (int i = 1; i < argc; ++i)
    304338            args.push_back(argv[i]);
    305         this->_parse(args);
    306 
     339        this->_parse(args, false);
     340    }
     341
     342    /**
     343    @brief
     344        Parses start.ini (or the file specified with --optionsFile) for CommandLineArguments.
     345    */
     346    void CommandLine::_parseFile()
     347    {
    307348        std::string filename = CommandLine::getValue("optionsFile").getString();
    308349        boost::filesystem::path filepath(Core::getConfigPath() / filename);
     
    312353        std::ifstream file;
    313354        file.open(filepath.string().c_str());
    314         args.clear();
     355        std::vector<std::string> args;
    315356        if (file)
    316357        {
     
    332373        }
    333374
    334         try
    335         {
    336             _parse(args);
    337         }
    338         catch (orxonox::ArgumentException& ex)
    339         {
    340             COUT(1) << "An Exception occured while parsing " << filename << std::endl;
    341             throw(ex);
    342         }
     375        _parse(args, true);
    343376    }
    344377}
  • code/trunk/src/core/CommandLine.h

    r3196 r3280  
    3838#define SetCommandLineArgument(name, defaultValue) \
    3939    orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \
    40     = orxonox::CommandLine::addArgument(#name, defaultValue)
     40    = orxonox::CommandLine::addArgument(#name, defaultValue, false)
     41#define SetCommandLineOnlyArgument(name, defaultValue) \
     42    orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \
     43    = orxonox::CommandLine::addArgument(#name, defaultValue, true)
    4144#define SetCommandLineSwitch(name) \
    4245    orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \
    43     = orxonox::CommandLine::addArgument(#name, false)
     46    = orxonox::CommandLine::addArgument(#name, false, false)
     47#define SetCommandLineOnlySwitch(name) \
     48    orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \
     49    = orxonox::CommandLine::addArgument(#name, false, true)
    4450
    4551
     
    7480
    7581        //! Returns the shortcut (example: "-p 22" for "--port 22") of the argument.
    76         //! Evaluates to "" if none there is none.
     82        //! Evaluates to "" if there is none.
    7783        const std::string& getShortcut() const { return shortcut_; }
    7884        //! Sets the shortcut for the argument
     
    9399    private:
    94100        //! Constructor initialises both value_ and defaultValue_ with defaultValue.
    95         CommandLineArgument(const std::string& name, const MultiType& defaultValue)
     101        CommandLineArgument(const std::string& name, const MultiType& defaultValue, bool bCommandLineOnly)
    96102            : bHasDefaultValue_(true)
    97103            , name_(name)
    98104            , value_(defaultValue)
    99105            , defaultValue_(defaultValue)
     106            , bCommandLineOnly_(bCommandLineOnly)
    100107        { }
    101108
     
    105112
    106113        //! Parses the value string of a command line argument.
    107         void parse(const std::string& value);
     114        void parse(const std::string& value, bool bParsingFile);
    108115
    109116        //! Tells whether the value has been changed by the command line.
     
    115122        std::string usageInformation_; //!< Tells about the usage of this parameter
    116123
    117         MultiType value_;            //!< The actual value
    118         MultiType defaultValue_;     //!< Default value. Should not be changed.
     124        MultiType   value_;            //!< The actual value
     125        MultiType   defaultValue_;     //!< Default value. Should not be changed.
     126        bool        bCommandLineOnly_; //!< Whether you cannot specify the value in a text file
    119127    };
    120128
     
    134142
    135143        //! Parse redirection to internal member method.
    136         static void parseAll(int argc, char** argv) { _getInstance()._parseAll(argc, argv); }
     144        static void parseCommandLine(int argc, char** argv) { _getInstance()._parseCommandLine(argc, argv); }
     145        static void parseFile() { _getInstance()._parseFile(); }
    137146
    138147        static std::string getUsageInformation();
     
    146155        { return getArgument(name)->getValue(); }
    147156        template <class T>
    148         static CommandLineArgument& addArgument(const std::string& name, T defaultValue);
     157        static CommandLineArgument& addArgument(const std::string& name, T defaultValue, bool bCommandLineOnly);
    149158
    150159        static bool existsArgument(const std::string& name)
     
    165174        static CommandLine& _getInstance();
    166175
    167         void _parseAll(int argc, char** argv);
    168         void _parse(const std::vector<std::string>& arguments);
    169         void checkFullArgument(const std::string& name, const std::string& value);
    170         void checkShortcut(const std::string& shortcut, const std::string& value);
     176        void _parseCommandLine(int argc, char** argv);
     177        void _parseFile();
     178        void _parse(const std::vector<std::string>& arguments, bool bParsingFile);
     179        void checkFullArgument(const std::string& name, const std::string& value, bool bParsingFile);
     180        void checkShortcut(const std::string& shortcut, const std::string& value, bool bParsingFile);
    171181
    172182        /**
     
    199209    */
    200210    template <class T>
    201     CommandLineArgument& CommandLine::addArgument(const std::string& name, T defaultValue)
     211    CommandLineArgument& CommandLine::addArgument(const std::string& name, T defaultValue, bool bCommandLineOnly)
    202212    {
    203213        OrxAssert(!_getInstance().existsArgument(name),
    204214            "Cannot add a command line argument with name '" + name + "' twice.");
    205 
    206         return *(_getInstance().cmdLineArgs_[name] = new CommandLineArgument(name, defaultValue));
     215        OrxAssert(MultiType(defaultValue).getType() != MT_Type::Bool || MultiType(defaultValue).getBool() != true,
     216               "Boolean command line arguments with positive default values are not supported." << std::endl
     217            << "Please use SetCommandLineSwitch and adjust your argument: " << name);
     218
     219        return *(_getInstance().cmdLineArgs_[name] = new CommandLineArgument(name, defaultValue, bCommandLineOnly));
    207220    }
    208221}
  • code/trunk/src/core/ConfigFileManager.cc

    r3198 r3280  
    3333#include "util/Convert.h"
    3434#include "util/Math.h"
    35 #include "util/String.h"
     35#include "util/StringUtils.h"
    3636#include "ConsoleCommand.h"
    3737#include "ConfigValueContainer.h"
     
    124124    {
    125125        if (this->additionalComment_ == "" || this->additionalComment_.size() == 0)
    126             return (this->name_ + "[" + getConvertedValue<unsigned int, std::string>(this->index_, "0") + "]" + "=" + this->value_);
    127         else
    128             return (this->name_ + "[" + getConvertedValue<unsigned int, std::string>(this->index_, "0") + "]=" + this->value_ + " " + this->additionalComment_);
     126            return (this->name_ + "[" + multi_cast<std::string>(this->index_) + "]" + "=" + this->value_);
     127        else
     128            return (this->name_ + "[" + multi_cast<std::string>(this->index_) + "]=" + this->value_ + " " + this->additionalComment_);
    129129    }
    130130
  • code/trunk/src/core/ConfigValueContainer.cc

    r3196 r3280  
    7878        for (unsigned int i = 0; i < this->valueVector_.size(); i++)
    7979        {
    80             ConfigFileManager::getInstance().getValue(this->type_, this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isType(MT_string));
     80            ConfigFileManager::getInstance().getValue(this->type_, this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isType(MT_Type::String));
    8181            this->defvalueStringVector_.push_back(this->valueVector_[i]);
    8282        }
     
    109109            if (this->tset(input))
    110110            {
    111                 ConfigFileManager::getInstance().setValue(this->type_, this->sectionname_, this->varname_, input, this->value_.isType(MT_string));
     111                ConfigFileManager::getInstance().setValue(this->type_, this->sectionname_, this->varname_, input, this->value_.isType(MT_Type::String));
    112112                return true;
    113113            }
     
    128128            if (this->tset(index, input))
    129129            {
    130                 ConfigFileManager::getInstance().setValue(this->type_, this->sectionname_, this->varname_, index, input, this->value_.isType(MT_string));
     130                ConfigFileManager::getInstance().setValue(this->type_, this->sectionname_, this->varname_, index, input, this->value_.isType(MT_Type::String));
    131131                return true;
    132132            }
     
    228228                this->valueVector_.erase(this->valueVector_.begin() + index);
    229229                for (unsigned int i = index; i < this->valueVector_.size(); i++)
    230                     ConfigFileManager::getInstance().setValue(this->type_, this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isType(MT_string));
     230                    ConfigFileManager::getInstance().setValue(this->type_, this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isType(MT_Type::String));
    231231                ConfigFileManager::getInstance().deleteVectorEntries(this->type_, this->sectionname_, this->varname_, this->valueVector_.size());
    232232
     
    264264    {
    265265        if (!this->bIsVector_)
    266             this->value_ = ConfigFileManager::getInstance().getValue(this->type_, this->sectionname_, this->varname_, this->defvalueString_, this->value_.isType(MT_string));
     266            this->value_ = ConfigFileManager::getInstance().getValue(this->type_, this->sectionname_, this->varname_, this->defvalueString_, this->value_.isType(MT_Type::String));
    267267        else
    268268        {
     
    273273                if (i < this->defvalueStringVector_.size())
    274274                {
    275                     this->value_ = ConfigFileManager::getInstance().getValue(this->type_, this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isType(MT_string));
     275                    this->value_ = ConfigFileManager::getInstance().getValue(this->type_, this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isType(MT_Type::String));
    276276                }
    277277                else
    278278                {
    279                     this->value_ = ConfigFileManager::getInstance().getValue(this->type_, this->sectionname_, this->varname_, i, MultiType(), this->value_.isType(MT_string));
     279                    this->value_ = ConfigFileManager::getInstance().getValue(this->type_, this->sectionname_, this->varname_, i, MultiType(), this->value_.isType(MT_Type::String));
    280280                }
    281281
  • code/trunk/src/core/ConfigValueIncludes.h

    r2171 r3280  
    5252    if (!container##varname) \
    5353    { \
    54         container##varname = new orxonox::ConfigValueContainer(ConfigFileType::Settings, identifier##varname, identifier##varname->getName(), #varname, defvalue, varname); \
     54        container##varname = new orxonox::ConfigValueContainer(type, identifier##varname, identifier##varname->getName(), #varname, defvalue, varname); \
    5555        identifier##varname->addConfigValueContainer(#varname, container##varname); \
    5656    } \
     
    7070    if (!container##varname) \
    7171    { \
    72         container##varname = new orxonox::ConfigValueContainer(ConfigFileType::Settings, identifier##varname, identifier##varname->getName(), #varname, defvalue); \
     72        container##varname = new orxonox::ConfigValueContainer(type, identifier##varname, identifier##varname->getName(), #varname, defvalue); \
    7373        identifier##varname->addConfigValueContainer(#varname, container##varname); \
    7474    } \
  • code/trunk/src/core/ConsoleCommand.h

    r3196 r3280  
    7171    namespace AccessLevel
    7272    {
    73         enum Level
     73        enum Value
    7474        {
    7575            None,
     
    106106                { this->Executor::setDefaultValue(index, param); return (*this); }
    107107
    108             inline ConsoleCommand& accessLevel(AccessLevel::Level level)
     108            inline ConsoleCommand& accessLevel(AccessLevel::Value level)
    109109                { this->accessLevel_ = level; return (*this); }
    110             inline AccessLevel::Level getAccessLevel() const
     110            inline AccessLevel::Value getAccessLevel() const
    111111                { return this->accessLevel_; }
    112112
     
    130130            }
    131131
    132             inline ConsoleCommand& keybindMode(KeybindMode::Enum mode)
     132            inline ConsoleCommand& keybindMode(KeybindMode::Value mode)
    133133                { this->keybindMode_ = mode; return *this; }
    134             inline KeybindMode::Enum getKeybindMode() const
     134            inline KeybindMode::Value getKeybindMode() const
    135135                { return this->keybindMode_; }
    136136
     
    141141
    142142        private:
    143             AccessLevel::Level accessLevel_;
     143            AccessLevel::Value accessLevel_;
    144144            ArgumentCompleter* argumentCompleter_[5];
    145145            ArgumentCompletionList argumentList_;
    146146
    147             KeybindMode::Enum keybindMode_;
     147            KeybindMode::Value keybindMode_;
    148148            int inputConfiguredParam_;
    149149    };
  • code/trunk/src/core/Core.cc

    r3214 r3280  
    7777namespace orxonox
    7878{
    79     //! Path to the parent directory of the ones above if program was installed with relativ pahts
    80     static boost::filesystem::path rootPath_g;
    81     static boost::filesystem::path executablePath_g;            //!< Path to the executable
    82     static boost::filesystem::path mediaPath_g;                 //!< Path to the media file folder
    83     static boost::filesystem::path configPath_g;                //!< Path to the config file folder
    84     static boost::filesystem::path logPath_g;                   //!< Path to the log file folder
    85 
    8679    //! Static pointer to the singleton
    8780    Core* Core::singletonRef_s  = 0;
    8881
    89     SetCommandLineArgument(mediaPath, "").information("PATH");
    90     SetCommandLineArgument(writingPathSuffix, "").information("DIR");
    91     SetCommandLineArgument(settingsFile, "orxonox.ini");
    92     SetCommandLineArgument(limitToCPU, 0).information("0: off | #cpu");
    93 
    94     Core::Core()
    95     {
    96         RegisterRootObject(Core);
    97 
    98         assert(Core::singletonRef_s == 0);
     82    SetCommandLineArgument(mediaPath, "").information("Path to the media/data files");
     83    SetCommandLineOnlyArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");
     84    SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file");
     85#ifdef ORXONOX_PLATFORM_WINDOWS
     86    SetCommandLineArgument(limitToCPU, 0).information("Limits the program to one cpu/core (1, 2, 3, etc.). 0 turns it off (default)");
     87#endif
     88
     89    /**
     90    @brief
     91        Helper class for the Core singleton: we cannot derive
     92        Core from OrxonoxClass because we need to handle the Identifier
     93        destruction in the Core destructor.
     94    */
     95    class CoreConfiguration : public OrxonoxClass
     96    {
     97    public:
     98        CoreConfiguration()
     99        {
     100        }
     101
     102        void initialise()
     103        {
     104            RegisterRootObject(CoreConfiguration);
     105            this->setConfigValues();
     106
     107            // Possible media path override by the command line
     108            if (!CommandLine::getArgument("mediaPath")->hasDefaultValue())
     109                tsetMediaPath(CommandLine::getValue("mediaPath"));
     110        }
     111
     112        /**
     113            @brief Function to collect the SetConfigValue-macro calls.
     114        */
     115        void setConfigValues()
     116        {
     117#ifdef NDEBUG
     118            const unsigned int defaultLevelConsole = 1;
     119            const unsigned int defaultLevelLogfile = 3;
     120            const unsigned int defaultLevelShell   = 1;
     121#else
     122            const unsigned int defaultLevelConsole = 3;
     123            const unsigned int defaultLevelLogfile = 4;
     124            const unsigned int defaultLevelShell   = 3;
     125#endif
     126            SetConfigValue(softDebugLevelConsole_, defaultLevelConsole)
     127                .description("The maximal level of debug output shown in the console")
     128                .callback(this, &CoreConfiguration::debugLevelChanged);
     129            SetConfigValue(softDebugLevelLogfile_, defaultLevelLogfile)
     130                .description("The maximal level of debug output shown in the logfile")
     131                .callback(this, &CoreConfiguration::debugLevelChanged);
     132            SetConfigValue(softDebugLevelShell_, defaultLevelShell)
     133                .description("The maximal level of debug output shown in the ingame shell")
     134                .callback(this, &CoreConfiguration::debugLevelChanged);
     135
     136            SetConfigValue(language_, Language::getLanguage().defaultLanguage_)
     137                .description("The language of the ingame text")
     138                .callback(this, &CoreConfiguration::languageChanged);
     139            SetConfigValue(bInitializeRandomNumberGenerator_, true)
     140                .description("If true, all random actions are different each time you start the game")
     141                .callback(this, &CoreConfiguration::initializeRandomNumberGenerator);
     142
     143            SetConfigValue(mediaPathString_, mediaPath_.string())
     144                .description("Relative path to the game data.")
     145                .callback(this, &CoreConfiguration::mediaPathChanged);
     146        }
     147
     148        /**
     149            @brief Callback function if the debug level has changed.
     150        */
     151        void debugLevelChanged()
     152        {
     153            // softDebugLevel_ is the maximum of the 3 variables
     154            this->softDebugLevel_ = this->softDebugLevelConsole_;
     155            if (this->softDebugLevelLogfile_ > this->softDebugLevel_)
     156                this->softDebugLevel_ = this->softDebugLevelLogfile_;
     157            if (this->softDebugLevelShell_ > this->softDebugLevel_)
     158                this->softDebugLevel_ = this->softDebugLevelShell_;
     159
     160            OutputHandler::setSoftDebugLevel(OutputHandler::LD_All,     this->softDebugLevel_);
     161            OutputHandler::setSoftDebugLevel(OutputHandler::LD_Console, this->softDebugLevelConsole_);
     162            OutputHandler::setSoftDebugLevel(OutputHandler::LD_Logfile, this->softDebugLevelLogfile_);
     163            OutputHandler::setSoftDebugLevel(OutputHandler::LD_Shell,   this->softDebugLevelShell_);
     164        }
     165
     166        /**
     167            @brief Callback function if the language has changed.
     168        */
     169        void languageChanged()
     170        {
     171            // Read the translation file after the language was configured
     172            Language::getLanguage().readTranslatedLanguageFile();
     173        }
     174
     175        /**
     176        @brief
     177            Callback function if the media path has changed.
     178        */
     179        void mediaPathChanged()
     180        {
     181            mediaPath_ = boost::filesystem::path(this->mediaPathString_);
     182        }
     183
     184        /**
     185            @brief Sets the language in the config-file back to the default.
     186        */
     187        void resetLanguage()
     188        {
     189            ResetConfigValue(language_);
     190        }
     191
     192        /**
     193        @brief
     194            Temporary sets the media path
     195        @param path
     196            The new media path
     197        */
     198        void tsetMediaPath(const std::string& path)
     199        {
     200            ModifyConfigValue(mediaPathString_, tset, path);
     201        }
     202
     203        void initializeRandomNumberGenerator()
     204        {
     205            static bool bInitialized = false;
     206            if (!bInitialized && this->bInitializeRandomNumberGenerator_)
     207            {
     208                srand(static_cast<unsigned int>(time(0)));
     209                rand();
     210                bInitialized = true;
     211            }
     212        }
     213
     214        int softDebugLevel_;                            //!< The debug level
     215        int softDebugLevelConsole_;                     //!< The debug level for the console
     216        int softDebugLevelLogfile_;                     //!< The debug level for the logfile
     217        int softDebugLevelShell_;                       //!< The debug level for the ingame shell
     218        std::string language_;                          //!< The language
     219        bool bInitializeRandomNumberGenerator_;         //!< If true, srand(time(0)) is called
     220        std::string mediaPathString_;                   //!< Path to the data/media file folder as string
     221
     222        //! Path to the parent directory of the ones above if program was installed with relativ pahts
     223        boost::filesystem::path rootPath_;
     224        boost::filesystem::path executablePath_;        //!< Path to the executable
     225        boost::filesystem::path mediaPath_;             //!< Path to the media file folder
     226        boost::filesystem::path configPath_;            //!< Path to the config file folder
     227        boost::filesystem::path logPath_;               //!< Path to the log file folder
     228    };
     229
     230
     231    Core::Core(int argc, char** argv)
     232    {
     233        if (singletonRef_s != 0)
     234        {
     235            COUT(0) << "Error: The Core singleton cannot be recreated! Shutting down." << std::endl;
     236            abort();
     237        }
    99238        Core::singletonRef_s = this;
    100     }
    101 
    102     void Core::initialise(int argc, char** argv)
    103     {
    104         // Parse command line arguments fist
    105         try
    106         {
    107             CommandLine::parseAll(argc, argv);
    108         }
    109         catch (ArgumentException& ex)
    110         {
    111             COUT(1) << ex.what() << std::endl;
    112             COUT(0) << "Usage:" << std::endl << "orxonox " << CommandLine::getUsageInformation() << std::endl;
    113         }
    114 
     239
     240        // We need the variables very soon. But don't configure them yet!
     241        this->configuration_ = new CoreConfiguration();
     242
     243        // Parse command line arguments first
     244        CommandLine::parseCommandLine(argc, argv);
     245
     246        // Determine and set the location of the executable
     247        setExecutablePath();
     248
     249        // Determine whether we have an installed or a binary dir run
     250        // The latter occurs when simply running from the build directory
     251        checkDevBuild();
     252
     253        // Make sure the directories we write in exist or else make them
     254        createDirectories();
     255
     256        // create a signal handler (only active for linux)
     257        // This call is placed as soon as possible, but after the directories are set
     258        this->signalHandler_ = new SignalHandler();
     259        this->signalHandler_->doCatch(configuration_->executablePath_.string(), Core::getLogPathString() + "orxonox_crash.log");
     260
     261        // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used
     262        OutputHandler::getOutStream().setLogPath(Core::getLogPathString());
     263
     264        // Parse additional options file now that we know its path
     265        CommandLine::parseFile();
     266
     267#ifdef ORXONOX_PLATFORM_WINDOWS
    115268        // limit the main thread to the first core so that QueryPerformanceCounter doesn't jump
    116269        // do this after ogre has initialised. Somehow Ogre changes the settings again (not through
     
    118271        int limitToCPU = CommandLine::getValue("limitToCPU");
    119272        if (limitToCPU > 0)
    120             setThreadAffinity((unsigned int)limitToCPU);
    121 
    122         // Determine and set the location of the executable
    123         setExecutablePath();
    124 
    125         // Determine whether we have an installed or a binary dir run
    126         // The latter occurs when simply running from the build directory
    127         checkDevBuild();
    128 
    129         // Make sure the directories we write in exist or else make them
    130         createDirectories();
    131 
    132         // create a signal handler (only active for linux)
    133         // This call is placed as soon as possible, but after the directories are set
    134         this->signalHandler_ = new SignalHandler();
    135         this->signalHandler_->doCatch(executablePath_g.string(), Core::getLogPathString() + "orxonox_crash.log");
    136 
    137         // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used
    138         OutputHandler::getOutStream().setLogPath(Core::getLogPathString());
     273            setThreadAffinity(static_cast<unsigned int>(limitToCPU));
     274#endif
    139275
    140276        // Manage ini files and set the default settings file (usually orxonox.ini)
     
    143279            CommandLine::getValue("settingsFile").getString());
    144280
     281        // Required as well for the config values
    145282        this->languageInstance_ = new Language();
    146283
    147284        // Do this soon after the ConfigFileManager has been created to open up the
    148285        // possibility to configure everything below here
    149         this->setConfigValues();
    150 
    151         // Possible media path override by the command line
    152         if (!CommandLine::getArgument("mediaPath")->hasDefaultValue())
    153         {
    154             //std::string mediaPath = CommandLine::getValue("mediaPath");
    155             Core::tsetMediaPath(CommandLine::getValue("mediaPath"));
    156         }
     286        this->configuration_->initialise();
    157287
    158288        // Create the lua interface
     
    168298        // creates the class hierarchy for all classes with factories
    169299        Factory::createClassHierarchy();
    170        
    171         this->loaded_ = true;
    172300    }
    173301
     
    177305    Core::~Core()
    178306    {
    179         this->loaded_ = false;
    180 
    181307        delete this->shell_;
    182308        delete this->tclThreadManager_;
    183309        delete this->tclBind_;
    184310        delete this->luaBind_;
     311        delete this->configuration_;
    185312        delete this->languageInstance_;
    186313        delete this->configFileManager_;
     
    190317        // Also delete external console command that don't belong to an Identifier
    191318        CommandExecutor::destroyExternalCommands();
    192 
    193         assert(Core::singletonRef_s);
    194         Core::singletonRef_s = 0;
     319        // Clean up class hierarchy stuff (identifiers, XMLPort, configValues, consoleCommand)
     320        Identifier::destroyAllIdentifiers();
     321
    195322        delete this->signalHandler_;
    196     }
    197 
    198     /**
    199         @brief Function to collect the SetConfigValue-macro calls.
    200     */
    201     void Core::setConfigValues()
    202     {
    203 #ifdef NDEBUG
    204         const unsigned int defaultLevelConsole = 1;
    205         const unsigned int defaultLevelLogfile = 3;
    206         const unsigned int defaultLevelShell   = 1;
    207 #else
    208         const unsigned int defaultLevelConsole = 3;
    209         const unsigned int defaultLevelLogfile = 4;
    210         const unsigned int defaultLevelShell   = 3;
    211 #endif
    212         SetConfigValue(softDebugLevelConsole_, defaultLevelConsole)
    213             .description("The maximal level of debug output shown in the console").callback(this, &Core::debugLevelChanged);
    214         SetConfigValue(softDebugLevelLogfile_, defaultLevelLogfile)
    215             .description("The maximal level of debug output shown in the logfile").callback(this, &Core::debugLevelChanged);
    216         SetConfigValue(softDebugLevelShell_, defaultLevelShell)
    217             .description("The maximal level of debug output shown in the ingame shell").callback(this, &Core::debugLevelChanged);
    218 
    219         SetConfigValue(language_, Language::getLanguage().defaultLanguage_).description("The language of the ingame text").callback(this, &Core::languageChanged);
    220         SetConfigValue(bInitializeRandomNumberGenerator_, true).description("If true, all random actions are different each time you start the game").callback(this, &Core::initializeRandomNumberGenerator);
    221 
    222         SetConfigValue(mediaPathString_, mediaPath_g.string())
    223             .description("Relative path to the game data.").callback(this, &Core::mediaPathChanged);
    224     }
    225 
    226     /**
    227         @brief Callback function if the debug level has changed.
    228     */
    229     void Core::debugLevelChanged()
    230     {
    231         // softDebugLevel_ is the maximum of the 3 variables
    232         this->softDebugLevel_ = this->softDebugLevelConsole_;
    233         if (this->softDebugLevelLogfile_ > this->softDebugLevel_)
    234             this->softDebugLevel_ = this->softDebugLevelLogfile_;
    235         if (this->softDebugLevelShell_ > this->softDebugLevel_)
    236             this->softDebugLevel_ = this->softDebugLevelShell_;
    237 
    238         OutputHandler::setSoftDebugLevel(OutputHandler::LD_All,     this->softDebugLevel_);
    239         OutputHandler::setSoftDebugLevel(OutputHandler::LD_Console, this->softDebugLevelConsole_);
    240         OutputHandler::setSoftDebugLevel(OutputHandler::LD_Logfile, this->softDebugLevelLogfile_);
    241         OutputHandler::setSoftDebugLevel(OutputHandler::LD_Shell,   this->softDebugLevelShell_);
    242     }
    243 
    244     /**
    245         @brief Callback function if the language has changed.
    246     */
    247     void Core::languageChanged()
    248     {
    249         // Read the translation file after the language was configured
    250         Language::getLanguage().readTranslatedLanguageFile();
    251     }
    252 
    253     /**
    254     @brief
    255         Callback function if the media path has changed.
    256     */
    257     void Core::mediaPathChanged()
    258     {
    259         mediaPath_g = boost::filesystem::path(this->mediaPathString_);
    260     }
    261 
    262     /**
    263         @brief Returns the softDebugLevel for the given device (returns a default-value if the class ist right about to be created).
     323
     324        // Don't assign singletonRef_s with NULL! Recreation is not supported
     325    }
     326
     327    /**
     328        @brief Returns the softDebugLevel for the given device (returns a default-value if the class is right about to be created).
    264329        @param device The device
    265330        @return The softDebugLevel
    266331    */
    267     int Core::getSoftDebugLevel(OutputHandler::OutputDevice device)
     332    /*static*/ int Core::getSoftDebugLevel(OutputHandler::OutputDevice device)
    268333    {
    269334        switch (device)
    270335        {
    271336        case OutputHandler::LD_All:
    272             return Core::getInstance().softDebugLevel_;
     337            return Core::getInstance().configuration_->softDebugLevel_;
    273338        case OutputHandler::LD_Console:
    274             return Core::getInstance().softDebugLevelConsole_;
     339            return Core::getInstance().configuration_->softDebugLevelConsole_;
    275340        case OutputHandler::LD_Logfile:
    276             return Core::getInstance().softDebugLevelLogfile_;
     341            return Core::getInstance().configuration_->softDebugLevelLogfile_;
    277342        case OutputHandler::LD_Shell:
    278             return Core::getInstance().softDebugLevelShell_;
     343            return Core::getInstance().configuration_->softDebugLevelShell_;
    279344        default:
    280345            assert(0);
     
    288353        @param level The level
    289354    */
    290     void Core::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
    291      {
     355    /*static*/ void Core::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
     356    {
    292357        if (device == OutputHandler::LD_All)
    293             Core::getInstance().softDebugLevel_ = level;
     358            Core::getInstance().configuration_->softDebugLevel_ = level;
    294359        else if (device == OutputHandler::LD_Console)
    295             Core::getInstance().softDebugLevelConsole_ = level;
     360            Core::getInstance().configuration_->softDebugLevelConsole_ = level;
    296361        else if (device == OutputHandler::LD_Logfile)
    297             Core::getInstance().softDebugLevelLogfile_ = level;
     362            Core::getInstance().configuration_->softDebugLevelLogfile_ = level;
    298363        else if (device == OutputHandler::LD_Shell)
    299             Core::getInstance().softDebugLevelShell_ = level;
     364            Core::getInstance().configuration_->softDebugLevelShell_ = level;
    300365
    301366        OutputHandler::setSoftDebugLevel(device, level);
    302      }
     367    }
    303368
    304369    /**
    305370        @brief Returns the configured language.
    306371    */
    307     const std::string& Core::getLanguage()
    308     {
    309         return Core::getInstance().language_;
     372    /*static*/ const std::string& Core::getLanguage()
     373    {
     374        return Core::getInstance().configuration_->language_;
    310375    }
    311376
     
    313378        @brief Sets the language in the config-file back to the default.
    314379    */
    315     void Core::resetLanguage()
    316     {
    317         Core::getInstance().resetLanguageIntern();
    318     }
    319 
    320     /**
    321         @brief Sets the language in the config-file back to the default.
    322     */
    323     void Core::resetLanguageIntern()
    324     {
    325         ResetConfigValue(language_);
    326     }
    327 
    328     /**
    329     @brief
    330         Temporary sets the media path
    331     @param path
    332         The new media path
    333     */
    334     void Core::_tsetMediaPath(const std::string& path)
    335     {
    336         ModifyConfigValue(mediaPathString_, tset, path);
     380    /*static*/ void Core::resetLanguage()
     381    {
     382        Core::getInstance().configuration_->resetLanguage();
     383    }
     384
     385    /*static*/ void Core::tsetMediaPath(const std::string& path)
     386    {
     387        getInstance().configuration_->tsetMediaPath(path);
    337388    }
    338389
    339390    /*static*/ const boost::filesystem::path& Core::getMediaPath()
    340391    {
    341         return mediaPath_g;
     392        return getInstance().configuration_->mediaPath_;
    342393    }
    343394    /*static*/ std::string Core::getMediaPathString()
    344395    {
    345         return mediaPath_g.string() + '/';
     396        return getInstance().configuration_->mediaPath_.string() + '/';
    346397    }
    347398
    348399    /*static*/ const boost::filesystem::path& Core::getConfigPath()
    349400    {
    350         return configPath_g;
     401        return getInstance().configuration_->configPath_;
    351402    }
    352403    /*static*/ std::string Core::getConfigPathString()
    353404    {
    354         return configPath_g.string() + '/';
     405        return getInstance().configuration_->configPath_.string() + '/';
    355406    }
    356407
    357408    /*static*/ const boost::filesystem::path& Core::getLogPath()
    358409    {
    359         return logPath_g;
     410        return getInstance().configuration_->logPath_;
    360411    }
    361412    /*static*/ std::string Core::getLogPathString()
    362413    {
    363         return logPath_g.string() + '/';
    364     }
    365 
    366     void Core::initializeRandomNumberGenerator()
    367     {
    368         static bool bInitialized = false;
    369         if (!bInitialized && this->bInitializeRandomNumberGenerator_)
    370         {
    371             srand(static_cast<unsigned int>(time(0)));
    372             rand();
    373             bInitialized = true;
    374         }
    375     }
    376 
     414        return getInstance().configuration_->logPath_.string() + '/';
     415    }
    377416
    378417    /**
     
    388427    void Core::setThreadAffinity(int limitToCPU)
    389428    {
     429#ifdef ORXONOX_PLATFORM_WINDOWS
     430
    390431        if (limitToCPU <= 0)
    391432            return;
    392433
    393 #ifdef ORXONOX_PLATFORM_WINDOWS
    394434        unsigned int coreNr = limitToCPU - 1;
    395435        // Get the current process core mask
     
    465505#endif
    466506
    467         executablePath_g = boost::filesystem::path(buffer);
     507        configuration_->executablePath_ = boost::filesystem::path(buffer);
    468508#ifndef ORXONOX_PLATFORM_APPLE
    469         executablePath_g = executablePath_g.branch_path(); // remove executable name
     509        configuration_->executablePath_ = configuration_->executablePath_.branch_path(); // remove executable name
    470510#endif
    471511    }
     
    481521    void Core::checkDevBuild()
    482522    {
    483         if (boost::filesystem::exists(executablePath_g / "orxonox_dev_build.keep_me"))
     523        if (boost::filesystem::exists(configuration_->executablePath_ / "orxonox_dev_build.keep_me"))
    484524        {
    485525            COUT(1) << "Running from the build tree." << std::endl;
    486526            Core::isDevBuild_ = true;
    487             mediaPath_g  = ORXONOX_MEDIA_DEV_PATH;
    488             configPath_g = ORXONOX_CONFIG_DEV_PATH;
    489             logPath_g    = ORXONOX_LOG_DEV_PATH;
     527            configuration_->mediaPath_  = ORXONOX_MEDIA_DEV_PATH;
     528            configuration_->configPath_ = ORXONOX_CONFIG_DEV_PATH;
     529            configuration_->logPath_    = ORXONOX_LOG_DEV_PATH;
    490530        }
    491531        else
     
    494534            // Also set the root path
    495535            boost::filesystem::path relativeExecutablePath(ORXONOX_RUNTIME_INSTALL_PATH);
    496             rootPath_g = executablePath_g;
    497             while (!boost::filesystem::equivalent(rootPath_g / relativeExecutablePath, executablePath_g) && !rootPath_g.empty())
    498                 rootPath_g = rootPath_g.branch_path();
    499             if (rootPath_g.empty())
     536            configuration_->rootPath_ = configuration_->executablePath_;
     537            while (!boost::filesystem::equivalent(configuration_->rootPath_ / relativeExecutablePath, configuration_->executablePath_)
     538                   && !configuration_->rootPath_.empty())
     539                configuration_->rootPath_ = configuration_->rootPath_.branch_path();
     540            if (configuration_->rootPath_.empty())
    500541                ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
    501542
    502543            // Using paths relative to the install prefix, complete them
    503             mediaPath_g  = rootPath_g / ORXONOX_MEDIA_INSTALL_PATH;
    504             configPath_g = rootPath_g / ORXONOX_CONFIG_INSTALL_PATH;
    505             logPath_g    = rootPath_g / ORXONOX_LOG_INSTALL_PATH;
     544            configuration_->mediaPath_  = configuration_->rootPath_ / ORXONOX_MEDIA_INSTALL_PATH;
     545            configuration_->configPath_ = configuration_->rootPath_ / ORXONOX_CONFIG_INSTALL_PATH;
     546            configuration_->logPath_    = configuration_->rootPath_ / ORXONOX_LOG_INSTALL_PATH;
    506547#else
    507548            // There is no root path, so don't set it at all
    508549
    509             mediaPath_g  = ORXONOX_MEDIA_INSTALL_PATH;
     550            configuration_->mediaPath_  = ORXONOX_MEDIA_INSTALL_PATH;
    510551
    511552            // Get user directory
     
    520561            userDataPath /= ".orxonox";
    521562
    522             configPath_g = userDataPath / ORXONOX_CONFIG_INSTALL_PATH;
    523             logPath_g    = userDataPath / ORXONOX_LOG_INSTALL_PATH;
     563            configuration_->configPath_ = userDataPath / ORXONOX_CONFIG_INSTALL_PATH;
     564            configuration_->logPath_    = userDataPath / ORXONOX_LOG_INSTALL_PATH;
    524565#endif
    525566        }
     
    529570        {
    530571            std::string directory(CommandLine::getValue("writingPathSuffix").getString());
    531             configPath_g = configPath_g / directory;
    532             logPath_g    = logPath_g    / directory;
     572            configuration_->configPath_ = configuration_->configPath_ / directory;
     573            configuration_->logPath_    = configuration_->logPath_    / directory;
    533574        }
    534575    }
     
    544585    {
    545586        std::vector<std::pair<boost::filesystem::path, std::string> > directories;
    546         directories.push_back(std::make_pair(boost::filesystem::path(configPath_g), "config"));
    547         directories.push_back(std::make_pair(boost::filesystem::path(logPath_g), "log"));
     587        directories.push_back(std::make_pair(boost::filesystem::path(configuration_->configPath_), "config"));
     588        directories.push_back(std::make_pair(boost::filesystem::path(configuration_->logPath_), "log"));
    548589
    549590        for (std::vector<std::pair<boost::filesystem::path, std::string> >::iterator it = directories.begin();
  • code/trunk/src/core/Core.h

    r3196 r3280  
    4343
    4444#include <cassert>
    45 #include "OrxonoxClass.h"
    4645#include "util/OutputHandler.h"
    4746
    4847namespace orxonox
    4948{
     49    class CoreConfiguration;
     50
    5051    /**
    5152    @brief
     
    5556        It determines those by the use of platform specific functions.
    5657    */
    57     class _CoreExport Core : public OrxonoxClass
     58    class _CoreExport Core
    5859    {
    5960        public:
     
    6566                GeneralException
    6667            */
    67             Core();
     68            Core(int argc, char** argv);
    6869            ~Core();
    6970
    70             void initialise(int argc, char** argv);
    7171            void setConfigValues();
    7272
     
    8080            static void  resetLanguage();
    8181
    82             static void tsetMediaPath(const std::string& path)
    83             { assert(singletonRef_s); singletonRef_s->_tsetMediaPath(path); }
     82            static void tsetMediaPath(const std::string& path);
    8483            //! Returns the path to the config files as boost::filesystem::path
    8584            static const boost::filesystem::path& getMediaPath();
     
    103102            void setThreadAffinity(int limitToCPU);
    104103
    105             void resetLanguageIntern();
    106             void initializeRandomNumberGenerator();
    107             void debugLevelChanged();
    108             void languageChanged();
    109             void mediaPathChanged();
    110             void _tsetMediaPath(const std::string& path);
    111 
    112104            // Singletons
    113105            ConfigFileManager*    configFileManager_;
     
    119111            TclThreadManager*     tclThreadManager_;
    120112
    121             int softDebugLevel_;                            //!< The debug level
    122             int softDebugLevelConsole_;                     //!< The debug level for the console
    123             int softDebugLevelLogfile_;                     //!< The debug level for the logfile
    124             int softDebugLevelShell_;                       //!< The debug level for the ingame shell
    125             std::string language_;                          //!< The language
    126             bool bInitializeRandomNumberGenerator_;         //!< If true, srand(time(0)) is called
    127             std::string mediaPathString_;                   //!< Path to the data/media file folder as string
    128113            bool isDevBuild_;                               //!< True for builds in the build directory (not installed)
    129             bool loaded_;                                   //!< Only true if constructor was interrupted
     114            CoreConfiguration*    configuration_;
    130115
    131116            static Core* singletonRef_s;
  • code/trunk/src/core/CorePrereqs.h

    r3196 r3280  
    7474    namespace KeybindMode
    7575    {
    76         enum Enum
     76        enum Value
    7777        {
    7878            OnPress,
     
    165165    // game states
    166166    class Game;
     167    struct GameStateConstrParams;
    167168    class GameState;
    168169    struct GameStateTreeNode;
  • code/trunk/src/core/Executor.cc

    r3196 r3280  
    9999
    100100            // assign all given arguments to the multitypes
    101             for (unsigned int i = 0; i < min(tokens.size(), (unsigned int)MAX_FUNCTOR_ARGUMENTS); i++)
     101            for (unsigned int i = 0; i < std::min(tokens.size(), (unsigned int)MAX_FUNCTOR_ARGUMENTS); i++)
    102102                param[i] = tokens[i];
    103103
    104104            // fill the remaining multitypes with default values
    105             for (unsigned int i = tokens.size(); i < min(paramCount, (unsigned int)MAX_FUNCTOR_ARGUMENTS); i++)
     105            for (unsigned int i = tokens.size(); i < std::min(paramCount, (unsigned int)MAX_FUNCTOR_ARGUMENTS); i++)
    106106                param[i] = this->defaultValue_[i];
    107107
    108108            // evaluate the param types through the functor
    109             for (unsigned int i = 0; i < min(paramCount, (unsigned int)MAX_FUNCTOR_ARGUMENTS); i++)
     109            for (unsigned int i = 0; i < std::min(paramCount, (unsigned int)MAX_FUNCTOR_ARGUMENTS); i++)
    110110                this->functor_->evaluateParam(i, param[i]);
    111111
  • code/trunk/src/core/Executor.h

    r3196 r3280  
    3333#include "CorePrereqs.h"
    3434
     35#include <algorithm>
     36#include <string>
     37
    3538#include "util/Debug.h"
    3639#include "util/Math.h"
    37 #include "util/String.h"
     40#include "util/StringUtils.h"
    3841#include "util/SubString.h"
    3942#include "Functor.h"
     
    101104            COUT(5) << tokens[i]; \
    102105        } \
    103         COUT(5) << ") and " << max((int)paramCount - (int)tokens.size(), 0) << " default values ("; \
     106        COUT(5) << ") and " << std::max((int)paramCount - (int)tokens.size(), 0) << " default values ("; \
    104107        for (unsigned int i = tokens.size(); i < paramCount; i++) \
    105108        { \
     
    175178            inline bool hasReturnvalue() const
    176179                { return this->functor_->hasReturnvalue(); }
    177             inline FunctionType getType() const
     180            inline FunctionType::Value getType() const
    178181                { return this->functor_->getType(); }
    179182            inline const MultiType& getReturnvalue() const
     
    201204                    return this->defaultValue_[index];
    202205
    203                 return MT_null;
     206                return MT_Type::Null;
    204207            }
    205208
  • code/trunk/src/core/Functor.h

    r3196 r3280  
    3535#include "util/Debug.h"
    3636#include "util/MultiType.h"
    37 #include "util/String.h"
     37#include "util/StringUtils.h"
    3838
    3939namespace orxonox
     
    4141    const unsigned int MAX_FUNCTOR_ARGUMENTS = 5;
    4242
    43     enum FunctionType
     43    namespace FunctionType
    4444    {
    45         FT_MEMBER,
    46         FT_CONSTMEMBER,
    47         FT_STATIC
    48     };
     45        enum Value
     46        {
     47            Member,
     48            ConstMember,
     49            Static
     50        };
     51    }
    4952
    5053
     
    98101            virtual ~Functor() {}
    99102
    100             virtual void operator()(const MultiType& param1 = MT_null, const MultiType& param2 = MT_null, const MultiType& param3 = MT_null, const MultiType& param4 = MT_null, const MultiType& param5 = MT_null) = 0;
     103            virtual void operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0;
    101104
    102105            inline unsigned int getParamCount() const { return this->numParams_; }
    103106            inline bool hasReturnvalue() const { return this->hasReturnValue_; }
    104             inline FunctionType getType() const { return this->type_; }
     107            inline FunctionType::Value getType() const { return this->type_; }
    105108            inline const MultiType& getReturnvalue() const { return this->returnedValue_; }
    106109
     
    113116            unsigned int numParams_;
    114117            bool hasReturnValue_;
    115             FunctionType type_;
     118            FunctionType::Value type_;
    116119            MultiType returnedValue_;
    117120
     
    124127        public:
    125128            virtual ~FunctorStatic() {}
    126             virtual void operator()(const MultiType& param1 = MT_null, const MultiType& param2 = MT_null, const MultiType& param3 = MT_null, const MultiType& param4 = MT_null, const MultiType& param5 = MT_null) = 0;
     129            virtual void operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0;
    127130    };
    128131
     
    139142            virtual ~FunctorMember() {}
    140143
    141             virtual void operator()(T* object, const MultiType& param1 = MT_null, const MultiType& param2 = MT_null, const MultiType& param3 = MT_null, const MultiType& param4 = MT_null, const MultiType& param5 = MT_null) = 0;
    142             virtual void operator()(const T* object, const MultiType& param1 = MT_null, const MultiType& param2 = MT_null, const MultiType& param3 = MT_null, const MultiType& param4 = MT_null, const MultiType& param5 = MT_null) = 0;
    143 
    144             virtual void operator()(const MultiType& param1 = MT_null, const MultiType& param2 = MT_null, const MultiType& param3 = MT_null, const MultiType& param4 = MT_null, const MultiType& param5 = MT_null)
     144            virtual void operator()(T* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0;
     145            virtual void operator()(const T* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0;
     146
     147            virtual void operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null)
    145148            {
    146149                if (this->bConstObject_)
     
    322325                this->numParams_ = numparams; \
    323326                this->hasReturnValue_ = returnvalue; \
    324                 this->type_ = FT_STATIC; \
     327                this->type_ = FunctionType::Static; \
    325328                this->functionPointer_ = functionPointer; \
    326329                \
     
    329332            } \
    330333    \
    331             void operator()(const MultiType& param1 = MT_null, const MultiType& param2 = MT_null, const MultiType& param3 = MT_null, const MultiType& param4 = MT_null, const MultiType& param5 = MT_null) \
     334            void operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) \
    332335            { \
    333336                FUNCTOR_STORE_RETURNVALUE(returnvalue, (*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
     
    363366                this->numParams_ = numparams; \
    364367                this->hasReturnValue_ = returnvalue; \
    365                 this->type_ = FT_MEMBER; \
     368                this->type_ = FunctionType::Member; \
    366369                this->functionPointer_ = functionPointer; \
    367370            } \
    368371    \
    369             void operator()(T* object, const MultiType& param1 = MT_null, const MultiType& param2 = MT_null, const MultiType& param3 = MT_null, const MultiType& param4 = MT_null, const MultiType& param5 = MT_null) \
     372            void operator()(T* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) \
    370373            { \
    371374                FUNCTOR_STORE_RETURNVALUE(returnvalue, (*object.*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
    372375            } \
    373376    \
    374             void operator()(const T* object, const MultiType& param1 = MT_null, const MultiType& param2 = MT_null, const MultiType& param3 = MT_null, const MultiType& param4 = MT_null, const MultiType& param5 = MT_null) \
     377            void operator()(const T* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) \
    375378            { \
    376379                COUT(1) << "An error occurred in Functor.h:" << std::endl; \
     
    396399                this->numParams_ = numparams; \
    397400                this->hasReturnValue_ = returnvalue; \
    398                 this->type_ = FT_CONSTMEMBER; \
     401                this->type_ = FunctionType::ConstMember; \
    399402                this->functionPointer_ = functionPointer; \
    400403            } \
    401404    \
    402             void operator()(T* object, const MultiType& param1 = MT_null, const MultiType& param2 = MT_null, const MultiType& param3 = MT_null, const MultiType& param4 = MT_null, const MultiType& param5 = MT_null) \
     405            void operator()(T* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) \
    403406            { \
    404407                FUNCTOR_STORE_RETURNVALUE(returnvalue, (*object.*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
    405408            } \
    406409    \
    407             void operator()(const T* object, const MultiType& param1 = MT_null, const MultiType& param2 = MT_null, const MultiType& param3 = MT_null, const MultiType& param4 = MT_null, const MultiType& param5 = MT_null) \
     410            void operator()(const T* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) \
    408411            { \
    409412                FUNCTOR_STORE_RETURNVALUE(returnvalue, (*object.*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
  • code/trunk/src/core/Game.cc

    r3196 r3280  
    5858    SetConsoleCommandShortcutExternAlias(stop_game, "exit");
    5959
    60     struct _CoreExport GameStateTreeNode
     60    std::map<std::string, Game::GameStateInfo> Game::gameStateDeclarations_s;
     61    Game* Game::singletonRef_s = 0;
     62
     63
     64    /**
     65    @brief
     66        Represents one node of the game state tree.
     67    */
     68    struct GameStateTreeNode
    6169    {
    6270        GameState* state_;
     
    6573    };
    6674
    67     std::map<std::string, GameState*> Game::allStates_s;
    68     Game* Game::singletonRef_s = 0;
     75
     76    /**
     77    @brief
     78        Another helper class for the Game singleton: we cannot derive
     79        Game from OrxonoxClass because we need to handle the Identifier
     80        destruction in the Core destructor.
     81    */
     82    class GameConfiguration : public OrxonoxClass
     83    {
     84    public:
     85        GameConfiguration()
     86        {
     87            RegisterRootObject(GameConfiguration);
     88            this->setConfigValues();
     89        }
     90
     91        void setConfigValues()
     92        {
     93            SetConfigValue(statisticsRefreshCycle_, 250000)
     94                .description("Sets the time in microseconds interval at which average fps, etc. get updated.");
     95            SetConfigValue(statisticsAvgLength_, 1000000)
     96                .description("Sets the time in microseconds interval at which average fps, etc. gets calculated.");
     97        }
     98
     99        unsigned int statisticsRefreshCycle_;
     100        unsigned int statisticsAvgLength_;
     101    };
     102
    69103
    70104    /**
     
    74108    Game::Game(int argc, char** argv)
    75109    {
    76         assert(singletonRef_s == 0);
     110        if (singletonRef_s != 0)
     111        {
     112            COUT(0) << "Error: The Game singleton cannot be recreated! Shutting down." << std::endl;
     113            abort();
     114        }
    77115        singletonRef_s = this;
    78116
    79         this->abort_ = false;
     117        this->bAbort_ = false;
     118        bChangingState_ = false;
     119
     120        // Create an empty root state
     121        declareGameState<GameState>("GameState", "emptyRootGameState", true, false);
    80122
    81123        // reset statistics
     
    87129        this->avgTickTime_ = 0.0f;
    88130
    89 
    90131        // Set up a basic clock to keep time
    91132        this->gameClock_ = new Clock();
    92133
    93         this->core_ = new orxonox::Core();
    94         this->core_->initialise(argc, argv);
    95 
    96         RegisterRootObject(Game);
    97         this->setConfigValues();
     134        // Create the Core
     135        this->core_ = new Core(argc, argv);
     136
     137        // After the core has been created, we can safely instantiate the GameStates
     138        for (std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.begin();
     139            it != gameStateDeclarations_s.end(); ++it)
     140        {
     141            // Only create the states appropriate for the game mode
     142            //if (GameMode::showsGraphics || !it->second.bGraphicsMode)
     143            GameStateConstrParams params = { it->second.stateName, it->second.bIgnoreTickTime };
     144            gameStates_[getLowercase(it->second.stateName)] = GameStateFactory::fabricate(it->second.className, params);
     145        }
     146
     147        // The empty root state is ALWAYS loaded!
     148        this->rootStateNode_ = shared_ptr<GameStateTreeNode>(new GameStateTreeNode());
     149        this->rootStateNode_->state_ = getState("emptyRootGameState");
     150        this->activeStateNode_ = this->rootStateNode_;
     151        this->activeStates_.push_back(this->rootStateNode_->state_);
     152
     153        // Do this after the Core creation!
     154        this->configuration_ = new GameConfiguration();
    98155    }
    99156
     
    103160    Game::~Game()
    104161    {
    105         // Destroy pretty much everyhting left
     162        // Destroy the configuration helper class instance
     163        delete this->configuration_;
     164
     165        // Destroy the GameStates (note that the nodes still point to them, but doesn't matter)
     166        for (std::map<std::string, GameState*>::const_iterator it = gameStates_.begin();
     167            it != gameStates_.end(); ++it)
     168            delete it->second;
     169
     170        // Destroy the Core and with it almost everything
    106171        delete this->core_;
    107 
    108172        delete this->gameClock_;
    109173
    110         assert(singletonRef_s);
    111         singletonRef_s = 0;
    112     }
    113 
    114     void Game::setConfigValues()
    115     {
    116         SetConfigValue(statisticsRefreshCycle_, 250000)
    117             .description("Sets the time in microseconds interval at which average fps, etc. get updated.");
    118         SetConfigValue(statisticsAvgLength_, 1000000)
    119             .description("Sets the time in microseconds interval at which average fps, etc. gets calculated.");
    120         SetConfigValue(levelName_, "presentation_dm.oxw")
    121             .description("Sets the preselection of the level in the main menu.");
    122     }
    123 
    124     void Game::setLevel(std::string levelName)
    125     {
    126         ModifyConfigValue(levelName_, set, levelName);
    127     }
    128 
    129     std::string Game::getLevel()
    130     {
    131         std::string levelName;
    132         CommandLine::getValue("level", &levelName);
    133         if (levelName == "")
    134             return levelName_;
    135         else
    136             return levelName;
     174        // Take care of the GameStateFactories
     175        GameStateFactory::destroyFactories();
     176
     177        // Don't assign singletonRef_s with NULL! Recreation is not supported
    137178    }
    138179
     
    147188    void Game::run()
    148189    {
    149         // Always start with the ROOT state
    150         this->requestedStateNodes_.push_back(this->rootStateNode_);
    151         this->activeStateNode_ = this->rootStateNode_;
    152         this->loadState(this->rootStateNode_->state_);
     190        if (this->requestedStateNodes_.empty())
     191            COUT(0) << "Warning: Starting game without requesting GameState. This automatically terminates the program." << std::endl;
    153192
    154193        // START GAME
    155194        this->gameClock_->capture(); // first delta time should be about 0 seconds
    156         while (!this->abort_ && !this->activeStates_.empty())
     195        while (!this->bAbort_ && (!this->activeStates_.empty() || this->requestedStateNodes_.size() > 0))
    157196        {
    158197            this->gameClock_->capture();
     
    160199
    161200            // STATISTICS
    162             statisticsTickInfo tickInfo = {currentTime, 0};
     201            StatisticsTickInfo tickInfo = {currentTime, 0};
    163202            statisticsTickTimes_.push_back(tickInfo);
    164203            this->periodTime_ += this->gameClock_->getDeltaTimeMicroseconds();
    165204
    166205            // UPDATE STATE STACK
    167             while (this->requestedStateNodes_.size() > 1)
    168             {
    169                 // Note: this->requestedStateNodes_.front() is the currently active state node
    170                 std::vector<shared_ptr<GameStateTreeNode> >::iterator it = this->requestedStateNodes_.begin() + 1;
    171                 if (*it == this->activeStateNode_->parent_.lock())
     206            while (this->requestedStateNodes_.size() > 0)
     207            {
     208                shared_ptr<GameStateTreeNode> requestedStateNode = this->requestedStateNodes_.front();
     209                assert(this->activeStateNode_);
     210                if (!this->activeStateNode_->parent_.expired() && requestedStateNode == this->activeStateNode_->parent_.lock())
    172211                    this->unloadState(this->activeStateNode_->state_);
    173212                else // has to be child
    174                     this->loadState((*it)->state_);
    175                 this->activeStateNode_ = *it;
     213                {
     214                    try
     215                    {
     216                        this->loadState(requestedStateNode->state_);
     217                    }
     218                    catch (const std::exception& ex)
     219                    {
     220                        COUT(1) << "Error: Loading GameState '" << requestedStateNode->state_->getName() << "' failed: " << ex.what() << std::endl;
     221                        // All scheduled operations have now been rendered inert --> flush them and issue a warning
     222                        if (this->requestedStateNodes_.size() > 1)
     223                            COUT(1) << "All " << this->requestedStateNodes_.size() - 1 << " scheduled transitions have been ignored." << std::endl;
     224                        this->requestedStateNodes_.clear();
     225                        break;
     226                    }
     227                }
     228                this->activeStateNode_ = requestedStateNode;
    176229                this->requestedStateNodes_.erase(this->requestedStateNodes_.begin());
    177230            }
    178231
    179             // UPDATE, bottom to top in the stack
    180             this->core_->update(*this->gameClock_);
    181             for (std::vector<GameState*>::const_iterator it = this->activeStates_.begin();
     232            // UPDATE, Core first
     233            try
     234            {
     235                this->core_->update(*this->gameClock_);
     236            }
     237            catch (...)
     238            {
     239                COUT(0) << "An exception occured while ticking the Core. This should really never happen!" << std::endl;
     240                COUT(0) << "Closing the program." << std::endl;
     241                this->stop();
     242                break;
     243            }
     244
     245            // UPDATE, GameStates bottom to top in the stack
     246            // Note: The first element is the empty root state, which doesn't need ticking
     247            for (std::vector<GameState*>::const_iterator it = this->activeStates_.begin() + 1;
    182248                it != this->activeStates_.end(); ++it)
    183249            {
    184                 // Add tick time for most of the states
    185                 uint64_t timeBeforeTick;
    186                 if ((*it)->getCountTickTime())
    187                     timeBeforeTick = this->gameClock_->getRealMicroseconds();
    188                
    189                 (*it)->update(*this->gameClock_);
    190 
    191                 if ((*it)->getCountTickTime())
    192                     this->addTickTime(static_cast<uint32_t>(this->gameClock_->getRealMicroseconds() - timeBeforeTick));
     250                bool threwException = false;
     251                try
     252                {
     253                    // Add tick time for most of the states
     254                    uint64_t timeBeforeTick;
     255                    if (!(*it)->ignoreTickTime())
     256                        timeBeforeTick = this->gameClock_->getRealMicroseconds();
     257                    (*it)->update(*this->gameClock_);
     258                    if (!(*it)->ignoreTickTime())
     259                        this->addTickTime(static_cast<uint32_t>(this->gameClock_->getRealMicroseconds() - timeBeforeTick));
     260                }
     261                catch (const std::exception& ex)
     262                {
     263                    threwException = true;
     264                    COUT(0) << "Exception while ticking: " << ex.what() << std::endl;
     265                }
     266                catch (...)
     267                {
     268                    threwException = true;
     269                }
     270                if (threwException)
     271                {
     272                    COUT(1) << "An exception occured while ticking GameState '" << (*it)->getName() << "'. This should really never happen!" << std::endl;
     273                    COUT(1) << "Unloading all GameStates depending on the one that crashed." << std::endl;
     274                    if ((*it)->getParent() != NULL)
     275                        this->requestState((*it)->getParent()->getName());
     276                    else
     277                        this->stop();
     278                    break;
     279                }
     280
    193281            }
    194282
    195283            // STATISTICS
    196             if (this->periodTime_ > statisticsRefreshCycle_)
    197             {
    198                 std::list<statisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
     284            if (this->periodTime_ > this->configuration_->statisticsRefreshCycle_)
     285            {
     286                std::list<StatisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
    199287                assert(it != this->statisticsTickTimes_.end());
    200                 int64_t lastTime = currentTime - this->statisticsAvgLength_;
     288                int64_t lastTime = currentTime - this->configuration_->statisticsAvgLength_;
    201289                if ((int64_t)it->tickTime < lastTime)
    202290                {
    203291                    do
    204292                    {
    205                         assert(this->periodTickTime_ > it->tickLength);
     293                        assert(this->periodTickTime_ >= it->tickLength);
    206294                        this->periodTickTime_ -= it->tickLength;
    207295                        ++it;
     
    215303                this->avgTickTime_ = static_cast<float>(this->periodTickTime_) / framesPerPeriod / 1000.0f;
    216304
    217                 this->periodTime_ -= this->statisticsRefreshCycle_;
     305                this->periodTime_ -= this->configuration_->statisticsRefreshCycle_;
    218306            }
    219307        }
    220308
    221309        // UNLOAD all remaining states
    222         while (!this->activeStates_.empty())
     310        while (this->activeStates_.size() > 1)
    223311            this->unloadState(this->activeStates_.back());
    224         this->activeStateNode_.reset();
     312        this->activeStateNode_ = this->rootStateNode_;
    225313        this->requestedStateNodes_.clear();
    226314    }
     
    228316    void Game::stop()
    229317    {
    230         this->abort_ = true;
     318        this->bAbort_ = true;
    231319    }
    232320
     
    244332    {
    245333        GameState* state = this->getState(name);
    246         if (state == NULL || this->activeStateNode_ == NULL)
     334        if (state == NULL)
    247335            return;
    248336
    249         shared_ptr<GameStateTreeNode> requestedNode;
    250 
    251         // this->requestedStateNodes_.back() is the currently active state
    252         shared_ptr<GameStateTreeNode> lastRequestedNode = this->requestedStateNodes_.back();
    253 
    254         // Already the active node?
     337        //if (this->bChangingState_)
     338        //{
     339        //    COUT(2) << "Warning: Requesting GameStates while loading/unloading a GameState is illegal! Ignoring." << std::endl;
     340        //    return;
     341        //}
     342
     343        shared_ptr<GameStateTreeNode> lastRequestedNode;
     344        if (this->requestedStateNodes_.empty())
     345            lastRequestedNode = this->activeStateNode_;
     346        else
     347            lastRequestedNode = this->requestedStateNodes_.back();
    255348        if (state == lastRequestedNode->state_)
    256349        {
     
    260353
    261354        // Check children first
     355        std::vector<shared_ptr<GameStateTreeNode> > requestedNodes;
    262356        for (unsigned int i = 0; i < lastRequestedNode->children_.size(); ++i)
    263357        {
    264358            if (lastRequestedNode->children_[i]->state_ == state)
    265359            {
    266                 requestedNode = lastRequestedNode->children_[i];
     360                requestedNodes.push_back(lastRequestedNode->children_[i]);
    267361                break;
    268362            }
    269363        }
    270364
    271         // Check parent and all its grand parents
    272         shared_ptr<GameStateTreeNode> currentNode = lastRequestedNode;
    273         while (requestedNode == NULL && currentNode != NULL)
    274         {
    275             if (currentNode->state_ == state)
    276                 requestedNode = currentNode;
    277             currentNode = currentNode->parent_.lock();
    278         }
    279 
    280         if (requestedNode == NULL)
     365        if (requestedNodes.empty())
     366        {
     367            // Check parent and all its grand parents
     368            shared_ptr<GameStateTreeNode> currentNode = lastRequestedNode;
     369            while (currentNode != NULL)
     370            {
     371                if (currentNode->state_ == state)
     372                    break;
     373                currentNode = currentNode->parent_.lock();
     374                requestedNodes.push_back(currentNode);
     375            }
     376        }
     377
     378        if (requestedNodes.empty())
    281379            COUT(1) << "Error: Requested GameState transition is not allowed. Ignoring." << std::endl;
    282380        else
    283             this->requestedStateNodes_.push_back(requestedNode);
     381            this->requestedStateNodes_.insert(requestedStateNodes_.end(), requestedNodes.begin(), requestedNodes.end());
    284382    }
    285383
     
    293391    void Game::popState()
    294392    {
    295         if (this->activeStateNode_ != NULL && this->requestedStateNodes_.back()->parent_.lock())
    296             this->requestState(this->requestedStateNodes_.back()->parent_.lock()->state_->getName());
     393        shared_ptr<GameStateTreeNode> lastRequestedNode;
     394        if (this->requestedStateNodes_.empty())
     395            lastRequestedNode = this->activeStateNode_;
    297396        else
    298             COUT(2) << "Warning: Could not pop GameState. Ignoring." << std::endl;
     397            lastRequestedNode = this->requestedStateNodes_.back();
     398        if (lastRequestedNode != this->rootStateNode_)
     399            this->requestState(lastRequestedNode->parent_.lock()->state_->getName());
     400        else
     401            COUT(2) << "Warning: Can't pop the internal dummy root GameState" << std::endl;
    299402    }
    300403
    301404    GameState* Game::getState(const std::string& name)
    302405    {
    303         std::map<std::string, GameState*>::const_iterator it = allStates_s.find(getLowercase(name));
    304         if (it != allStates_s.end())
     406        std::map<std::string, GameState*>::const_iterator it = gameStates_.find(getLowercase(name));
     407        if (it != gameStates_.end())
    305408            return it->second;
    306409        else
     
    325428            while(pos < str.size() && str[pos] != ' ')
    326429                ++pos;
    327             stateStrings.push_back(std::pair<std::string, unsigned>(
    328                 str.substr(startPos, pos - startPos), indentation));
     430            stateStrings.push_back(std::make_pair(str.substr(startPos, pos - startPos), indentation));
    329431        }
    330432        unsigned int currentLevel = 0;
    331         shared_ptr<GameStateTreeNode> currentNode;
     433        shared_ptr<GameStateTreeNode> currentNode = this->rootStateNode_;
    332434        for (std::vector<std::pair<std::string, unsigned> >::const_iterator it = stateStrings.begin(); it != stateStrings.end(); ++it)
    333435        {
    334436            std::string newStateName = it->first;
    335             unsigned newLevel = it->second;
     437            unsigned newLevel = it->second + 1; // empty root is 0
    336438            GameState* newState = this->getState(newStateName);
    337439            if (!newState)
    338                 ThrowException(GameState, std::string("GameState with name '") + newStateName + "' not found!");
    339             if (newLevel == 0)
    340             {
    341                 // root
    342                 if (this->rootStateNode_ != NULL)
    343                     ThrowException(GameState, "No two root GameStates are allowed!");
    344                 shared_ptr<GameStateTreeNode> newNode(new GameStateTreeNode);
    345                 newNode->state_ = newState;
    346                 this->rootStateNode_ = newNode;
    347                 currentNode = this->rootStateNode_;
    348             }
    349             else if (currentNode)
    350             {
    351                 shared_ptr<GameStateTreeNode> newNode(new GameStateTreeNode);
    352                 newNode->state_ = newState;
    353                 if (newLevel < currentLevel)
    354                 {
    355                     // Get down the hierarchy
    356                     do
    357                         currentNode = currentNode->parent_.lock();
    358                     while (newLevel < --currentLevel);
    359                 }
    360                 if (newLevel == currentLevel)
    361                 {
    362                     // same level
    363                     newNode->parent_ = currentNode->parent_;
    364                     newNode->parent_.lock()->children_.push_back(newNode);
    365                 }
    366                 else if (newLevel == currentLevel + 1)
    367                 {
    368                     // child
    369                     newNode->parent_ = currentNode;
    370                     currentNode->children_.push_back(newNode);
    371                 }
    372                 else
    373                     ThrowException(GameState, "Indentation error while parsing the hierarchy.");
    374                 currentNode = newNode;
    375                 currentLevel = newLevel;
     440                ThrowException(GameState, "GameState with name '" << newStateName << "' not found!");
     441            if (newState == this->rootStateNode_->state_)
     442                ThrowException(GameState, "You shouldn't use 'emptyRootGameState' in the hierarchy...");
     443            shared_ptr<GameStateTreeNode> newNode(new GameStateTreeNode);
     444            newNode->state_ = newState;
     445
     446            if (newLevel <= currentLevel)
     447            {
     448                do
     449                    currentNode = currentNode->parent_.lock();
     450                while (newLevel <= --currentLevel);
     451            }
     452            if (newLevel == currentLevel + 1)
     453            {
     454                // Add the child
     455                newNode->parent_ = currentNode;
     456                currentNode->children_.push_back(newNode);
     457                currentNode->state_->addChild(newNode->state_);
    376458            }
    377459            else
    378             {
    379                 ThrowException(GameState, "No root GameState specified!");
    380             }
     460                ThrowException(GameState, "Indentation error while parsing the hierarchy.");
     461            currentNode = newNode;
     462            currentLevel = newLevel;
    381463        }
    382464    }
     
    386468    void Game::loadState(GameState* state)
    387469    {
     470        this->bChangingState_ = true;
     471        state->activate();
    388472        if (!this->activeStates_.empty())
    389473            this->activeStates_.back()->activity_.topState = false;
    390         state->activate();
     474        this->activeStates_.push_back(state);
    391475        state->activity_.topState = true;
    392         this->activeStates_.push_back(state);
     476        this->bChangingState_ = false;
    393477    }
    394478
    395479    void Game::unloadState(orxonox::GameState* state)
    396480    {
     481        this->bChangingState_ = true;
    397482        state->activity_.topState = false;
    398         state->deactivate();
    399483        this->activeStates_.pop_back();
    400484        if (!this->activeStates_.empty())
    401485            this->activeStates_.back()->activity_.topState = true;
    402     }
    403 
    404     /*static*/ bool Game::addGameState(GameState* state)
    405     {
    406         std::map<std::string, GameState*>::const_iterator it = allStates_s.find(getLowercase(state->getName()));
    407         if (it == allStates_s.end())
    408             allStates_s[getLowercase(state->getName())] = state;
    409         else
    410             ThrowException(GameState, "Cannot add two GameStates with the same name to 'Game'.");
    411 
    412         // just a required dummy return value
    413         return true;
    414     }
    415 
    416     /*static*/ void Game::destroyStates()
    417     {
    418         // Delete all GameStates created by the macros
    419         for (std::map<std::string, GameState*>::const_iterator it = allStates_s.begin(); it != allStates_s.end(); ++it)
     486        try
     487        {
     488            state->deactivate();
     489        }
     490        catch (const std::exception& ex)
     491        {
     492            COUT(2) << "Warning: Unloading GameState '" << state->getName() << "' threw an exception: " << ex.what() << std::endl;
     493            COUT(2) << "         There might be potential resource leaks involved! To avoid this, improve exception-safety." << std::endl;
     494        }
     495        this->bChangingState_ = false;
     496    }
     497
     498    std::map<std::string, Game::GameStateFactory*> Game::GameStateFactory::factories_s;
     499
     500    /*static*/ GameState* Game::GameStateFactory::fabricate(const std::string& className, const GameStateConstrParams& params)
     501    {
     502        std::map<std::string, GameStateFactory*>::const_iterator it = factories_s.find(className);
     503        assert(it != factories_s.end());
     504        return it->second->fabricate(params);
     505    }
     506
     507    /*static*/ void Game::GameStateFactory::destroyFactories()
     508    {
     509        for (std::map<std::string, GameStateFactory*>::const_iterator it = factories_s.begin(); it != factories_s.end(); ++it)
    420510            delete it->second;
    421         allStates_s.clear();
     511        factories_s.clear();
    422512    }
    423513}
  • code/trunk/src/core/Game.h

    r3196 r3280  
    4646#include <boost/preprocessor/cat.hpp>
    4747
    48 #include "OrxonoxClass.h"
     48#include "util/Debug.h"
     49#include "util/StringUtils.h"
    4950
    5051/**
     
    5354    and every following paramter is a constructor argument (which is usually non existent)
    5455*/
    55 #define AddGameState(classname, ...) \
    56     static bool BOOST_PP_CAT(bGameStateDummy_##classname, __LINE__) = orxonox::Game::addGameState(new classname(__VA_ARGS__))
     56#define DeclareGameState(className, stateName, bIgnoreTickTime, bGraphicsMode) \
     57    static bool BOOST_PP_CAT(bGameStateDummy_##className, __LINE__) = orxonox::Game::declareGameState<className>(#className, stateName, bIgnoreTickTime, bGraphicsMode)
    5758
    58 // tolua_begin
    5959namespace orxonox
    6060{
     61    class GameConfiguration;
     62
    6163    /**
    6264    @brief
     
    6466    */
    6567    class _CoreExport Game
    66     // tolua_end
    67         : public OrxonoxClass
    68     // tolua_begin
    6968    {
    70     //tolua_end
    7169    public:
    7270        Game(int argc, char** argv);
    7371        ~Game();
    74         void setConfigValues();
    7572
    7673        void setStateHierarchy(const std::string& str);
     
    9188        void addTickTime(uint32_t length);
    9289
    93         static bool addGameState(GameState* state);
    94         static void destroyStates();
    95         static Game& getInstance() { assert(singletonRef_s); return *singletonRef_s; } //tolua_export
    96 
    97         void setLevel(std::string levelName); //tolua_export
    98         std::string getLevel(); //tolua_export
     90        template <class T>
     91        static bool declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bConsoleMode);
     92        static Game& getInstance() { assert(singletonRef_s); return *singletonRef_s; }
    9993
    10094    private:
    101         struct statisticsTickInfo
     95        class _CoreExport GameStateFactory
     96        {
     97        public:
     98            virtual ~GameStateFactory() { }
     99            static GameState* fabricate(const std::string& className, const GameStateConstrParams& params);
     100            template <class T>
     101            static void createFactory(const std::string& className)
     102                { factories_s[className] = new TemplateGameStateFactory<T>(); }
     103            static void destroyFactories();
     104        private:
     105            virtual GameState* fabricate(const GameStateConstrParams& params) = 0;
     106            static std::map<std::string, GameStateFactory*> factories_s;
     107        };
     108        template <class T>
     109        class TemplateGameStateFactory : public GameStateFactory
     110        {
     111        public:
     112            GameState* fabricate(const GameStateConstrParams& params)
     113                { return new T(params); }
     114        };
     115
     116        struct GameStateInfo
     117        {
     118            std::string stateName;
     119            std::string className;
     120            bool bIgnoreTickTime;
     121            bool bGraphicsMode;
     122        };
     123
     124        struct StatisticsTickInfo
    102125        {
    103126            uint64_t    tickTime;
     
    110133        void unloadState(GameState* state);
    111134
    112         std::vector<GameState*>         activeStates_;
     135        std::map<std::string, GameState*>    gameStates_;
     136        std::vector<GameState*>              activeStates_;
    113137        boost::shared_ptr<GameStateTreeNode> rootStateNode_;
    114138        boost::shared_ptr<GameStateTreeNode> activeStateNode_;
     
    117141        Core*                           core_;
    118142        Clock*                          gameClock_;
     143        GameConfiguration*              configuration_;
    119144
    120         bool                            abort_;
     145        bool                            bChangingState_;
     146        bool                            bAbort_;
    121147
    122148        // variables for time statistics
    123149        uint64_t                        statisticsStartTime_;
    124         std::list<statisticsTickInfo>   statisticsTickTimes_;
     150        std::list<StatisticsTickInfo>   statisticsTickTimes_;
    125151        uint32_t                        periodTime_;
    126152        uint32_t                        periodTickTime_;
     
    128154        float                           avgTickTime_;
    129155
    130         // config values
    131         unsigned int                    statisticsRefreshCycle_;
    132         unsigned int                    statisticsAvgLength_;
    133         std::string                     levelName_;
     156        static std::map<std::string, GameStateInfo> gameStateDeclarations_s;
     157        static Game* singletonRef_s;        //!< Pointer to the Singleton
     158    };
    134159
    135         static std::map<std::string, GameState*> allStates_s;
    136         static Game* singletonRef_s;        //!< Pointer to the Singleton
    137         // tolua_begin
    138     };
     160    template <class T>
     161    /*static*/ bool Game::declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bGraphicsMode)
     162    {
     163        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(getLowercase(stateName));
     164        if (it == gameStateDeclarations_s.end())
     165        {
     166            GameStateInfo& info = gameStateDeclarations_s[getLowercase(stateName)];
     167            info.stateName = stateName;
     168            info.className = className;
     169            info.bIgnoreTickTime = bIgnoreTickTime;
     170            info.bGraphicsMode = bGraphicsMode;
     171        }
     172        else
     173        {
     174            COUT(0) << "Error: Cannot declare two GameStates with the same name." << std::endl;
     175            COUT(0) << "       Ignoring second one ('" << stateName << "')." << std::endl;
     176        }
     177
     178        // Create a factory to delay GameState creation
     179        GameStateFactory::createFactory<T>(className);
     180
     181        // just a required dummy return value
     182        return true;
     183    }
    139184}
    140 //tolua_end
     185
    141186#endif /* _Game_H__ */
  • code/trunk/src/core/GameState.cc

    r3196 r3280  
    4545        Constructor only initialises variables and sets the name permanently.
    4646    */
    47     GameState::GameState(const std::string& name, bool countTickTime)
    48         : name_(name)
    49         , bCountTickTime_(countTickTime)
     47    GameState::GameState(const GameStateConstrParams& params)
     48        : name_(params.name)
     49        , bIgnoreTickTime_(params.bIgnoreTickTime)
    5050        , parent_(0)
    5151    {
  • code/trunk/src/core/GameState.h

    r3196 r3280  
    4545    /**
    4646    @brief
     47        Helper class to group construction parameters for better genericity.
     48    */
     49    struct GameStateConstrParams
     50    {
     51        std::string name;
     52        bool bIgnoreTickTime;
     53    };
     54
     55    /**
     56    @brief
    4757        An implementation of a tree to manage game states.
    4858        This leads to a certain hierarchy that is created at runtime.
     
    7787
    7888    public:
    79         GameState(const std::string& name, bool countTicktime = true);
     89        GameState(const GameStateConstrParams& params);
    8090        virtual ~GameState();
    8191
     
    8494        GameState* getParent()       const { return this->parent_; }
    8595
    86         bool getCountTickTime()      const { return this->bCountTickTime_; }
     96        bool ignoreTickTime()        const { return this->bIgnoreTickTime_; }
    8797
    8898        void addChild(GameState* state);
     
    90100
    91101    protected:
    92         virtual void activate() = 0;
    93         virtual void deactivate() = 0;
    94         virtual void update(const Clock& time) = 0;
     102        virtual void activate() { }
     103        virtual void deactivate() { }
     104        virtual void update(const Clock& time) { }
    95105
    96106    private:
     
    103113        const std::string                        name_;
    104114        State                                    activity_;
    105         const bool                               bCountTickTime_;
     115        const bool                               bIgnoreTickTime_;
    106116        GameState*                               parent_;
    107117        std::map<std::string, GameState*>        children_;
  • code/trunk/src/core/IRC.cc

    r3196 r3280  
    6868        {   COUT(1) << "Error while initializing Tcl (IRC): " << e.what();   }
    6969
    70         this->nickname_ = "orx" + getConvertedValue<int, std::string>((unsigned int)rand());
     70        this->nickname_ = "orx" + multi_cast<std::string>(static_cast<unsigned int>(rand()));
    7171        TclThreadManager::execute(threadID, "set nickname " + this->nickname_);
    7272        TclThreadManager::execute(threadID, "source irc.tcl");
  • code/trunk/src/core/Identifier.cc

    r3196 r3280  
    3636#include <ostream>
    3737
    38 #include "util/String.h"
     38#include "util/StringUtils.h"
    3939#include "ConfigValueContainer.h"
    4040#include "ConsoleCommand.h"
  • code/trunk/src/core/Language.cc

    r3198 r3280  
    194194        @return The filename
    195195    */
    196     const std::string Language::getFilename(const std::string& language)
     196    std::string Language::getFilename(const std::string& language)
    197197    {
    198198        return std::string("translation_" + language + ".lang");
  • code/trunk/src/core/Language.h

    r2662 r3280  
    114114    class _CoreExport Language
    115115    {
    116         friend class Core;
     116        friend class CoreConfiguration;
    117117
    118118        public:
     
    130130            void readTranslatedLanguageFile();
    131131            void writeDefaultLanguageFile() const;
    132             static const std::string getFilename(const std::string& language);
     132            static std::string getFilename(const std::string& language);
    133133            LanguageEntry* createEntry(const LanguageEntryLabel& label, const std::string& entry);
    134134
  • code/trunk/src/core/LuaBind.cc

    r3198 r3280  
    3838
    3939#include "util/Debug.h"
    40 #include "util/String.h"
     40#include "util/StringUtils.h"
    4141#include "ToluaBindCore.h"
    4242#include "Core.h"
  • code/trunk/src/core/OrxonoxClass.cc

    r3196 r3280  
    7878
    7979    /** @brief Returns true if the objects class is of the given type or a derivative. */
    80     bool OrxonoxClass::isA(const SubclassIdentifier<class B>* identifier)
     80    template <class B> bool OrxonoxClass::isA(const SubclassIdentifier<B>* identifier)
    8181        { return this->getIdentifier()->isA(identifier->getIdentifier()); }
    8282    /** @brief Returns true if the objects class is exactly of the given type. */
    83     bool OrxonoxClass::isExactlyA(const SubclassIdentifier<class B>* identifier)
     83    template <class B> bool OrxonoxClass::isExactlyA(const SubclassIdentifier<B>* identifier)
    8484        { return this->getIdentifier()->isExactlyA(identifier->getIdentifier()); }
    8585    /** @brief Returns true if the objects class is a child of the given type. */
    86     bool OrxonoxClass::isChildOf(const SubclassIdentifier<class B>* identifier)
     86    template <class B> bool OrxonoxClass::isChildOf(const SubclassIdentifier<B>* identifier)
    8787        { return this->getIdentifier()->isChildOf(identifier->getIdentifier()); }
    8888    /** @brief Returns true if the objects class is a direct child of the given type. */
    89     bool OrxonoxClass::isDirectChildOf(const SubclassIdentifier<class B>* identifier)
     89    template <class B> bool OrxonoxClass::isDirectChildOf(const SubclassIdentifier<B>* identifier)
    9090        { return this->getIdentifier()->isDirectChildOf(identifier->getIdentifier()); }
    9191    /** @brief Returns true if the objects class is a parent of the given type. */
    92     bool OrxonoxClass::isParentOf(const SubclassIdentifier<class B>* identifier)
     92    template <class B> bool OrxonoxClass::isParentOf(const SubclassIdentifier<B>* identifier)
    9393        { return this->getIdentifier()->isParentOf(identifier->getIdentifier()); }
    9494    /** @brief Returns true if the objects class is a direct parent of the given type. */
    95     bool OrxonoxClass::isDirectParentOf(const SubclassIdentifier<class B>* identifier)
     95    template <class B> bool OrxonoxClass::isDirectParentOf(const SubclassIdentifier<B>* identifier)
    9696        { return this->getIdentifier()->isDirectParentOf(identifier->getIdentifier()); }
    9797
    9898
    9999    /** @brief Returns true if the objects class is of the given type or a derivative. */
    100     bool OrxonoxClass::isA(const SubclassIdentifier<class B> identifier)
     100    template <class B> bool OrxonoxClass::isA(const SubclassIdentifier<B> identifier)
    101101        { return this->getIdentifier()->isA(identifier.getIdentifier()); }
    102102    /** @brief Returns true if the objects class is exactly of the given type. */
    103     bool OrxonoxClass::isExactlyA(const SubclassIdentifier<class B> identifier)
     103    template <class B> bool OrxonoxClass::isExactlyA(const SubclassIdentifier<B> identifier)
    104104        { return this->getIdentifier()->isExactlyA(identifier.getIdentifier()); }
    105105    /** @brief Returns true if the objects class is a child of the given type. */
    106     bool OrxonoxClass::isChildOf(const SubclassIdentifier<class B> identifier)
     106    template <class B> bool OrxonoxClass::isChildOf(const SubclassIdentifier<B> identifier)
    107107        { return this->getIdentifier()->isChildOf(identifier.getIdentifier()); }
    108108    /** @brief Returns true if the objects class is a direct child of the given type. */
    109     bool OrxonoxClass::isDirectChildOf(const SubclassIdentifier<class B> identifier)
     109    template <class B> bool OrxonoxClass::isDirectChildOf(const SubclassIdentifier<B> identifier)
    110110        { return this->getIdentifier()->isDirectChildOf(identifier.getIdentifier()); }
    111111    /** @brief Returns true if the objects class is a parent of the given type. */
    112     bool OrxonoxClass::isParentOf(const SubclassIdentifier<class B> identifier)
     112    template <class B> bool OrxonoxClass::isParentOf(const SubclassIdentifier<B> identifier)
    113113        { return this->getIdentifier()->isParentOf(identifier.getIdentifier()); }
    114114    /** @brief Returns true if the objects class is a direct parent of the given type. */
    115     bool OrxonoxClass::isDirectParentOf(const SubclassIdentifier<class B> identifier)
     115    template <class B> bool OrxonoxClass::isDirectParentOf(const SubclassIdentifier<B> identifier)
    116116        { return this->getIdentifier()->isDirectParentOf(identifier.getIdentifier()); }
    117117
  • code/trunk/src/core/OrxonoxClass.h

    r3196 r3280  
    8080            bool isDirectParentOf(const Identifier* identifier);
    8181
    82             bool isA(const SubclassIdentifier<class B>* identifier);
    83             bool isExactlyA(const SubclassIdentifier<class B>* identifier);
    84             bool isChildOf(const SubclassIdentifier<class B>* identifier);
    85             bool isDirectChildOf(const SubclassIdentifier<class B>* identifier);
    86             bool isParentOf(const SubclassIdentifier<class B>* identifier);
    87             bool isDirectParentOf(const SubclassIdentifier<class B>* identifier);
     82            template <class B> bool isA(const SubclassIdentifier<B>* identifier);
     83            template <class B> bool isExactlyA(const SubclassIdentifier<B>* identifier);
     84            template <class B> bool isChildOf(const SubclassIdentifier<B>* identifier);
     85            template <class B> bool isDirectChildOf(const SubclassIdentifier<B>* identifier);
     86            template <class B> bool isParentOf(const SubclassIdentifier<B>* identifier);
     87            template <class B> bool isDirectParentOf(const SubclassIdentifier<B>* identifier);
    8888
    89             bool isA(const SubclassIdentifier<class B> identifier);
    90             bool isExactlyA(const SubclassIdentifier<class B> identifier);
    91             bool isChildOf(const SubclassIdentifier<class B> identifier);
    92             bool isDirectChildOf(const SubclassIdentifier<class B> identifier);
    93             bool isParentOf(const SubclassIdentifier<class B> identifier);
    94             bool isDirectParentOf(const SubclassIdentifier<class B> identifier);
     89            template <class B> bool isA(const SubclassIdentifier<B> identifier);
     90            template <class B> bool isExactlyA(const SubclassIdentifier<B> identifier);
     91            template <class B> bool isChildOf(const SubclassIdentifier<B> identifier);
     92            template <class B> bool isDirectChildOf(const SubclassIdentifier<B> identifier);
     93            template <class B> bool isParentOf(const SubclassIdentifier<B> identifier);
     94            template <class B> bool isDirectParentOf(const SubclassIdentifier<B> identifier);
    9595
    9696            bool isA(const OrxonoxClass* object);
  • code/trunk/src/core/Shell.cc

    r3196 r3280  
    7878        OutputHandler::getOutStream().setOutputBuffer(&this->outputBuffer_);
    7979
     80        // Get a config file for the command history
     81        this->commandHistoryConfigFileType_ = ConfigFileManager::getInstance().getNewConfigFileType();
     82        ConfigFileManager::getInstance().setFilename(this->commandHistoryConfigFileType_, "commandHistory.ini");
     83
    8084        this->setConfigValues();
    8185
     
    9397    void Shell::setConfigValues()
    9498    {
    95         SetConfigValue(maxHistoryLength_, 100).callback(this, &Shell::commandHistoryLengthChanged);
    96         SetConfigValue(historyOffset_, 0).callback(this, &Shell::commandHistoryOffsetChanged);
    97         SetConfigValueVector(commandHistory_, std::vector<std::string>());
     99        SetConfigValueGeneric(commandHistoryConfigFileType_, maxHistoryLength_, 100)
     100            .callback(this, &Shell::commandHistoryLengthChanged);
     101        SetConfigValueGeneric(commandHistoryConfigFileType_, historyOffset_, 0)
     102            .callback(this, &Shell::commandHistoryOffsetChanged);
     103        SetConfigValueVectorGeneric(commandHistoryConfigFileType_, commandHistory_, std::vector<std::string>());
    98104    }
    99105
  • code/trunk/src/core/Shell.h

    r3196 r3280  
    3737#include <vector>
    3838
     39#include "util/OutputBuffer.h"
     40#include "input/InputBuffer.h"
    3941#include "OrxonoxClass.h"
    40 #include "input/InputBuffer.h"
    41 #include "util/OutputBuffer.h"
     42#include "ConfigFileManager.h"
    4243
    4344namespace orxonox
     
    145146            bool bAddOutputLevel_;
    146147
     148            ConfigFileType commandHistoryConfigFileType_;
     149
    147150            static Shell* singletonRef_s;
    148151    };
  • code/trunk/src/core/TclBind.cc

    r3196 r3280  
    3434
    3535#include "util/Debug.h"
    36 #include "util/String.h"
     36#include "util/StringUtils.h"
    3737#include "CommandExecutor.h"
    3838#include "ConsoleCommand.h"
  • code/trunk/src/core/TclThreadManager.cc

    r3196 r3280  
    9494        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
    9595        TclThreadManager::getInstance().threadCounter_++;
    96         std::string name = getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().threadCounter_);
     96        std::string name = multi_cast<std::string>(TclThreadManager::getInstance().threadCounter_);
    9797
    9898        TclInterpreterBundle* bundle = new TclInterpreterBundle;
     
    192192        {
    193193            boost::mutex::scoped_lock queue_lock(TclThreadManager::getInstance().orxonoxInterpreterBundle_.queueMutex_);
    194             output += getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().orxonoxInterpreterBundle_.queue_.size());
     194            output += multi_cast<std::string>(TclThreadManager::getInstance().orxonoxInterpreterBundle_.queue_.size());
    195195        }
    196196        output += "\t\t";
     
    201201        for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = TclThreadManager::getInstance().interpreterBundles_.begin(); it != TclThreadManager::getInstance().interpreterBundles_.end(); ++it)
    202202        {
    203             std::string output = getConvertedValue<unsigned int, std::string>((*it).first);
     203            std::string output = multi_cast<std::string>((*it).first);
    204204            output += "\t\t";
    205205            {
    206206                boost::mutex::scoped_lock queue_lock((*it).second->queueMutex_);
    207                 output += getConvertedValue<unsigned int, std::string>((*it).second->queue_.size());
     207                output += multi_cast<std::string>((*it).second->queue_.size());
    208208            }
    209209            output += "\t\t";
     
    342342        else
    343343        {
    344             this->error("Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + " existing.");
     344            this->error("Error: No Tcl-interpreter with ID " + multi_cast<std::string>(threadID) + " existing.");
    345345            return 0;
    346346        }
     
    355355                output += " ";
    356356
    357             output += getConvertedValue<unsigned int, std::string>(*it);
     357            output += multi_cast<std::string>(*it);
    358358        }
    359359        return output;
     
    444444            if (bundle->queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
    445445            {
    446                 this->error("Error: Queue of Tcl-interpreter " + getConvertedValue<unsigned int, std::string>(threadID) + " is full, couldn't add command.");
     446                this->error("Error: Queue of Tcl-interpreter " + multi_cast<std::string>(threadID) + " is full, couldn't add command.");
    447447                return;
    448448            }
     
    492492        if (std::find(target->queriers_.begin(), target->queriers_.end(), target->id_) != target->queriers_.end())
    493493        {
    494             this->error("Error: Circular query (" + this->dumpList(target->queriers_) + " -> " + getConvertedValue<unsigned int, std::string>(target->id_) + "), couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target->id_) + " from other interpreter with ID " + getConvertedValue<unsigned int, std::string>(querier->id_) + ".");
     494            this->error("Error: Circular query (" + this->dumpList(target->queriers_) + " -> " + multi_cast<std::string>(target->id_) + "), couldn't query Tcl-interpreter with ID " + multi_cast<std::string>(target->id_) + " from other interpreter with ID " + multi_cast<std::string>(querier->id_) + ".");
    495495            return false;
    496496        }
     
    585585                    else
    586586                    {
    587                         this->error("Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + ", interpreter is busy right now.");
     587                        this->error("Error: Couldn't query Tcl-interpreter with ID " + multi_cast<std::string>(threadID) + ", interpreter is busy right now.");
    588588                    }
    589589                }
     
    665665        catch (Tcl::tcl_error const &e)
    666666        {
    667             TclThreadManager::getInstance().error("Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + ") error: " + e.what());
     667            TclThreadManager::getInstance().error("Tcl (ID " + multi_cast<std::string>(interpreterBundle->id_) + ") error: " + e.what());
    668668        }
    669669        catch (std::exception const &e)
    670670        {
    671             TclThreadManager::getInstance().error("Error while executing Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + "): " + e.what());
     671            TclThreadManager::getInstance().error("Error while executing Tcl (ID " + multi_cast<std::string>(interpreterBundle->id_) + "): " + e.what());
    672672        }
    673673
  • code/trunk/src/core/input/Button.cc

    r2662 r3280  
    3737#include "util/Convert.h"
    3838#include "util/SubString.h"
    39 #include "util/String.h"
     39#include "util/StringUtils.h"
    4040#include "util/Debug.h"
    4141#include "core/ConsoleCommand.h"
     
    127127                    '\\', false, '"', false, '(', ')', false, '\0');
    128128
    129                 KeybindMode::Enum mode = KeybindMode::None;
     129                KeybindMode::Value mode = KeybindMode::None;
    130130                float paramModifier = 1.0f;
    131131                std::string commandStr = "";
  • code/trunk/src/core/input/Button.h

    r2662 r3280  
    5454        void parse();
    5555        void readConfigValue(ConfigFileType configFile);
    56         bool execute(KeybindMode::Enum mode, float abs = 1.0f, float rel = 1.0f);
     56        bool execute(KeybindMode::Value mode, float abs = 1.0f, float rel = 1.0f);
    5757
    5858        //! Container to allow for better configValue support
     
    7979    };
    8080
    81     inline bool Button::execute(KeybindMode::Enum mode, float abs, float rel)
     81    inline bool Button::execute(KeybindMode::Value mode, float abs, float rel)
    8282    {
    8383        // execute all the parsed commands in the string
  • code/trunk/src/core/input/InputManager.cc

    r3196 r3280  
    4343#include "util/Convert.h"
    4444#include "util/Exception.h"
    45 #include "util/Debug.h"
     45#include "util/ScopeGuard.h"
    4646#include "core/Clock.h"
    4747#include "core/CoreIncludes.h"
     
    7070    SetConsoleCommand(InputManager, ungrabMouse, true);
    7171#endif
    72     SetCommandLineSwitch(keyboard_no_grab);
     72    SetCommandLineSwitch(keyboard_no_grab).information("Whether not to exclusively grab the keyboard");
    7373
    7474    EmptyHandler InputManager::EMPTY_HANDLER;
     
    177177            windowHndStr << (unsigned int)windowHnd_;
    178178            paramList.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
     179#if defined(ORXONOX_PLATFORM_WINDOWS)
    179180            //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
    180181            //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND")));
    181 #if defined ORXONOX_PLATFORM_LINUX
     182            //paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
     183            //paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));
     184#elif defined(ORXONOX_PLATFORM_LINUX)
    182185            paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
    183186            paramList.insert(std::make_pair(std::string("x11_mouse_grab"), "true"));
     
    191194#endif
    192195
    193             inputSystem_ = OIS::InputManager::createInputSystem(paramList);
    194             CCOUT(ORX_DEBUG) << "Created OIS input system" << std::endl;
    195 
    196             _initialiseKeyboard();
     196            try
     197            {
     198                inputSystem_ = OIS::InputManager::createInputSystem(paramList);
     199                // Exception-safety
     200                Loki::ScopeGuard guard = Loki::MakeGuard(OIS::InputManager::destroyInputSystem, inputSystem_);
     201                CCOUT(ORX_DEBUG) << "Created OIS input system" << std::endl;
     202
     203                _initialiseKeyboard();
     204
     205                // Nothing below should throw anymore, dismiss the guard
     206                guard.Dismiss();
     207            }
     208            catch (OIS::Exception& ex)
     209            {
     210                ThrowException(InitialisationFailed, "Could not initialise the input system: " << ex.what());
     211            }
    197212
    198213            _initialiseMouse();
     
    200215            if (joyStickSupport)
    201216                _initialiseJoySticks();
    202             // Do this anyway to also inform everything when a joystick was detached.
     217            // Do this anyway to also inform when a joystick was detached.
    203218            _configureJoySticks();
    204219
     
    273288        else
    274289        {
    275             ThrowException(InitialisationFailed, "No keyboard found!");
     290            ThrowException(InitialisationFailed, "InputManager: No keyboard found, cannot proceed!");
    276291        }
    277292    }
     
    301316            else
    302317            {
    303                 CCOUT(ORX_WARNING) << "Warning: No mouse found!" << std::endl;
     318                CCOUT(ORX_WARNING) << "Warning: No mouse found! Proceeding without mouse support." << std::endl;
    304319            }
    305320        }
     
    307322        {
    308323            CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS mouse\n"
    309                 << "OIS error message: \"" << ex.eText << "\"" << std::endl;
     324                << "OIS error message: \"" << ex.eText << "\"\n Proceeding without mouse support." << std::endl;
    310325            mouse_ = 0;
    311326        }
     
    345360            }
    346361        }
    347         else
    348         {
    349             //CCOUT(ORX_WARNING) << "Warning: Joy stick support requested, but no joy stick was found" << std::endl;
    350         }
    351362    }
    352363
     
    528539        if (internalState_ != Uninitialised)
    529540        {
     541            CCOUT(3) << "Destroying ..." << std::endl;
     542
     543            // kick all active states 'nicely'
     544            for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
     545                rit != activeStates_.rend(); ++rit)
     546            {
     547                (*rit).second->onLeave();
     548            }
     549
     550            // Destroy calibrator helper handler and state
     551            delete keyDetector_;
     552            requestDestroyState("calibrator");
     553            // Destroy KeyDetector and state
     554            delete calibratorCallbackBuffer_;
     555            requestDestroyState("detector");
     556            // destroy the empty InputState
     557            _destroyState(this->stateEmpty_);
     558
     559            // destroy all user InputStates
     560            while (inputStatesByName_.size() > 0)
     561                _destroyState((*inputStatesByName_.rbegin()).second);
     562
     563            // destroy the devices
     564            _destroyKeyboard();
     565            _destroyMouse();
     566            _destroyJoySticks();
     567
    530568            try
    531569            {
    532                 CCOUT(3) << "Destroying ..." << std::endl;
    533 
    534                 // kick all active states 'nicely'
    535                 for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
    536                     rit != activeStates_.rend(); ++rit)
    537                 {
    538                     (*rit).second->onLeave();
    539                 }
    540 
    541                 // Destroy calibrator helper handler and state
    542                 delete keyDetector_;
    543                 requestDestroyState("calibrator");
    544                 // Destroy KeyDetector and state
    545                 delete calibratorCallbackBuffer_;
    546                 requestDestroyState("detector");
    547                 // destroy the empty InputState
    548                 _destroyState(this->stateEmpty_);
    549 
    550                 // destroy all user InputStates
    551                 while (inputStatesByName_.size() > 0)
    552                     _destroyState((*inputStatesByName_.rbegin()).second);
    553 
    554                 // destroy the devices
    555                 _destroyKeyboard();
    556                 _destroyMouse();
    557                 _destroyJoySticks();
    558 
    559570                OIS::InputManager::destroyInputSystem(inputSystem_);
    560 
    561                 CCOUT(3) << "Destroying done." << std::endl;
    562             }
    563             catch (OIS::Exception& ex)
    564             {
    565                 CCOUT(1) << "An exception has occured while destroying:\n" << ex.what()
    566                          << "This could lead to a possible memory/resource leak!" << std::endl;
     571            }
     572            catch (...)
     573            {
     574                CCOUT(1) << "OIS::InputManager destruction failed! Potential resource leak!" << std::endl;
    567575            }
    568576        }
     
    578586    {
    579587        assert(inputSystem_);
    580         if (keyboard_)
    581             inputSystem_->destroyInputObject(keyboard_);
    582         keyboard_ = 0;
    583         CCOUT(4) << "Keyboard destroyed." << std::endl;
     588        try
     589        {
     590            if (keyboard_)
     591                inputSystem_->destroyInputObject(keyboard_);
     592            keyboard_ = 0;
     593            CCOUT(4) << "Keyboard destroyed." << std::endl;
     594        }
     595        catch (...)
     596        {
     597            CCOUT(1) << "Keyboard destruction failed! Potential resource leak!" << std::endl;
     598        }
    584599    }
    585600
     
    591606    {
    592607        assert(inputSystem_);
    593         if (mouse_)
    594             inputSystem_->destroyInputObject(mouse_);
    595         mouse_ = 0;
    596         CCOUT(4) << "Mouse destroyed." << std::endl;
     608        try
     609        {
     610            if (mouse_)
     611                inputSystem_->destroyInputObject(mouse_);
     612            mouse_ = 0;
     613            CCOUT(4) << "Mouse destroyed." << std::endl;
     614        }
     615        catch (...)
     616        {
     617            CCOUT(1) << "Mouse destruction failed! Potential resource leak!" << std::endl;
     618        }
    597619    }
    598620
     
    607629            assert(inputSystem_);
    608630            for (unsigned int i = 0; i < joySticksSize_; i++)
    609                 if (joySticks_[i] != 0)
    610                     inputSystem_->destroyInputObject(joySticks_[i]);
     631            {
     632                try
     633                {
     634                    if (joySticks_[i] != 0)
     635                        inputSystem_->destroyInputObject(joySticks_[i]);
     636                }
     637                catch (...)
     638                {
     639                    CCOUT(1) << "Joy stick destruction failed! Potential resource leak!" << std::endl;
     640                }
     641            }
    611642
    612643            joySticks_.clear();
  • code/trunk/src/core/input/KeyBinder.cc

    r3196 r3280  
    9696        }
    9797
    98         // Get a new ConfigFileType from the ConfigFileManager
    99         this->configFile_ = ConfigFileManager::getInstance().getNewConfigFileType();
     98        // We might not even load any bindings at all (KeyDetector for instance)
     99        this->configFile_ = ConfigFileType::NoType;
    100100
    101101        // initialise joy sticks separatly to allow for reloading
     
    187187        for (unsigned int iDev = 0; iDev < numberOfJoySticks_; iDev++)
    188188        {
    189             std::string deviceNumber = convertToString(iDev);
     189            std::string deviceNumber = multi_cast<std::string>(iDev);
    190190            // joy stick buttons
    191191            for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; i++)
     
    249249        if (filename.empty())
    250250            return;
     251
     252        if (this->configFile_ == ConfigFileType::NoType)
     253        {
     254            // Get a new ConfigFileType from the ConfigFileManager
     255            this->configFile_ = ConfigFileManager::getInstance().getNewConfigFileType();
     256        }
    251257
    252258        ConfigFileManager::getInstance().setFilename(this->configFile_, filename);
Note: See TracChangeset for help on using the changeset viewer.