[Orxonox-commit 2495] r7202 - in code/branches/consolecommands3/src/libraries/core: . command
landauf at orxonox.net
landauf at orxonox.net
Mon Aug 23 00:54:09 CEST 2010
Author: landauf
Date: 2010-08-23 00:54:08 +0200 (Mon, 23 Aug 2010)
New Revision: 7202
Added:
code/branches/consolecommands3/src/libraries/core/command/
code/branches/consolecommands3/src/libraries/core/command/ArgumentCompleter.h
code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionFunctions.cc
code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionFunctions.h
code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionListElement.h
code/branches/consolecommands3/src/libraries/core/command/CMakeLists.txt
code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.cc
code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.h
code/branches/consolecommands3/src/libraries/core/command/CommandExecutor.cc
code/branches/consolecommands3/src/libraries/core/command/CommandExecutor.h
code/branches/consolecommands3/src/libraries/core/command/ConsoleCommand.cc
code/branches/consolecommands3/src/libraries/core/command/ConsoleCommand.h
code/branches/consolecommands3/src/libraries/core/command/ConsoleCommandCompilation.cc
code/branches/consolecommands3/src/libraries/core/command/ConsoleCommandCompilation.h
code/branches/consolecommands3/src/libraries/core/command/Executor.cc
code/branches/consolecommands3/src/libraries/core/command/Executor.h
code/branches/consolecommands3/src/libraries/core/command/ExecutorPtr.h
code/branches/consolecommands3/src/libraries/core/command/Functor.h
code/branches/consolecommands3/src/libraries/core/command/FunctorPtr.h
code/branches/consolecommands3/src/libraries/core/command/IOConsole.cc
code/branches/consolecommands3/src/libraries/core/command/IOConsole.h
code/branches/consolecommands3/src/libraries/core/command/IRC.cc
code/branches/consolecommands3/src/libraries/core/command/IRC.h
code/branches/consolecommands3/src/libraries/core/command/Shell.cc
code/branches/consolecommands3/src/libraries/core/command/Shell.h
code/branches/consolecommands3/src/libraries/core/command/TclBind.cc
code/branches/consolecommands3/src/libraries/core/command/TclBind.h
code/branches/consolecommands3/src/libraries/core/command/TclThreadList.h
code/branches/consolecommands3/src/libraries/core/command/TclThreadManager.cc
code/branches/consolecommands3/src/libraries/core/command/TclThreadManager.h
Removed:
code/branches/consolecommands3/src/libraries/core/ArgumentCompleter.h
code/branches/consolecommands3/src/libraries/core/ArgumentCompletionFunctions.cc
code/branches/consolecommands3/src/libraries/core/ArgumentCompletionFunctions.h
code/branches/consolecommands3/src/libraries/core/ArgumentCompletionListElement.h
code/branches/consolecommands3/src/libraries/core/CommandEvaluation.cc
code/branches/consolecommands3/src/libraries/core/CommandEvaluation.h
code/branches/consolecommands3/src/libraries/core/CommandExecutor.cc
code/branches/consolecommands3/src/libraries/core/CommandExecutor.h
code/branches/consolecommands3/src/libraries/core/ConsoleCommand.cc
code/branches/consolecommands3/src/libraries/core/ConsoleCommand.h
code/branches/consolecommands3/src/libraries/core/ConsoleCommandCompilation.cc
code/branches/consolecommands3/src/libraries/core/ConsoleCommandCompilation.h
code/branches/consolecommands3/src/libraries/core/Executor.cc
code/branches/consolecommands3/src/libraries/core/Executor.h
code/branches/consolecommands3/src/libraries/core/ExecutorPtr.h
code/branches/consolecommands3/src/libraries/core/Functor.h
code/branches/consolecommands3/src/libraries/core/FunctorPtr.h
code/branches/consolecommands3/src/libraries/core/IOConsole.cc
code/branches/consolecommands3/src/libraries/core/IOConsole.h
code/branches/consolecommands3/src/libraries/core/IRC.cc
code/branches/consolecommands3/src/libraries/core/IRC.h
code/branches/consolecommands3/src/libraries/core/Shell.cc
code/branches/consolecommands3/src/libraries/core/Shell.h
code/branches/consolecommands3/src/libraries/core/TclBind.cc
code/branches/consolecommands3/src/libraries/core/TclBind.h
code/branches/consolecommands3/src/libraries/core/TclThreadList.h
code/branches/consolecommands3/src/libraries/core/TclThreadManager.cc
code/branches/consolecommands3/src/libraries/core/TclThreadManager.h
Modified:
code/branches/consolecommands3/src/libraries/core/CMakeLists.txt
Log:
moved all files related to the command execution chain to core/command (includes not yet adjusted, doesn't compile)
Deleted: code/branches/consolecommands3/src/libraries/core/ArgumentCompleter.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/ArgumentCompleter.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/ArgumentCompleter.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,79 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _ArgumentCompleter_H__
-#define _ArgumentCompleter_H__
-
-#include "CorePrereqs.h"
-#include "ArgumentCompletionListElement.h"
-
-namespace orxonox
-{
- class _CoreExport ArgumentCompleter
- {
- public:
- ArgumentCompleter(ArgumentCompletionList (*function) (void)) : paramCount_(0), function_0_(function) {}
- ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1)) : paramCount_(1), function_1_(function) {}
- ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2)) : paramCount_(2), function_2_(function) {}
- ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3)) : paramCount_(3), function_3_(function) {}
- ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4)) : paramCount_(4), function_4_(function) {}
- ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5)) : paramCount_(5), function_5_(function) {}
-
- ArgumentCompletionList operator()(const std::string& param1 = "", const std::string& param2 = "", const std::string& param3 = "", const std::string& param4 = "", const std::string& param5 = "")
- {
- switch (this->paramCount_)
- {
- case 0:
- return (*this->function_0_)();
- case 1:
- return (*this->function_1_)(param1);
- case 2:
- return (*this->function_2_)(param1, param2);
- case 3:
- return (*this->function_3_)(param1, param2, param3);
- case 4:
- return (*this->function_4_)(param1, param2, param3, param4);
- case 5:
- return (*this->function_5_)(param1, param2, param3, param4, param5);
- default:
- return ArgumentCompletionList();
- }
- }
-
- private:
- unsigned char paramCount_;
- ArgumentCompletionList (*function_0_) (void);
- ArgumentCompletionList (*function_1_) (const std::string& param1);
- ArgumentCompletionList (*function_2_) (const std::string& param1, const std::string& param2);
- ArgumentCompletionList (*function_3_) (const std::string& param1, const std::string& param2, const std::string& param3);
- ArgumentCompletionList (*function_4_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4);
- ArgumentCompletionList (*function_5_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5);
- };
-}
-
-#endif /* _ArgumentCompleter_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/ArgumentCompletionFunctions.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/ArgumentCompletionFunctions.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/ArgumentCompletionFunctions.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,154 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#include "ArgumentCompletionFunctions.h"
-
-#include <map>
-#include <boost/version.hpp>
-#include <boost/filesystem.hpp>
-
-#include "util/Convert.h"
-#include "util/StringUtils.h"
-#include "Identifier.h"
-#include "ConfigFileManager.h"
-#include "ConfigValueContainer.h"
-#include "TclThreadManager.h"
-
-// Boost 1.36 has some issues with deprecated functions that have been omitted
-#if (BOOST_VERSION == 103600)
-# define BOOST_LEAF_FUNCTION filename
-#else
-# define BOOST_LEAF_FUNCTION leaf
-#endif
-
-namespace orxonox
-{
- namespace autocompletion
- {
- ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(fallback)()
- {
- return ArgumentCompletionList();
- }
-
- ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(files)(const std::string& fragment)
- {
- ArgumentCompletionList dirlist;
- ArgumentCompletionList filelist;
-
- try
- {
- boost::filesystem::path input(fragment);
- boost::filesystem::path startdirectory(input.branch_path());
-
- if (!boost::filesystem::exists(startdirectory))
- {
- startdirectory = ".";
- }
-#ifdef ORXONOX_PLATFORM_WINDOWS
- else
- {
- const std::string& dir = startdirectory.string();
- if (dir.size() > 0 && dir[dir.size() - 1] == ':')
- startdirectory = dir + '/';
- }
-#endif
-
- boost::filesystem::directory_iterator file(startdirectory);
- boost::filesystem::directory_iterator end;
-
- while (file != end)
- {
- if (boost::filesystem::is_directory(*file))
- dirlist.push_back(ArgumentCompletionListElement(file->string() + '/', getLowercase(file->string()) + '/', file->BOOST_LEAF_FUNCTION() + '/'));
- else
- filelist.push_back(ArgumentCompletionListElement(file->string(), getLowercase(file->string()), file->BOOST_LEAF_FUNCTION()));
- ++file;
- }
- }
- catch (...) {}
-
- filelist.insert(filelist.begin(), dirlist.begin(), dirlist.end());
- return filelist;
- }
-
- ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingssections)()
- {
- ArgumentCompletionList sectionList;
-
- const std::set<std::string>& names = SettingsConfigFile::getInstance().getSectionNames();
- for (std::set<std::string>::const_iterator it = names.begin(); it != names.end(); ++it)
- sectionList.push_back(ArgumentCompletionListElement(*it, getLowercase(*it)));
-
- return sectionList;
- }
-
- ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsentries)(const std::string& fragment, const std::string& section)
- {
- ArgumentCompletionList entryList;
- SettingsConfigFile& settings = SettingsConfigFile::getInstance();
- const std::string& sectionLC = getLowercase(section);
-
- SettingsConfigFile::ContainerMap::const_iterator upper = settings.getContainerUpperBound(sectionLC);
- for (SettingsConfigFile::ContainerMap::const_iterator it = settings.getContainerLowerBound(sectionLC); it != upper; ++it)
- entryList.push_back(ArgumentCompletionListElement(it->second.second->getName(), it->second.first));
-
- return entryList;
- }
-
- ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsvalue)(const std::string& fragment, const std::string& entry, const std::string& section)
- {
- ArgumentCompletionList oldValue;
- SettingsConfigFile& settings = SettingsConfigFile::getInstance();
- const std::string& sectionLC = getLowercase(section);
- const std::string& entryLC = getLowercase(entry);
-
- SettingsConfigFile::ContainerMap::const_iterator upper = settings.getContainerUpperBound(sectionLC);
- for (SettingsConfigFile::ContainerMap::const_iterator it = settings.getContainerLowerBound(sectionLC); it != upper; ++it)
- {
- if (it->second.first == entryLC)
- {
- const std::string& valuestring = it->second.second->toString();
- oldValue.push_back(ArgumentCompletionListElement(valuestring, getLowercase(valuestring), "Old value: " + valuestring));
- }
- }
-
- return oldValue;
- }
-
- ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(tclthreads)()
- {
- std::list<unsigned int> threadnumbers = TclThreadManager::getInstance().getThreadList();
- ArgumentCompletionList threads;
-
- for (std::list<unsigned int>::const_iterator it = threadnumbers.begin(); it != threadnumbers.end(); ++it)
- threads.push_back(ArgumentCompletionListElement(multi_cast<std::string>(*it)));
-
- return threads;
- }
- }
-}
Deleted: code/branches/consolecommands3/src/libraries/core/ArgumentCompletionFunctions.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/ArgumentCompletionFunctions.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/ArgumentCompletionFunctions.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,63 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _ArgumentCompletionFunctions_H__
-#define _ArgumentCompletionFunctions_H__
-
-#include "CorePrereqs.h"
-#include "ArgumentCompleter.h"
-
-
-#define ARGUMENT_COMPLETION_FUNCTION_DECLARATION(functionname) \
- _CoreExport ArgumentCompleter* functionname(); \
- _CoreExport ArgumentCompletionList acf_##functionname
-
-#define ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(functionname) \
- ArgumentCompleter* functionname() \
- { \
- static ArgumentCompleter completer = ArgumentCompleter(&acf_##functionname); \
- return &completer; \
- } \
- \
- ArgumentCompletionList acf_##functionname
-
-
-namespace orxonox
-{
- namespace autocompletion
- {
- ARGUMENT_COMPLETION_FUNCTION_DECLARATION(fallback)();
- ARGUMENT_COMPLETION_FUNCTION_DECLARATION(files)(const std::string& fragment);
- ARGUMENT_COMPLETION_FUNCTION_DECLARATION(settingssections)();
- ARGUMENT_COMPLETION_FUNCTION_DECLARATION(settingsentries)(const std::string& fragment, const std::string& section);
- ARGUMENT_COMPLETION_FUNCTION_DECLARATION(settingsvalue)(const std::string& fragment, const std::string& entry, const std::string& section);
- ARGUMENT_COMPLETION_FUNCTION_DECLARATION(tclthreads)();
- }
-}
-
-#endif /* _ArgumentCompletionFunctions_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/ArgumentCompletionListElement.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/ArgumentCompletionListElement.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/ArgumentCompletionListElement.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,73 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _ArgumentCompletionListElement_H__
-#define _ArgumentCompletionListElement_H__
-
-#include "CorePrereqs.h"
-
-#include <list>
-#include <string>
-
-namespace orxonox
-{
- const int ACL_MODE_NORMAL = 1;
- const int ACL_MODE_LOWERCASE = 2;
- const int ACL_MODE_DISPLAY = 4;
-
- typedef std::list<ArgumentCompletionListElement> ArgumentCompletionList;
-
- class _CoreExport ArgumentCompletionListElement
- {
- public:
- ArgumentCompletionListElement(const std::string& normalcase) : mode_(ACL_MODE_NORMAL), normalCase_(normalcase) {}
- ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase) : mode_(ACL_MODE_NORMAL | ACL_MODE_LOWERCASE), normalCase_(normalcase), lowerCase_(lowercase) {}
- ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase, const std::string& display) : mode_(ACL_MODE_NORMAL | ACL_MODE_LOWERCASE | ACL_MODE_DISPLAY), normalCase_(normalcase), lowerCase_(lowercase), display_(display) {}
-
- const std::string& getString() const
- { return this->normalCase_; }
- const std::string& getComparable() const
- { if (this->mode_ & ACL_MODE_LOWERCASE) { return this->lowerCase_; } else { return this->normalCase_; } }
- const std::string& getDisplay() const
- { if (this->mode_ & ACL_MODE_DISPLAY) { return this->display_; } else { return this->normalCase_; } }
-
- bool lowercaseComparison() const
- { return (this->mode_ & ACL_MODE_LOWERCASE); }
-
- bool operator<(const ArgumentCompletionListElement& other) const
- { return (this->getComparable() < other.getComparable()); }
-
- private:
- unsigned char mode_;
- std::string normalCase_;
- std::string lowerCase_;
- std::string display_;
- };
-}
-
-#endif /* _ArgumentCompletionListElement_H__ */
Modified: code/branches/consolecommands3/src/libraries/core/CMakeLists.txt
===================================================================
--- code/branches/consolecommands3/src/libraries/core/CMakeLists.txt 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/CMakeLists.txt 2010-08-22 22:54:08 UTC (rev 7202)
@@ -18,6 +18,7 @@
#
SET_SOURCE_FILES(CORE_SRC_FILES
+ CommandLineParser.cc
ConfigValueContainer.cc
Core.cc
DynLib.cc
@@ -28,7 +29,6 @@
GameState.cc
GraphicsManager.cc
GUIManager.cc
- IOConsole.cc
Language.cc
LuaState.cc
ObjectListBase.cc
@@ -37,14 +37,6 @@
ScopedSingletonManager.cc
WindowEventListener.cc
- # command
- CommandEvaluation.cc
- CommandExecutor.cc
- CommandLineParser.cc
- ConsoleCommand.cc
- ConsoleCommandCompilation.cc
- Executor.cc
-
# hierarchy
Identifier.cc
MetaObjectList.cc
@@ -59,13 +51,8 @@
XMLPort.cc
XMLNameListener.cc
- # shell
- IRC.cc
- Shell.cc
- TclBind.cc
-
COMPILATION_BEGIN FilesystemCompilation.cc
- ArgumentCompletionFunctions.cc
+ command/ArgumentCompletionFunctions.cc
ConfigFileManager.cc
MemoryArchive.cc
PathConfig.cc
@@ -74,17 +61,18 @@
# multithreading
ThreadPool.cc
COMPILATION_BEGIN ThreadCompilation.cc
- TclThreadManager.cc
+ command/TclThreadManager.cc
Thread.cc
COMPILATION_END
)
+ADD_SUBDIRECTORY(command)
ADD_SUBDIRECTORY(input)
ORXONOX_ADD_LIBRARY(core
FIND_HEADER_FILES
TOLUA_FILES
- CommandExecutor.h
+ command/CommandExecutor.h
ConfigFileManager.h
Game.h
GameMode.h
Deleted: code/branches/consolecommands3/src/libraries/core/CommandEvaluation.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/CommandEvaluation.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/CommandEvaluation.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,307 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#include "CommandEvaluation.h"
-
-#include "util/Debug.h"
-#include "util/StringUtils.h"
-#include "ConsoleCommand.h"
-#include "Identifier.h"
-
-namespace orxonox
-{
- CommandEvaluation::CommandEvaluation()
- {
- this->initialize("");
- this->state_ = CommandState::Uninitialized;
- }
-
- void CommandEvaluation::initialize(const std::string& command)
- {
- this->bNewCommand_ = true;
- this->bCommandChanged_ = false;
- this->originalCommand_ = command;
- this->command_ = command;
- this->commandTokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
-
- this->additionalParameter_.clear();
-
- this->bEvaluatedParams_ = false;
-
- this->listOfPossibleIdentifiers_.clear();
- this->listOfPossibleFunctions_.clear();
- this->listOfPossibleArguments_.clear();
-
- this->functionclass_ = 0;
- this->function_ = 0;
- this->possibleArgument_.clear();
- this->argument_.clear();
-
- this->errorMessage_.clear();
- this->state_ = CommandState::Empty;
- }
-
- bool CommandEvaluation::isValid() const
- {
- return (this->function_);
- }
-
- bool CommandEvaluation::execute() const
- {
- bool success;
- this->query(&success);
- return success;
- }
-
- MultiType CommandEvaluation::query(bool* success) const
- {
- if (success)
- *success = false;
-
- if (!this->isValid())
- return MT_Type::Null;
-
- if (this->bEvaluatedParams_ && this->function_)
- {
- if (success)
- *success = true;
- COUT(6) << "CE_execute (evaluation): " << this->function_->getName() << ' ' << this->param_[0] << ' ' << this->param_[1] << ' ' << this->param_[2] << ' ' << this->param_[3] << ' ' << this->param_[4] << std::endl;
- return (*this->function_)(this->param_[0], this->param_[1], this->param_[2], this->param_[3], this->param_[4]);
- }
-
- if (!this->bCommandChanged_ || nocaseCmp(removeTrailingWhitespaces(this->command_), removeTrailingWhitespaces(this->originalCommand_)) == 0)
- {
- COUT(4) << "CE_execute: " << this->command_ << "\n";
-
- unsigned int startindex = this->getStartindex();
- if (this->commandTokens_.size() > startindex)
- return this->function_->parse(removeSlashes(this->commandTokens_.subSet(startindex).join() + this->getAdditionalParameter()), success);
- else
- return this->function_->parse(removeSlashes(this->additionalParameter_), success);
- }
-
- return MT_Type::Null;
- }
-
- const std::string& CommandEvaluation::complete()
- {
- if (!this->bNewCommand_)
- {
- switch (this->state_)
- {
- case CommandState::Uninitialized:
- break;
- case CommandState::Empty:
- break;
- case CommandState::ShortcutOrIdentifier:
- if (this->function_)
- {
- if (this->function_->getParamCount() == 0)
- return (this->command_ = this->function_->getName());
- else
- return (this->command_ = this->function_->getName() + ' ');
- }
- else if (this->functionclass_)
- return (this->command_ = this->functionclass_->getName() + ' ');
- break;
- case CommandState::Function:
- if (this->function_)
- {
- if (this->function_->getParamCount() == 0)
- return (this->command_ = this->functionclass_->getName() + ' ' + this->function_->getName());
- else
- return (this->command_ = this->functionclass_->getName() + ' ' + this->function_->getName() + ' ');
- }
- break;
- case CommandState::ParamPreparation:
- case CommandState::Params:
- {
- if (this->argument_.empty() && this->possibleArgument_.empty())
- break;
-
- unsigned int maxIndex = this->commandTokens_.size();
- if (this->command_[this->command_.size() - 1] != ' ')
- maxIndex -= 1;
- std::string whitespace;
-
- if (!this->possibleArgument_.empty())
- {
- this->argument_ = this->possibleArgument_;
- if (this->function_->getParamCount() > (maxIndex + 1 - this->getStartindex()))
- whitespace = " ";
- }
-
- return (this->command_ = this->commandTokens_.subSet(0, maxIndex).join() + ' ' + this->argument_ + whitespace);
- break;
- }
- case CommandState::Finished:
- break;
- case CommandState::Error:
- break;
- }
- }
- this->bNewCommand_ = false;
- return this->command_;
- }
-
- std::string CommandEvaluation::hint() const
- {
- switch (this->state_)
- {
- case CommandState::Uninitialized:
- break;
- case CommandState::Empty:
- case CommandState::ShortcutOrIdentifier:
- if (this->listOfPossibleFunctions_.size() == 0)
- return CommandEvaluation::dump(this->listOfPossibleIdentifiers_);
- else if (this->listOfPossibleIdentifiers_.size() == 0)
- return CommandEvaluation::dump(this->listOfPossibleFunctions_);
- else
- return (CommandEvaluation::dump(this->listOfPossibleFunctions_) + "\n" + CommandEvaluation::dump(this->listOfPossibleIdentifiers_));
- break;
- case CommandState::Function:
- return CommandEvaluation::dump(this->listOfPossibleFunctions_);
- break;
- case CommandState::ParamPreparation:
- case CommandState::Params:
- if (this->listOfPossibleArguments_.size() > 0)
- return CommandEvaluation::dump(this->listOfPossibleArguments_);
- else
- return CommandEvaluation::dump(this->function_);
- case CommandState::Finished:
- if (this->function_)
- return CommandEvaluation::dump(this->function_);
- break;
- case CommandState::Error:
- return this->errorMessage_;
- break;
- }
-
- return "";
- }
-
- void CommandEvaluation::evaluateParams()
- {
- this->bEvaluatedParams_ = false;
-
- for (unsigned int i = 0; i < MAX_FUNCTOR_ARGUMENTS; i++)
- this->param_[i] = MT_Type::Null;
-
- if (!this->isValid())
- return;
-
- unsigned int startindex = this->getStartindex();
-
- if (this->commandTokens_.size() <= startindex)
- {
- if (this->function_->evaluate(this->getAdditionalParameter(), this->param_, " "))
- this->bEvaluatedParams_ = true;
- }
- else if (this->commandTokens_.size() > startindex)
- {
- if (this->function_->evaluate(this->commandTokens_.subSet(startindex).join() + this->getAdditionalParameter(), this->param_, " "))
- this->bEvaluatedParams_ = true;
- }
- }
-
- void CommandEvaluation::setEvaluatedParameter(unsigned int index, MultiType param)
- {
- if (index < MAX_FUNCTOR_ARGUMENTS)
- this->param_[index] = param;
- }
-
- MultiType CommandEvaluation::getEvaluatedParameter(unsigned int index) const
- {
- if (index < MAX_FUNCTOR_ARGUMENTS)
- return this->param_[index];
-
- return MT_Type::Null;
- }
-
- unsigned int CommandEvaluation::getStartindex() const
- {
- if (this->functionclass_ && this->function_)
- return 2;
- else if (this->function_)
- return 1;
- else
- return 0;
- }
-
- std::string CommandEvaluation::dump(const std::list<std::pair<const std::string*, const std::string*> >& list)
- {
- std::string output;
- for (std::list<std::pair<const std::string*, const std::string*> >::const_iterator it = list.begin(); it != list.end(); ++it)
- {
- if (it != list.begin())
- output += ' ';
-
- output += *(it->second);
- }
- return output;
- }
-
- std::string CommandEvaluation::dump(const ArgumentCompletionList& list)
- {
- std::string output;
- for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
- {
- if (it != list.begin())
- output += ' ';
-
- output += it->getDisplay();
- }
- return output;
- }
-
- std::string CommandEvaluation::dump(const ConsoleCommand* command)
- {
- std::string output = command->getName();
- if (command->getParamCount() > 0)
- output += ": ";
-
- for (unsigned int i = 0; i < command->getParamCount(); i++)
- {
- if (i != 0)
- output += ' ';
-
- if (command->defaultValueSet(i))
- output += '[';
- else
- output += '{';
-
- output += command->getTypenameParam(i);
-
- if (command->defaultValueSet(i))
- output += '=' + command->getDefaultValue(i).getString() + ']';
- else
- output += '}';
- }
- return output;
- }
-}
Deleted: code/branches/consolecommands3/src/libraries/core/CommandEvaluation.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/CommandEvaluation.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/CommandEvaluation.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,123 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _CommandEvaluation_H__
-#define _CommandEvaluation_H__
-
-#include "CorePrereqs.h"
-
-#include <string>
-#include <list>
-
-#include "ArgumentCompletionListElement.h"
-#include "util/SubString.h"
-#include "util/MultiType.h"
-
-namespace orxonox
-{
- namespace CommandState
- {
- enum Value
- {
- Uninitialized,
- Empty,
- ShortcutOrIdentifier,
- Function,
- ParamPreparation,
- Params,
- Finished,
- Error
- };
- }
-
- class _CoreExport CommandEvaluation
- {
- friend class CommandExecutor;
-
- public:
- CommandEvaluation();
-
- void initialize(const std::string& command);
-
- bool execute() const;
- MultiType query(bool* success = 0) const;
-
- const std::string& complete();
- std::string hint() const;
- void evaluateParams();
-
- bool isValid() const;
-
- inline ConsoleCommand* getConsoleCommand() const
- { return this->function_; }
- inline const std::string& getOriginalCommand() const
- { return this->originalCommand_; }
- inline const std::string& getCommand() const
- { return this->command_; }
-
- inline void setAdditionalParameter(const std::string& param)
- { this->additionalParameter_ = param; this->bEvaluatedParams_ = false; }
- inline std::string getAdditionalParameter() const
- { return (!this->additionalParameter_.empty()) ? (' ' + this->additionalParameter_) : ""; }
-
- void setEvaluatedParameter(unsigned int index, MultiType param);
- MultiType getEvaluatedParameter(unsigned int index) const;
-
- private:
- unsigned int getStartindex() const;
- static std::string dump(const std::list<std::pair<const std::string*, const std::string*> >& list);
- static std::string dump(const ArgumentCompletionList& list);
- static std::string dump(const ConsoleCommand* command);
-
-
- bool bNewCommand_;
- bool bCommandChanged_;
-
- std::string originalCommand_;
- std::string command_;
- SubString commandTokens_;
- std::string additionalParameter_;
-
- std::list<std::pair<const std::string*, const std::string*> > listOfPossibleIdentifiers_;
- std::list<std::pair<const std::string*, const std::string*> > listOfPossibleFunctions_;
- ArgumentCompletionList listOfPossibleArguments_;
-
- Identifier* functionclass_;
- ConsoleCommand* function_;
- std::string possibleArgument_;
- std::string argument_;
-
- std::string errorMessage_;
- CommandState::Value state_;
-
- bool bEvaluatedParams_;
- MultiType param_[5];
- };
-}
-
-#endif /* _CommandEvaluation_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/CommandExecutor.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/CommandExecutor.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/CommandExecutor.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,699 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#include "CommandExecutor.h"
-
-#include "util/Debug.h"
-#include "util/StringUtils.h"
-#include "ConsoleCommand.h"
-#include "Identifier.h"
-#include "Language.h"
-#include "TclBind.h"
-
-namespace orxonox
-{
- CommandExecutor& CommandExecutor::getInstance()
- {
- static CommandExecutor instance;
- return instance;
- }
-
- CommandEvaluation& CommandExecutor::getEvaluation()
- {
- return CommandExecutor::getInstance().evaluation_;
- }
-
- const CommandEvaluation& CommandExecutor::getLastEvaluation()
- {
- return CommandExecutor::getInstance().evaluation_;
- }
-
- ConsoleCommand& CommandExecutor::addConsoleCommandShortcut(ConsoleCommand* command, bool bDeleteAtExit)
- {
- std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(command->getName());
- if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
- {
- COUT(2) << "Warning: Overwriting console-command shortcut with name " << command->getName() << '.' << std::endl;
- }
-
- // Make sure we can also delete the external ConsoleCommands that don't belong to an Identifier
- if (command && bDeleteAtExit)
- {
- CommandExecutor::getInstance().consoleCommandExternals_.insert(command);
- }
-
- CommandExecutor::getInstance().consoleCommandShortcuts_[command->getName()] = command;
- CommandExecutor::getInstance().consoleCommandShortcuts_LC_[getLowercase(command->getName())] = command;
- return (*command);
- }
-
- /**
- @brief Returns the executor of a console command shortcut with given name.
- @brief name The name of the requested console command shortcut
- @return The executor of the requested console command shortcut
- */
- ConsoleCommand* CommandExecutor::getConsoleCommandShortcut(const std::string& name)
- {
- std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(name);
- if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
- return it->second;
- else
- return 0;
- }
-
- /**
- @brief Returns the executor of a console command shortcut with given name in lowercase.
- @brief name The name of the requested console command shortcut in lowercase
- @return The executor of the requested console command shortcut
- */
- ConsoleCommand* CommandExecutor::getLowercaseConsoleCommandShortcut(const std::string& name)
- {
- std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_LC_.find(name);
- if (it != CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end())
- return it->second;
- else
- return 0;
- }
-
- bool CommandExecutor::execute(const std::string& command, bool useTcl)
- {
- if (useTcl)
- {
- bool success;
- TclBind::eval(command, &success);
- return success;
- }
- else
- {
- CommandExecutor::parseIfNeeded(command);
- return CommandExecutor::getEvaluation().execute();
- }
- }
-
- MultiType CommandExecutor::queryMT(const std::string& command, bool* success, bool useTcl)
- {
- if (useTcl)
- {
- return TclBind::eval(command, success);
- }
- else
- {
- CommandExecutor::parseIfNeeded(command);
- return CommandExecutor::getEvaluation().query(success);
- }
- }
-
- std::string CommandExecutor::query(const std::string& command, bool* success, bool useTcl)
- {
- if (useTcl)
- {
- return TclBind::eval(command, success);
- }
- else
- {
- CommandExecutor::parseIfNeeded(command);
- return CommandExecutor::getEvaluation().query(success).getString();
- }
- }
-
- std::string CommandExecutor::complete(const std::string& command)
- {
- CommandExecutor::parseIfNeeded(command);
- return CommandExecutor::getEvaluation().complete();
- }
-
- std::string CommandExecutor::hint(const std::string& command)
- {
- CommandExecutor::parseIfNeeded(command);
- return CommandExecutor::getEvaluation().hint();
- }
-
- CommandEvaluation CommandExecutor::evaluate(const std::string& command)
- {
- CommandExecutor::parse(command);
- CommandExecutor::getEvaluation().evaluateParams();
- return CommandExecutor::getEvaluation();
- }
-
- void CommandExecutor::parseIfNeeded(const std::string& command)
- {
- if (CommandExecutor::getEvaluation().state_ == CommandState::Uninitialized)
- {
- CommandExecutor::parse(command);
- }
- else if (CommandExecutor::getEvaluation().originalCommand_ != command)
- {
- if (CommandExecutor::getEvaluation().command_ == command)
- {
- CommandExecutor::parse(command);
- CommandExecutor::getEvaluation().bNewCommand_ = false;
- }
- else
- {
- CommandExecutor::parse(command);
- }
- }
- }
-
- void CommandExecutor::parse(const std::string& command, bool bInitialize)
- {
- if (bInitialize)
- CommandExecutor::getEvaluation().initialize(command);
-
- CommandExecutor::getEvaluation().commandTokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
- CommandExecutor::getEvaluation().command_ = command;
-
- switch (CommandExecutor::getEvaluation().state_)
- {
- case CommandState::Uninitialized:
- {
- // Impossible
- break;
- }
- case CommandState::Empty:
- {
- if (CommandExecutor::argumentsGiven() == 0)
- {
- CommandExecutor::createListOfPossibleFunctions("");
- CommandExecutor::createListOfPossibleIdentifiers("");
- break;
- }
- else
- {
- CommandExecutor::getEvaluation().state_ = CommandState::ShortcutOrIdentifier;
- // Move on to next case
- }
- }
- case CommandState::ShortcutOrIdentifier:
- {
- if (CommandExecutor::argumentsGiven() > 1)
- {
- // There's a finished first argument - check if it's a shortcut or a classname
- CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0));
- CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0));
-
- if (CommandExecutor::getEvaluation().function_)
- {
- // It's a shortcut
- CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
- CommandExecutor::getEvaluation().functionclass_ = 0;
- // Move on to next case
- }
- else if (CommandExecutor::getEvaluation().functionclass_)
- {
- // It's a functionname
- CommandExecutor::getEvaluation().state_ = CommandState::Function;
- CommandExecutor::getEvaluation().function_ = 0;
- // Move on to next case
- }
- else
- {
- // The first argument is bad
- CommandExecutor::getEvaluation().state_ = CommandState::Error;
- AddLanguageEntry("commandexecutorunknownfirstargument", "is not a shortcut nor a classname");
- CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(0) + ' ' + GetLocalisation("commandexecutorunknownfirstargument") + '.';
- return;
- }
- }
- else
- {
- // There's no finished first argument - search possible shortcuts or classnames
- CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(0));
- CommandExecutor::createListOfPossibleIdentifiers(CommandExecutor::getArgument(0));
-
- unsigned int num_functions = CommandExecutor::getEvaluation().listOfPossibleFunctions_.size();
- unsigned int num_identifiers = CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.size();
-
- if (num_functions == 1 && num_identifiers == 0)
- {
- // It's a shortcut
- const std::string& functionname = *CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()->first;
- CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(functionname);
- if (getLowercase(functionname) != getLowercase(CommandExecutor::getArgument(0)))
- {
- // Unfinished shortcut
- CommandExecutor::getEvaluation().bCommandChanged_ = true;
- }
- CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
- CommandExecutor::getEvaluation().functionclass_ = 0;
- CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().function_->getName();
- if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
- {
- CommandExecutor::getEvaluation().command_ += ' ';
- CommandExecutor::getEvaluation().bCommandChanged_ = true;
- }
- // Move on to next case
- }
- else if (num_identifiers == 1 && num_functions == 0)
- {
- // It's a classname
- const std::string& classname = *CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.begin()->first;
- CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(classname);
- if (getLowercase(classname) != getLowercase(CommandExecutor::getArgument(0)))
- {
- // Unfinished classname
- CommandExecutor::getEvaluation().bCommandChanged_ = true;
- }
- CommandExecutor::getEvaluation().state_ = CommandState::Function;
- CommandExecutor::getEvaluation().function_ = 0;
- CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + ' ';
- // Move on to next case
- }
- else if (num_identifiers == 0 && num_functions == 0)
- {
- // No possibilities
- CommandExecutor::getEvaluation().state_ = CommandState::Error;
- AddLanguageEntry("commandexecutorunknownfirstargumentstart", "There is no command or classname starting with");
- CommandExecutor::getEvaluation().errorMessage_ = "Error: " + GetLocalisation("commandexecutorunknownfirstargumentstart") + ' ' + CommandExecutor::getArgument(0) + '.';
- return;
- }
- else
- {
- // There are several possiblilities
- std::list<std::pair<const std::string*, const std::string*> > temp;
- temp.insert(temp.end(), CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin(), CommandExecutor::getEvaluation().listOfPossibleFunctions_.end());
- temp.insert(temp.end(), CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.begin(), CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.end());
- CommandExecutor::getEvaluation().command_ = CommandExecutor::getCommonBegin(temp);
- CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0));
- CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0));
- CommandExecutor::getEvaluation().bCommandChanged_ = true;
- return;
- }
- }
- }
- case CommandState::Function:
- {
- if (CommandExecutor::getEvaluation().functionclass_)
- {
- // There is a classname - search for the commandname
- if (CommandExecutor::argumentsGiven() > 2)
- {
- // There is a finished second argument - check if it's a commandname
- CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
-
- if (CommandExecutor::getEvaluation().function_)
- {
- // It's a function
- CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
- // Move on to next case
- }
- else
- {
- // The second argument is bad
- CommandExecutor::getEvaluation().state_ = CommandState::Error;
- AddLanguageEntry("commandexecutorunknownsecondargument", "is not a function of");
- CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(1) + " " + GetLocalisation("commandexecutorunknownsecondargument") + " " + CommandExecutor::getEvaluation().functionclass_->getName() + ".";
- return;
- }
- }
- else
- {
- // There is no finished second argument - search for possibilities
- CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
- unsigned int num_functions = CommandExecutor::getEvaluation().listOfPossibleFunctions_.size();
-
- if (num_functions == 1)
- {
- // It's a function
- const std::string& functionname = *CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()->first;
- CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(functionname, CommandExecutor::getEvaluation().functionclass_);
- if (getLowercase(functionname) != getLowercase(CommandExecutor::getArgument(1)))
- {
- // Unfinished function
- CommandExecutor::getEvaluation().bCommandChanged_ = true;
- }
- CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
- CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + ' ' + CommandExecutor::getEvaluation().function_->getName();
- if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
- {
- CommandExecutor::getEvaluation().command_ += ' ';
- CommandExecutor::getEvaluation().bCommandChanged_ = true;
- }
- // Move on to next case
- }
- else if (num_functions == 0)
- {
- // No possibilities
- CommandExecutor::getEvaluation().state_ = CommandState::Error;
- AddLanguageEntry("commandexecutorunknownsecondargumentstart", "has no function starting with");
- CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getEvaluation().functionclass_->getName() + ' ' + GetLocalisation("commandexecutorunknownsecondargumentstart") + ' ' + CommandExecutor::getArgument(1) + '.';
- return;
- }
- else
- {
- // There are several possibilities
- CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + ' ' + CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleFunctions_);
- CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
- CommandExecutor::getEvaluation().bCommandChanged_ = true;
- return;
- }
- }
- }
- else
- {
- // There is no classname - move on to CommandState::ParamPreparation
- }
- }
- case CommandState::ParamPreparation:
- {
- if (CommandExecutor::getEvaluation().function_->getParamCount() == 0 || CommandExecutor::enoughArgumentsGiven(CommandExecutor::getEvaluation().function_))
- {
- CommandExecutor::getEvaluation().state_ = CommandState::Finished;
- return;
- }
- else
- {
- unsigned int argumentNumber = CommandExecutor::argumentsGiven() - 2;
- if (CommandExecutor::getEvaluation().functionclass_)
- argumentNumber -= 1;
-
- CommandExecutor::createListOfPossibleArguments(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
- CommandExecutor::getEvaluation().state_ = CommandState::Params;
-
- if (CommandExecutor::getEvaluation().bCommandChanged_)
- {
- // Don't do more than one change
- return;
- }
- }
- }
- case CommandState::Params:
- {
- if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 1)
- {
- // There is exactly one possible argument
- CommandExecutor::getEvaluation().argument_ = CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()->getString();
- CommandExecutor::getEvaluation().possibleArgument_ = CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()->getString();
- CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
- return;
- }
- else if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 0)
- {
- // The user tries something new - we let him do
- CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
- CommandExecutor::getEvaluation().argument_ = CommandExecutor::getLastArgument();
- return;
- }
- else
- {
- // There are several possibilities
- unsigned int argumentNumber = CommandExecutor::argumentsGiven();
- if (argumentNumber > 0)
- --argumentNumber;
- if (CommandExecutor::getEvaluation().functionclass_ && argumentNumber > 0)
- --argumentNumber;
-
- CommandExecutor::getEvaluation().argument_ = CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleArguments_);
- CommandExecutor::getEvaluation().possibleArgument_ = CommandExecutor::getPossibleArgument(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
- CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
- return;
- }
- }
- case CommandState::Finished:
- {
- // Nothing more to do
- break;
- }
- case CommandState::Error:
- {
- // Bad, very bad
- break;
- }
- }
- }
-
- unsigned int CommandExecutor::argumentsFinished()
- {
- unsigned int argumentsGiven = CommandExecutor::argumentsGiven();
- if (argumentsGiven > 0)
- return argumentsGiven - 1;
- else
- return 0;
- }
-
- unsigned int CommandExecutor::argumentsGiven()
- {
- if (CommandExecutor::getEvaluation().command_.size() > 0 && CommandExecutor::getEvaluation().command_[CommandExecutor::getEvaluation().command_.size() - 1] == ' ')
- return CommandExecutor::getEvaluation().commandTokens_.size() + 1;
- else
- return CommandExecutor::getEvaluation().commandTokens_.size();
- }
-
- bool CommandExecutor::enoughArgumentsGiven(ConsoleCommand* command)
- {
- if (CommandExecutor::getEvaluation().functionclass_)
- return (CommandExecutor::argumentsGiven() > (2 + command->getParamCount()));
- else
- return (CommandExecutor::argumentsGiven() > (1 + command->getParamCount()));
- }
-
- const std::string& CommandExecutor::getArgument(unsigned int index)
- {
- if (index < (CommandExecutor::getEvaluation().commandTokens_.size()))
- return CommandExecutor::getEvaluation().commandTokens_[index];
- else
- return BLANKSTRING;
- }
-
- const std::string& CommandExecutor::getLastArgument()
- {
- return CommandExecutor::getArgument(CommandExecutor::argumentsGiven() - 1);
- }
-
- void CommandExecutor::createListOfPossibleIdentifiers(const std::string& fragment)
- {
- CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.clear();
- const std::string& lowercase = getLowercase(fragment);
- for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseStringIdentifierMapBegin(); it != Identifier::getLowercaseStringIdentifierMapEnd(); ++it)
- if (it->second->hasConsoleCommands())
- if (it->first.find(lowercase) == 0 || fragment.empty())
- CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.push_back(std::pair<const std::string*, const std::string*>(&it->first, &it->second->getName()));
- }
-
- void CommandExecutor::createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier)
- {
- CommandExecutor::getEvaluation().listOfPossibleFunctions_.clear();
- const std::string& lowercase = getLowercase(fragment);
- if (!identifier)
- {
- for (std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMapBegin(); it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd(); ++it)
- if (it->first.find(lowercase) == 0 || fragment.empty())
- CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&it->first, &it->second->getName()));
- }
- else
- {
- for (std::map<std::string, ConsoleCommand*>::const_iterator it = identifier->getLowercaseConsoleCommandMapBegin(); it != identifier->getLowercaseConsoleCommandMapEnd(); ++it)
- if (it->first.find(lowercase) == 0 || fragment.empty())
- CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&it->first, &it->second->getName()));
- }
- }
-
- void CommandExecutor::createListOfPossibleArguments(const std::string& fragment, ConsoleCommand* command, unsigned int param)
- {
- CommandExecutor::createArgumentCompletionList(command, param);
-
- CommandExecutor::getEvaluation().listOfPossibleArguments_.clear();
- const std::string& lowercase = getLowercase(fragment);
- for (ArgumentCompletionList::const_iterator it = command->getArgumentCompletionListBegin(); it != command->getArgumentCompletionListEnd(); ++it)
- {
- if (it->lowercaseComparison())
- {
- if (it->getComparable().find(lowercase) == 0 || fragment.empty())
- CommandExecutor::getEvaluation().listOfPossibleArguments_.push_back(*it);
- }
- else
- {
- if (it->getComparable().find(fragment) == 0 || fragment.empty())
- CommandExecutor::getEvaluation().listOfPossibleArguments_.push_back(*it);
- }
- }
- }
-
- Identifier* CommandExecutor::getPossibleIdentifier(const std::string& name)
- {
- const std::string& lowercase = getLowercase(name);
- std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseStringIdentifierMap().find(lowercase);
- if ((it != Identifier::getLowercaseStringIdentifierMapEnd()) && it->second->hasConsoleCommands())
- return it->second;
-
- return 0;
- }
-
- ConsoleCommand* CommandExecutor::getPossibleCommand(const std::string& name, Identifier* identifier)
- {
- const std::string& lowercase = getLowercase(name);
- if (!identifier)
- {
- std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMap().find(lowercase);
- if (it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd())
- return it->second;
- }
- else
- {
- std::map<std::string, ConsoleCommand*>::const_iterator it = identifier->getLowercaseConsoleCommandMap().find(lowercase);
- if (it != identifier->getLowercaseConsoleCommandMapEnd())
- return it->second;
- }
- return 0;
- }
-
- const std::string& CommandExecutor::getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param)
- {
- CommandExecutor::createArgumentCompletionList(command, param);
-
- const std::string& lowercase = getLowercase(name);
- for (ArgumentCompletionList::const_iterator it = command->getArgumentCompletionListBegin(); it != command->getArgumentCompletionListEnd(); ++it)
- {
- if (it->lowercaseComparison())
- {
- if (it->getComparable() == lowercase)
- return it->getString();
- }
- else
- {
- if (it->getComparable() == name)
- return it->getString();
- }
- }
-
- return BLANKSTRING;
- }
-
- void CommandExecutor::createArgumentCompletionList(ConsoleCommand* command, unsigned int param)
- {
- std::string params[5];
-
- unsigned int index = 0;
- unsigned int lowestIndex = 1 + (CommandExecutor::getEvaluation().functionclass_ != 0);
-
- for (unsigned int i = CommandExecutor::argumentsGiven() - 1; i >= lowestIndex; --i)
- {
- params[index] = CommandExecutor::getArgument(i);
- ++index;
- if (index >= 5)
- break;
- }
-
- command->createArgumentCompletionList(param, params[0], params[1], params[2], params[3], params[4]);
- }
-
- std::string CommandExecutor::getCommonBegin(const std::list<std::pair<const std::string*, const std::string*> >& list)
- {
- if (list.size() == 0)
- {
- return "";
- }
- else if (list.size() == 1)
- {
- return ((*list.begin()->first) + ' ');
- }
- else
- {
- std::string output;
- for (unsigned int i = 0; true; i++)
- {
- char temp = 0;
- for (std::list<std::pair<const std::string*, const std::string*> >::const_iterator it = list.begin(); it != list.end(); ++it)
- {
- if (it->first->size() > i)
- {
- if (it == list.begin())
- {
- temp = (*it->first)[i];
- }
- else
- {
- if (temp != (*it->first)[i])
- return output;
- }
- }
- else
- {
- return output;
- }
- }
- output += temp;
- }
- return output;
- }
- }
-
- std::string CommandExecutor::getCommonBegin(const ArgumentCompletionList& list)
- {
- if (list.size() == 0)
- {
- return "";
- }
- else if (list.size() == 1)
- {
- return (list.begin()->getComparable() + ' ');
- }
- else
- {
- std::string output;
- for (unsigned int i = 0; true; i++)
- {
- char tempComparable = 0;
- char temp = 0;
- for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
- {
- const std::string& argumentComparable = it->getComparable();
- const std::string& argument = it->getString();
- if (argument.size() > i)
- {
- if (it == list.begin())
- {
- tempComparable = argumentComparable[i];
- temp = argument[i];
- }
- else
- {
- if (tempComparable != argumentComparable[i])
- return output;
- else if (temp != argument[i])
- temp = tempComparable;
- }
- }
- else
- {
- return output;
- }
- }
- output += temp;
- }
- return output;
- }
- }
-
- void CommandExecutor::destroyExternalCommands()
- {
- for (std::set<ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandExternals_.begin();
- it != CommandExecutor::getInstance().consoleCommandExternals_.end(); ++it)
- delete *it;
- }
-}
Deleted: code/branches/consolecommands3/src/libraries/core/CommandExecutor.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/CommandExecutor.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/CommandExecutor.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,115 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _CommandExecutor_H__
-#define _CommandExecutor_H__
-
-#include "CorePrereqs.h"
-
-#include <map>
-#include <set>
-#include <string>
-
-#include "util/MultiType.h"
-#include "CommandEvaluation.h"
-
-// tolua_begin
-namespace orxonox
-{
- class _CoreExport CommandExecutor
- {
-// tolua_end
- public:
- static bool execute(const std::string& command, bool useTcl = true); // tolua_export
-
- static MultiType queryMT(const std::string& command, bool* success = 0, bool useTcl = true);
- static std::string query(const std::string& command, bool* success = 0, bool useTcl = true); // tolua_export
-
- static std::string complete(const std::string& command);
- static std::string hint(const std::string& command);
-
- static CommandEvaluation evaluate(const std::string& command);
- static const CommandEvaluation& getLastEvaluation();
-
- static ConsoleCommand& addConsoleCommandShortcut(ConsoleCommand* command, bool bDeleteAtExit = false);
- static ConsoleCommand* getConsoleCommandShortcut(const std::string& name);
- static ConsoleCommand* getLowercaseConsoleCommandShortcut(const std::string& name);
-
- /** @brief Returns the map that stores all console commands. @return The const_iterator */
- static inline const std::map<std::string, ConsoleCommand*>& getConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_; }
- /** @brief Returns a const_iterator to the beginning of the map that stores all console commands. @return The const_iterator */
- static inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_.begin(); }
- /** @brief Returns a const_iterator to the end of the map that stores all console commands. @return The const_iterator */
- static inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_.end(); }
-
- /** @brief Returns the map that stores all console commands with their names in lowercase. @return The const_iterator */
- static inline const std::map<std::string, ConsoleCommand*>& getLowercaseConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_; }
- /** @brief Returns a const_iterator to the beginning of the map that stores all console commands with their names in lowercase. @return The const_iterator */
- static inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.begin(); }
- /** @brief Returns a const_iterator to the end of the map that stores all console commands with their names in lowercase. @return The const_iterator */
- static inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end(); }
-
- static void destroyExternalCommands();
-
- private:
- CommandExecutor() {}
- CommandExecutor(const CommandExecutor& other);
- ~CommandExecutor() {}
-
- static CommandExecutor& getInstance();
- static CommandEvaluation& getEvaluation();
-
- static void parseIfNeeded(const std::string& command);
- static void parse(const std::string& command, bool bInitialize = true);
-
- static unsigned int argumentsFinished();
- static unsigned int argumentsGiven();
- static bool enoughArgumentsGiven(ConsoleCommand* command);
- static const std::string& getArgument(unsigned int index);
- static const std::string& getLastArgument();
-
- static void createListOfPossibleIdentifiers(const std::string& fragment);
- static void createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier = 0);
- static void createListOfPossibleArguments(const std::string& fragment, ConsoleCommand* command, unsigned int param);
-
- static Identifier* getPossibleIdentifier(const std::string& name);
- static ConsoleCommand* getPossibleCommand(const std::string& name, Identifier* identifier = 0);
- static const std::string& getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param);
-
- static void createArgumentCompletionList(ConsoleCommand* command, unsigned int param);
- static std::string getCommonBegin(const std::list<std::pair<const std::string*, const std::string*> >& list);
- static std::string getCommonBegin(const ArgumentCompletionList& list);
-
- CommandEvaluation evaluation_;
- std::map<std::string, ConsoleCommand*> consoleCommandShortcuts_;
- std::map<std::string, ConsoleCommand*> consoleCommandShortcuts_LC_;
- std::set<ConsoleCommand*> consoleCommandExternals_;
- }; // tolua_export
-} // tolua_export
-
-#endif /* _CommandExecutor_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/ConsoleCommand.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/ConsoleCommand.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/ConsoleCommand.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,295 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#include "ConsoleCommand.h"
-#include <cassert>
-
-#include "Language.h"
-
-namespace orxonox
-{
- ConsoleCommand::ConsoleCommand(const FunctorPtr& functor, const std::string& name) : Executor(functor, name)
- {
- this->accessLevel_ = AccessLevel::None;
- this->argumentCompleter_[0] = 0;
- this->argumentCompleter_[1] = 0;
- this->argumentCompleter_[2] = 0;
- this->argumentCompleter_[3] = 0;
- this->argumentCompleter_[4] = 0;
-
- this->keybindMode_ = KeybindMode::OnPress;
- this->inputConfiguredParam_ = -1;
- }
-
- ConsoleCommand& ConsoleCommand::argumentCompleter(unsigned int param, ArgumentCompleter* completer)
- {
- if (param < 5)
- this->argumentCompleter_[param] = completer;
- else
- {
- COUT(2) << "Warning: Couldn't add autocompletion-function for param " << param << ": index out of bound." << std::endl;
- }
- return (*this);
- }
-
- ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int param) const
- {
- if (param < 5)
- return this->argumentCompleter_[param];
- else
- return 0;
- }
-
- void ConsoleCommand::createArgumentCompletionList(unsigned int param, const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5)
- {
- if (param < 5 && this->argumentCompleter_[param])
- this->argumentList_ = (*this->argumentCompleter_[param])(param1, param2, param3, param4, param5);
- else
- this->argumentList_.clear();
- }
-
- ConsoleCommand& ConsoleCommand::description(const std::string& description)
- {
- this->description_ = std::string("ConsoleCommandDescription::" + this->name_ + "::function");
- AddLanguageEntry(this->description_, description);
- return (*this);
- }
-
- const std::string& ConsoleCommand::getDescription() const
- {
- return GetLocalisation_noerror(this->description_);
- }
-
- ConsoleCommand& ConsoleCommand::descriptionParam(unsigned int param, const std::string& description)
- {
- if (param < MAX_FUNCTOR_ARGUMENTS)
- {
- this->descriptionParam_[param] = std::string("ConsoleCommandDescription::" + this->name_ + "::param" + multi_cast<std::string>(param));
- AddLanguageEntry(this->descriptionParam_[param], description);
- }
- return (*this);
- }
-
- const std::string& ConsoleCommand::getDescriptionParam(unsigned int param) const
- {
- if (param < MAX_FUNCTOR_ARGUMENTS)
- return GetLocalisation_noerror(this->descriptionParam_[param]);
-
- return this->descriptionParam_[0];
- }
-
- ConsoleCommand& ConsoleCommand::descriptionReturnvalue(const std::string& description)
- {
- this->descriptionReturnvalue_ = std::string("ConsoleCommandDescription::" + this->name_ + "::returnvalue");
- AddLanguageEntry(this->descriptionReturnvalue_, description);
- return (*this);
- }
-
- const std::string& ConsoleCommand::getDescriptionReturnvalue(int param) const
- {
- return GetLocalisation_noerror(this->descriptionReturnvalue_);
- }
-}
-
-#include "BaseObject.h" // remove this
-
-namespace orxonox
-{
- _SetConsoleCommand("BaseObject", "setName", &BaseObject::setName, (BaseObject*)0);
- _ConsoleCommand::_ConsoleCommandManipulator test(_ModifyConsoleCommand("BaseObject", "setName").setFunction(&BaseObject::setActive));
-
- _ConsoleCommand::_ConsoleCommand(const std::string& group, const std::string& name, const FunctorPtr& functor, bool bInitialized) : Executor(functor, name), functionHeader_(functor->getHeaderIdentifier())
- {
- this->bActive_ = true;
- this->bInitialized_ = bInitialized;
- _ConsoleCommand::registerCommand(group, name, this);
- }
-
- _ConsoleCommand& _ConsoleCommand::addShortcut()
- {
- _ConsoleCommand::registerCommand("", this->getName(), this);
- return *this;
- }
-
- _ConsoleCommand& _ConsoleCommand::addShortcut(const std::string& name)
- {
- _ConsoleCommand::registerCommand("", name, this);
- return *this;
- }
-
- _ConsoleCommand& _ConsoleCommand::addGroup(const std::string& group)
- {
- _ConsoleCommand::registerCommand(group, this->getName(), this);
- return *this;
- }
-
- _ConsoleCommand& _ConsoleCommand::addGroup(const std::string& group, const std::string& name)
- {
- _ConsoleCommand::registerCommand(group, name, this);
- return *this;
- }
-
- bool _ConsoleCommand::setFunctor(const FunctorPtr& functor, bool bForce)
- {
- if (!functor)
- {
- this->bInitialized_ = false;
- return true;
- }
-
- if (!bForce && !this->functionHeaderMatches(functor))
- {
- COUT(1) << "Error: Couldn't assign new function to console command with name \"" << this->getName() << "\", headers don't match." << std::endl;
- return false;
- }
-
- this->functor_ = functor;
- this->bInitialized_ = true;
- return true;
- }
-
- void _ConsoleCommand::pushFunctor(const FunctorPtr& functor, bool bForce)
- {
- const FunctorPtr& oldfunctor = this->getFunctor();
-
- if (this->setFunctor(functor, bForce));
- this->functorStack_.push(oldfunctor);
- }
-
- void _ConsoleCommand::popFunctor()
- {
- FunctorPtr newfunctor;
- if (!this->functorStack_.empty())
- {
- newfunctor = this->functorStack_.top();
- this->functorStack_.pop();
- }
- this->setFunctor(newfunctor);
- }
-
- const FunctorPtr& _ConsoleCommand::getFunctor() const
- {
-// if (this->bInitialized_) // FIXME
- return this->functor_;
-// else
-// return 0;
- }
-
- bool _ConsoleCommand::functionHeaderMatches(const FunctorPtr& functor) const
- {
- if (!this->functor_)
- {
- assert(false);
- return true;
- }
- return (functor->getHeaderIdentifier() == this->functionHeader_);
- }
-
- void _ConsoleCommand::setObject(void* object)
- {
- if (this->functor_)
- this->functor_->setRawObjectPointer(object);
- else if (object)
- COUT(1) << "Error: Can't set object in console command \"" << this->getName() << "\", no functor set." << std::endl;
- }
-
- void _ConsoleCommand::pushObject(void* object)
- {
- if (this->functor_)
- {
- this->objectStack_.push(this->getObject());
- this->setObject(object);
- }
- else
- COUT(1) << "Error: Can't set object in console command \"" << this->getName() << "\", no functor set." << std::endl;
- }
-
- void _ConsoleCommand::popObject()
- {
- void* newobject = 0;
- if (!this->objectStack_.empty())
- {
- newobject = this->objectStack_.top();
- this->objectStack_.pop();
- }
- this->setObject(newobject);
- }
-
- void* _ConsoleCommand::getObject() const
- {
- if (this->functor_)
- return this->functor_->getRawObjectPointer();
- else
- return 0;
- }
-
- /* static */ const _ConsoleCommand* _ConsoleCommand::getCommand(const std::string& group, const std::string& name, bool bPrintError)
- {
- std::map<std::string, std::map<std::string, _ConsoleCommand*> >::const_iterator it_group = _ConsoleCommand::getCommandMap().find(group);
- if (it_group != _ConsoleCommand::getCommandMap().end())
- {
- std::map<std::string, _ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
- if (it_name != it_group->second.end())
- {
- return it_name->second;
- }
- }
- if (bPrintError)
- {
- if (group == "")
- COUT(1) << "Error: Couldn't find console command with shortcut \"" << name << "\"" << std::endl;
- else
- COUT(1) << "Error: Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << std::endl;
- }
- return 0;
- }
-
- /* static */ std::map<std::string, std::map<std::string, _ConsoleCommand*> >& _ConsoleCommand::getCommandMap()
- {
- static std::map<std::string, std::map<std::string, _ConsoleCommand*> > commandMap;
- return commandMap;
- }
-
- /* static */ void _ConsoleCommand::registerCommand(const std::string& group, const std::string& name, _ConsoleCommand* command)
- {
- if (name == "")
- return;
-
- if (_ConsoleCommand::getCommand(group, name) != 0)
- {
- if (group == "")
- COUT(2) << "Warning: A console command with shortcut name \"" << name << "\" already exists." << std::endl;
- else
- COUT(2) << "Warning: A console command with group \"" << group << "\" and name \"" << name << "\" already exists." << std::endl;
- }
- else
- {
- _ConsoleCommand::getCommandMap()[group][name] = command;
- }
- }
-}
Deleted: code/branches/consolecommands3/src/libraries/core/ConsoleCommand.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/ConsoleCommand.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/ConsoleCommand.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,303 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _ConsoleCommand_H__
-#define _ConsoleCommand_H__
-
-#include "CorePrereqs.h"
-
-#include <stack>
-#include <boost/preprocessor/cat.hpp>
-#include <boost/preprocessor/facilities/expand.hpp>
-
-#include "util/VA_NARGS.h"
-#include "ArgumentCompletionFunctions.h"
-#include "CommandExecutor.h"
-#include "Executor.h"
-#include "Identifier.h"
-
-
-#define SetConsoleCommand(classname, function, bCreateShortcut) \
- SetConsoleCommandGeneric(classname, function, #function, bCreateShortcut)
-#define SetConsoleCommandAlias(classname, function, name, bCreateShortcut) \
- SetConsoleCommandGeneric(classname, function, name, bCreateShortcut)
-
-#define SetConsoleCommandGeneric(classname, function, name, bCreateShortcut) \
- orxonox::ConsoleCommand& BOOST_PP_CAT(classname##function##consolecommand__, __LINE__) = orxonox::ClassIdentifier<classname>::getIdentifier(#classname)->addConsoleCommand(orxonox::createConsoleCommand(orxonox::createFunctor(&classname::function), name), bCreateShortcut)
-
-
-#define SetConsoleCommandShortcut(classname, function) \
- SetConsoleCommandShortcutAliasGeneric(classname, function, #function)
-#define SetConsoleCommandShortcutAlias(classname, function, name) \
- SetConsoleCommandShortcutAliasGeneric(classname, function, name)
-#define SetConsoleCommandShortcutAliasGeneric(classname, function, name) \
- SetConsoleCommandShortcutGeneric(BOOST_PP_CAT(function##consolecommand__, __LINE__), orxonox::createConsoleCommand(orxonox::createFunctor(&classname::function), name))
-
-#define SetConsoleCommandShortcutExtern(function) \
- SetConsoleCommandShortcutExternAliasGeneric(function, #function)
-#define SetConsoleCommandShortcutExternAlias(function, name) \
- SetConsoleCommandShortcutExternAliasGeneric(function, name)
-#define SetConsoleCommandShortcutExternAliasGeneric(function, name) \
- SetConsoleCommandShortcutGeneric(BOOST_PP_CAT(function##consolecommand__, __LINE__), orxonox::createConsoleCommand(orxonox::createFunctor(&function), name))
-
-#define SetConsoleCommandShortcutGeneric(fakevariable, command) \
- orxonox::ConsoleCommand& fakevariable = orxonox::CommandExecutor::addConsoleCommandShortcut(command, true)
-
-
-namespace orxonox
-{
- namespace AccessLevel
- {
- enum Value
- {
- None,
- User,
- Admin,
- Offline,
- Debug,
- Disabled
- };
- }
-
- class _CoreExport ConsoleCommand : public Executor
- {
- public:
- ConsoleCommand(const FunctorPtr& functor, const std::string& name = "");
-
- ConsoleCommand& description(const std::string& description);
- const std::string& getDescription() const;
-
- ConsoleCommand& descriptionParam(unsigned int param, const std::string& description);
- const std::string& getDescriptionParam(unsigned int param) const;
-
- ConsoleCommand& descriptionReturnvalue(const std::string& description);
- const std::string& getDescriptionReturnvalue(int param) const;
-
- inline ConsoleCommand& defaultValues(const MultiType& param1)
- { this->Executor::setDefaultValues(param1); return (*this); }
- inline ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2)
- { this->Executor::setDefaultValues(param1, param2); return (*this); }
- inline ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
- { this->Executor::setDefaultValues(param1, param2, param3); return (*this); }
- inline ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
- { this->Executor::setDefaultValues(param1, param2, param3, param4); return (*this); }
- inline ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
- { this->Executor::setDefaultValues(param1, param2, param3, param4, param5); return (*this); }
- inline ConsoleCommand& defaultValue(unsigned int index, const MultiType& param)
- { this->Executor::setDefaultValue(index, param); return (*this); }
-
- inline ConsoleCommand& accessLevel(AccessLevel::Value level)
- { this->accessLevel_ = level; return (*this); }
- inline AccessLevel::Value getAccessLevel() const
- { return this->accessLevel_; }
-
- ConsoleCommand& argumentCompleter(unsigned int param, ArgumentCompleter* completer);
- ArgumentCompleter* getArgumentCompleter(unsigned int param) const;
-
- void createArgumentCompletionList(unsigned int param, const std::string& param1 = "", const std::string& param2 = "", const std::string& param3 = "", const std::string& param4 = "", const std::string& param5 = "");
- const ArgumentCompletionList& getArgumentCompletionList() const
- { return this->argumentList_; }
- ArgumentCompletionList::const_iterator getArgumentCompletionListBegin() const
- { return this->argumentList_.begin(); }
- ArgumentCompletionList::const_iterator getArgumentCompletionListEnd() const
- { return this->argumentList_.end(); }
-
- inline ConsoleCommand& setAsInputCommand()
- {
- this->keybindMode(KeybindMode::OnHold);
- this->defaultValue(0, Vector2(0.0f, 0.0f));
- this->inputConfiguredParam(0);
- return *this;
- }
-
- inline ConsoleCommand& keybindMode(KeybindMode::Value mode)
- { this->keybindMode_ = mode; return *this; }
- inline KeybindMode::Value getKeybindMode() const
- { return this->keybindMode_; }
-
- inline ConsoleCommand& inputConfiguredParam(int index)
- { this->inputConfiguredParam_ = index; return *this; }
- inline int getInputConfiguredParam_() const
- { return this->inputConfiguredParam_; }
-
- private:
- AccessLevel::Value accessLevel_;
- ArgumentCompleter* argumentCompleter_[5];
- ArgumentCompletionList argumentList_;
-
- KeybindMode::Value keybindMode_;
- int inputConfiguredParam_;
-
- LanguageEntryLabel description_;
- LanguageEntryLabel descriptionReturnvalue_;
- LanguageEntryLabel descriptionParam_[MAX_FUNCTOR_ARGUMENTS];
- };
-
- inline ConsoleCommand* createConsoleCommand(const FunctorPtr& functor, const std::string& name = "")
- {
- return new ConsoleCommand(functor, name);
- }
-}
-
-
-#define _SetConsoleCommand(...) \
- BOOST_PP_EXPAND(BOOST_PP_CAT(_SetConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
-#define _SetConsoleCommand2(name, functionpointer) \
- _SetConsoleCommandGeneric("", name, orxonox::createFunctor(functionpointer))
-#define _SetConsoleCommand3(group, name, functionpointer) \
- _SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer))
-#define _SetConsoleCommand4(group, name, functionpointer, object) \
- _SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer, object))
-
-#define _SetConsoleCommandGeneric(group, name, functor) \
- orxonox::_ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __LINE__) = (*orxonox::_createConsoleCommand(group, name, functor))
-
-
-#define _DeclareConsoleCommand(...) \
- BOOST_PP_CAT(_DeclareConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__)
-#define _DeclareConsoleCommand2(name, functionpointer) \
- _DeclareConsoleCommandGeneric("", name, functionpointer)
-#define _DeclareConsoleCommand3(group, name, functionpointer) \
- _DeclareConsoleCommandGeneric(group, name, functionpointer)
-
-#define _DeclareConsoleCommandGeneric(group, name, functionpointer) \
- orxonox::_ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __LINE__) = (*orxonox::_createConsoleCommand(group, name, orxonox::createFunctor(functionpointer), false))
-
-
-#define _ModifyConsoleCommand(...) \
- orxonox::_ConsoleCommand::getCommand(__VA_ARGS__, true)->getManipulator()
-
-
-namespace orxonox
-{
- class _CoreExport _ConsoleCommand : protected Executor
- {
- friend struct _ConsoleCommandManipulator;
-
- public:
- struct _ConsoleCommandManipulator
- {
- public:
- _ConsoleCommandManipulator(const _ConsoleCommand* command) : command_(const_cast<_ConsoleCommand*>(command)) {}
-
- template <class F>
- inline _ConsoleCommandManipulator& setFunction(F function, bool bForce = false)
- { if (this->command_) { this->command_->setFunctor(createFunctor(function), bForce); } return *this; }
- template <class F, class O>
- inline _ConsoleCommandManipulator& setFunction(F function, O* object, bool bForce = false)
- { if (this->command_) { this->command_->setFunctor(createFunctor(function, object), bForce); } return *this; }
- inline _ConsoleCommandManipulator& setFunction(const FunctorPtr& functor, bool bForce = false)
- { if (this->command_) { this->command_->setFunctor(functor, bForce); } return *this; }
-
- template <class F>
- inline _ConsoleCommandManipulator& pushFunction(F function, bool bForce = false)
- { if (this->command_) { this->command_->pushFunctor(createFunctor(function), bForce); } return *this; }
- template <class F, class O>
- inline _ConsoleCommandManipulator& pushFunction(F function, O* object, bool bForce = false)
- { if (this->command_) { this->command_->pushFunctor(createFunctor(function, object), bForce); } return *this; }
- inline _ConsoleCommandManipulator& pushFunction(const FunctorPtr& functor, bool bForce = false)
- { if (this->command_) { this->command_->pushFunctor(functor, bForce); } return *this; }
-
- inline _ConsoleCommandManipulator& popFunction()
- { if (this->command_) { this->command_->popFunctor(); } return *this; }
-
- inline _ConsoleCommandManipulator& setObject(void* object)
- { if (this->command_) { this->command_->setObject(object); } return *this; }
- inline _ConsoleCommandManipulator& pushObject(void* object)
- { if (this->command_) { this->command_->pushObject(object); } return *this; }
- inline _ConsoleCommandManipulator& popObject()
- { if (this->command_) { this->command_->popObject(); } return *this; }
-
- inline void* getObject() const
- { if (this->command_) { return this->command_->getObject(); } else { return 0; } }
-
- inline _ConsoleCommandManipulator& setActive(bool bActive)
- { if (this->command_) { this->command_->setActive(bActive); } return *this; }
-
- private:
- _ConsoleCommand* command_;
- };
-
- public:
- _ConsoleCommand(const std::string& group, const std::string& name, const FunctorPtr& functor, bool bInitialized = true);
-
- _ConsoleCommand& addShortcut();
- _ConsoleCommand& addShortcut(const std::string& name);
- _ConsoleCommand& addGroup(const std::string& group);
- _ConsoleCommand& addGroup(const std::string& group, const std::string& name);
-
- inline void setActive(bool bActive)
- { this->bActive_ = bActive; }
- inline bool isActive() const
- { return (this->bActive_ && this->bInitialized_); }
-
- inline _ConsoleCommandManipulator getManipulator() const
- { return this; }
-
- static inline const std::map<std::string, std::map<std::string, _ConsoleCommand*> >& getCommands()
- { return _ConsoleCommand::getCommandMap(); }
-
- static inline const _ConsoleCommand* getCommand(const std::string& name, bool bPrintError = false)
- { return _ConsoleCommand::getCommand("", name, bPrintError); }
- static const _ConsoleCommand* getCommand(const std::string& group, const std::string& name, bool bPrintError = false);
-
- private:
- static std::map<std::string, std::map<std::string, _ConsoleCommand*> >& getCommandMap();
- static void registerCommand(const std::string& group, const std::string& name, _ConsoleCommand* command);
-
- bool setFunctor(const FunctorPtr& functor, bool bForce = false);
- void pushFunctor(const FunctorPtr& functor, bool bForce = false);
- void popFunctor();
- const FunctorPtr& getFunctor() const;
-
- bool functionHeaderMatches(const FunctorPtr& functor) const;
-
- void setObject(void* object);
- void pushObject(void* object);
- void popObject();
- void* getObject() const;
-
- bool bActive_;
- bool bInitialized_;
- const std::type_info& functionHeader_;
- std::stack<FunctorPtr> functorStack_;
- std::stack<void*> objectStack_;
- };
-
- inline _ConsoleCommand* _createConsoleCommand(const std::string& name, const FunctorPtr& functor, bool bInitialized = true)
- {
- return new _ConsoleCommand("", name, functor, bInitialized);
- }
-
- inline _ConsoleCommand* _createConsoleCommand(const std::string& group, const std::string& name, const FunctorPtr& functor, bool bInitialized = true)
- {
- return new _ConsoleCommand(group, name, functor, bInitialized);
- }
-}
-
-#endif /* _ConsoleCommand_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/ConsoleCommandCompilation.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/ConsoleCommandCompilation.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/ConsoleCommandCompilation.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,181 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#include "ConsoleCommandCompilation.h"
-
-#include <fstream>
-#include <set>
-#include <string>
-
-#include "util/Debug.h"
-#include "util/ExprParser.h"
-#include "util/StringUtils.h"
-#include "ConsoleCommand.h"
-
-namespace orxonox
-{
- SetConsoleCommandShortcutExtern(source).argumentCompleter(0, autocompletion::files());
- SetConsoleCommandShortcutExtern(echo);
- SetConsoleCommandShortcutExtern(puts);
-
- SetConsoleCommandShortcutExtern(read).argumentCompleter(0, autocompletion::files());
- SetConsoleCommandShortcutExtern(append).argumentCompleter(0, autocompletion::files());
- SetConsoleCommandShortcutExtern(write).argumentCompleter(0, autocompletion::files());
-
- SetConsoleCommandShortcutExtern(calculate);
-
- void source(const std::string& filename)
- {
- static std::set<std::string> executingFiles;
-
- std::set<std::string>::const_iterator it = executingFiles.find(filename);
- if (it != executingFiles.end())
- {
- COUT(1) << "Error: Recurring source command in \"" << filename << "\". Stopped execution." << std::endl;
- return;
- }
-
- // Open the file
- std::ifstream file;
- file.open(filename.c_str(), std::fstream::in);
-
- if (!file.is_open())
- {
- COUT(1) << "Error: Couldn't open file \"" << filename << "\"." << std::endl;
- return;
- }
-
- executingFiles.insert(filename);
-
- // Iterate through the file and put the lines into the CommandExecutor
- while (file.good() && !file.eof())
- {
- std::string line;
- std::getline(file, line);
- CommandExecutor::execute(line);
- }
-
- executingFiles.erase(filename);
- file.close();
- }
-
- std::string echo(const std::string& text)
- {
- return text;
- }
-
- void puts(bool newline, const std::string& text)
- {
- if (newline)
- {
- COUT(0) << stripEnclosingBraces(text) << std::endl;
- }
- else
- {
- COUT(0) << stripEnclosingBraces(text);
- }
- }
-
- void write(const std::string& filename, const std::string& text)
- {
- std::ofstream file;
- file.open(filename.c_str(), std::fstream::out);
-
- if (!file.is_open())
- {
- COUT(1) << "Error: Couldn't write to file \"" << filename << "\"." << std::endl;
- return;
- }
-
- file << text << std::endl;
- file.close();
- }
-
- void append(const std::string& filename, const std::string& text)
- {
- std::ofstream file;
- file.open(filename.c_str(), std::fstream::app);
-
- if (!file.is_open())
- {
- COUT(1) << "Error: Couldn't append to file \"" << filename << "\"." << std::endl;
- return;
- }
-
- file << text << std::endl;
- file.close();
- }
-
- std::string read(const std::string& filename)
- {
- std::ifstream file;
- file.open(filename.c_str(), std::fstream::in);
-
- if (!file.is_open())
- {
- COUT(1) << "Error: Couldn't read from file \"" << filename << "\"." << std::endl;
- return "";
- }
-
- std::string output;
- while (file.good() && !file.eof())
- {
- std::string line;
- std::getline(file, line);
- output += line;
- output += "\n";
- }
-
- file.close();
-
- return output;
- }
-
- float calculate(const std::string& calculation)
- {
- ExprParser expr;
- expr.parse(calculation);
- if (expr.getSuccess())
- {
- if (expr.getResult() == 42.0)
- {
- COUT(3) << "Greetings from the restaurant at the end of the universe." << std::endl;
- }
- if (!expr.getRemains().empty())
- {
- COUT(2) << "Warning: Expression could not be parsed to the end! Remains: '" << expr.getRemains() << '\'' << std::endl;
- }
- return static_cast<float>(expr.getResult());
- }
- else
- {
- COUT(1) << "Error: Cannot calculate expression: Parse error." << std::endl;
- return 0;
- }
- }
-}
Deleted: code/branches/consolecommands3/src/libraries/core/ConsoleCommandCompilation.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/ConsoleCommandCompilation.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/ConsoleCommandCompilation.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,47 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _ConsoleCommandCompilation_H__
-#define _ConsoleCommandCompilation_H__
-
-#include "CorePrereqs.h"
-
-namespace orxonox
-{
- _CoreExport void source(const std::string& filename);
- _CoreExport std::string echo(const std::string& text);
- _CoreExport void puts(bool newline, const std::string& test);
-
- _CoreExport void write(const std::string& filename, const std::string& text);
- _CoreExport void append(const std::string& filename, const std::string& text);
- _CoreExport std::string read(const std::string& filename);
-
- _CoreExport float calculate(const std::string& calculation);
-}
-
-#endif /* _ConsoleCommandCompilation_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/Executor.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/Executor.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/Executor.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,237 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- * Inspiration: Executor by Benjamin Grauer
- */
-
-#include "Executor.h"
-
-#include <algorithm>
-
-#include "util/Convert.h"
-#include "util/Debug.h"
-#include "util/StringUtils.h"
-#include "util/SubString.h"
-
-namespace orxonox
-{
- Executor::Executor(const FunctorPtr& functor, const std::string& name)
- {
- this->functor_ = functor;
- this->name_ = name;
- }
-
- Executor::~Executor()
- {
- }
-
- MultiType Executor::parse(const std::string& params, bool* success, const std::string& delimiter) const
- {
- if (success)
- *success = true;
-
- unsigned int paramCount = this->functor_->getParamCount();
-
- if (paramCount == 0)
- {
- COUT(5) << "Calling Executor " << this->name_ << " through parser without parameters." << std::endl;
- return (*this->functor_)();
- }
- else if (paramCount == 1)
- {
- const std::string& temp = getStripped(params);
- if (!temp.empty())
- {
- COUT(5) << "Calling Executor " << this->name_ << " through parser with one parameter, using whole string: " << params << std::endl;
- return (*this->functor_)(MultiType(params));
- }
- else if (!this->defaultValue_[0].null())
- {
- COUT(5) << "Calling Executor " << this->name_ << " through parser with one parameter, using default value: " << this->defaultValue_[0] << std::endl;
- return (*this->functor_)(this->defaultValue_[0]);
- }
- else
- {
- COUT(2) << "Warning: Can't call executor " << this->name_ << " through parser: Not enough parameters or default values given (input: " << temp << ")." << std::endl;
- if (success)
- *success = false;
- return MT_Type::Null;
- }
- }
- else
- {
- SubString tokens(params, delimiter, SubString::WhiteSpaces, false, '\\', true, '"', true, '(', ')', true, '\0');
-
- for (unsigned int i = tokens.size(); i < this->functor_->getParamCount(); i++)
- {
- if (this->defaultValue_[i].null())
- {
- COUT(2) << "Warning: Can't call executor " << this->name_ << " through parser: Not enough parameters or default values given (input:" << params << ")." << std::endl;
- if (success)
- *success = false;
- return MT_Type::Null;
- }
- }
-
- MultiType param[MAX_FUNCTOR_ARGUMENTS];
- COUT(5) << "Calling Executor " << this->name_ << " through parser with " << paramCount << " parameters, using " << tokens.size() << " tokens (";
- for (unsigned int i = 0; i < tokens.size() && i < MAX_FUNCTOR_ARGUMENTS; i++)
- {
- param[i] = tokens[i];
- if (i != 0)
- {
- COUT(5) << ", ";
- }
- COUT(5) << tokens[i];
- }
- COUT(5) << ") and " << std::max((int)paramCount - (int)tokens.size(), 0) << " default values (";
- for (unsigned int i = tokens.size(); i < paramCount; i++)
- {
- param[i] = this->defaultValue_[i];
- if (i != 0)
- {
- COUT(5) << ", ";
- }
- COUT(5) << this->defaultValue_[i];
- }
- COUT(5) << ")." << std::endl;
-
- if ((tokens.size() > paramCount) && (this->functor_->getTypenameParam(paramCount - 1) == "string"))
- param[paramCount - 1] = tokens.subSet(paramCount - 1).join();
-
- switch(paramCount)
- {
- case 2:
- return (*this->functor_)(param[0], param[1]);
- case 3:
- return (*this->functor_)(param[0], param[1], param[2]);
- case 4:
- return (*this->functor_)(param[0], param[1], param[2], param[3]);
- case 5:
- return (*this->functor_)(param[0], param[1], param[2], param[3], param[4]);
- }
- }
-
- return MT_Type::Null;
- }
-
- bool Executor::evaluate(const std::string& params, MultiType param[5], const std::string& delimiter) const
- {
- unsigned int paramCount = this->functor_->getParamCount();
-
- if (paramCount == 1)
- {
- // only one param: check if there are params given, otherwise try to use default values
- if (!getStripped(params).empty())
- {
- param[0] = params;
- this->functor_->evaluateParam(0, param[0]);
- return true;
- }
- else if (!this->defaultValue_[0].null())
- {
- param[0] = this->defaultValue_[0];
- this->functor_->evaluateParam(0, param[0]);
- return true;
- }
- return false;
- }
- else
- {
- // more than one param
- SubString tokens(params, delimiter, SubString::WhiteSpaces, false, '\\', true, '"', true, '(', ')', true, '\0');
-
- // if there are not enough params given, check if there are default values
- for (unsigned int i = tokens.size(); i < this->functor_->getParamCount(); i++)
- if (this->defaultValue_[i].null())
- return false;
-
- // assign all given arguments to the multitypes
- for (unsigned int i = 0; i < std::min(tokens.size(), MAX_FUNCTOR_ARGUMENTS); i++)
- param[i] = tokens[i];
-
- // fill the remaining multitypes with default values
- for (unsigned int i = tokens.size(); i < std::min(paramCount, MAX_FUNCTOR_ARGUMENTS); i++)
- param[i] = this->defaultValue_[i];
-
- // evaluate the param types through the functor
- for (unsigned int i = 0; i < std::min(paramCount, MAX_FUNCTOR_ARGUMENTS); i++)
- this->functor_->evaluateParam(i, param[i]);
-
- return true;
- }
- }
-
- void Executor::setDefaultValues(const MultiType& param1)
- {
- this->defaultValue_[0] = param1;
- }
-
- void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2)
- {
- this->defaultValue_[0] = param1;
- this->defaultValue_[1] = param2;
- }
-
- void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
- {
- this->defaultValue_[0] = param1;
- this->defaultValue_[1] = param2;
- this->defaultValue_[2] = param3;
- }
-
- void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
- {
- this->defaultValue_[0] = param1;
- this->defaultValue_[1] = param2;
- this->defaultValue_[2] = param3;
- this->defaultValue_[3] = param4;
- }
-
- void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
- {
- this->defaultValue_[0] = param1;
- this->defaultValue_[1] = param2;
- this->defaultValue_[2] = param3;
- this->defaultValue_[3] = param4;
- this->defaultValue_[4] = param5;
- }
-
- void Executor::setDefaultValue(unsigned int index, const MultiType& param)
- {
- if (index < MAX_FUNCTOR_ARGUMENTS)
- this->defaultValue_[index] = param;
- }
-
- bool Executor::allDefaultValuesSet() const
- {
- for (unsigned int i = 0; i < this->functor_->getParamCount(); i++)
- if (this->defaultValue_[i].null())
- return false;
-
- return true;
- }
-}
Deleted: code/branches/consolecommands3/src/libraries/core/Executor.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/Executor.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/Executor.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,206 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- * Inspiration: Executor by Benjamin Grauer
- */
-
-#ifndef _Executor_H__
-#define _Executor_H__
-
-#include "CorePrereqs.h"
-
-#include <string>
-#include "util/MultiType.h"
-#include "Functor.h"
-#include "ExecutorPtr.h"
-
-namespace orxonox
-{
- class _CoreExport Executor
- {
- public:
- Executor(const FunctorPtr& functor, const std::string& name = "");
- virtual ~Executor();
-
- inline MultiType operator()() const
- { return (*this->functor_)(this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const MultiType& param1) const
- { return (*this->functor_)(param1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const MultiType& param1, const MultiType& param2) const
- { return (*this->functor_)(param1, param2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const MultiType& param1, const MultiType& param2, const MultiType& param3) const
- { return (*this->functor_)(param1, param2, param3, this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) const
- { return (*this->functor_)(param1, param2, param3, param4, this->defaultValue_[4]); }
- inline MultiType operator()(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) const
- { return (*this->functor_)(param1, param2, param3, param4, param5); }
-
- MultiType parse(const std::string& params, bool* success = 0, const std::string& delimiter = " ") const;
-
- bool evaluate(const std::string& params, MultiType param[5], const std::string& delimiter = " ") const;
-
- inline const FunctorPtr& getFunctor() const
- { return this->functor_; }
- inline unsigned int getParamCount() const
- { return this->functor_->getParamCount(); }
- inline bool hasReturnvalue() const
- { return this->functor_->hasReturnvalue(); }
- inline Functor::Type::Enum getType() const
- { return this->functor_->getType(); }
- inline std::string getTypenameParam(unsigned int param) const
- { return this->functor_->getTypenameParam(param); }
- inline std::string getTypenameReturnvalue() const
- { return this->functor_->getTypenameReturnvalue(); }
-
- inline void setName(const std::string& name)
- { this->name_ = name; }
- inline const std::string& getName() const
- { return this->name_; }
-
- void setDefaultValues(const MultiType& param1);
- void setDefaultValues(const MultiType& param1, const MultiType& param2);
- void setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3);
- void setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4);
- void setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5);
- void setDefaultValue(unsigned int index, const MultiType& param);
-
- inline MultiType getDefaultValue(unsigned int index) const
- {
- if (index < MAX_FUNCTOR_ARGUMENTS)
- return this->defaultValue_[index];
-
- return MT_Type::Null;
- }
-
- bool allDefaultValuesSet() const;
- inline bool defaultValueSet(unsigned int index) const
- {
- if (index < MAX_FUNCTOR_ARGUMENTS)
- return !this->defaultValue_[index].null();
-
- return false;
- }
-
- protected:
- FunctorPtr functor_;
- std::string name_;
- MultiType defaultValue_[MAX_FUNCTOR_ARGUMENTS];
- };
-
- class _CoreExport ExecutorStatic : public Executor
- {
- public:
- ExecutorStatic(const FunctorStaticPtr& functor, const std::string& name = "") : Executor(functor, name) {}
- virtual ~ExecutorStatic() {}
- };
-
- template <class T>
- class ExecutorMember : public Executor
- {
- public:
- ExecutorMember(const FunctorMemberPtr<T>& functor, const std::string& name = "") : Executor(functor, name), functorMember_(functor) {}
- virtual ~ExecutorMember() {}
-
- using Executor::operator();
-
- inline MultiType operator()(T* object) const
- { return (*this->functorMember_)(object, this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(T* object, const MultiType& param1) const
- { return (*this->functorMember_)(object, param1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2) const
- { return (*this->functorMember_)(object, param1, param2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3) const
- { return (*this->functorMember_)(object, param1, param2, param3, this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) const
- { return (*this->functorMember_)(object, param1, param2, param3, param4, this->defaultValue_[4]); }
- inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) const
- { return (*this->functorMember_)(object, param1, param2, param3, param4, param5); }
-
-
- inline MultiType operator()(const T* object) const
- { return (*this->functorMember_)(object, this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const T* object, const MultiType& param1) const
- { return (*this->functorMember_)(object, param1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2) const
- { return (*this->functorMember_)(object, param1, param2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3) const
- { return (*this->functorMember_)(object, param1, param2, param3, this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) const
- { return (*this->functorMember_)(object, param1, param2, param3, param4, this->defaultValue_[4]); }
- inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) const
- { return (*this->functorMember_)(object, param1, param2, param3, param4, param5); }
-
- inline void setObject(T* object) const
- { this->functorMember_->setObject(object); }
- inline void setObject(const T* object) const
- { this->functorMember_->setObject(object); }
-
- using Executor::parse;
-
- MultiType parse(T* object, const std::string& params, bool* success = 0, const std::string& delimiter = " ") const
- {
- const typename FunctorMember<T>::Objects& objects = this->functorMember_->getObjects();
-
- this->functorMember_->setObject(object);
- const MultiType& result = this->Executor::parse(params, success, delimiter);
- this->functorMember_->setObjects(objects);
-
- return result;
- }
-
- MultiType parse(const T* object, const std::string& params, bool* success = 0, const std::string& delimiter = " ") const
- {
- const typename FunctorMember<T>::Objects& objects = this->functorMember_->getObjects();
-
- this->functorMember_->setObject(object);
- const MultiType& result = this->Executor::parse(params, success, delimiter);
- this->functorMember_->setObjects(objects);
-
- return result;
- }
-
- protected:
- FunctorMemberPtr<T> functorMember_;
- };
-
- inline ExecutorPtr createExecutor(const FunctorPtr& functor, const std::string& name = "")
- {
- return new Executor(functor, name);
- }
-
- template <class T>
- inline ExecutorMemberPtr<T> createExecutor(const FunctorMemberPtr<T>& functor, const std::string& name = "")
- {
- return new ExecutorMember<T>(functor, name);
- }
-
- inline ExecutorStaticPtr createExecutor(const FunctorStaticPtr& functor, const std::string& name = "")
- {
- return new ExecutorStatic(functor, name);
- }
-}
-
-#endif /* _Executor_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/ExecutorPtr.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/ExecutorPtr.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/ExecutorPtr.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,51 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _ExecutorPtr_H__
-#define _ExecutorPtr_H__
-
-#include "CorePrereqs.h"
-#include "SharedPtr.h"
-
-namespace orxonox
-{
- typedef SharedPtr<Executor> ExecutorPtr;
-
- typedef SharedChildPtr<ExecutorStatic, ExecutorPtr> ExecutorStaticPtr;
-
- template <class T>
- class ExecutorMemberPtr : public SharedChildPtr<ExecutorMember<T>, ExecutorPtr>
- {
- public:
- inline ExecutorMemberPtr() : SharedChildPtr<ExecutorMember<T>, ExecutorPtr>() {}
- inline ExecutorMemberPtr(ExecutorMember<T>* pointer) : SharedChildPtr<ExecutorMember<T>, ExecutorPtr>(pointer) {}
- inline ExecutorMemberPtr(const SharedPtr<ExecutorMember<T> >& other) : SharedChildPtr<ExecutorMember<T>, ExecutorPtr>(other) {}
- };
-}
-
-#endif /* _ExecutorPtr_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/Functor.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/Functor.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/Functor.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,589 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- * Inspiration: Functor by Benjamin Grauer
- */
-
-#ifndef _Functor_H__
-#define _Functor_H__
-
-#include <typeinfo>
-
-#include "CorePrereqs.h"
-
-#include "util/Convert.h"
-#include "util/Debug.h"
-#include "util/MultiType.h"
-#include "FunctorPtr.h"
-
-namespace orxonox
-{
- const unsigned int MAX_FUNCTOR_ARGUMENTS = 5;
-
- template <class T>
- inline std::string typeToString() { return "unknown"; }
-
-#define CreateTypeToStringTemplate(type) \
- template <> \
- inline std::string typeToString<type>() { return #type; } \
- template <> \
- inline std::string typeToString<type&>() { return #type; } \
- template <> \
- inline std::string typeToString<const type>() { return #type; } \
- template <> \
- inline std::string typeToString<const type&>() { return #type; }
-
- CreateTypeToStringTemplate(int);
- CreateTypeToStringTemplate(unsigned int);
- CreateTypeToStringTemplate(char);
- CreateTypeToStringTemplate(unsigned char);
- CreateTypeToStringTemplate(short);
- CreateTypeToStringTemplate(unsigned short);
- CreateTypeToStringTemplate(long);
- CreateTypeToStringTemplate(unsigned long);
- CreateTypeToStringTemplate(long long);
- CreateTypeToStringTemplate(unsigned long long);
- CreateTypeToStringTemplate(float);
- CreateTypeToStringTemplate(double);
- CreateTypeToStringTemplate(long double);
- CreateTypeToStringTemplate(bool);
- CreateTypeToStringTemplate(Vector2);
- CreateTypeToStringTemplate(Vector3);
- CreateTypeToStringTemplate(Quaternion);
- CreateTypeToStringTemplate(ColourValue);
- CreateTypeToStringTemplate(Radian);
- CreateTypeToStringTemplate(Degree);
-
- template <>
- inline std::string typeToString<std::string>() { return "string"; }
- template <>
- inline std::string typeToString<std::string&>() { return "string"; }
- template <>
- inline std::string typeToString<const std::string>() { return "string"; }
- template <>
- inline std::string typeToString<const std::string&>() { return "string"; }
-
- class _CoreExport Functor
- {
- public:
- struct Type
- {
- enum Enum
- {
- Member,
- ConstMember,
- Static,
- Lua
- };
- };
-
- public:
- Functor() {}
- virtual ~Functor() {}
-
- virtual MultiType 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;
-
- virtual Type::Enum getType() const = 0;
- virtual unsigned int getParamCount() const = 0;
- virtual bool hasReturnvalue() const = 0;
-
- virtual std::string getTypenameParam(unsigned int param) const = 0;
- virtual std::string getTypenameReturnvalue() const = 0;
-
- virtual void evaluateParam(unsigned int index, MultiType& param) const = 0;
-
- virtual void setRawObjectPointer(void* object) {}
- virtual void* getRawObjectPointer() const { return 0; }
-
- virtual const std::type_info& getHeaderIdentifier() const = 0;
- };
-
- class _CoreExport FunctorStatic : public Functor
- {
- public:
- virtual ~FunctorStatic() {}
- virtual MultiType 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;
- };
-
- template <class T>
- class FunctorMember : public Functor
- {
- public:
- FunctorMember()
- {
- this->object_ = 0;
- this->constObject_ = 0;
- }
- virtual ~FunctorMember() {}
-
- virtual MultiType 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;
- virtual MultiType 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;
-
- virtual MultiType 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)
- {
- if (this->object_)
- return (*this)(this->object_, param1, param2, param3, param4, param5);
- else if (this->constObject_)
- return (*this)(this->constObject_, param1, param2, param3, param4, param5);
- else
- {
- COUT(1) << "An error occurred in Functor.h:" << std::endl;
- COUT(1) << "Error: No object set." << std::endl;
- return MT_Type::Null;
- }
- }
-
- inline FunctorMember<T>* setObject(T* object)
- {
- this->object_ = object;
- this->constObject_ = 0;
- return this;
- }
-
- inline FunctorMember<T>* setObject(const T* object)
- {
- this->object_ = 0;
- this->constObject_ = object;
- return this;
- }
-
- void setRawObjectPointer(void* object)
- {
- this->object_ = (T*)object;
- this->constObject_ = 0;
- }
-
- void* getRawObjectPointer() const
- {
- if (this->object_)
- return (void*)this->object_;
- else
- return (void*)this->constObject_;
- }
-
- typedef std::pair<T*, const T*> Objects;
-
- inline Objects getObjects() const
- {
- return Objects(this->object_, this->constObject_);
- }
-
- inline void setObjects(const Objects& objects)
- {
- this->object_ = objects.first;
- this->constObject_ = objects.second;
- }
-
- private:
- T* object_;
- const T* constObject_;
- };
-
-
-
- template <class R, class P1, class P2, class P3, class P4, class P5>
- struct FunctorHeaderIdentifier {};
-
-
-
- inline const FunctorPtr& createFunctor(const FunctorPtr& functor)
- {
- return functor;
- }
-
-
-
-#define FUNCTOR_TEMPLATE(ismember, returnvalue, numparams, additionalobject) FUNCTOR_TEMPLATE##ismember##returnvalue##numparams(additionalobject)
-#define FUNCTOR_TEMPLATE000(additionalobject)
-#define FUNCTOR_TEMPLATE001(additionalobject) template <class P1>
-#define FUNCTOR_TEMPLATE002(additionalobject) template <class P1, class P2>
-#define FUNCTOR_TEMPLATE003(additionalobject) template <class P1, class P2, class P3>
-#define FUNCTOR_TEMPLATE004(additionalobject) template <class P1, class P2, class P3, class P4>
-#define FUNCTOR_TEMPLATE005(additionalobject) template <class P1, class P2, class P3, class P4, class P5>
-#define FUNCTOR_TEMPLATE010(additionalobject) template <class R>
-#define FUNCTOR_TEMPLATE011(additionalobject) template <class R, class P1>
-#define FUNCTOR_TEMPLATE012(additionalobject) template <class R, class P1, class P2>
-#define FUNCTOR_TEMPLATE013(additionalobject) template <class R, class P1, class P2, class P3>
-#define FUNCTOR_TEMPLATE014(additionalobject) template <class R, class P1, class P2, class P3, class P4>
-#define FUNCTOR_TEMPLATE015(additionalobject) template <class R, class P1, class P2, class P3, class P4, class P5>
-#define FUNCTOR_TEMPLATE100(additionalobject) template <class T FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE101(additionalobject) template <class T, class P1 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE102(additionalobject) template <class T, class P1, class P2 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE103(additionalobject) template <class T, class P1, class P2, class P3 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE104(additionalobject) template <class T, class P1, class P2, class P3, class P4 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE105(additionalobject) template <class T, class P1, class P2, class P3, class P4, class P5 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE110(additionalobject) template <class T, class R FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE111(additionalobject) template <class T, class R, class P1 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE112(additionalobject) template <class T, class R, class P1, class P2 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE113(additionalobject) template <class T, class R, class P1, class P2, class P3 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE114(additionalobject) template <class T, class R, class P1, class P2, class P3, class P4 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-#define FUNCTOR_TEMPLATE115(additionalobject) template <class T, class R, class P1, class P2, class P3, class P4, class P5 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
-
-
-
-#define FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT##additionalobject
-#define FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT0
-#define FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT1 , class O
-
-
-
-#define FUNCTOR_TEMPLATE_CLASSES(ismember, returnvalue, numparams) FUNCTOR_TEMPLATE_CLASSES##ismember##returnvalue##numparams
-#define FUNCTOR_TEMPLATE_CLASSES000
-#define FUNCTOR_TEMPLATE_CLASSES001 <P1>
-#define FUNCTOR_TEMPLATE_CLASSES002 <P1, P2>
-#define FUNCTOR_TEMPLATE_CLASSES003 <P1, P2, P3>
-#define FUNCTOR_TEMPLATE_CLASSES004 <P1, P2, P3, P4>
-#define FUNCTOR_TEMPLATE_CLASSES005 <P1, P2, P3, P4, P5>
-#define FUNCTOR_TEMPLATE_CLASSES010 <R>
-#define FUNCTOR_TEMPLATE_CLASSES011 <R, P1>
-#define FUNCTOR_TEMPLATE_CLASSES012 <R, P1, P2>
-#define FUNCTOR_TEMPLATE_CLASSES013 <R, P1, P2, P3>
-#define FUNCTOR_TEMPLATE_CLASSES014 <R, P1, P2, P3, P4>
-#define FUNCTOR_TEMPLATE_CLASSES015 <R, P1, P2, P3, P4, P5>
-#define FUNCTOR_TEMPLATE_CLASSES100 <T>
-#define FUNCTOR_TEMPLATE_CLASSES101 <T, P1>
-#define FUNCTOR_TEMPLATE_CLASSES102 <T, P1, P2>
-#define FUNCTOR_TEMPLATE_CLASSES103 <T, P1, P2, P3>
-#define FUNCTOR_TEMPLATE_CLASSES104 <T, P1, P2, P3, P4>
-#define FUNCTOR_TEMPLATE_CLASSES105 <T, P1, P2, P3, P4, P5>
-#define FUNCTOR_TEMPLATE_CLASSES110 <T, R>
-#define FUNCTOR_TEMPLATE_CLASSES111 <T, R, P1>
-#define FUNCTOR_TEMPLATE_CLASSES112 <T, R, P1, P2>
-#define FUNCTOR_TEMPLATE_CLASSES113 <T, R, P1, P2, P3>
-#define FUNCTOR_TEMPLATE_CLASSES114 <T, R, P1, P2, P3, P4>
-#define FUNCTOR_TEMPLATE_CLASSES115 <T, R, P1, P2, P3, P4, P5>
-
-
-
-#define FUNCTOR_TYPENAME_PARAM(numparams) FUNCTOR_TYPENAME_PARAM##numparams
-#define FUNCTOR_TYPENAME_PARAM0 \
- return BLANKSTRING
-#define FUNCTOR_TYPENAME_PARAM1 \
- if (param == 0) { return typeToString<P1>(); } \
- else { return BLANKSTRING; }
-#define FUNCTOR_TYPENAME_PARAM2 \
- if (param == 0) { return typeToString<P1>(); } \
- else if (param == 1) { return typeToString<P2>(); } \
- else { return BLANKSTRING; }
-#define FUNCTOR_TYPENAME_PARAM3 \
- if (param == 0) { return typeToString<P1>(); } \
- else if (param == 1) { return typeToString<P2>(); } \
- else if (param == 2) { return typeToString<P3>(); } \
- else { return BLANKSTRING; }
-#define FUNCTOR_TYPENAME_PARAM4 \
- if (param == 0) { return typeToString<P1>(); } \
- else if (param == 1) { return typeToString<P2>(); } \
- else if (param == 2) { return typeToString<P3>(); } \
- else if (param == 3) { return typeToString<P4>(); } \
- else { return BLANKSTRING; }
-#define FUNCTOR_TYPENAME_PARAM5 \
- if (param == 0) { return typeToString<P1>(); } \
- else if (param == 1) { return typeToString<P2>(); } \
- else if (param == 2) { return typeToString<P3>(); } \
- else if (param == 3) { return typeToString<P4>(); } \
- else if (param == 4) { return typeToString<P5>(); } \
- else { return BLANKSTRING; }
-
-#define FUNCTOR_TYPENAME_RETURN(returnvalue) FUNCTOR_TYPENAME_RETURN##returnvalue
-#define FUNCTOR_TYPENAME_RETURN0 BLANKSTRING
-#define FUNCTOR_TYPENAME_RETURN1 typeToString<R>()
-
-
-
-#define FUNCTOR_FUNCTION_PARAMS(numparams) FUNCTOR_FUNCTION_PARAMS##numparams
-#define FUNCTOR_FUNCTION_PARAMS0
-#define FUNCTOR_FUNCTION_PARAMS1 P1 param1
-#define FUNCTOR_FUNCTION_PARAMS2 P1 param1, P2 param2
-#define FUNCTOR_FUNCTION_PARAMS3 P1 param1, P2 param2, P3 param3
-#define FUNCTOR_FUNCTION_PARAMS4 P1 param1, P2 param2, P3 param3, P4 param4
-#define FUNCTOR_FUNCTION_PARAMS5 P1 param1, P2 param2, P3 param3, P4 param4, P5 param5
-
-#define FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) FUNCTOR_FUNCTION_RETURNVALUE##returnvalue
-#define FUNCTOR_FUNCTION_RETURNVALUE0 void
-#define FUNCTOR_FUNCTION_RETURNVALUE1 R
-
-
-
-#define FUNCTOR_FUNCTION_CALL(numparams) FUNCTOR_FUNCTION_CALL##numparams
-#define FUNCTOR_FUNCTION_CALL0
-#define FUNCTOR_FUNCTION_CALL1 param1
-#define FUNCTOR_FUNCTION_CALL2 param1, param2
-#define FUNCTOR_FUNCTION_CALL3 param1, param2, param3
-#define FUNCTOR_FUNCTION_CALL4 param1, param2, param3, param4
-#define FUNCTOR_FUNCTION_CALL5 param1, param2, param3, param4, param5
-
-#define FUNCTOR_STORE_RETURNVALUE(returnvalue, functioncall) FUNCTOR_STORE_RETURNVALUE##returnvalue(functioncall)
-#define FUNCTOR_STORE_RETURNVALUE0(functioncall) functioncall; return MT_Type::Null
-#define FUNCTOR_STORE_RETURNVALUE1(functioncall) return functioncall
-
-
-
-#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES(returnvalue, numparams) FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES##numparams(returnvalue)
-#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES0(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), void, void, void, void, void>
-#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES1(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), P1, void, void, void, void>
-#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES2(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), P1, P2, void, void, void>
-#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES3(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), P1, P2, P3, void, void>
-#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES4(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), P1, P2, P3, P4, void>
-#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES5(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), P1, P2, P3, P4, P5>
-
-#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue) FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE##returnvalue
-#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE0 void
-#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE1 R
-
-
-
-#define FUNCTOR_EVALUATE_PARAM(numparams) FUNCTOR_EVALUATE_PARAM##numparams
-#define FUNCTOR_EVALUATE_PARAM0
-#define FUNCTOR_EVALUATE_PARAM1 \
- if (index == 0) { param.convert<P1>(); }
-#define FUNCTOR_EVALUATE_PARAM2 \
- if (index == 0) { param.convert<P1>(); } \
- else if (index == 1) { param.convert<P2>(); }
-#define FUNCTOR_EVALUATE_PARAM3 \
- if (index == 0) { param.convert<P1>(); } \
- else if (index == 1) { param.convert<P2>(); } \
- else if (index == 2) { param.convert<P3>(); }
-#define FUNCTOR_EVALUATE_PARAM4 \
- if (index == 0) { param.convert<P1>(); } \
- else if (index == 1) { param.convert<P2>(); } \
- else if (index == 2) { param.convert<P3>(); } \
- else if (index == 3) { param.convert<P4>(); }
-#define FUNCTOR_EVALUATE_PARAM5 \
- if (index == 0) { param.convert<P1>(); } \
- else if (index == 1) { param.convert<P2>(); } \
- else if (index == 2) { param.convert<P3>(); } \
- else if (index == 3) { param.convert<P4>(); } \
- else if (index == 4) { param.convert<P5>(); }
-
-
-
-
-#define CREATE_STATIC_FUNCTOR(returnvalue, numparams) \
- FUNCTOR_TEMPLATE(0, returnvalue, numparams, 0) \
- class FunctorStatic##returnvalue##numparams : public FunctorStatic \
- { \
- public: \
- FunctorStatic##returnvalue##numparams(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams))) \
- { \
- this->functionPointer_ = functionPointer; \
- } \
- \
- MultiType 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) \
- { \
- FUNCTOR_STORE_RETURNVALUE(returnvalue, (*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
- } \
- \
- void evaluateParam(unsigned int index, MultiType& param) const \
- { \
- FUNCTOR_EVALUATE_PARAM(numparams); \
- } \
- \
- Functor::Type::Enum getType() const { return Functor::Type::Static; } \
- unsigned int getParamCount() const { return numparams; } \
- bool hasReturnvalue() const { return returnvalue; } \
- std::string getTypenameParam(unsigned int param) const { FUNCTOR_TYPENAME_PARAM(numparams); } \
- std::string getTypenameReturnvalue() const { return FUNCTOR_TYPENAME_RETURN(returnvalue); } \
- \
- const std::type_info& getHeaderIdentifier() const \
- { \
- return typeid(FunctorHeaderIdentifier FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES(returnvalue, numparams)); \
- } \
- \
- private: \
- FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (*functionPointer_)(FUNCTOR_FUNCTION_PARAMS(numparams)); \
- }; \
- \
- \
- FUNCTOR_TEMPLATE(0, returnvalue, numparams, 0) \
- inline SharedChildPtr<FunctorStatic##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(0, returnvalue, numparams), FunctorStaticPtr> createFunctor(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams))) \
- { \
- return new FunctorStatic##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(0, returnvalue, numparams) (functionPointer); \
- }
-
-
-
-
-
-#define CREATE_MEMBER_FUNCTOR(returnvalue, numparams) \
- FUNCTOR_TEMPLATE(1, returnvalue, numparams, 0) \
- class FunctorMember##returnvalue##numparams : public FunctorMember<T> \
- { \
- public: \
- FunctorMember##returnvalue##numparams(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams))) \
- { \
- this->functionPointer_ = functionPointer; \
- } \
- \
- MultiType 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) \
- { \
- FUNCTOR_STORE_RETURNVALUE(returnvalue, (*object.*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
- } \
- \
- MultiType 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) \
- { \
- COUT(1) << "An error occurred in Functor.h:" << std::endl; \
- COUT(1) << "Error: Function is not const." << std::endl; \
- return MT_Type::Null; \
- } \
- \
- void evaluateParam(unsigned int index, MultiType& param) const \
- { \
- FUNCTOR_EVALUATE_PARAM(numparams); \
- } \
- \
- Functor::Type::Enum getType() const { return Functor::Type::Member; } \
- unsigned int getParamCount() const { return numparams; } \
- bool hasReturnvalue() const { return returnvalue; } \
- std::string getTypenameParam(unsigned int param) const { FUNCTOR_TYPENAME_PARAM(numparams); } \
- std::string getTypenameReturnvalue() const { return FUNCTOR_TYPENAME_RETURN(returnvalue); } \
- \
- const std::type_info& getHeaderIdentifier() const \
- { \
- return typeid(FunctorHeaderIdentifier FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES(returnvalue, numparams)); \
- } \
- \
- private: \
- FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer_)(FUNCTOR_FUNCTION_PARAMS(numparams)); \
- }; \
- \
- \
- FUNCTOR_TEMPLATE(1, returnvalue, numparams, 0) \
- class FunctorConstMember##returnvalue##numparams : public FunctorMember<T> \
- { \
- public: \
- FunctorConstMember##returnvalue##numparams(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams)) const) \
- { \
- this->functionPointer_ = functionPointer; \
- } \
- \
- MultiType 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) \
- { \
- FUNCTOR_STORE_RETURNVALUE(returnvalue, (*object.*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
- } \
- \
- MultiType 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) \
- { \
- FUNCTOR_STORE_RETURNVALUE(returnvalue, (*object.*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
- } \
- \
- void evaluateParam(unsigned int index, MultiType& param) const \
- { \
- FUNCTOR_EVALUATE_PARAM(numparams); \
- } \
- \
- Functor::Type::Enum getType() const { return Functor::Type::ConstMember; } \
- unsigned int getParamCount() const { return numparams; } \
- bool hasReturnvalue() const { return returnvalue; } \
- std::string getTypenameParam(unsigned int param) const { FUNCTOR_TYPENAME_PARAM(numparams); } \
- std::string getTypenameReturnvalue() const { return FUNCTOR_TYPENAME_RETURN(returnvalue); } \
- \
- const std::type_info& getHeaderIdentifier() const \
- { \
- return typeid(FunctorHeaderIdentifier FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES(returnvalue, numparams)); \
- } \
- \
- private: \
- FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer_)(FUNCTOR_FUNCTION_PARAMS(numparams)) const; \
- }; \
- \
- \
- FUNCTOR_TEMPLATE(1, returnvalue, numparams, 0) \
- inline SharedChildPtr<FunctorMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams), FunctorMemberPtr<T> > createFunctor(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams))) \
- { \
- return new FunctorMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams) (functionPointer); \
- } \
- \
- \
- FUNCTOR_TEMPLATE(1, returnvalue, numparams, 0) \
- inline SharedChildPtr<FunctorConstMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams), FunctorMemberPtr<T> > createFunctor(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams)) const) \
- { \
- return new FunctorConstMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams) (functionPointer); \
- } \
- \
- FUNCTOR_TEMPLATE(1, returnvalue, numparams, 1) \
- inline SharedChildPtr<FunctorMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams), FunctorMemberPtr<T> > createFunctor(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams)), O* object) \
- { \
- FunctorMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams)* functor = new FunctorMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams) (functionPointer); \
- functor->setObject(object); \
- return functor; \
- } \
- \
- \
- FUNCTOR_TEMPLATE(1, returnvalue, numparams, 1) \
- inline SharedChildPtr<FunctorConstMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams), FunctorMemberPtr<T> > createFunctor(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams)) const, O* object) \
- { \
- FunctorConstMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams)* functor = new FunctorConstMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams) (functionPointer); \
- functor->setObject(object); \
- return functor; \
- }
-
-
-
-// disable annoying warning about forcing value to boolean
-#ifdef ORXONOX_COMPILER_MSVC
-#pragma warning(push)
-#pragma warning(disable:4100 4800)
-#endif
-
-#define CREATE_ALL_STATIC_FUNCTORS() \
- CREATE_STATIC_FUNCTOR(0, 0); \
- CREATE_STATIC_FUNCTOR(0, 1); \
- CREATE_STATIC_FUNCTOR(0, 2); \
- CREATE_STATIC_FUNCTOR(0, 3); \
- CREATE_STATIC_FUNCTOR(0, 4); \
- CREATE_STATIC_FUNCTOR(0, 5); \
- CREATE_STATIC_FUNCTOR(1, 0); \
- CREATE_STATIC_FUNCTOR(1, 1); \
- CREATE_STATIC_FUNCTOR(1, 2); \
- CREATE_STATIC_FUNCTOR(1, 3); \
- CREATE_STATIC_FUNCTOR(1, 4); \
- CREATE_STATIC_FUNCTOR(1, 5)
-
-
-#define CREATE_ALL_MEMBER_FUNCTORS() \
- CREATE_MEMBER_FUNCTOR(0, 0); \
- CREATE_MEMBER_FUNCTOR(0, 1); \
- CREATE_MEMBER_FUNCTOR(0, 2); \
- CREATE_MEMBER_FUNCTOR(0, 3); \
- CREATE_MEMBER_FUNCTOR(0, 4); \
- CREATE_MEMBER_FUNCTOR(0, 5); \
- CREATE_MEMBER_FUNCTOR(1, 0); \
- CREATE_MEMBER_FUNCTOR(1, 1); \
- CREATE_MEMBER_FUNCTOR(1, 2); \
- CREATE_MEMBER_FUNCTOR(1, 3); \
- CREATE_MEMBER_FUNCTOR(1, 4); \
- CREATE_MEMBER_FUNCTOR(1, 5)
-
-
- CREATE_ALL_STATIC_FUNCTORS();
- CREATE_ALL_MEMBER_FUNCTORS();
-}
-
-#ifdef ORXONOX_COMPILER_MSVC
-#pragma warning(pop)
-#endif
-
-#endif /* _Functor_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/FunctorPtr.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/FunctorPtr.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/FunctorPtr.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,51 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _FunctorPtr_H__
-#define _FunctorPtr_H__
-
-#include "CorePrereqs.h"
-#include "SharedPtr.h"
-
-namespace orxonox
-{
- typedef SharedPtr<Functor> FunctorPtr;
-
- typedef SharedChildPtr<FunctorStatic, FunctorPtr> FunctorStaticPtr;
-
- template <class T>
- class FunctorMemberPtr : public SharedChildPtr<FunctorMember<T>, FunctorPtr>
- {
- public:
- inline FunctorMemberPtr() : SharedChildPtr<FunctorMember<T>, FunctorPtr>() {}
- inline FunctorMemberPtr(FunctorMember<T>* pointer) : SharedChildPtr<FunctorMember<T>, FunctorPtr>(pointer) {}
- inline FunctorMemberPtr(const SharedPtr<FunctorMember<T> >& other) : SharedChildPtr<FunctorMember<T>, FunctorPtr>(other) {}
- };
-}
-
-#endif /* _FunctorPtr_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/IOConsole.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/IOConsole.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/IOConsole.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,799 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Oliver Scheuss
- * Reto Grieder
- * Co-authors:
- * ...
- *
- */
-
-#include "IOConsole.h"
-
-#include <iomanip>
-#include <iostream>
-
-#include "util/Clock.h"
-#include "util/Math.h"
-#include "Game.h"
-#include "input/InputBuffer.h"
-
-// ##########################
-// ### Mutual methods ###
-// ##########################
-namespace orxonox
-{
- IOConsole* IOConsole::singletonPtr_s = NULL;
-
- // ###############################
- // ### ShellListener methods ###
- // ###############################
-
- //! Called if all output-lines have to be reprinted
- void IOConsole::linesChanged()
- {
- // Method only gets called upon start to draw all the lines
- // or when scrolling. But scrolling is disabled and the output
- // is already in std::cout when we start the IOConsole
- }
-
- //! Called if a command is about to be executed
- void IOConsole::executed()
- {
- this->shell_->addOutput(this->promptString_ + this->shell_->getInput() + '\n', Shell::Command);
- }
-
- //! Called if the console gets closed
- void IOConsole::exit()
- {
- // Exit is not an option, just do nothing (Shell doesn't really exit too)
- }
-}
-
-#ifdef ORXONOX_PLATFORM_UNIX
-// ###############################
-// ### Unix Implementation ###
-// ###############################
-
-#include <termios.h>
-#include <sys/ioctl.h>
-
-namespace orxonox
-{
- namespace EscapeMode
- {
- enum Value
- {
- None,
- First,
- Second
- };
- }
-
- IOConsole::IOConsole()
- : shell_(new Shell("IOConsole", false))
- , buffer_(shell_->getInputBuffer())
- , cout_(std::cout.rdbuf())
- , promptString_("orxonox # ")
- , bStatusPrinted_(false)
- , originalTerminalSettings_(0)
- {
- this->setTerminalMode();
- this->shell_->registerListener(this);
-
- // Manually set the widths of the individual status lines
- this->statusLineWidths_.push_back(29);
- this->statusLineMaxWidth_ = 29;
-
- this->getTerminalSize();
- this->lastTerminalWidth_ = this->terminalWidth_;
- this->lastTerminalHeight_ = this->terminalHeight_;
-
- // Disable standard std::cout logging
- OutputHandler::getInstance().disableCout();
- // Redirect std::cout to an ostringstream
- // (Other part is in the initialiser list)
- std::cout.rdbuf(this->origCout_.rdbuf());
-
- // Make sure we make way for the status lines
- this->preUpdate(Game::getInstance().getGameClock());
- }
-
- IOConsole::~IOConsole()
- {
- // Process output written to std::cout in the meantime
- std::cout.flush();
- if (!this->origCout_.str().empty())
- this->shell_->addOutput(this->origCout_.str(), Shell::None);
- // Erase input and status lines
- this->cout_ << "\033[1G\033[J";
- // Move cursor to the bottom
- this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B';
- // Scroll terminal to compensate for erased lines
- this->cout_ << "\033[" << this->statusLineWidths_.size() << 'T';
-
- resetTerminalMode();
- this->shell_->destroy();
-
- // Restore this->cout_ redirection
- std::cout.rdbuf(this->cout_.rdbuf());
- // Enable standard std::cout logging again
- OutputHandler::getInstance().enableCout();
- }
-
- void IOConsole::preUpdate(const Clock& time)
- {
- unsigned char c;
- std::string escapeSequence;
- EscapeMode::Value escapeMode = EscapeMode::None;
- while (std::cin.good())
- {
- c = std::cin.get();
- if (!std::cin.good())
- break;
-
- if (escapeMode == EscapeMode::First && (c == '[' || c=='O') )
- escapeMode = EscapeMode::Second;
- // Get Alt+Tab combination when switching applications
- else if (escapeMode == EscapeMode::First && c == '\t')
- {
- this->buffer_->buttonPressed(KeyEvent(KeyCode::Tab, '\t', KeyboardModifier::Alt));
- escapeMode = EscapeMode::None;
- }
- else if (escapeMode == EscapeMode::Second)
- {
- escapeSequence += c;
- escapeMode = EscapeMode::None;
- if (escapeSequence == "A")
- this->buffer_->buttonPressed(KeyEvent(KeyCode::Up, 0, 0));
- else if (escapeSequence == "B")
- this->buffer_->buttonPressed(KeyEvent(KeyCode::Down, 0, 0));
- else if (escapeSequence == "C")
- this->buffer_->buttonPressed(KeyEvent(KeyCode::Right, 0, 0));
- else if (escapeSequence == "D")
- this->buffer_->buttonPressed(KeyEvent(KeyCode::Left, 0, 0));
- else if (escapeSequence == "1~" || escapeSequence == "H")
- this->buffer_->buttonPressed(KeyEvent(KeyCode::Home, 0, 0));
- else if (escapeSequence == "2~")
- this->buffer_->buttonPressed(KeyEvent(KeyCode::Insert, 0, 0));
- else if (escapeSequence == "3~")
- this->buffer_->buttonPressed(KeyEvent(KeyCode::Delete, 0, 0));
- else if (escapeSequence == "4~" || escapeSequence == "F")
- this->buffer_->buttonPressed(KeyEvent(KeyCode::End, 0, 0));
- else if (escapeSequence == "5~")
- this->buffer_->buttonPressed(KeyEvent(KeyCode::PageUp, 0, 0));
- else if (escapeSequence == "6~")
- this->buffer_->buttonPressed(KeyEvent(KeyCode::PageDown, 0, 0));
- else
- // Waiting for sequence to complete
- // If the user presses ESC and then '[' or 'O' while the loop is not
- // running (for instance while loading), the whole sequence gets dropped
- escapeMode = EscapeMode::Second;
- }
- else // not in an escape sequence OR user might have pressed just ESC
- {
- if (escapeMode == EscapeMode::First)
- {
- this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, c, 0));
- escapeMode = EscapeMode::None;
- }
- if (c == '\033')
- {
- escapeMode = EscapeMode::First;
- escapeSequence.clear();
- }
- else
- {
- KeyCode::ByEnum code;
- switch (c)
- {
- case '\n' : case '\r': code = KeyCode::Return; break;
- case '\177': case '\b': code = KeyCode::Back; break;
- case '\t' : code = KeyCode::Tab; break;
- default:
- // We don't encode the key code (would be a very large switch)
- // because the InputBuffer will only insert the text anyway
- // Replacement character is simply KeyCode::A
- code = KeyCode::A;
- }
- this->buffer_->buttonPressed(KeyEvent(code, c, 0));
- }
- }
- }
- // Reset error flags in std::cin
- std::cin.clear();
-
- // If there is still an escape key pending (escape key ONLY), then
- // it sure isn't an escape sequence anymore
- if (escapeMode == EscapeMode::First)
- this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, '\033', 0));
-
- // Determine terminal width and height
- this->lastTerminalWidth_ = this->terminalWidth_;
- this->lastTerminalHeight_ = this->terminalHeight_;
- this->getTerminalSize();
-
- int heightDiff = this->terminalHeight_ - this->lastTerminalHeight_;
- if (this->bStatusPrinted_ && heightDiff < 0)
- {
- // Terminal width has shrunk. The cursor will still be on the input line,
- // but that line might very well be the last
- int newLines = std::min((int)this->statusLineWidths_.size(), -heightDiff);
- // Scroll terminal to create new lines
- this->cout_ << "\033[" << newLines << 'S';
- }
-
- if (!this->bStatusPrinted_ && this->willPrintStatusLines())
- {
- // Scroll console to make way for status lines
- this->cout_ << "\033[" << this->statusLineWidths_.size() << 'S';
- this->bStatusPrinted_ = true;
- }
-
- // We always assume that the cursor is on the input line.
- // But we cannot always be sure about that, esp. if we scroll the console
- this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B';
- this->cout_ << "\033[" << this->statusLineWidths_.size() << 'A';
-
- // Erase status and input lines
- this->cout_ << "\033[1G\033[J";
- this->printInputLine();
- this->printStatusLines();
- this->cout_.flush();
-
- // Process output written to std::cout
- std::cout.flush();
- if (!this->origCout_.str().empty())
- {
- this->shell_->addOutput(this->origCout_.str(), Shell::None);
- this->origCout_.str("");
- }
- }
-
- void IOConsole::printOutputLine(const std::string& text, Shell::LineType type)
- {
-/*
- // Colour line
- switch (type)
- {
- case Shell::None: this->cout_ << "\033[37m"; break;
- case Shell::Error: this->cout_ << "\033[91m"; break;
- case Shell::Warning: this->cout_ << "\033[31m"; break;
- case Shell::Info: this->cout_ << "\033[34m"; break;
- case Shell::Debug: this->cout_ << "\033[36m"; break;
- case Shell::Verbose: this->cout_ << "\033[35m"; break;
- case Shell::Ultra: this->cout_ << "\033[37m"; break;
- default: break;
- }
-*/
-
- // Print output line
- this->cout_ << text;
-
- // Reset colour to white
-// this->cout_ << "\033[37m";
- }
-
- void IOConsole::printInputLine()
- {
- // Set cursor to the beginning of the line and erase the line
- this->cout_ << "\033[1G\033[K";
- // Indicate a command prompt
- this->cout_ << this->promptString_;
- // Save cursor position
- this->cout_ << "\033[s";
- // Print command line buffer
- this->cout_ << this->shell_->getInput();
- // Restore cursor position and move it to the right
- this->cout_ << "\033[u";
- if (this->buffer_->getCursorPosition() > 0)
- this->cout_ << "\033[" << this->buffer_->getCursorPosition() << 'C';
- }
-
- void IOConsole::printStatusLines()
- {
- if (this->willPrintStatusLines())
- {
- // Save cursor position
- this->cout_ << "\033[s";
- // Move cursor down (don't create a new line here because the buffer might flush then!)
- this->cout_ << "\033[1B\033[1G";
- this->cout_ << std::fixed << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgFPS() << " fps, ";
- this->cout_ << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgTickTime() << " ms tick time";
- // Restore cursor position
- this->cout_ << "\033[u";
- this->bStatusPrinted_ = true;
- }
- else
- this->bStatusPrinted_ = false;
- }
-
- void IOConsole::setTerminalMode()
- {
- termios new_settings;
- this->originalTerminalSettings_ = new termios();
-
- tcgetattr(0, this->originalTerminalSettings_);
- new_settings = *this->originalTerminalSettings_;
- new_settings.c_lflag &= ~(ICANON | ECHO);
- //new_settings.c_lflag |= (ISIG | IEXTEN);
- new_settings.c_cc[VTIME] = 0;
- new_settings.c_cc[VMIN] = 0;
- tcsetattr(0, TCSANOW, &new_settings);
- atexit(&IOConsole::resetTerminalMode);
- }
-
- /*static*/ void IOConsole::resetTerminalMode()
- {
- if (IOConsole::singletonPtr_s && IOConsole::singletonPtr_s->originalTerminalSettings_)
- {
- tcsetattr(0, TCSANOW, IOConsole::singletonPtr_s->originalTerminalSettings_);
- delete IOConsole::singletonPtr_s->originalTerminalSettings_;
- IOConsole::singletonPtr_s->originalTerminalSettings_ = 0;
- }
- }
-
- void IOConsole::getTerminalSize()
- {
-#ifdef TIOCGSIZE
- struct ttysize win;
- if (!ioctl(STDIN_FILENO, TIOCGSIZE, &win))
- {
- this->terminalWidth_ = win.ts_cols;
- this->terminalHeight_ = win.ts_lines;
- return;
- }
-#elif defined TIOCGWINSZ
- struct winsize win;
- if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &win))
- {
- this->terminalWidth_ = win.ws_col;
- this->terminalHeight_ = win.ws_row;
- return;
- }
-#else
- const char* s = getenv("COLUMNS");
- this->terminalWidth_ = s ? strtol(s, NULL, 10) : 80;
- s = getenv("LINES");
- this->terminalHeight_ = s ? strtol(s, NULL, 10) : 24;
- return;
-#endif
- this->terminalWidth_ = 80;
- this->terminalHeight_ = 24;
- }
-
- inline bool IOConsole::willPrintStatusLines()
- {
- return !this->statusLineWidths_.empty()
- && this->terminalWidth_ >= this->statusLineMaxWidth_
- && this->terminalHeight_ >= this->minOutputLines_ + (int)this->statusLineWidths_.size();
- }
-
- // ###############################
- // ### ShellListener methods ###
- // ###############################
-
- //! Called if only the last output-line has changed
- void IOConsole::onlyLastLineChanged()
- {
- // Save cursor position and move it to the beginning of the first output line
- this->cout_ << "\033[s\033[1A\033[1G";
- // Erase the line
- this->cout_ << "\033[K";
- // Reprint the last output line
- this->printOutputLine(this->shell_->getNewestLineIterator()->first, this->shell_->getNewestLineIterator()->second);
- // Restore cursor
- this->cout_ << "\033[u";
- this->cout_.flush();
- }
-
- //! Called if a new output-line was added
- void IOConsole::lineAdded()
- {
- int newLines = this->shell_->getNewestLineIterator()->first.size() / this->terminalWidth_ + 1;
- // Create new lines by scrolling the screen
- this->cout_ << "\033[" << newLines << 'S';
- // Move cursor to the beginning of the new (last) output line
- this->cout_ << "\033[" << newLines << "A\033[1G";
- // Erase screen from here
- this->cout_ << "\033[J";
- // Print the new output lines
- for (int i = 0; i < newLines; ++i)
- {
- Shell::LineList::const_iterator it = this->shell_->getNewestLineIterator();
- this->printOutputLine(it->first.substr(i*this->terminalWidth_, this->terminalWidth_), it->second);
- }
- // Move cursor down
- this->cout_ << "\033[1B\033[1G";
- // Print status and input lines
- this->printInputLine();
- this->printStatusLines();
- this->cout_.flush();
- }
-
- //! Called if the text in the input-line has changed
- void IOConsole::inputChanged()
- {
- this->printInputLine();
- this->cout_.flush();
- }
-
- //! Called if the position of the cursor in the input-line has changed
- void IOConsole::cursorChanged()
- {
- this->printInputLine();
- this->cout_.flush();
- }
-}
-
-#elif defined(ORXONOX_PLATFORM_WINDOWS)
-// ##################################
-// ### Windows Implementation ###
-// ##################################
-
-#include <windows.h>
-
-namespace orxonox
-{
- //! Redirects std::cout, creates the corresponding Shell and changes the terminal mode
- IOConsole::IOConsole()
- : shell_(new Shell("IOConsole", false))
- , buffer_(shell_->getInputBuffer())
- , cout_(std::cout.rdbuf())
- , promptString_("orxonox # ")
- , inputLineHeight_(1)
- , statusLines_(1)
- , lastOutputLineHeight_(0)
- {
- // Disable standard this->cout_ logging
- OutputHandler::getInstance().disableCout();
- // Redirect std::cout to an ostringstream
- // (Other part is in the initialiser list)
- std::cout.rdbuf(this->origCout_.rdbuf());
-
- this->setTerminalMode();
- CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
- GetConsoleScreenBufferInfo(this->stdOutHandle_, &screenBufferInfo);
- this->terminalWidth_ = screenBufferInfo.dwSize.X;
- this->terminalHeight_ = screenBufferInfo.dwSize.Y;
- // Determines where we are in respect to output already written with std::cout
- this->inputLineRow_ = screenBufferInfo.dwCursorPosition.Y;
-/*
- this->lastTerminalWidth_ = this->terminalWidth_;
- this->lastTerminalHeight_ = this->terminalHeight_;
-*/
-
- // Cursor already at the end of the screen buffer?
- // (assuming the current input line height is 1)
- if (this->inputLineRow_ >= this->terminalHeight_ - this->statusLines_)
- SetConsoleCursorPosition(this->stdOutHandle_, makeCOORD(0, this->terminalHeight_ - this->statusLines_));
-
- // Prevent input line from overflowing
- int maxInputLength = (this->terminalHeight_ - this->statusLines_) * this->terminalWidth_ - 1 - this->promptString_.size();
- // Consider that the echo of a command might include the command plus some other characters (assumed max 80)
- // Also put a minimum so the config file parser is not overwhelmed with the command history
- this->buffer_->setMaxLength(std::min(8192, (maxInputLength - 80) / 2));
-
- // Print input and status line and position cursor
- this->inputChanged();
- this->cursorChanged();
- this->lastRefreshTime_ = Game::getInstance().getGameClock().getRealMicroseconds();
- this->preUpdate(Game::getInstance().getGameClock());
-
- this->shell_->registerListener(this);
- }
-
- //! Resets std::cout redirection and restores the terminal mode
- IOConsole::~IOConsole()
- {
- // Process output written to std::cout in the meantime
- std::cout.flush();
- if (!this->origCout_.str().empty())
- this->shell_->addOutput(this->origCout_.str(), Shell::None);
-
- this->shell_->unregisterListener(this);
-
- // Erase input and status lines
- COORD pos = {0, this->inputLineRow_};
- this->writeText(std::string((this->inputLineHeight_ + this->statusLines_) * this->terminalWidth_, ' '), pos);
- // Move cursor to the beginning of the line
- SetConsoleCursorPosition(stdOutHandle_, pos);
-
- // Restore this->cout_ redirection
- std::cout.rdbuf(this->cout_.rdbuf());
- // Enable standard this->cout_ logging again
- OutputHandler::getInstance().enableCout();
-
- resetTerminalMode();
- this->shell_->destroy();
- }
-
- //! Processes the pending input key strokes, refreshes the status lines and handles std::cout (redirected)
- void IOConsole::preUpdate(const Clock& time)
- {
- // Process input
- while (true)
- {
- DWORD count;
- INPUT_RECORD inrec;
- PeekConsoleInput(this->stdInHandle_, &inrec, 1, &count);
- if (count == 0)
- break;
- ReadConsoleInput(this->stdInHandle_, &inrec, 1, &count);
- if (inrec.EventType == KEY_EVENT && inrec.Event.KeyEvent.bKeyDown)
- {
- // Process keyboard modifiers (Ctrl, Alt and Shift)
- DWORD modifiersIn = inrec.Event.KeyEvent.dwControlKeyState;
- int modifiersOut = 0;
- if ((modifiersIn & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0)
- modifiersOut |= KeyboardModifier::Alt;
- if ((modifiersIn & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
- modifiersOut |= KeyboardModifier::Ctrl;
- if ((modifiersIn & SHIFT_PRESSED) != 0)
- modifiersOut |= KeyboardModifier::Shift;
-
- // ASCII character (0 for special keys)
- char asciiChar = inrec.Event.KeyEvent.uChar.AsciiChar;
-
- // Process special keys and if not found, use Key::A as dummy (InputBuffer uses the ASCII text anyway)
- switch (inrec.Event.KeyEvent.wVirtualKeyCode)
- {
- case VK_BACK: this->buffer_->buttonPressed(KeyEvent(KeyCode::Back, asciiChar, modifiersOut)); break;
- case VK_TAB: this->buffer_->buttonPressed(KeyEvent(KeyCode::Tab, asciiChar, modifiersOut)); break;
- case VK_RETURN: this->buffer_->buttonPressed(KeyEvent(KeyCode::Return, asciiChar, modifiersOut)); break;
- case VK_PAUSE: this->buffer_->buttonPressed(KeyEvent(KeyCode::Pause, asciiChar, modifiersOut)); break;
- case VK_ESCAPE: this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, asciiChar, modifiersOut)); break;
- case VK_SPACE: this->buffer_->buttonPressed(KeyEvent(KeyCode::Space, asciiChar, modifiersOut)); break;
- case VK_PRIOR: this->buffer_->buttonPressed(KeyEvent(KeyCode::PageUp, asciiChar, modifiersOut)); break;
- case VK_NEXT: this->buffer_->buttonPressed(KeyEvent(KeyCode::PageDown, asciiChar, modifiersOut)); break;
- case VK_END: this->buffer_->buttonPressed(KeyEvent(KeyCode::End, asciiChar, modifiersOut)); break;
- case VK_HOME: this->buffer_->buttonPressed(KeyEvent(KeyCode::Home, asciiChar, modifiersOut)); break;
- case VK_LEFT: this->buffer_->buttonPressed(KeyEvent(KeyCode::Left, asciiChar, modifiersOut)); break;
- case VK_UP: this->buffer_->buttonPressed(KeyEvent(KeyCode::Up, asciiChar, modifiersOut)); break;
- case VK_RIGHT: this->buffer_->buttonPressed(KeyEvent(KeyCode::Right, asciiChar, modifiersOut)); break;
- case VK_DOWN: this->buffer_->buttonPressed(KeyEvent(KeyCode::Down, asciiChar, modifiersOut)); break;
- case VK_INSERT: this->buffer_->buttonPressed(KeyEvent(KeyCode::Insert, asciiChar, modifiersOut)); break;
- case VK_DELETE: this->buffer_->buttonPressed(KeyEvent(KeyCode::Delete, asciiChar, modifiersOut)); break;
- default: this->buffer_->buttonPressed(KeyEvent(KeyCode::A, asciiChar, modifiersOut));
- }
- }
- }
-
- // TODO: Respect screen buffer size changes
-/*
- // The user can manually adjust the screen buffer size on Windows
- // And we don't want to screw the console because of that
- this->lastTerminalWidth_ = this->terminalWidth_;
- this->lastTerminalHeight_ = this->terminalHeight_;
- this->getTerminalSize(); // Also sets this->inputLineRow_ according to the cursor position
- // Is there still enough space below the cursor for the status line(s)?
- if (this->inputLineRow_ >= this->terminalHeight_ - this->statusLines_)
- this->moveCursor(0, -this->inputLineRow_ + this->terminalHeight_ - this->statusLines_ - 1);
-*/
-
- // Refresh status line 5 times per second
- if (time.getMicroseconds() > this->lastRefreshTime_ + 1000000)
- {
- this->printStatusLines();
- this->lastRefreshTime_ = time.getMicroseconds();
- }
-
- // Process output written to std::cout
- std::cout.flush();
- if (!this->origCout_.str().empty())
- {
- this->shell_->addOutput(this->origCout_.str(), Shell::None);
- this->origCout_.str("");
- }
- }
-
- //! Prints output text. Similar to writeText, but sets the colour according to the output level
- void IOConsole::printOutputLine(const std::string& text, Shell::LineType type, const COORD& pos)
- {
- // Colour line
- WORD colour = 0;
- switch (type)
- {
- case Shell::Error: colour = FOREGROUND_INTENSITY | FOREGROUND_RED; break;
- case Shell::Warning: colour = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED; break;
- case Shell::Info:
- case Shell::Debug:
- case Shell::Verbose:
- case Shell::Ultra: colour = FOREGROUND_INTENSITY ; break;
- case Shell::Command: colour = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
- case Shell::Hint: colour = FOREGROUND_GREEN | FOREGROUND_RED ; break;
- default: colour = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE; break;
- }
-
- // Print output line
- this->writeText(text, pos, colour);
- }
-
- //! Prints all status lines with current content
- void IOConsole::printStatusLines()
- {
- // Prepare text to be written
- std::ostringstream oss;
- oss << std::fixed << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgFPS() << " fps, ";
- oss << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgTickTime() << " ms tick time";
- // Clear rest of the line by inserting spaces
- oss << std::string(this->terminalWidth_ - oss.str().size(), ' ');
- this->writeText(oss.str(), makeCOORD(0, this->inputLineRow_ + this->inputLineHeight_), FOREGROUND_GREEN);
- }
-
- //! Changes the console parameters for unbuffered input
- void IOConsole::setTerminalMode()
- {
- // Set the console mode to no-echo, raw input, and no window or mouse events
- this->stdOutHandle_ = GetStdHandle(STD_OUTPUT_HANDLE);
- this->stdInHandle_ = GetStdHandle(STD_INPUT_HANDLE);
- if (this->stdInHandle_ == INVALID_HANDLE_VALUE
- || !GetConsoleMode(this->stdInHandle_, &this->originalTerminalSettings_)
- || !SetConsoleMode(this->stdInHandle_, 0))
- {
- COUT(1) << "Error: Could not set Windows console settings" << std::endl;
- return;
- }
- FlushConsoleInputBuffer(this->stdInHandle_);
- }
-
- //! Restores the console parameters
- void IOConsole::resetTerminalMode()
- {
- SetConsoleMode(this->stdInHandle_, this->originalTerminalSettings_);
- }
-
- //! Sets this->terminalWidth_ and this->terminalHeight_
- void IOConsole::getTerminalSize()
- {
- CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
- GetConsoleScreenBufferInfo(this->stdOutHandle_, &screenBufferInfo);
- this->terminalWidth_ = screenBufferInfo.dwSize.X;
- this->terminalHeight_ = screenBufferInfo.dwSize.Y;
- }
-
- //! Writes arbitrary text to the console with a certain colour and screen buffer position
- void IOConsole::writeText(const std::string& text, const COORD& coord, WORD attributes)
- {
- DWORD count;
- WriteConsoleOutputCharacter(stdOutHandle_, text.c_str(), text.size(), coord, &count);
- FillConsoleOutputAttribute(stdOutHandle_, attributes, text.size(), coord, &count);
- }
-
- /** Scrolls the console screen buffer to create empty lines above the input line.
- @details
- If the input and status lines are already at the bottom of the screen buffer
- the whole output gets scrolled up. In the other case the input and status
- lines get scrolled down.
- In any case the status and input lines get scrolled down as far as possible.
- @param lines
- Number of lines to be inserted. Behavior for negative values is undefined.
- */
- void IOConsole::createNewOutputLines(int lines)
- {
- CHAR_INFO fillChar = {{' '}, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED};
- // Lines to scroll input/status down (if possible)
- int linesDown = clamp(terminalHeight_ - inputLineRow_ - inputLineHeight_ - statusLines_, 0, lines);
- if (linesDown > 0)
- {
- // Scroll input and status lines down
- SMALL_RECT oldRect = {0, this->inputLineRow_,
- this->terminalWidth_ - 1, this->inputLineRow_ + this->inputLineHeight_ + this->statusLines_ - 1};
- this->inputLineRow_ += linesDown;
- ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, makeCOORD(0, this->inputLineRow_), &fillChar);
- // Move cursor down to the new bottom so the user can see the status lines
- COORD pos = {0, this->inputLineRow_ + this->inputLineHeight_ - 1 + this->statusLines_};
- SetConsoleCursorPosition(stdOutHandle_, pos);
- // Get cursor back to the right position
- this->cursorChanged();
- }
- // Check how many lines we still have to scroll up the output
- if (lines - linesDown > 0)
- {
- // Scroll output up
- SMALL_RECT oldRect = {0, lines - linesDown, this->terminalWidth_ - 1, this->inputLineRow_ - 1};
- ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, makeCOORD(0, 0), &fillChar);
- }
- }
-
- // ###############################
- // ### ShellListener methods ###
- // ###############################
-
- //! Called if the text in the input line has changed
- void IOConsole::inputChanged()
- {
- int newInputLineLength = this->promptString_.size() + this->shell_->getInput().size();
- int newInputLineHeight = 1 + newInputLineLength / this->terminalWidth_;
- int newLines = newInputLineHeight - this->inputLineHeight_;
- if (newLines > 0)
- {
- // Abuse this function to scroll the console
- this->createNewOutputLines(newLines);
- // Either Compensate for side effects (input/status lines scrolled down)
- // or we have to do this anyway (output scrolled up)
- this->inputLineRow_ -= newLines;
- }
- else if (newLines < 0)
- {
- // Scroll status lines up
- int statusLineRow = this->inputLineRow_ + this->inputLineHeight_;
- SMALL_RECT oldRect = {0, statusLineRow, this->terminalWidth_ - 1, statusLineRow + this->statusLines_};
- CHAR_INFO fillChar = {{' '}, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED};
- ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, makeCOORD(0, statusLineRow + newLines), &fillChar);
- // Clear potential leftovers
- if (-newLines - this->statusLines_ > 0)
- {
- COORD pos = {0, this->inputLineRow_ + newInputLineHeight + this->statusLines_};
- this->writeText(std::string((-newLines - this->statusLines_) * this->terminalWidth_, ' '), pos);
- }
- }
- this->inputLineHeight_ = newInputLineHeight;
-
- // Print the whole line, including spaces that erase leftovers
- std::string inputLine = this->promptString_ + this->shell_->getInput();
- inputLine += std::string(this->terminalWidth_ - newInputLineLength % this->terminalWidth_, ' ');
- this->writeText(inputLine, makeCOORD(0, this->inputLineRow_), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
- // If necessary, move cursor
- if (newLines != 0)
- this->cursorChanged();
- }
-
- //! Called if the position of the cursor in the input-line has changed
- void IOConsole::cursorChanged()
- {
- int rawCursorPos = this->promptString_.size() + this->buffer_->getCursorPosition();
- // Compensate for cursor further to the right than the terminal width
- COORD pos;
- pos.X = rawCursorPos % this->terminalWidth_;
- pos.Y = this->inputLineRow_ + rawCursorPos / this->terminalWidth_;
- SetConsoleCursorPosition(stdOutHandle_, pos);
- }
-
- //! Called if only the last output-line has changed
- void IOConsole::onlyLastLineChanged()
- {
- int newLineHeight = 1 + this->shell_->getNewestLineIterator()->first.size() / this->terminalWidth_;
- // Compute the number of new lines needed
- int newLines = newLineHeight - this->lastOutputLineHeight_;
- this->lastOutputLineHeight_ = newLineHeight;
- // Scroll console if necessary
- if (newLines > 0) // newLines < 0 is assumed impossible
- this->createNewOutputLines(newLines);
- Shell::LineList::const_iterator it = this->shell_->getNewestLineIterator();
- this->printOutputLine(it->first, it->second, makeCOORD(0, this->inputLineRow_ - newLineHeight));
- }
-
- //! Called if a new output line was added
- void IOConsole::lineAdded()
- {
- Shell::LineList::const_iterator it = this->shell_->getNewestLineIterator();
- // Scroll console
- this->lastOutputLineHeight_ = 1 + it->first.size() / this->terminalWidth_;
- this->createNewOutputLines(this->lastOutputLineHeight_);
- // Write the text
- COORD pos = {0, this->inputLineRow_ - this->lastOutputLineHeight_};
- this->printOutputLine(it->first, it->second, pos);
- }
-}
-
-#endif /* ORXONOX_PLATFORM_UNIX */
Deleted: code/branches/consolecommands3/src/libraries/core/IOConsole.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/IOConsole.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/IOConsole.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,128 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Oliver Scheuss
- * Reto Grieder
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _IOConsole_H__
-#define _IOConsole_H__
-
-#include "CorePrereqs.h"
-
-#include <sstream>
-#include <string>
-#include <vector>
-#include "util/Singleton.h"
-#include "Shell.h"
-
-#ifdef ORXONOX_PLATFORM_UNIX
-struct termios;
-#elif defined(ORXONOX_PLATFORM_WINDOWS)
-#define WIN32_LEAN_AND_MEAN
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-#include <windows.h>
-#endif
-
-namespace orxonox
-{
- class _CoreExport IOConsole : public Singleton<IOConsole>, public ShellListener
- {
- friend class Singleton<IOConsole>;
-
- public:
- IOConsole();
- ~IOConsole();
-
- void preUpdate(const Clock& time);
-
- private:
- void setTerminalMode();
- void getTerminalSize();
- void printStatusLines();
- static int extractLogLevel(std::string* text);
-
- // Methods from ShellListener
- void linesChanged();
- void onlyLastLineChanged();
- void lineAdded();
- void inputChanged();
- void cursorChanged();
- void executed();
- void exit();
-
- Shell* shell_;
- InputBuffer* buffer_;
- std::ostream cout_;
- std::ostringstream origCout_;
- int terminalWidth_;
- int terminalHeight_;
- int lastTerminalWidth_;
- int lastTerminalHeight_;
- const std::string promptString_;
-
-#ifdef ORXONOX_PLATFORM_UNIX
- bool willPrintStatusLines();
- void printInputLine();
- void printOutputLine(const std::string& line, Shell::LineType type);
- static void resetTerminalMode();
-
- bool bPrintStatusLine_;
- bool bStatusPrinted_;
- std::vector<int> statusLineWidths_;
- int statusLineMaxWidth_;
- static const int minOutputLines_ = 3;
- termios* originalTerminalSettings_;
-
-#elif defined(ORXONOX_PLATFORM_WINDOWS)
- void resetTerminalMode();
- void moveCursor(int dx, int dy);
- void writeText(const std::string& text, const COORD& pos, WORD attributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
- void createNewOutputLines(int lines);
- void printOutputLine(const std::string& line, Shell::LineType type, const COORD& pos);
-
- static inline COORD makeCOORD(int x, int y)
- {
- COORD val = {x, y};
- return val;
- }
-
- DWORD originalTerminalSettings_;
- HANDLE stdInHandle_;
- HANDLE stdOutHandle_;
- int inputLineRow_;
- int inputLineHeight_;
- const int statusLines_;
- int lastOutputLineHeight_;
- uint64_t lastRefreshTime_;
-#endif
-
- static IOConsole* singletonPtr_s;
- };
-}
-
-#endif /* _IOConsole_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/IRC.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/IRC.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/IRC.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,137 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#include "IRC.h"
-
-#include <cpptcl/cpptcl.h>
-
-#include "util/Convert.h"
-#include "util/Exception.h"
-#include "util/StringUtils.h"
-#include "ConsoleCommand.h"
-#include "CoreIncludes.h"
-#include "TclThreadManager.h"
-
-namespace orxonox
-{
- static const unsigned int IRC_TCL_THREADID = 1421421421;
-
- SetConsoleCommand(IRC, say, true).accessLevel(AccessLevel::User);
- SetConsoleCommand(IRC, msg, false).accessLevel(AccessLevel::User);
- SetConsoleCommand(IRC, nick, false).accessLevel(AccessLevel::User);
-
- IRC::IRC()
- {
- RegisterRootObject(IRC);
- this->interpreter_ = 0;
- }
-
- void IRC::initialize()
- {
- unsigned int threadID = IRC_TCL_THREADID;
- this->interpreter_ = TclThreadManager::createWithId(threadID);
-
- try
- {
- this->interpreter_->def("::orxonox::irc::say", IRC::tcl_say, Tcl::variadic());
- this->interpreter_->def("::orxonox::irc::privmsg", IRC::tcl_privmsg, Tcl::variadic());
- this->interpreter_->def("::orxonox::irc::action", IRC::tcl_action, Tcl::variadic());
- this->interpreter_->def("::orxonox::irc::info", IRC::tcl_info, Tcl::variadic());
- }
- catch (Tcl::tcl_error const &e)
- { COUT(1) << "Tcl (IRC) error: " << e.what(); }
-
- this->nickname_ = "orx" + multi_cast<std::string>(static_cast<unsigned int>(rand()));
- TclThreadManager::execute(threadID, "set nickname " + this->nickname_);
- TclThreadManager::execute(threadID, "source irc.tcl");
- }
-
- IRC& IRC::getInstance()
- {
- static IRC instance;
- return instance;
- }
-
- bool IRC::eval(const std::string& command)
- {
- if (!IRC::getInstance().interpreter_)
- {
- IRC::getInstance().initialize();
- COUT(1) << "Error: IRC client wasn't yet initialized, please try again." << std::endl;
- return false;
- }
-
- try
- {
- IRC::getInstance().interpreter_->eval(command);
- return true;
- }
- catch (Tcl::tcl_error const &e)
- { COUT(1) << "Tcl (IRC) error: " << e.what(); }
-
- return false;
- }
-
- void IRC::say(const std::string& message)
- {
- if (IRC::eval("irk::say $conn #orxonox {" + message + '}'))
- IRC::tcl_say(Tcl::object(), Tcl::object(IRC::getInstance().nickname_), Tcl::object(message));
- }
-
- void IRC::msg(const std::string& channel, const std::string& message)
- {
- if (IRC::eval("irk::say $conn " + channel + " {" + message + '}'))
- IRC::tcl_privmsg(Tcl::object(channel), Tcl::object(IRC::getInstance().nickname_), Tcl::object(message));
- }
-
- void IRC::nick(const std::string& nickname)
- {
- if (IRC::eval("irk::nick $conn " + nickname))
- IRC::getInstance().nickname_ = nickname;
- }
-
- void IRC::tcl_say(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args)
- {
- COUT(0) << "IRC> " << nick.get() << ": " << stripEnclosingBraces(args.get()) << std::endl;
- }
-
- void IRC::tcl_privmsg(Tcl::object const &query, Tcl::object const &nick, Tcl::object const &args)
- {
- COUT(0) << "IRC (" << query.get() << ")> " << nick.get() << ": " << stripEnclosingBraces(args.get()) << std::endl;
- }
-
- void IRC::tcl_action(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args)
- {
- COUT(0) << "IRC> * " << nick.get() << ' ' << stripEnclosingBraces(args.get()) << std::endl;
- }
-
- void IRC::tcl_info(Tcl::object const &channel, Tcl::object const &args)
- {
- COUT(0) << "IRC> --> " << stripEnclosingBraces(args.get()) << std::endl;
- }
-}
Deleted: code/branches/consolecommands3/src/libraries/core/IRC.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/IRC.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/IRC.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,66 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _IRC_H__
-#define _IRC_H__
-
-#include "CorePrereqs.h"
-
-#include <string>
-#include "OrxonoxClass.h"
-
-namespace orxonox
-{
- class _CoreExport IRC : public OrxonoxClass
- {
- public:
- static IRC& getInstance();
-
- static void say(const std::string& message);
- static void msg(const std::string& channel, const std::string& message);
- static void nick(const std::string& nickname);
-
- static void tcl_say(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args);
- static void tcl_privmsg(Tcl::object const &query, Tcl::object const &nick, Tcl::object const &args);
- static void tcl_action(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args);
- static void tcl_info(Tcl::object const &channel, Tcl::object const &args);
-
- private:
- static bool eval(const std::string& command);
- void initialize();
-
- IRC();
- IRC(const IRC& other);
- ~IRC() {}
-
- Tcl::interpreter* interpreter_;
- std::string nickname_;
- };
-}
-
-#endif /* _IRC_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/Shell.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/Shell.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/Shell.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,469 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * Reto Grieder
- *
- */
-
-#include "Shell.h"
-
-#include "util/OutputHandler.h"
-#include "util/StringUtils.h"
-#include "util/SubString.h"
-#include "CommandExecutor.h"
-#include "CoreIncludes.h"
-#include "ConfigFileManager.h"
-#include "ConfigValueIncludes.h"
-#include "ConsoleCommand.h"
-
-namespace orxonox
-{
- SetConsoleCommandShortcut(OutputHandler, log);
- SetConsoleCommandShortcut(OutputHandler, error);
- SetConsoleCommandShortcut(OutputHandler, warning);
- SetConsoleCommandShortcut(OutputHandler, info);
- SetConsoleCommandShortcut(OutputHandler, debug);
-
- Shell::Shell(const std::string& consoleName, bool bScrollable)
- : OutputListener(consoleName)
- , inputBuffer_(new InputBuffer())
- , consoleName_(consoleName)
- , bScrollable_(bScrollable)
- {
- RegisterRootObject(Shell);
-
- this->scrollPosition_ = 0;
- this->maxHistoryLength_ = 100;
- this->historyPosition_ = 0;
- this->historyOffset_ = 0;
- this->bFinishedLastLine_ = true;
-
- this->clearOutput();
- this->configureInputBuffer();
-
- // Specify file for the command history
- ConfigFileManager::getInstance().setFilename(ConfigFileType::CommandHistory, "commandHistory.ini");
-
- // Use a stringstream object to buffer the output
- this->outputStream_ = &this->outputBuffer_;
-
- this->setConfigValues();
-
- // Get the previous output and add it to the Shell
- for (OutputHandler::OutputVectorIterator it = OutputHandler::getInstance().getOutputVectorBegin();
- it != OutputHandler::getInstance().getOutputVectorEnd(); ++it)
- {
- if (it->first <= this->getSoftDebugLevel())
- {
- this->outputBuffer_ << it->second;
- this->outputChanged(it->first);
- }
- }
-
- // Register the shell as output listener
- OutputHandler::getInstance().registerOutputListener(this);
- }
-
- Shell::~Shell()
- {
- OutputHandler::getInstance().unregisterOutputListener(this);
- this->inputBuffer_->destroy();
- }
-
- void Shell::setConfigValues()
- {
- SetConfigValue(maxHistoryLength_, 100)
- .callback(this, &Shell::commandHistoryLengthChanged);
- SetConfigValue(historyOffset_, 0)
- .callback(this, &Shell::commandHistoryOffsetChanged);
- setConfigValueGeneric(this, &commandHistory_, ConfigFileType::CommandHistory, "Shell", "commandHistory_", std::vector<std::string>());
-
-#ifdef ORXONOX_RELEASE
- const unsigned int defaultLevel = 1;
-#else
- const unsigned int defaultLevel = 3;
-#endif
- SetConfigValueExternal(softDebugLevel_, "OutputHandler", "softDebugLevel" + this->consoleName_, defaultLevel)
- .description("The maximal level of debug output shown in the Shell");
- this->setSoftDebugLevel(this->softDebugLevel_);
- }
-
- void Shell::commandHistoryOffsetChanged()
- {
- if (this->historyOffset_ >= this->maxHistoryLength_)
- this->historyOffset_ = 0;
- }
-
- void Shell::commandHistoryLengthChanged()
- {
- this->commandHistoryOffsetChanged();
-
- while (this->commandHistory_.size() > this->maxHistoryLength_)
- {
- unsigned int index = this->commandHistory_.size() - 1;
- this->commandHistory_.erase(this->commandHistory_.begin() + index);
- ModifyConfigValue(commandHistory_, remove, index);
- }
- }
-
- void Shell::configureInputBuffer()
- {
- this->inputBuffer_->registerListener(this, &Shell::inputChanged, true);
- this->inputBuffer_->registerListener(this, &Shell::execute, '\r', false);
- this->inputBuffer_->registerListener(this, &Shell::execute, '\n', false);
- this->inputBuffer_->registerListener(this, &Shell::hintAndComplete, '\t', true);
- this->inputBuffer_->registerListener(this, &Shell::backspace, '\b', true);
- this->inputBuffer_->registerListener(this, &Shell::backspace, '\177', true);
- this->inputBuffer_->registerListener(this, &Shell::exit, '\033', true); // escape
- this->inputBuffer_->registerListener(this, &Shell::deleteChar, KeyCode::Delete);
- this->inputBuffer_->registerListener(this, &Shell::cursorRight, KeyCode::Right);
- this->inputBuffer_->registerListener(this, &Shell::cursorLeft, KeyCode::Left);
- this->inputBuffer_->registerListener(this, &Shell::cursorEnd, KeyCode::End);
- this->inputBuffer_->registerListener(this, &Shell::cursorHome, KeyCode::Home);
- this->inputBuffer_->registerListener(this, &Shell::historyUp, KeyCode::Up);
- this->inputBuffer_->registerListener(this, &Shell::historyDown, KeyCode::Down);
- if (this->bScrollable_)
- {
- this->inputBuffer_->registerListener(this, &Shell::scrollUp, KeyCode::PageUp);
- this->inputBuffer_->registerListener(this, &Shell::scrollDown, KeyCode::PageDown);
- }
- else
- {
- this->inputBuffer_->registerListener(this, &Shell::historySearchUp, KeyCode::PageUp);
- this->inputBuffer_->registerListener(this, &Shell::historySearchDown, KeyCode::PageDown);
- }
- }
-
- /*
- void Shell::history()
- {
- Shell& instance = Shell::getInstance();
-
- for (unsigned int i = instance.historyOffset_; i < instance.commandHistory_.size(); ++i)
- instance.addOutput(instance.commandHistory_[i] + '\n', -1);
- for (unsigned int i = 0; i < instance.historyOffset_; ++i)
- instance.addOutput(instance.commandHistory_[i] + '\n', -1);
- }
- */
-
- void Shell::registerListener(ShellListener* listener)
- {
- this->listeners_.push_back(listener);
- }
-
- void Shell::unregisterListener(ShellListener* listener)
- {
- for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
- {
- if ((*it) == listener)
- it = this->listeners_.erase(it);
- else
- ++it;
- }
- }
-
- void Shell::setCursorPosition(unsigned int cursor)
- {
- this->inputBuffer_->setCursorPosition(cursor);
- this->updateListeners<&ShellListener::cursorChanged>();
- }
-
- void Shell::addOutput(const std::string& text, LineType type)
- {
- this->outputBuffer_ << text;
- this->outputChanged(type);
- }
-
- void Shell::clearOutput()
- {
- this->outputLines_.clear();
- this->scrollIterator_ = this->outputLines_.begin();
-
- this->scrollPosition_ = 0;
- this->bFinishedLastLine_ = true;
-
- this->updateListeners<&ShellListener::linesChanged>();
- }
-
- Shell::LineList::const_iterator Shell::getNewestLineIterator() const
- {
- if (this->scrollPosition_)
- return this->scrollIterator_;
- else
- return this->outputLines_.begin();
- }
-
- Shell::LineList::const_iterator Shell::getEndIterator() const
- {
- return this->outputLines_.end();
- }
-
- void Shell::addToHistory(const std::string& command)
- {
- if (command == "")
- return;
-
- size_t previous_offset = mod(this->historyOffset_ - 1, this->maxHistoryLength_);
- if (previous_offset < this->commandHistory_.size() && command == this->commandHistory_[previous_offset])
- return;
-
- ModifyConfigValue(commandHistory_, set, this->historyOffset_, command);
- this->historyPosition_ = 0;
- ModifyConfigValue(historyOffset_, set, (this->historyOffset_ + 1) % this->maxHistoryLength_);
- }
-
- const std::string& Shell::getFromHistory() const
- {
- unsigned int index = mod(static_cast<int>(this->historyOffset_) - static_cast<int>(this->historyPosition_), this->maxHistoryLength_);
- if (index < this->commandHistory_.size() && this->historyPosition_ != 0)
- return this->commandHistory_[index];
- else
- return BLANKSTRING;
- }
-
- void Shell::outputChanged(int lineType)
- {
- bool newline = false;
- do
- {
- std::string output;
- std::getline(this->outputBuffer_, output);
-
- bool eof = this->outputBuffer_.eof();
- bool fail = this->outputBuffer_.fail();
- if (eof)
- this->outputBuffer_.flush();
- if (eof || fail)
- this->outputBuffer_.clear();
- newline = (!eof && !fail);
-
- if (!newline && output.empty())
- break;
-
- if (this->bFinishedLastLine_)
- {
- this->outputLines_.push_front(std::make_pair(output, static_cast<LineType>(lineType)));
-
- if (this->scrollPosition_)
- this->scrollPosition_++;
- else
- this->scrollIterator_ = this->outputLines_.begin();
-
- this->bFinishedLastLine_ = newline;
-
- if (!this->scrollPosition_)
- this->updateListeners<&ShellListener::lineAdded>();
- }
- else
- {
- this->outputLines_.front().first += output;
- this->bFinishedLastLine_ = newline;
- this->updateListeners<&ShellListener::onlyLastLineChanged>();
- }
- this->bFinishedLastLine_ = newline;
-
- } while (newline);
- }
-
- void Shell::clearInput()
- {
- this->inputBuffer_->clear();
- this->historyPosition_ = 0;
- this->updateListeners<&ShellListener::inputChanged>();
- this->updateListeners<&ShellListener::cursorChanged>();
- }
-
- void Shell::setPromptPrefix(const std::string& str)
- {
- }
-
-
- // ##########################################
- // ### InputBuffer callback functions ###
- // ##########################################
-
- void Shell::inputChanged()
- {
- this->updateListeners<&ShellListener::inputChanged>();
- this->updateListeners<&ShellListener::cursorChanged>();
- }
-
- void Shell::execute()
- {
- this->addToHistory(this->inputBuffer_->get());
- this->updateListeners<&ShellListener::executed>();
-
- bool success;
- const std::string& result = CommandExecutor::query(this->inputBuffer_->get(), &success);
- if (!success)
- {
- this->outputBuffer_ << "Error: Can't execute \"" << this->inputBuffer_->get() << "\"." << std::endl;
- this->outputChanged(Error);
- }
- else if (result != "")
- {
- this->outputBuffer_ << result << std::endl;
- this->outputChanged(Command);
- }
-
- this->clearInput();
- }
-
- void Shell::hintAndComplete()
- {
- this->inputBuffer_->set(CommandExecutor::complete(this->inputBuffer_->get()));
- this->outputBuffer_ << CommandExecutor::hint(this->inputBuffer_->get()) << std::endl;
- this->outputChanged(Hint);
-
- this->inputChanged();
- }
-
- void Shell::backspace()
- {
- this->inputBuffer_->removeBehindCursor();
- this->updateListeners<&ShellListener::inputChanged>();
- this->updateListeners<&ShellListener::cursorChanged>();
- }
-
- void Shell::exit()
- {
- if (this->inputBuffer_->getSize() > 0)
- {
- this->clearInput();
- return;
- }
-
- this->clearInput();
- this->scrollPosition_ = 0;
- this->scrollIterator_ = this->outputLines_.begin();
-
- this->updateListeners<&ShellListener::exit>();
- }
-
- void Shell::deleteChar()
- {
- this->inputBuffer_->removeAtCursor();
- this->updateListeners<&ShellListener::inputChanged>();
- }
-
- void Shell::cursorRight()
- {
- this->inputBuffer_->increaseCursor();
- this->updateListeners<&ShellListener::cursorChanged>();
- }
-
- void Shell::cursorLeft()
- {
- this->inputBuffer_->decreaseCursor();
- this->updateListeners<&ShellListener::cursorChanged>();
- }
-
- void Shell::cursorEnd()
- {
- this->inputBuffer_->setCursorToEnd();
- this->updateListeners<&ShellListener::cursorChanged>();
- }
-
- void Shell::cursorHome()
- {
- this->inputBuffer_->setCursorToBegin();
- this->updateListeners<&ShellListener::cursorChanged>();
- }
-
- void Shell::historyUp()
- {
- if (this->historyPosition_ < this->commandHistory_.size())
- {
- this->historyPosition_++;
- this->inputBuffer_->set(this->getFromHistory());
- }
- }
-
- void Shell::historyDown()
- {
- if (this->historyPosition_ > 0)
- {
- this->historyPosition_--;
- this->inputBuffer_->set(this->getFromHistory());
- }
- }
-
- void Shell::historySearchUp()
- {
- if (this->historyPosition_ == this->historyOffset_)
- return;
- unsigned int cursorPosition = this->getCursorPosition();
- const std::string& input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning of the inputline until the cursor position
- for (unsigned int newPos = this->historyPosition_ + 1; newPos <= this->historyOffset_; newPos++)
- {
- if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // search case insensitive
- {
- this->historyPosition_ = newPos;
- this->inputBuffer_->set(this->getFromHistory());
- this->setCursorPosition(cursorPosition);
- return;
- }
- }
- }
-
- void Shell::historySearchDown()
- {
- if (this->historyPosition_ == 0)
- return;
- unsigned int cursorPosition = this->getCursorPosition();
- const std::string& input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning
- for (unsigned int newPos = this->historyPosition_ - 1; newPos > 0; newPos--)
- {
- if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // sear$
- {
- this->historyPosition_ = newPos;
- this->inputBuffer_->set(this->getFromHistory());
- this->setCursorPosition(cursorPosition);
- return;
- }
- }
- }
-
- void Shell::scrollUp()
- {
- if (this->scrollIterator_ != this->outputLines_.end())
- {
- ++this->scrollIterator_;
- ++this->scrollPosition_;
-
- this->updateListeners<&ShellListener::linesChanged>();
- }
- }
-
- void Shell::scrollDown()
- {
- if (this->scrollIterator_ != this->outputLines_.begin())
- {
- --this->scrollIterator_;
- --this->scrollPosition_;
-
- this->updateListeners<&ShellListener::linesChanged>();
- }
- }
-}
Deleted: code/branches/consolecommands3/src/libraries/core/Shell.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/Shell.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/Shell.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,172 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * Reto Grieder
- *
- */
-
-#ifndef _Shell_H__
-#define _Shell_H__
-
-#include "CorePrereqs.h"
-
-#include <list>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "util/OutputHandler.h"
-#include "OrxonoxClass.h"
-#include "input/InputBuffer.h"
-
-namespace orxonox
-{
- class _CoreExport ShellListener
- {
- friend class Shell;
-
- public:
- virtual ~ShellListener() {}
-
- private:
- virtual void linesChanged() {}
- virtual void onlyLastLineChanged() {}
- virtual void lineAdded() {}
- virtual void inputChanged() {}
- virtual void cursorChanged() {}
- virtual void executed() {}
- virtual void exit() {}
- };
-
-
- class _CoreExport Shell : virtual public OrxonoxClass, public OutputListener
- {
- public:
- enum LineType
- {
- None = OutputLevel::None,
- Warning = OutputLevel::Warning,
- Error = OutputLevel::Error,
- Info = OutputLevel::Info,
- Debug = OutputLevel::Debug,
- Verbose = OutputLevel::Verbose,
- Ultra = OutputLevel::Ultra,
- Input,
- Command,
- Hint
- };
-
- Shell(const std::string& consoleName, bool bScrollable);
- ~Shell();
-
- void setConfigValues();
- void commandHistoryOffsetChanged();
- void commandHistoryLengthChanged();
-
- void registerListener(ShellListener* listener);
- void unregisterListener(ShellListener* listener);
-
- inline InputBuffer* getInputBuffer()
- { return this->inputBuffer_; }
-
- void setCursorPosition(unsigned int cursor);
- inline unsigned int getCursorPosition() const
- { return this->inputBuffer_->getCursorPosition(); }
-
- inline const std::string& getInput() const
- { return this->inputBuffer_->get(); }
-
- typedef std::list<std::pair<std::string, LineType> > LineList;
- LineList::const_iterator getNewestLineIterator() const;
- LineList::const_iterator getEndIterator() const;
-
- void addOutput(const std::string& text, LineType type = None);
- void clearOutput();
-
- inline unsigned int getNumLines() const
- { return this->outputLines_.size(); }
- inline unsigned int getScrollPosition() const
- { return this->scrollPosition_; }
-
- inline const std::string& getPromptPrefix() const { return this->promptPrefix_; }
- void setPromptPrefix(const std::string& str);
-
- private:
- Shell(const Shell& other);
-
- void addToHistory(const std::string& command);
- const std::string& getFromHistory() const;
- void clearInput();
- // OutputListener
- void outputChanged(int level);
-
- void configureInputBuffer();
-
- // InputBuffer callbacks
- void inputChanged();
- void execute();
- void hintAndComplete();
- void backspace();
- void deleteChar();
- void cursorRight();
- void cursorLeft();
- void cursorEnd();
- void cursorHome();
- void historyUp();
- void historyDown();
- void historySearchUp();
- void historySearchDown();
- void scrollUp();
- void scrollDown();
- void exit();
-
- template <void (ShellListener::*F)()>
- void updateListeners()
- {
- for (std::list<ShellListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
- ((*(it++))->*F)();
- }
-
- std::list<ShellListener*> listeners_;
- InputBuffer* inputBuffer_;
- std::stringstream outputBuffer_;
- bool bFinishedLastLine_;
- LineList outputLines_;
- LineList::const_iterator scrollIterator_;
- unsigned int scrollPosition_;
- unsigned int historyPosition_;
-
- std::string promptPrefix_;
- const std::string consoleName_;
- const bool bScrollable_;
-
- // Config values
- unsigned int maxHistoryLength_;
- unsigned int historyOffset_;
- std::vector<std::string> commandHistory_;
- int softDebugLevel_;
- };
-}
-
-#endif /* _Shell_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/TclBind.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/TclBind.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/TclBind.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,198 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#include "TclBind.h"
-
-#include <exception>
-#include <string>
-#include <cpptcl/cpptcl.h>
-
-#include "SpecialConfig.h"
-#include "util/Debug.h"
-#include "util/Exception.h"
-#include "util/StringUtils.h"
-#include "CommandExecutor.h"
-#include "ConsoleCommand.h"
-#include "PathConfig.h"
-#include "TclThreadManager.h"
-
-namespace orxonox
-{
- SetConsoleCommandShortcut(TclBind, tcl);
- SetConsoleCommandShortcut(TclBind, bgerror);
-
- TclBind* TclBind::singletonPtr_s = 0;
-
- TclBind::TclBind(const std::string& datapath)
- {
- this->interpreter_ = 0;
- this->bSetTclDataPath_ = false;
- this->setDataPath(datapath);
- }
-
- TclBind::~TclBind()
- {
- if (this->interpreter_)
- delete this->interpreter_;
- }
-
- void TclBind::setDataPath(const std::string& datapath)
- {
- // String has POSIX slashes
- this->tclDataPath_ = datapath + "tcl" + '/';
- this->bSetTclDataPath_ = true;
-
- this->initializeTclInterpreter();
- }
-
- void TclBind::initializeTclInterpreter()
- {
- if (this->bSetTclDataPath_ && !this->interpreter_)
- {
- this->interpreter_ = this->createTclInterpreter();
-
- this->interpreter_->def("::orxonox::query", TclBind::tcl_query, Tcl::variadic());
- this->interpreter_->def("::orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
- this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
- this->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
-
- try
- {
- this->interpreter_->eval("proc query {args} { ::orxonox::query $args }");
- this->interpreter_->eval("proc crossquery {id args} { ::orxonox::crossquery 0 $id $args }");
- this->interpreter_->eval("proc crossexecute {id args} { ::orxonox::crossquery 0 $id $args }");
- this->interpreter_->eval("proc running {} { return 1 }");
- this->interpreter_->eval("set id 0");
- this->interpreter_->eval("rename exit ::tcl::exit; proc exit {} { execute exit }");
- }
- catch (Tcl::tcl_error const &e)
- { COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl; }
- }
- }
-
- Tcl::interpreter* TclBind::createTclInterpreter()
- {
- Tcl::interpreter* interpreter = new Tcl::interpreter();
- const std::string& libpath = TclBind::getTclLibraryPath();
-
- try
- {
- if (!libpath.empty())
- interpreter->eval("set tcl_library \"" + libpath + '"');
-
- Tcl_Init(interpreter->get());
-
- interpreter->eval("source \"" + TclBind::getInstance().tclDataPath_ + "/init.tcl\"");
- }
- catch (Tcl::tcl_error const &e)
- { COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl; COUT(1) << "Error: Tcl isn't properly initialized. Orxonox might possibly not work like that." << std::endl; }
-
- return interpreter;
- }
-
- std::string TclBind::getTclLibraryPath()
- {
-#ifdef DEPENDENCY_PACKAGE_ENABLE
- if (PathConfig::isDevelopmentRun())
- return (std::string(specialConfig::dependencyLibraryDirectory) + "/tcl");
- else
- return (PathConfig::getRootPathString() + "lib/tcl");
-#else
- return "";
-#endif
- }
-
- std::string TclBind::tcl_query(Tcl::object const &args)
- {
- COUT(4) << "Tcl_query: " << args.get() << std::endl;
-
- const std::string& command = stripEnclosingBraces(args.get());
-
- bool success;
- const std::string& result = CommandExecutor::query(command, &success, false);
- if (!success)
- {
- COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
- }
-
- return result;
- }
-
- void TclBind::tcl_execute(Tcl::object const &args)
- {
- COUT(4) << "Tcl_execute: " << args.get() << std::endl;
- const std::string& command = stripEnclosingBraces(args.get());
-
- if (!CommandExecutor::execute(command, false))
- {
- COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
- }
- }
-
- std::string TclBind::tcl(const std::string& tclcode)
- {
- if (TclBind::getInstance().interpreter_)
- {
- try
- {
- const std::string& output = TclBind::getInstance().interpreter_->eval("uplevel #0 " + tclcode);
- if (!output.empty())
- {
- COUT(0) << "tcl> " << output << std::endl;
- }
- return output;
- }
- catch (Tcl::tcl_error const &e)
- { COUT(1) << "tcl> Error: " << e.what() << std::endl; }
- }
-
- return "";
- }
-
- void TclBind::bgerror(const std::string& error)
- {
- COUT(1) << "Tcl background error: " << stripEnclosingBraces(error) << std::endl;
- }
-
- std::string TclBind::eval(const std::string& tclcode, bool* success)
- {
- if (success)
- *success = true;
-
- try
- {
- return TclBind::getInstance().interpreter_->eval(tclcode);
- }
- catch (Tcl::tcl_error const &e)
- { COUT(1) << "Tcl error: " << e.what() << std::endl; }
-
- if (success)
- *success = false;
- return "";
- }
-}
Deleted: code/branches/consolecommands3/src/libraries/core/TclBind.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/TclBind.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/TclBind.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,74 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _TclBind_H__
-#define _TclBind_H__
-
-#include "CorePrereqs.h"
-
-#include <cassert>
-#include <string>
-#include "util/Singleton.h"
-
-namespace orxonox
-{
- class _CoreExport TclBind : public Singleton<TclBind>
- {
- friend class Singleton<TclBind>;
- public:
- TclBind(const std::string& datapath);
- ~TclBind();
-
- static std::string tcl(const std::string& tclcode);
- static void bgerror(const std::string& error);
-
- void setDataPath(const std::string& datapath);
- const std::string& getTclDataPath() const { return this->tclDataPath_; }
- static std::string getTclLibraryPath();
-
- void initializeTclInterpreter();
- static Tcl::interpreter* createTclInterpreter();
- Tcl::interpreter* getTclInterpreter() const { return this->interpreter_; }
-
- static std::string tcl_query(Tcl::object const &args);
- static void tcl_execute(Tcl::object const &args);
-
- static std::string eval(const std::string& tclcode, bool* success = 0);
-
- private:
- TclBind(const TclBind& other);
-
- Tcl::interpreter* interpreter_;
- std::string tclDataPath_;
- bool bSetTclDataPath_;
-
- static TclBind* singletonPtr_s;
- };
-}
-
-#endif /* _TclBind_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/TclThreadList.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/TclThreadList.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/TclThreadList.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,263 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _TclThreadList_H__
-#define _TclThreadList_H__
-
-#include "CorePrereqs.h"
-
-#include <list>
-
-#include <boost/thread/condition_variable.hpp>
-#include <boost/thread/shared_mutex.hpp>
-#include <boost/thread/locks.hpp>
-
-namespace orxonox
-{
- template <class T>
- class TclThreadList
- {
- public:
- void push_front(const T& value);
- void push_back(const T& value);
- template <class InputIterator> void insert(typename std::list<T>::iterator position, InputIterator begin, InputIterator end);
-
- void wait_and_pop_front(T* value);
- void wait_and_pop_back(T* value);
- bool try_pop_front(T* value);
- bool try_pop_back(T* value);
- void clear();
-
- size_t size() const;
- bool empty() const;
- bool is_in(const T& value) const;
-
- /**
- @brief Returns a reference to the list. Don't forget to lock the mutex (see @ref getMutex).
- */
- inline std::list<T>& getList()
- { return this->list_; }
-
- /**
- @brief Returns a reference to the list. Don't forget to lock the mutex (see @ref getMutex).
- */
- inline const std::list<T>& getList() const
- { return this->list_; }
-
- /**
- @brief Returns a reference to the mutex which might be useful if you want to iterate through the list (see @ref begin and @ref end).
- */
- inline boost::shared_mutex& getMutex() const
- { return this->mutex_; }
-
- private:
- std::list<T> list_; ///< A standard list for type T
- mutable boost::shared_mutex mutex_; ///< A mutex to grant exclusive access to the list
- boost::condition_variable_any condition_; ///< A condition variable to wake threads waiting for the mutex to become ready
- };
-
- /**
- @brief Pushes a new element to the front of the list. A unique_lock is needed.
- */
- template <class T>
- void TclThreadList<T>::push_front(const T& value)
- {
- boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
- this->list_.push_front(value);
- lock.unlock(); // unlock the mutex...
- this->condition_.notify_all(); // ...then call notify_all to wake threads waiting in wait_and_pop_front/back
- }
-
- /**
- @brief Pushes a new element to the back of the list. A unique_lock is needed.
- */
- template <class T>
- void TclThreadList<T>::push_back(const T& value)
- {
- boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
- this->list_.push_back(value);
- lock.unlock(); // unlock the mutex...
- this->condition_.notify_all(); // ...then call notify_all to wake threads waiting in wait_and_pop_front/back
- }
-
- /**
- @brief Inserts new elements into the list. A unique_lock is needed.
- */
- template <class T>
- template <class InputIterator> void TclThreadList<T>::insert(typename std::list<T>::iterator position, InputIterator begin, InputIterator end)
- {
- boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
- this->list_.insert(position, begin, end);
- lock.unlock(); // unlock the mutex...
- this->condition_.notify_all(); // ...then call notify_all to wake threads waiting in wait_and_pop_front/back
- }
-
- /**
- @brief Waits until the list contains at least one element and then pops and returns the front element.
- @param value The front value will be stored in the variable referenced by this pointer.
- */
- template <class T>
- void TclThreadList<T>::wait_and_pop_front(T* value)
- {
- boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
-
- while (this->list_.empty()) // check if there's an element in the list
- this->condition_.wait(lock); // wait until the condition becomes true (a notification comes from push_front, push_back or insert
-
- *value = this->list_.front();
- this->list_.pop_front();
- }
-
- /**
- @brief Waits until the list contains at least one element and then pops and returns the back element.
- @param value The back value will be stored in the variable referenced by this pointer.
- */
- template <class T>
- void TclThreadList<T>::wait_and_pop_back(T* value)
- {
- boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
-
- while (this->list_.empty()) // check if there's an element in the list
- this->condition_.wait(lock); // wait until the condition becomes true (a notification comes from push_front, push_back or insert
-
- *value = this->list_.back();
- this->list_.pop_back();
- }
-
- /**
- @brief Pops and returns the front element if there's at least one element in the list.
- @param value The front value will be stored in the variable referenced by this pointer.
- @return Returns true if there was at least one element in the list (which got poped). If the list was empty, false is returned immediately.
-
- Needs a unique_lock if there's an element to pop. If not, shared_lock is sufficient.
- */
- template <class T>
- bool TclThreadList<T>::try_pop_front(T* value)
- {
- boost::upgrade_lock<boost::shared_mutex> lock(this->mutex_); // gain shared lock
-
- if (this->list_.empty())
- {
- // No elements - return immediately
- return false;
- }
- else
- {
- // At least one element - write it into the passed variable and pop it from the list
- boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); // upgrade to unique lock to modify the list
- *value = this->list_.front();
- this->list_.pop_front();
- }
- return true;
- }
-
- /**
- @brief Pops and returns the back element if there's at least one element in the list.
- @param value The back value will be stored in the variable referenced by this pointer.
- @return Returns true if there was at least one element in the list (which got poped). If the list was empty, false is returned immediately.
-
- Needs a unique_lock if there's an element to pop. If not, shared_lock is sufficient.
- */
- template <class T>
- bool TclThreadList<T>::try_pop_back(T* value)
- {
- boost::upgrade_lock<boost::shared_mutex> lock(this->mutex_); // gain shared lock
-
- if (this->list_.empty())
- {
- // No elements - return immediately
- return false;
- }
- else
- {
- // At least one element - write it into the passed variable and pop it from the list
- boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); // upgrade to unique lock to modify the list
- *value = this->list_.back();
- this->list_.pop_back();
- }
- return true;
- }
-
- /**
- @brief Clears the list. A unique_lock is needed.
- */
- template <class T>
- void TclThreadList<T>::clear()
- {
- boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
- this->list_.clear();
- }
-
- /**
- @brief Returns the size of the list. A shared_lock is needed.
-
- Warning: Don't change the list based on the result of size(). Use an atomic function instead. Other threads may change the list
- beween your call to size() and your further actions, so be careful and use this function only if you really want nothing else than
- just the size of the list.
- */
- template <class T>
- size_t TclThreadList<T>::size() const
- {
- boost::shared_lock<boost::shared_mutex> lock(this->mutex_);
- return this->list_.size();
- }
-
- /**
- @brief Returns true if the list is empty, false otherwise. A shared_lock is needed.
-
- Warning: Don't change the list based on the result of empty(). Use an atomic function instead. Other threads may change the list
- beween your call to empty() and your further actions, so be careful and use this function only if you really want nothing else than
- just if the list is empty or not.
- */
- template <class T>
- bool TclThreadList<T>::empty() const
- {
- boost::shared_lock<boost::shared_mutex> lock(this->mutex_);
- return this->list_.empty();
- }
-
- /**
- @brief Returns true if a given element is in the list, false otherwise. A shared_lock is needed.
-
- Warning: The result of this function might be wrong just one instruction after the call. Use this function just to get information
- about a temporary snapshot and don't change the list based on the result of this function.
- */
- template <class T>
- bool TclThreadList<T>::is_in(const T& value) const
- {
- boost::shared_lock<boost::shared_mutex> lock(this->mutex_);
-
- for (typename std::list<T>::const_iterator it = this->list_.begin(); it != this->list_.end(); ++it)
- if (*it == value)
- return true;
-
- return false;
- }
-}
-
-#endif /* _TclThreadList_H__ */
Deleted: code/branches/consolecommands3/src/libraries/core/TclThreadManager.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/TclThreadManager.cc 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/TclThreadManager.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,669 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#include "TclThreadManager.h"
-
-#include <boost/bind.hpp>
-#include <boost/thread/thread.hpp>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/shared_mutex.hpp>
-#include <OgreTimer.h>
-#include <cpptcl/cpptcl.h>
-
-#include "util/Clock.h"
-#include "util/Convert.h"
-#include "util/Exception.h"
-#include "util/StringUtils.h"
-#include "CommandExecutor.h"
-#include "ConsoleCommand.h"
-#include "CoreIncludes.h"
-#include "TclBind.h"
-#include "TclThreadList.h"
-
-namespace orxonox
-{
- const float TCLTHREADMANAGER_MAX_CPU_USAGE = 0.50f;
-
- SetConsoleCommandShortcutAlias(TclThreadManager, execute, "tclexecute").argumentCompleter(0, autocompletion::tclthreads());
- SetConsoleCommandShortcutAlias(TclThreadManager, query, "tclquery" ).argumentCompleter(0, autocompletion::tclthreads());
- SetConsoleCommand(TclThreadManager, create, false);
- SetConsoleCommand(TclThreadManager, destroy, false).argumentCompleter(0, autocompletion::tclthreads());
- SetConsoleCommand(TclThreadManager, execute, false).argumentCompleter(0, autocompletion::tclthreads());
- SetConsoleCommand(TclThreadManager, query, false).argumentCompleter(0, autocompletion::tclthreads());
- SetConsoleCommand(TclThreadManager, source, false).argumentCompleter(0, autocompletion::tclthreads());
-
- /**
- @brief A struct containing all information about a Tcl-interpreter
- */
- struct TclInterpreterBundle
- {
- TclInterpreterBundle()
- {
- this->lock_ = new boost::unique_lock<boost::mutex>(this->mutex_, boost::defer_lock);
- this->bRunning_ = true;
- }
-
- ~TclInterpreterBundle()
- {
- delete this->lock_;
- }
-
- unsigned int id_; ///< The id of the interpreter
- Tcl::interpreter* interpreter_; ///< The Tcl-interpreter
- boost::mutex mutex_; ///< A mutex to lock the interpreter while it's being used
- boost::unique_lock<boost::mutex>* lock_; ///< The corresponding lock for the mutex
- TclThreadList<std::string> queue_; ///< The command queue for commands passed by execute(command)
- TclThreadList<unsigned int> queriers_; ///< A list containing the id's of all other threads sending a query to this interpreter (to avoid circular queries and deadlocks)
- bool bRunning_; ///< This variable stays true until destroy() gets called
- };
-
- TclThreadManager* TclThreadManager::singletonPtr_s = 0;
-
- /**
- @brief Constructor
- @param interpreter A pointer to the standard Tcl-interpreter (see @ref TclBind)
- */
- TclThreadManager::TclThreadManager(Tcl::interpreter* interpreter)
- {
- RegisterRootObject(TclThreadManager);
-
- this->numInterpreterBundles_ = 0;
-
- this->interpreterBundlesMutex_ = new boost::shared_mutex();
- this->mainInterpreterMutex_ = new boost::mutex();
- this->messageQueue_ = new TclThreadList<std::string>();
-
- TclInterpreterBundle* newbundle = new TclInterpreterBundle();
- newbundle->id_ = 0;
- newbundle->interpreter_ = interpreter;
- newbundle->lock_->lock();
-
- {
- boost::unique_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
- this->interpreterBundles_[0] = newbundle;
- }
- }
-
- /**
- @brief Destructor
- */
- TclThreadManager::~TclThreadManager()
- {
- delete this->interpreterBundlesMutex_;
-// delete this->mainInterpreterMutex_; // <-- temporary disabled to avoid crash if a thread is still actively queriyng
- delete this->messageQueue_;
- }
-
- /**
- @brief The "main loop" of the TclThreadManager. Creates new threads if needed and handles queries and queued commands for the main interpreter.
- */
- void TclThreadManager::preUpdate(const Clock& time)
- {
- // Get the bundle of the main interpreter (0)
- TclInterpreterBundle* bundle = this->getInterpreterBundle(0);
- if (bundle)
- {
- // Unlock the mutex to allow other threads accessing the main interpreter
- bundle->lock_->unlock();
-
- // Lock the main interpreter mutex once to synchronize with threads that want to query the main interpreter
- {
- boost::unique_lock<boost::mutex> lock(*this->mainInterpreterMutex_);
- }
-
- // Lock the mutex again to gain exclusive access to the interpreter for the rest of the mainloop
- bundle->lock_->lock();
-
- // Execute commands in the queues of the threaded interpreters
- {
- boost::shared_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
- for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
- {
- if (it->first == 0)
- continue; // We'll handle the default interpreter later (and without threads of course)
-
- TclInterpreterBundle* bundle = it->second;
- if (!bundle->queue_.empty())
- {
- // There are commands in the queue
- try
- {
- if (!bundle->lock_->owns_lock() && bundle->lock_->try_lock())
- {
- // We sucessfully obtained a lock for the interpreter
- std::string command;
- if (bundle->queue_.try_pop_front(&command))
- {
- // Start a thread to execute the command
- boost::thread(boost::bind(&tclThread, bundle, command));
- }
- else
- {
- // Somehow the queue become empty (maybe multiple consumers) - unlock the mutex
- bundle->lock_->unlock();
- }
- }
- }
- catch (...)
- {
- // A lock error occurred - this is possible if the lock gets locked between !bundle->lock_->owns_lock() and bundle->lock_->try_lock()
- // This isn't too bad, just continue
- }
- }
- }
- }
-
- // Execute commands in the message queue
- if (!this->messageQueue_->empty())
- {
- std::string command;
- while (true)
- {
- // Pop the front value from the list (break the loop if there are no elements in the list)
- if (!this->messageQueue_->try_pop_front(&command))
- break;
-
- // Execute the command
- CommandExecutor::execute(command, false);
- }
- }
-
- // Execute commands in the queue of the main interpreter
- if (!bundle->queue_.empty())
- {
- // Calculate the time we have until we reach the maximal cpu usage
- unsigned long maxtime = (unsigned long)(time.getDeltaTime() * 1000000 * TCLTHREADMANAGER_MAX_CPU_USAGE);
-
- Ogre::Timer timer;
- std::string command;
-
- while (timer.getMicroseconds() < maxtime)
- {
- // Pop the front value from the list (break the loop if there are no elements in the list)
- if (!bundle->queue_.try_pop_front(&command))
- break;
-
- // Execute the command
- CommandExecutor::execute(command, false);
- }
- }
- }
- }
-
- /**
- @brief Creates a new Tcl-interpreter.
- */
- unsigned int TclThreadManager::create()
- {
- TclThreadManager::getInstance().numInterpreterBundles_++;
- TclThreadManager::createWithId(TclThreadManager::getInstance().numInterpreterBundles_);
- COUT(0) << "Created new Tcl-interpreter with ID " << TclThreadManager::getInstance().numInterpreterBundles_ << std::endl;
- return TclThreadManager::getInstance().numInterpreterBundles_;
- }
-
- /**
- @brief Creates a new Tcl-interpreter with a given id.
-
- Use with caution - if the id collides with an already existing interpreter, this call will fail.
- This will also be a problem, if the auto-numbered interpreters (by using create()) reach an id
- which was previously used in this function. Use high numbers to be safe.
- */
- Tcl::interpreter* TclThreadManager::createWithId(unsigned int id)
- {
- TclInterpreterBundle* newbundle = new TclInterpreterBundle();
- newbundle->id_ = id;
- newbundle->interpreter_ = TclBind::createTclInterpreter();
-
- TclThreadManager::initialize(newbundle);
-
- {
- // Add the new bundle to the map
- boost::unique_lock<boost::shared_mutex> lock(*TclThreadManager::getInstance().interpreterBundlesMutex_);
- TclThreadManager::getInstance().interpreterBundles_[id] = newbundle;
- }
-
- return newbundle->interpreter_;
- }
-
- void TclThreadManager::initialize(TclInterpreterBundle* bundle)
- {
- const std::string& id_string = getConvertedValue<unsigned int, std::string>(bundle->id_);
-
- // Initialize the new interpreter
- try
- {
- // Define the functions which are implemented in C++
- bundle->interpreter_->def("::orxonox::execute", TclThreadManager::tcl_execute, Tcl::variadic());
- bundle->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
- bundle->interpreter_->def("::orxonox::query", TclThreadManager::tcl_query, Tcl::variadic());
- bundle->interpreter_->def("::orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
- bundle->interpreter_->def("::orxonox::running", TclThreadManager::tcl_running);
-
- // Create threadspecific shortcuts for the functions above
- bundle->interpreter_->def("execute", TclThreadManager::tcl_execute, Tcl::variadic());
- bundle->interpreter_->def("crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
- bundle->interpreter_->eval("proc query {args} { ::orxonox::query " + id_string + " $args }");
- bundle->interpreter_->eval("proc crossquery {id args} { ::orxonox::crossquery " + id_string + " $id $args }");
- bundle->interpreter_->eval("proc running {} { return [::orxonox::running " + id_string + "] }");
-
- // Define a variable containing the thread id
- bundle->interpreter_->eval("set id " + id_string);
-
- // Use our own exit function to avoid shutting down the whole program instead of just the interpreter
- bundle->interpreter_->eval("rename exit ::tcl::exit");
- bundle->interpreter_->eval("proc exit {} { execute TclThreadManager destroy " + id_string + " }");
-
- // Redefine some native functions
- bundle->interpreter_->eval("rename while ::tcl::while");
- bundle->interpreter_->eval("rename ::orxonox::while while");
- bundle->interpreter_->eval("rename for ::tcl::for");
- bundle->interpreter_->eval("rename ::orxonox::for for");
- }
- catch (const Tcl::tcl_error& e)
- { bundle->interpreter_ = 0; COUT(1) << "Tcl error while creating Tcl-interpreter (" << id_string << "): " << e.what() << std::endl; }
- }
-
- /**
- @brief Stops and destroys a given Tcl-interpreter
- */
- void TclThreadManager::destroy(unsigned int id)
- {
- // TODO
- // Not yet implemented
- TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(id);
- if (bundle)
- {
- bundle->bRunning_ = false;
- }
- }
-
- /**
- @brief Sends a command to the queue of a given Tcl-interpreter
- @param id The id of the target interpreter
- @param command The command to be sent
- */
- void TclThreadManager::execute(unsigned int target_id, const std::string& command)
- {
- TclThreadManager::getInstance()._execute(target_id, command);
- }
-
- /**
- @brief This function can be called from Tcl to execute a console command.
-
- Commands which shall be executed are put into a queue and processed as soon as the
- main thread feels ready to do so. The queue may also be full which results in a temporary
- suspension of the calling thread until the queue gets ready again.
- */
- void TclThreadManager::tcl_execute(const Tcl::object& args)
- {
- TclThreadManager::getInstance()._execute(0, stripEnclosingBraces(args.get()));
- }
-
- /**
- @brief This function can be called from Tcl to send a command to the queue of any interpreter.
- @param target_id The id of the target thread
- */
- void TclThreadManager::tcl_crossexecute(int target_id, const Tcl::object& args)
- {
- TclThreadManager::getInstance()._execute(static_cast<unsigned int>(target_id), stripEnclosingBraces(args.get()));
- }
-
- /**
- @brief Sends a command to the queue of a given Tcl-interpreter
- @param id The id of the target interpreter
- @param command The command to be sent
- */
- void TclThreadManager::_execute(unsigned int target_id, const std::string& command)
- {
- TclInterpreterBundle* bundle = this->getInterpreterBundle(target_id);
- if (bundle)
- bundle->queue_.push_back(command);
- }
-
-
- /**
- @brief Sends a query to a given Tcl-interpreter and waits for the result
- @param id The id of the target interpreter
- @param command The command to be sent
- @return The result of the command
- */
- std::string TclThreadManager::query(unsigned int target_id, const std::string& command)
- {
- return TclThreadManager::getInstance()._query(0, target_id, command);
- }
-
- /**
- @brief This function can be called from Tcl to send a query to the main thread.
- @param source_id The id of the calling thread
-
- A query waits for the result of the command. This means, the calling thread will be blocked until
- the main thread answers the query. In return, the main thread sends the result of the console
- command back to Tcl.
- */
- std::string TclThreadManager::tcl_query(int source_id, const Tcl::object& args)
- {
- return TclThreadManager::getInstance()._query(static_cast<unsigned int>(source_id), 0, stripEnclosingBraces(args.get()), true);
- }
-
- /**
- @brief This function can be called from Tcl to send a query to another thread.
- @param source_id The id of the calling thread
- @param target_id The id of the target thread
- */
- std::string TclThreadManager::tcl_crossquery(int source_id, int target_id, const Tcl::object& args)
- {
- return TclThreadManager::getInstance()._query(static_cast<unsigned int>(source_id), static_cast<unsigned int>(target_id), stripEnclosingBraces(args.get()));
- }
-
- /**
- @brief This function performs a query to any Tcl interpreter
- @param source_id The id of the calling thread
- @param target_id The id of the target thread
- @param command The command to send as a query
- @param bUseCommandExecutor Only used if the target_id is 0 (which references the main interpreter). In this case it means if the command should be passed to the CommandExecutor (true) or to the main Tcl interpreter (false). This is true when called by tcl_query and false when called by tcl_crossquery.
- */
- std::string TclThreadManager::_query(unsigned int source_id, unsigned int target_id, const std::string& command, bool bUseCommandExecutor)
- {
- TclInterpreterBundle* source_bundle = this->getInterpreterBundle(source_id);
- TclInterpreterBundle* target_bundle = this->getInterpreterBundle(target_id);
- std::string output;
-
- if (source_bundle && target_bundle)
- {
- // At this point we assume the mutex of source_bundle to be locked (because it's executing this query right now an waits for the return value)
- // We can safely use it's querier list (because there's no other place in the code using the list except this query - and the interpreter can't start more than one query)
-
- if ((source_bundle->id_ == target_bundle->id_) || source_bundle->queriers_.is_in(target_bundle->id_))
- {
- // This query would lead to a deadlock - return with an error
- TclThreadManager::error("Error: Circular query (" + this->dumpList(source_bundle->queriers_.getList()) + ' ' + getConvertedValue<unsigned int, std::string>(source_bundle->id_) \
- + " -> " + getConvertedValue<unsigned int, std::string>(target_bundle->id_) \
- + "), couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target_bundle->id_) \
- + " from other interpreter with ID " + getConvertedValue<unsigned int, std::string>(source_bundle->id_) + '.');
- }
- else
- {
- boost::unique_lock<boost::mutex> lock(target_bundle->mutex_, boost::try_to_lock);
- boost::unique_lock<boost::mutex> mainlock(*this->mainInterpreterMutex_, boost::defer_lock);
-
- if (!lock.owns_lock() && source_bundle->id_ != 0)
- {
- // We couldn't obtain the try_lock immediately and we're not the main interpreter - wait until the lock becomes possible (note: the main interpreter won't wait and instead returns an error - see below)
- if (target_bundle->id_ == 0)
- {
- // We're querying the main interpreter - use the main interpreter mutex to synchronize
- mainlock.lock();
- lock.lock();
- }
- else
- {
- // We're querying a threaded interpreter - no synchronization needed
- lock.lock();
- }
- }
-
- if (lock.owns_lock())
- {
- // Now the mutex of target_bundle is also locked an we can update the querier list
- target_bundle->queriers_.insert(target_bundle->queriers_.getList().begin(), source_bundle->queriers_.getList().begin(), source_bundle->queriers_.getList().end());
- target_bundle->queriers_.push_back(source_bundle->id_);
-
- // Perform the query (note: this happens in the main thread because we need the returnvalue)
- if (target_bundle->id_ == 0 && bUseCommandExecutor)
- {
- // It's a query to the CommandExecutor
- TclThreadManager::debug("TclThread_query -> CE: " + command);
- bool success;
- output = CommandExecutor::query(command, &success, false);
- if (!success)
- TclThreadManager::error("Error: Can't execute command \"" + command + "\"!");
- }
- else
- {
- // It's a query to a Tcl interpreter
- TclThreadManager::debug("TclThread_query: " + command);
-
- output = TclThreadManager::eval(target_bundle, command, "query");
- }
-
- // Clear the queriers list of the target
- target_bundle->queriers_.clear();
-
- // Unlock the mutex of the target_bundle
- lock.unlock();
-
- // Finally unlock the main interpreter lock if necessary
- if (mainlock.owns_lock())
- mainlock.unlock();
- }
- else
- {
- // This happens if the main thread tries to query a busy interpreter
- // To avoid a lock of the main thread, we simply don't proceed with the query in this case
- TclThreadManager::error("Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target_bundle->id_) + ", interpreter is busy right now.");
- }
- }
-
- }
-
- return output;
- }
-
- /**
- @brief Creates a non-interactive Tcl-interpreter which executes a file.
- */
- void TclThreadManager::source(const std::string& file)
- {
- boost::thread(boost::bind(&sourceThread, file));
- }
-
- /**
- @brief This function can be called from Tcl to ask if the thread is still suposed to be running.
- @param id The id of the thread in question
- */
- bool TclThreadManager::tcl_running(int id)
- {
- TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(static_cast<unsigned int>(id));
- if (bundle)
- return bundle->bRunning_;
- else
- return false;
- }
-
- /**
- @brief Returns the interpreter bundle with the given id.
- @param id The id of the interpreter
- @return The interpreter or 0 if the id doesn't exist
- */
- TclInterpreterBundle* TclThreadManager::getInterpreterBundle(unsigned int id)
- {
- boost::shared_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
-
- std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = this->interpreterBundles_.find(id);
- if (it != this->interpreterBundles_.end())
- {
- return it->second;
- }
- else
- {
- TclThreadManager::error("Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(id) + " existing.");
- return 0;
- }
- }
-
- /**
- @brief Returns a string containing all elements of a unsigned-integer-list separated by spaces.
- */
- std::string TclThreadManager::dumpList(const std::list<unsigned int>& list)
- {
- std::string output;
- for (std::list<unsigned int>::const_iterator it = list.begin(); it != list.end(); ++it)
- {
- if (it != list.begin())
- output += ' ';
-
- output += getConvertedValue<unsigned int, std::string>(*it);
- }
- return output;
- }
-
- /**
- @brief Returns a list with the numbers of all existing Tcl-interpreters.
-
- This function is used by the auto completion function.
- */
- std::list<unsigned int> TclThreadManager::getThreadList() const
- {
- boost::shared_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
-
- std::list<unsigned int> threads;
- for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
- if (it->first > 0 && it->first <= this->numInterpreterBundles_) // only list autonumbered interpreters (created with create()) - exclude the default interpreter 0 and all manually numbered interpreters)
- threads.push_back(it->first);
- return threads;
- }
-
- /**
- @brief A helper function to print errors in a thread safe manner.
- */
- void TclThreadManager::error(const std::string& error)
- {
- TclThreadManager::getInstance().messageQueue_->push_back("error " + error);
- }
-
- /**
- @brief A helper function to print debug information in a thread safe manner.
- */
- void TclThreadManager::debug(const std::string& error)
- {
- TclThreadManager::getInstance().messageQueue_->push_back("debug " + error);
- }
-
- /**
- @brief Evaluates a Tcl command without throwing exceptions (which may rise problems on certain machines).
- @return The Tcl return value
-
- Errors are reported through the @ref error function.
- */
- std::string TclThreadManager::eval(TclInterpreterBundle* bundle, const std::string& command, const std::string& action)
- {
- Tcl_Interp* interpreter = bundle->interpreter_->get();
- int cc = Tcl_Eval(interpreter, command.c_str());
-
- Tcl::details::result result(interpreter);
-
- if (cc != TCL_OK)
- {
- TclThreadManager::error("Tcl error (" + action + ", ID " + getConvertedValue<unsigned int, std::string>(bundle->id_) + "): " + static_cast<std::string>(result));
- return "";
- }
- else
- {
- return result;
- }
- }
-
- ////////////////
- // The Thread //
- ////////////////
-
- /**
- @brief The main function of the thread. Executes a Tcl command.
- @param bundle The interpreter bundle containing all necessary variables
- @param command the Command to execute
- */
- void tclThread(TclInterpreterBundle* bundle, const std::string& command)
- {
- TclThreadManager::debug("TclThread_execute: " + command);
-
- TclThreadManager::eval(bundle, command, "execute");
-
- bundle->lock_->unlock();
- }
-
- /**
- @brief The main function of a non-interactive source thread. Executes the file.
- @param file The name of the file that should be executed by the non-interactive interpreter.
- */
- void sourceThread(const std::string& file)
- {
- TclThreadManager::debug("TclThread_source: " + file);
-
- // Prepare the command-line arguments
- const int argc = 2;
- char* argv[argc];
- argv[0] = const_cast<char*>("tclthread");
- argv[1] = const_cast<char*>(file.c_str());
-
- // Start the Tcl-command Tcl_Main with the Tcl_OrxonoxAppInit hook
- Tcl_Main(argc, argv, Tcl_OrxonoxAppInit);
-
-// Tcl::object object(file);
-// int cc = Tcl_FSEvalFile(bundle->interpreter_->get(), object.get_object());
-// Tcl::details::result result(bundle->interpreter_->get());
-// if (cc != TCL_OK)
-// TclThreadManager::error("Tcl error (source, ID " + getConvertedValue<unsigned int, std::string>(bundle->id_) + "): " + static_cast<std::string>(result));
-//
-// // Unlock the mutex
-// bundle->lock_->unlock();
- }
-
- /**
- @brief A tcl-init hook to inject the non-interactive Tcl-interpreter into the TclThreadManager.
- */
- int Tcl_OrxonoxAppInit(Tcl_Interp* interp)
- {
- // Create a new interpreter bundle
- unsigned int id = TclThreadManager::create();
- TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(id);
-
- // Replace the default interpreter in the bundle with the non-interactive one (passed as an argument to this function)
- if (bundle->interpreter_)
- delete bundle->interpreter_;
- bundle->interpreter_ = new Tcl::interpreter(interp, true);
-
- // Initialize the non-interactive interpreter (like in @ref TclBind::createTclInterpreter but exception safe)
- const std::string& libpath = TclBind::getTclLibraryPath();
- if (!libpath.empty())
- TclThreadManager::eval(bundle, "set tcl_library \"" + libpath + '"', "source");
- int cc = Tcl_Init(interp);
- TclThreadManager::eval(bundle, "source \"" + TclBind::getInstance().getTclDataPath() + "/init.tcl\"", "source");
-
- // Initialize the non-interactive interpreter also with the thread-specific stuff
- TclThreadManager::initialize(bundle);
-
- // Lock the mutex (this will be locked until the thread finishes - no chance to interact with the interpreter)
- bundle->lock_->lock();
-
- // Return to Tcl_Main
- if (!bundle->interpreter_)
- return TCL_ERROR;
- else
- return cc;
- }
-}
Deleted: code/branches/consolecommands3/src/libraries/core/TclThreadManager.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/TclThreadManager.h 2010-08-21 22:48:55 UTC (rev 7201)
+++ code/branches/consolecommands3/src/libraries/core/TclThreadManager.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -1,102 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-#ifndef _TclThreadManager_H__
-#define _TclThreadManager_H__
-
-#include "CorePrereqs.h"
-
-#include <cassert>
-#include <list>
-#include <map>
-#include <string>
-
-#include "util/Singleton.h"
-#include "OrxonoxClass.h"
-
-struct Tcl_Interp;
-
-namespace orxonox
-{
- class _CoreExport TclThreadManager : public Singleton<TclThreadManager>, public OrxonoxClass
- {
- friend class Singleton<TclThreadManager>;
- friend class TclBind;
- friend _CoreExport void tclThread(TclInterpreterBundle* bundle, const std::string& command);
- friend _CoreExport void sourceThread(const std::string& file);
- friend _CoreExport int Tcl_OrxonoxAppInit(Tcl_Interp* interp);
-
- public:
- TclThreadManager(Tcl::interpreter* interpreter);
- virtual ~TclThreadManager();
-
- static unsigned int create();
- static Tcl::interpreter* createWithId(unsigned int id);
- static void destroy(unsigned int id);
- static void execute(unsigned int target_id, const std::string& command);
- static std::string query(unsigned int target_id, const std::string& command);
- static void source(const std::string& file);
-
- static void error(const std::string& error);
- static void debug(const std::string& error);
-
- void preUpdate(const Clock& time);
-
- std::list<unsigned int> getThreadList() const;
-
- private:
- static void tcl_execute(const Tcl::object& args);
- static void tcl_crossexecute(int target_id, const Tcl::object& args);
- static std::string tcl_query(int source_id, const Tcl::object& args);
- static std::string tcl_crossquery(int source_id, int target_id, const Tcl::object& args);
- static bool tcl_running(int id);
-
- void _execute(unsigned int target_id, const std::string& command);
- std::string _query(unsigned int source_id, unsigned int target_id, const std::string& command, bool bUseCommandExecutor = false);
-
- TclInterpreterBundle* getInterpreterBundle(unsigned int id);
- std::string dumpList(const std::list<unsigned int>& list);
-
- static void initialize(TclInterpreterBundle* bundle);
- static std::string eval(TclInterpreterBundle* bundle, const std::string& command, const std::string& action);
-
- static TclThreadManager* singletonPtr_s; ///< Singleton pointer
-
- unsigned int numInterpreterBundles_; ///< Number of created Tcl-interpreters (only used for auto-numbered interpreters, not affected by @ref createWithId)
- std::map<unsigned int, TclInterpreterBundle*> interpreterBundles_; ///< A map containing all Tcl-interpreters
- boost::shared_mutex* interpreterBundlesMutex_; ///< A mutex used to synchronize threads when accessing @ref interpreterBundles_
- TclThreadList<std::string>* messageQueue_; ///< A queue to pass messages from Tcl-threads to the main thread
- boost::mutex* mainInterpreterMutex_; ///< A mutex to synchronize queries to the main interpreter
- };
-
- _CoreExport void tclThread(TclInterpreterBundle* bundle, const std::string& command);
- _CoreExport void sourceThread(const std::string& file);
- _CoreExport int Tcl_OrxonoxAppInit(Tcl_Interp* interp);
-}
-
-#endif /* _TclThreadManager_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/ArgumentCompleter.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/ArgumentCompleter.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/ArgumentCompleter.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/ArgumentCompleter.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,79 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _ArgumentCompleter_H__
+#define _ArgumentCompleter_H__
+
+#include "CorePrereqs.h"
+#include "ArgumentCompletionListElement.h"
+
+namespace orxonox
+{
+ class _CoreExport ArgumentCompleter
+ {
+ public:
+ ArgumentCompleter(ArgumentCompletionList (*function) (void)) : paramCount_(0), function_0_(function) {}
+ ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1)) : paramCount_(1), function_1_(function) {}
+ ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2)) : paramCount_(2), function_2_(function) {}
+ ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3)) : paramCount_(3), function_3_(function) {}
+ ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4)) : paramCount_(4), function_4_(function) {}
+ ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5)) : paramCount_(5), function_5_(function) {}
+
+ ArgumentCompletionList operator()(const std::string& param1 = "", const std::string& param2 = "", const std::string& param3 = "", const std::string& param4 = "", const std::string& param5 = "")
+ {
+ switch (this->paramCount_)
+ {
+ case 0:
+ return (*this->function_0_)();
+ case 1:
+ return (*this->function_1_)(param1);
+ case 2:
+ return (*this->function_2_)(param1, param2);
+ case 3:
+ return (*this->function_3_)(param1, param2, param3);
+ case 4:
+ return (*this->function_4_)(param1, param2, param3, param4);
+ case 5:
+ return (*this->function_5_)(param1, param2, param3, param4, param5);
+ default:
+ return ArgumentCompletionList();
+ }
+ }
+
+ private:
+ unsigned char paramCount_;
+ ArgumentCompletionList (*function_0_) (void);
+ ArgumentCompletionList (*function_1_) (const std::string& param1);
+ ArgumentCompletionList (*function_2_) (const std::string& param1, const std::string& param2);
+ ArgumentCompletionList (*function_3_) (const std::string& param1, const std::string& param2, const std::string& param3);
+ ArgumentCompletionList (*function_4_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4);
+ ArgumentCompletionList (*function_5_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5);
+ };
+}
+
+#endif /* _ArgumentCompleter_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionFunctions.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/ArgumentCompletionFunctions.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionFunctions.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionFunctions.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,154 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#include "ArgumentCompletionFunctions.h"
+
+#include <map>
+#include <boost/version.hpp>
+#include <boost/filesystem.hpp>
+
+#include "util/Convert.h"
+#include "util/StringUtils.h"
+#include "Identifier.h"
+#include "ConfigFileManager.h"
+#include "ConfigValueContainer.h"
+#include "TclThreadManager.h"
+
+// Boost 1.36 has some issues with deprecated functions that have been omitted
+#if (BOOST_VERSION == 103600)
+# define BOOST_LEAF_FUNCTION filename
+#else
+# define BOOST_LEAF_FUNCTION leaf
+#endif
+
+namespace orxonox
+{
+ namespace autocompletion
+ {
+ ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(fallback)()
+ {
+ return ArgumentCompletionList();
+ }
+
+ ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(files)(const std::string& fragment)
+ {
+ ArgumentCompletionList dirlist;
+ ArgumentCompletionList filelist;
+
+ try
+ {
+ boost::filesystem::path input(fragment);
+ boost::filesystem::path startdirectory(input.branch_path());
+
+ if (!boost::filesystem::exists(startdirectory))
+ {
+ startdirectory = ".";
+ }
+#ifdef ORXONOX_PLATFORM_WINDOWS
+ else
+ {
+ const std::string& dir = startdirectory.string();
+ if (dir.size() > 0 && dir[dir.size() - 1] == ':')
+ startdirectory = dir + '/';
+ }
+#endif
+
+ boost::filesystem::directory_iterator file(startdirectory);
+ boost::filesystem::directory_iterator end;
+
+ while (file != end)
+ {
+ if (boost::filesystem::is_directory(*file))
+ dirlist.push_back(ArgumentCompletionListElement(file->string() + '/', getLowercase(file->string()) + '/', file->BOOST_LEAF_FUNCTION() + '/'));
+ else
+ filelist.push_back(ArgumentCompletionListElement(file->string(), getLowercase(file->string()), file->BOOST_LEAF_FUNCTION()));
+ ++file;
+ }
+ }
+ catch (...) {}
+
+ filelist.insert(filelist.begin(), dirlist.begin(), dirlist.end());
+ return filelist;
+ }
+
+ ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingssections)()
+ {
+ ArgumentCompletionList sectionList;
+
+ const std::set<std::string>& names = SettingsConfigFile::getInstance().getSectionNames();
+ for (std::set<std::string>::const_iterator it = names.begin(); it != names.end(); ++it)
+ sectionList.push_back(ArgumentCompletionListElement(*it, getLowercase(*it)));
+
+ return sectionList;
+ }
+
+ ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsentries)(const std::string& fragment, const std::string& section)
+ {
+ ArgumentCompletionList entryList;
+ SettingsConfigFile& settings = SettingsConfigFile::getInstance();
+ const std::string& sectionLC = getLowercase(section);
+
+ SettingsConfigFile::ContainerMap::const_iterator upper = settings.getContainerUpperBound(sectionLC);
+ for (SettingsConfigFile::ContainerMap::const_iterator it = settings.getContainerLowerBound(sectionLC); it != upper; ++it)
+ entryList.push_back(ArgumentCompletionListElement(it->second.second->getName(), it->second.first));
+
+ return entryList;
+ }
+
+ ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsvalue)(const std::string& fragment, const std::string& entry, const std::string& section)
+ {
+ ArgumentCompletionList oldValue;
+ SettingsConfigFile& settings = SettingsConfigFile::getInstance();
+ const std::string& sectionLC = getLowercase(section);
+ const std::string& entryLC = getLowercase(entry);
+
+ SettingsConfigFile::ContainerMap::const_iterator upper = settings.getContainerUpperBound(sectionLC);
+ for (SettingsConfigFile::ContainerMap::const_iterator it = settings.getContainerLowerBound(sectionLC); it != upper; ++it)
+ {
+ if (it->second.first == entryLC)
+ {
+ const std::string& valuestring = it->second.second->toString();
+ oldValue.push_back(ArgumentCompletionListElement(valuestring, getLowercase(valuestring), "Old value: " + valuestring));
+ }
+ }
+
+ return oldValue;
+ }
+
+ ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(tclthreads)()
+ {
+ std::list<unsigned int> threadnumbers = TclThreadManager::getInstance().getThreadList();
+ ArgumentCompletionList threads;
+
+ for (std::list<unsigned int>::const_iterator it = threadnumbers.begin(); it != threadnumbers.end(); ++it)
+ threads.push_back(ArgumentCompletionListElement(multi_cast<std::string>(*it)));
+
+ return threads;
+ }
+ }
+}
Copied: code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionFunctions.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/ArgumentCompletionFunctions.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionFunctions.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionFunctions.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,63 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _ArgumentCompletionFunctions_H__
+#define _ArgumentCompletionFunctions_H__
+
+#include "CorePrereqs.h"
+#include "ArgumentCompleter.h"
+
+
+#define ARGUMENT_COMPLETION_FUNCTION_DECLARATION(functionname) \
+ _CoreExport ArgumentCompleter* functionname(); \
+ _CoreExport ArgumentCompletionList acf_##functionname
+
+#define ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(functionname) \
+ ArgumentCompleter* functionname() \
+ { \
+ static ArgumentCompleter completer = ArgumentCompleter(&acf_##functionname); \
+ return &completer; \
+ } \
+ \
+ ArgumentCompletionList acf_##functionname
+
+
+namespace orxonox
+{
+ namespace autocompletion
+ {
+ ARGUMENT_COMPLETION_FUNCTION_DECLARATION(fallback)();
+ ARGUMENT_COMPLETION_FUNCTION_DECLARATION(files)(const std::string& fragment);
+ ARGUMENT_COMPLETION_FUNCTION_DECLARATION(settingssections)();
+ ARGUMENT_COMPLETION_FUNCTION_DECLARATION(settingsentries)(const std::string& fragment, const std::string& section);
+ ARGUMENT_COMPLETION_FUNCTION_DECLARATION(settingsvalue)(const std::string& fragment, const std::string& entry, const std::string& section);
+ ARGUMENT_COMPLETION_FUNCTION_DECLARATION(tclthreads)();
+ }
+}
+
+#endif /* _ArgumentCompletionFunctions_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionListElement.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/ArgumentCompletionListElement.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionListElement.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/ArgumentCompletionListElement.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,73 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _ArgumentCompletionListElement_H__
+#define _ArgumentCompletionListElement_H__
+
+#include "CorePrereqs.h"
+
+#include <list>
+#include <string>
+
+namespace orxonox
+{
+ const int ACL_MODE_NORMAL = 1;
+ const int ACL_MODE_LOWERCASE = 2;
+ const int ACL_MODE_DISPLAY = 4;
+
+ typedef std::list<ArgumentCompletionListElement> ArgumentCompletionList;
+
+ class _CoreExport ArgumentCompletionListElement
+ {
+ public:
+ ArgumentCompletionListElement(const std::string& normalcase) : mode_(ACL_MODE_NORMAL), normalCase_(normalcase) {}
+ ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase) : mode_(ACL_MODE_NORMAL | ACL_MODE_LOWERCASE), normalCase_(normalcase), lowerCase_(lowercase) {}
+ ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase, const std::string& display) : mode_(ACL_MODE_NORMAL | ACL_MODE_LOWERCASE | ACL_MODE_DISPLAY), normalCase_(normalcase), lowerCase_(lowercase), display_(display) {}
+
+ const std::string& getString() const
+ { return this->normalCase_; }
+ const std::string& getComparable() const
+ { if (this->mode_ & ACL_MODE_LOWERCASE) { return this->lowerCase_; } else { return this->normalCase_; } }
+ const std::string& getDisplay() const
+ { if (this->mode_ & ACL_MODE_DISPLAY) { return this->display_; } else { return this->normalCase_; } }
+
+ bool lowercaseComparison() const
+ { return (this->mode_ & ACL_MODE_LOWERCASE); }
+
+ bool operator<(const ArgumentCompletionListElement& other) const
+ { return (this->getComparable() < other.getComparable()); }
+
+ private:
+ unsigned char mode_;
+ std::string normalCase_;
+ std::string lowerCase_;
+ std::string display_;
+ };
+}
+
+#endif /* _ArgumentCompletionListElement_H__ */
Added: code/branches/consolecommands3/src/libraries/core/command/CMakeLists.txt
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/CMakeLists.txt (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/CMakeLists.txt 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,11 @@
+ADD_SOURCE_FILES(CORE_SRC_FILES
+ CommandEvaluation.cc
+ CommandExecutor.cc
+ ConsoleCommand.cc
+ ConsoleCommandCompilation.cc
+ Executor.cc
+ IOConsole.cc
+ IRC.cc
+ Shell.cc
+ TclBind.cc
+)
Property changes on: code/branches/consolecommands3/src/libraries/core/command/CMakeLists.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Copied: code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/CommandEvaluation.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,307 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#include "CommandEvaluation.h"
+
+#include "util/Debug.h"
+#include "util/StringUtils.h"
+#include "ConsoleCommand.h"
+#include "Identifier.h"
+
+namespace orxonox
+{
+ CommandEvaluation::CommandEvaluation()
+ {
+ this->initialize("");
+ this->state_ = CommandState::Uninitialized;
+ }
+
+ void CommandEvaluation::initialize(const std::string& command)
+ {
+ this->bNewCommand_ = true;
+ this->bCommandChanged_ = false;
+ this->originalCommand_ = command;
+ this->command_ = command;
+ this->commandTokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
+
+ this->additionalParameter_.clear();
+
+ this->bEvaluatedParams_ = false;
+
+ this->listOfPossibleIdentifiers_.clear();
+ this->listOfPossibleFunctions_.clear();
+ this->listOfPossibleArguments_.clear();
+
+ this->functionclass_ = 0;
+ this->function_ = 0;
+ this->possibleArgument_.clear();
+ this->argument_.clear();
+
+ this->errorMessage_.clear();
+ this->state_ = CommandState::Empty;
+ }
+
+ bool CommandEvaluation::isValid() const
+ {
+ return (this->function_);
+ }
+
+ bool CommandEvaluation::execute() const
+ {
+ bool success;
+ this->query(&success);
+ return success;
+ }
+
+ MultiType CommandEvaluation::query(bool* success) const
+ {
+ if (success)
+ *success = false;
+
+ if (!this->isValid())
+ return MT_Type::Null;
+
+ if (this->bEvaluatedParams_ && this->function_)
+ {
+ if (success)
+ *success = true;
+ COUT(6) << "CE_execute (evaluation): " << this->function_->getName() << ' ' << this->param_[0] << ' ' << this->param_[1] << ' ' << this->param_[2] << ' ' << this->param_[3] << ' ' << this->param_[4] << std::endl;
+ return (*this->function_)(this->param_[0], this->param_[1], this->param_[2], this->param_[3], this->param_[4]);
+ }
+
+ if (!this->bCommandChanged_ || nocaseCmp(removeTrailingWhitespaces(this->command_), removeTrailingWhitespaces(this->originalCommand_)) == 0)
+ {
+ COUT(4) << "CE_execute: " << this->command_ << "\n";
+
+ unsigned int startindex = this->getStartindex();
+ if (this->commandTokens_.size() > startindex)
+ return this->function_->parse(removeSlashes(this->commandTokens_.subSet(startindex).join() + this->getAdditionalParameter()), success);
+ else
+ return this->function_->parse(removeSlashes(this->additionalParameter_), success);
+ }
+
+ return MT_Type::Null;
+ }
+
+ const std::string& CommandEvaluation::complete()
+ {
+ if (!this->bNewCommand_)
+ {
+ switch (this->state_)
+ {
+ case CommandState::Uninitialized:
+ break;
+ case CommandState::Empty:
+ break;
+ case CommandState::ShortcutOrIdentifier:
+ if (this->function_)
+ {
+ if (this->function_->getParamCount() == 0)
+ return (this->command_ = this->function_->getName());
+ else
+ return (this->command_ = this->function_->getName() + ' ');
+ }
+ else if (this->functionclass_)
+ return (this->command_ = this->functionclass_->getName() + ' ');
+ break;
+ case CommandState::Function:
+ if (this->function_)
+ {
+ if (this->function_->getParamCount() == 0)
+ return (this->command_ = this->functionclass_->getName() + ' ' + this->function_->getName());
+ else
+ return (this->command_ = this->functionclass_->getName() + ' ' + this->function_->getName() + ' ');
+ }
+ break;
+ case CommandState::ParamPreparation:
+ case CommandState::Params:
+ {
+ if (this->argument_.empty() && this->possibleArgument_.empty())
+ break;
+
+ unsigned int maxIndex = this->commandTokens_.size();
+ if (this->command_[this->command_.size() - 1] != ' ')
+ maxIndex -= 1;
+ std::string whitespace;
+
+ if (!this->possibleArgument_.empty())
+ {
+ this->argument_ = this->possibleArgument_;
+ if (this->function_->getParamCount() > (maxIndex + 1 - this->getStartindex()))
+ whitespace = " ";
+ }
+
+ return (this->command_ = this->commandTokens_.subSet(0, maxIndex).join() + ' ' + this->argument_ + whitespace);
+ break;
+ }
+ case CommandState::Finished:
+ break;
+ case CommandState::Error:
+ break;
+ }
+ }
+ this->bNewCommand_ = false;
+ return this->command_;
+ }
+
+ std::string CommandEvaluation::hint() const
+ {
+ switch (this->state_)
+ {
+ case CommandState::Uninitialized:
+ break;
+ case CommandState::Empty:
+ case CommandState::ShortcutOrIdentifier:
+ if (this->listOfPossibleFunctions_.size() == 0)
+ return CommandEvaluation::dump(this->listOfPossibleIdentifiers_);
+ else if (this->listOfPossibleIdentifiers_.size() == 0)
+ return CommandEvaluation::dump(this->listOfPossibleFunctions_);
+ else
+ return (CommandEvaluation::dump(this->listOfPossibleFunctions_) + "\n" + CommandEvaluation::dump(this->listOfPossibleIdentifiers_));
+ break;
+ case CommandState::Function:
+ return CommandEvaluation::dump(this->listOfPossibleFunctions_);
+ break;
+ case CommandState::ParamPreparation:
+ case CommandState::Params:
+ if (this->listOfPossibleArguments_.size() > 0)
+ return CommandEvaluation::dump(this->listOfPossibleArguments_);
+ else
+ return CommandEvaluation::dump(this->function_);
+ case CommandState::Finished:
+ if (this->function_)
+ return CommandEvaluation::dump(this->function_);
+ break;
+ case CommandState::Error:
+ return this->errorMessage_;
+ break;
+ }
+
+ return "";
+ }
+
+ void CommandEvaluation::evaluateParams()
+ {
+ this->bEvaluatedParams_ = false;
+
+ for (unsigned int i = 0; i < MAX_FUNCTOR_ARGUMENTS; i++)
+ this->param_[i] = MT_Type::Null;
+
+ if (!this->isValid())
+ return;
+
+ unsigned int startindex = this->getStartindex();
+
+ if (this->commandTokens_.size() <= startindex)
+ {
+ if (this->function_->evaluate(this->getAdditionalParameter(), this->param_, " "))
+ this->bEvaluatedParams_ = true;
+ }
+ else if (this->commandTokens_.size() > startindex)
+ {
+ if (this->function_->evaluate(this->commandTokens_.subSet(startindex).join() + this->getAdditionalParameter(), this->param_, " "))
+ this->bEvaluatedParams_ = true;
+ }
+ }
+
+ void CommandEvaluation::setEvaluatedParameter(unsigned int index, MultiType param)
+ {
+ if (index < MAX_FUNCTOR_ARGUMENTS)
+ this->param_[index] = param;
+ }
+
+ MultiType CommandEvaluation::getEvaluatedParameter(unsigned int index) const
+ {
+ if (index < MAX_FUNCTOR_ARGUMENTS)
+ return this->param_[index];
+
+ return MT_Type::Null;
+ }
+
+ unsigned int CommandEvaluation::getStartindex() const
+ {
+ if (this->functionclass_ && this->function_)
+ return 2;
+ else if (this->function_)
+ return 1;
+ else
+ return 0;
+ }
+
+ std::string CommandEvaluation::dump(const std::list<std::pair<const std::string*, const std::string*> >& list)
+ {
+ std::string output;
+ for (std::list<std::pair<const std::string*, const std::string*> >::const_iterator it = list.begin(); it != list.end(); ++it)
+ {
+ if (it != list.begin())
+ output += ' ';
+
+ output += *(it->second);
+ }
+ return output;
+ }
+
+ std::string CommandEvaluation::dump(const ArgumentCompletionList& list)
+ {
+ std::string output;
+ for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
+ {
+ if (it != list.begin())
+ output += ' ';
+
+ output += it->getDisplay();
+ }
+ return output;
+ }
+
+ std::string CommandEvaluation::dump(const ConsoleCommand* command)
+ {
+ std::string output = command->getName();
+ if (command->getParamCount() > 0)
+ output += ": ";
+
+ for (unsigned int i = 0; i < command->getParamCount(); i++)
+ {
+ if (i != 0)
+ output += ' ';
+
+ if (command->defaultValueSet(i))
+ output += '[';
+ else
+ output += '{';
+
+ output += command->getTypenameParam(i);
+
+ if (command->defaultValueSet(i))
+ output += '=' + command->getDefaultValue(i).getString() + ']';
+ else
+ output += '}';
+ }
+ return output;
+ }
+}
Copied: code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/CommandEvaluation.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,123 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _CommandEvaluation_H__
+#define _CommandEvaluation_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include <list>
+
+#include "ArgumentCompletionListElement.h"
+#include "util/SubString.h"
+#include "util/MultiType.h"
+
+namespace orxonox
+{
+ namespace CommandState
+ {
+ enum Value
+ {
+ Uninitialized,
+ Empty,
+ ShortcutOrIdentifier,
+ Function,
+ ParamPreparation,
+ Params,
+ Finished,
+ Error
+ };
+ }
+
+ class _CoreExport CommandEvaluation
+ {
+ friend class CommandExecutor;
+
+ public:
+ CommandEvaluation();
+
+ void initialize(const std::string& command);
+
+ bool execute() const;
+ MultiType query(bool* success = 0) const;
+
+ const std::string& complete();
+ std::string hint() const;
+ void evaluateParams();
+
+ bool isValid() const;
+
+ inline ConsoleCommand* getConsoleCommand() const
+ { return this->function_; }
+ inline const std::string& getOriginalCommand() const
+ { return this->originalCommand_; }
+ inline const std::string& getCommand() const
+ { return this->command_; }
+
+ inline void setAdditionalParameter(const std::string& param)
+ { this->additionalParameter_ = param; this->bEvaluatedParams_ = false; }
+ inline std::string getAdditionalParameter() const
+ { return (!this->additionalParameter_.empty()) ? (' ' + this->additionalParameter_) : ""; }
+
+ void setEvaluatedParameter(unsigned int index, MultiType param);
+ MultiType getEvaluatedParameter(unsigned int index) const;
+
+ private:
+ unsigned int getStartindex() const;
+ static std::string dump(const std::list<std::pair<const std::string*, const std::string*> >& list);
+ static std::string dump(const ArgumentCompletionList& list);
+ static std::string dump(const ConsoleCommand* command);
+
+
+ bool bNewCommand_;
+ bool bCommandChanged_;
+
+ std::string originalCommand_;
+ std::string command_;
+ SubString commandTokens_;
+ std::string additionalParameter_;
+
+ std::list<std::pair<const std::string*, const std::string*> > listOfPossibleIdentifiers_;
+ std::list<std::pair<const std::string*, const std::string*> > listOfPossibleFunctions_;
+ ArgumentCompletionList listOfPossibleArguments_;
+
+ Identifier* functionclass_;
+ ConsoleCommand* function_;
+ std::string possibleArgument_;
+ std::string argument_;
+
+ std::string errorMessage_;
+ CommandState::Value state_;
+
+ bool bEvaluatedParams_;
+ MultiType param_[5];
+ };
+}
+
+#endif /* _CommandEvaluation_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/CommandExecutor.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/CommandExecutor.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/CommandExecutor.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/CommandExecutor.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,699 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#include "CommandExecutor.h"
+
+#include "util/Debug.h"
+#include "util/StringUtils.h"
+#include "ConsoleCommand.h"
+#include "Identifier.h"
+#include "Language.h"
+#include "TclBind.h"
+
+namespace orxonox
+{
+ CommandExecutor& CommandExecutor::getInstance()
+ {
+ static CommandExecutor instance;
+ return instance;
+ }
+
+ CommandEvaluation& CommandExecutor::getEvaluation()
+ {
+ return CommandExecutor::getInstance().evaluation_;
+ }
+
+ const CommandEvaluation& CommandExecutor::getLastEvaluation()
+ {
+ return CommandExecutor::getInstance().evaluation_;
+ }
+
+ ConsoleCommand& CommandExecutor::addConsoleCommandShortcut(ConsoleCommand* command, bool bDeleteAtExit)
+ {
+ std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(command->getName());
+ if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
+ {
+ COUT(2) << "Warning: Overwriting console-command shortcut with name " << command->getName() << '.' << std::endl;
+ }
+
+ // Make sure we can also delete the external ConsoleCommands that don't belong to an Identifier
+ if (command && bDeleteAtExit)
+ {
+ CommandExecutor::getInstance().consoleCommandExternals_.insert(command);
+ }
+
+ CommandExecutor::getInstance().consoleCommandShortcuts_[command->getName()] = command;
+ CommandExecutor::getInstance().consoleCommandShortcuts_LC_[getLowercase(command->getName())] = command;
+ return (*command);
+ }
+
+ /**
+ @brief Returns the executor of a console command shortcut with given name.
+ @brief name The name of the requested console command shortcut
+ @return The executor of the requested console command shortcut
+ */
+ ConsoleCommand* CommandExecutor::getConsoleCommandShortcut(const std::string& name)
+ {
+ std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(name);
+ if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
+ return it->second;
+ else
+ return 0;
+ }
+
+ /**
+ @brief Returns the executor of a console command shortcut with given name in lowercase.
+ @brief name The name of the requested console command shortcut in lowercase
+ @return The executor of the requested console command shortcut
+ */
+ ConsoleCommand* CommandExecutor::getLowercaseConsoleCommandShortcut(const std::string& name)
+ {
+ std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_LC_.find(name);
+ if (it != CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end())
+ return it->second;
+ else
+ return 0;
+ }
+
+ bool CommandExecutor::execute(const std::string& command, bool useTcl)
+ {
+ if (useTcl)
+ {
+ bool success;
+ TclBind::eval(command, &success);
+ return success;
+ }
+ else
+ {
+ CommandExecutor::parseIfNeeded(command);
+ return CommandExecutor::getEvaluation().execute();
+ }
+ }
+
+ MultiType CommandExecutor::queryMT(const std::string& command, bool* success, bool useTcl)
+ {
+ if (useTcl)
+ {
+ return TclBind::eval(command, success);
+ }
+ else
+ {
+ CommandExecutor::parseIfNeeded(command);
+ return CommandExecutor::getEvaluation().query(success);
+ }
+ }
+
+ std::string CommandExecutor::query(const std::string& command, bool* success, bool useTcl)
+ {
+ if (useTcl)
+ {
+ return TclBind::eval(command, success);
+ }
+ else
+ {
+ CommandExecutor::parseIfNeeded(command);
+ return CommandExecutor::getEvaluation().query(success).getString();
+ }
+ }
+
+ std::string CommandExecutor::complete(const std::string& command)
+ {
+ CommandExecutor::parseIfNeeded(command);
+ return CommandExecutor::getEvaluation().complete();
+ }
+
+ std::string CommandExecutor::hint(const std::string& command)
+ {
+ CommandExecutor::parseIfNeeded(command);
+ return CommandExecutor::getEvaluation().hint();
+ }
+
+ CommandEvaluation CommandExecutor::evaluate(const std::string& command)
+ {
+ CommandExecutor::parse(command);
+ CommandExecutor::getEvaluation().evaluateParams();
+ return CommandExecutor::getEvaluation();
+ }
+
+ void CommandExecutor::parseIfNeeded(const std::string& command)
+ {
+ if (CommandExecutor::getEvaluation().state_ == CommandState::Uninitialized)
+ {
+ CommandExecutor::parse(command);
+ }
+ else if (CommandExecutor::getEvaluation().originalCommand_ != command)
+ {
+ if (CommandExecutor::getEvaluation().command_ == command)
+ {
+ CommandExecutor::parse(command);
+ CommandExecutor::getEvaluation().bNewCommand_ = false;
+ }
+ else
+ {
+ CommandExecutor::parse(command);
+ }
+ }
+ }
+
+ void CommandExecutor::parse(const std::string& command, bool bInitialize)
+ {
+ if (bInitialize)
+ CommandExecutor::getEvaluation().initialize(command);
+
+ CommandExecutor::getEvaluation().commandTokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
+ CommandExecutor::getEvaluation().command_ = command;
+
+ switch (CommandExecutor::getEvaluation().state_)
+ {
+ case CommandState::Uninitialized:
+ {
+ // Impossible
+ break;
+ }
+ case CommandState::Empty:
+ {
+ if (CommandExecutor::argumentsGiven() == 0)
+ {
+ CommandExecutor::createListOfPossibleFunctions("");
+ CommandExecutor::createListOfPossibleIdentifiers("");
+ break;
+ }
+ else
+ {
+ CommandExecutor::getEvaluation().state_ = CommandState::ShortcutOrIdentifier;
+ // Move on to next case
+ }
+ }
+ case CommandState::ShortcutOrIdentifier:
+ {
+ if (CommandExecutor::argumentsGiven() > 1)
+ {
+ // There's a finished first argument - check if it's a shortcut or a classname
+ CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0));
+ CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0));
+
+ if (CommandExecutor::getEvaluation().function_)
+ {
+ // It's a shortcut
+ CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
+ CommandExecutor::getEvaluation().functionclass_ = 0;
+ // Move on to next case
+ }
+ else if (CommandExecutor::getEvaluation().functionclass_)
+ {
+ // It's a functionname
+ CommandExecutor::getEvaluation().state_ = CommandState::Function;
+ CommandExecutor::getEvaluation().function_ = 0;
+ // Move on to next case
+ }
+ else
+ {
+ // The first argument is bad
+ CommandExecutor::getEvaluation().state_ = CommandState::Error;
+ AddLanguageEntry("commandexecutorunknownfirstargument", "is not a shortcut nor a classname");
+ CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(0) + ' ' + GetLocalisation("commandexecutorunknownfirstargument") + '.';
+ return;
+ }
+ }
+ else
+ {
+ // There's no finished first argument - search possible shortcuts or classnames
+ CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(0));
+ CommandExecutor::createListOfPossibleIdentifiers(CommandExecutor::getArgument(0));
+
+ unsigned int num_functions = CommandExecutor::getEvaluation().listOfPossibleFunctions_.size();
+ unsigned int num_identifiers = CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.size();
+
+ if (num_functions == 1 && num_identifiers == 0)
+ {
+ // It's a shortcut
+ const std::string& functionname = *CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()->first;
+ CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(functionname);
+ if (getLowercase(functionname) != getLowercase(CommandExecutor::getArgument(0)))
+ {
+ // Unfinished shortcut
+ CommandExecutor::getEvaluation().bCommandChanged_ = true;
+ }
+ CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
+ CommandExecutor::getEvaluation().functionclass_ = 0;
+ CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().function_->getName();
+ if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
+ {
+ CommandExecutor::getEvaluation().command_ += ' ';
+ CommandExecutor::getEvaluation().bCommandChanged_ = true;
+ }
+ // Move on to next case
+ }
+ else if (num_identifiers == 1 && num_functions == 0)
+ {
+ // It's a classname
+ const std::string& classname = *CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.begin()->first;
+ CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(classname);
+ if (getLowercase(classname) != getLowercase(CommandExecutor::getArgument(0)))
+ {
+ // Unfinished classname
+ CommandExecutor::getEvaluation().bCommandChanged_ = true;
+ }
+ CommandExecutor::getEvaluation().state_ = CommandState::Function;
+ CommandExecutor::getEvaluation().function_ = 0;
+ CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + ' ';
+ // Move on to next case
+ }
+ else if (num_identifiers == 0 && num_functions == 0)
+ {
+ // No possibilities
+ CommandExecutor::getEvaluation().state_ = CommandState::Error;
+ AddLanguageEntry("commandexecutorunknownfirstargumentstart", "There is no command or classname starting with");
+ CommandExecutor::getEvaluation().errorMessage_ = "Error: " + GetLocalisation("commandexecutorunknownfirstargumentstart") + ' ' + CommandExecutor::getArgument(0) + '.';
+ return;
+ }
+ else
+ {
+ // There are several possiblilities
+ std::list<std::pair<const std::string*, const std::string*> > temp;
+ temp.insert(temp.end(), CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin(), CommandExecutor::getEvaluation().listOfPossibleFunctions_.end());
+ temp.insert(temp.end(), CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.begin(), CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.end());
+ CommandExecutor::getEvaluation().command_ = CommandExecutor::getCommonBegin(temp);
+ CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0));
+ CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0));
+ CommandExecutor::getEvaluation().bCommandChanged_ = true;
+ return;
+ }
+ }
+ }
+ case CommandState::Function:
+ {
+ if (CommandExecutor::getEvaluation().functionclass_)
+ {
+ // There is a classname - search for the commandname
+ if (CommandExecutor::argumentsGiven() > 2)
+ {
+ // There is a finished second argument - check if it's a commandname
+ CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
+
+ if (CommandExecutor::getEvaluation().function_)
+ {
+ // It's a function
+ CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
+ // Move on to next case
+ }
+ else
+ {
+ // The second argument is bad
+ CommandExecutor::getEvaluation().state_ = CommandState::Error;
+ AddLanguageEntry("commandexecutorunknownsecondargument", "is not a function of");
+ CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(1) + " " + GetLocalisation("commandexecutorunknownsecondargument") + " " + CommandExecutor::getEvaluation().functionclass_->getName() + ".";
+ return;
+ }
+ }
+ else
+ {
+ // There is no finished second argument - search for possibilities
+ CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
+ unsigned int num_functions = CommandExecutor::getEvaluation().listOfPossibleFunctions_.size();
+
+ if (num_functions == 1)
+ {
+ // It's a function
+ const std::string& functionname = *CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()->first;
+ CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(functionname, CommandExecutor::getEvaluation().functionclass_);
+ if (getLowercase(functionname) != getLowercase(CommandExecutor::getArgument(1)))
+ {
+ // Unfinished function
+ CommandExecutor::getEvaluation().bCommandChanged_ = true;
+ }
+ CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
+ CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + ' ' + CommandExecutor::getEvaluation().function_->getName();
+ if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
+ {
+ CommandExecutor::getEvaluation().command_ += ' ';
+ CommandExecutor::getEvaluation().bCommandChanged_ = true;
+ }
+ // Move on to next case
+ }
+ else if (num_functions == 0)
+ {
+ // No possibilities
+ CommandExecutor::getEvaluation().state_ = CommandState::Error;
+ AddLanguageEntry("commandexecutorunknownsecondargumentstart", "has no function starting with");
+ CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getEvaluation().functionclass_->getName() + ' ' + GetLocalisation("commandexecutorunknownsecondargumentstart") + ' ' + CommandExecutor::getArgument(1) + '.';
+ return;
+ }
+ else
+ {
+ // There are several possibilities
+ CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + ' ' + CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleFunctions_);
+ CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
+ CommandExecutor::getEvaluation().bCommandChanged_ = true;
+ return;
+ }
+ }
+ }
+ else
+ {
+ // There is no classname - move on to CommandState::ParamPreparation
+ }
+ }
+ case CommandState::ParamPreparation:
+ {
+ if (CommandExecutor::getEvaluation().function_->getParamCount() == 0 || CommandExecutor::enoughArgumentsGiven(CommandExecutor::getEvaluation().function_))
+ {
+ CommandExecutor::getEvaluation().state_ = CommandState::Finished;
+ return;
+ }
+ else
+ {
+ unsigned int argumentNumber = CommandExecutor::argumentsGiven() - 2;
+ if (CommandExecutor::getEvaluation().functionclass_)
+ argumentNumber -= 1;
+
+ CommandExecutor::createListOfPossibleArguments(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
+ CommandExecutor::getEvaluation().state_ = CommandState::Params;
+
+ if (CommandExecutor::getEvaluation().bCommandChanged_)
+ {
+ // Don't do more than one change
+ return;
+ }
+ }
+ }
+ case CommandState::Params:
+ {
+ if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 1)
+ {
+ // There is exactly one possible argument
+ CommandExecutor::getEvaluation().argument_ = CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()->getString();
+ CommandExecutor::getEvaluation().possibleArgument_ = CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()->getString();
+ CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
+ return;
+ }
+ else if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 0)
+ {
+ // The user tries something new - we let him do
+ CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
+ CommandExecutor::getEvaluation().argument_ = CommandExecutor::getLastArgument();
+ return;
+ }
+ else
+ {
+ // There are several possibilities
+ unsigned int argumentNumber = CommandExecutor::argumentsGiven();
+ if (argumentNumber > 0)
+ --argumentNumber;
+ if (CommandExecutor::getEvaluation().functionclass_ && argumentNumber > 0)
+ --argumentNumber;
+
+ CommandExecutor::getEvaluation().argument_ = CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleArguments_);
+ CommandExecutor::getEvaluation().possibleArgument_ = CommandExecutor::getPossibleArgument(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
+ CommandExecutor::getEvaluation().state_ = CommandState::ParamPreparation;
+ return;
+ }
+ }
+ case CommandState::Finished:
+ {
+ // Nothing more to do
+ break;
+ }
+ case CommandState::Error:
+ {
+ // Bad, very bad
+ break;
+ }
+ }
+ }
+
+ unsigned int CommandExecutor::argumentsFinished()
+ {
+ unsigned int argumentsGiven = CommandExecutor::argumentsGiven();
+ if (argumentsGiven > 0)
+ return argumentsGiven - 1;
+ else
+ return 0;
+ }
+
+ unsigned int CommandExecutor::argumentsGiven()
+ {
+ if (CommandExecutor::getEvaluation().command_.size() > 0 && CommandExecutor::getEvaluation().command_[CommandExecutor::getEvaluation().command_.size() - 1] == ' ')
+ return CommandExecutor::getEvaluation().commandTokens_.size() + 1;
+ else
+ return CommandExecutor::getEvaluation().commandTokens_.size();
+ }
+
+ bool CommandExecutor::enoughArgumentsGiven(ConsoleCommand* command)
+ {
+ if (CommandExecutor::getEvaluation().functionclass_)
+ return (CommandExecutor::argumentsGiven() > (2 + command->getParamCount()));
+ else
+ return (CommandExecutor::argumentsGiven() > (1 + command->getParamCount()));
+ }
+
+ const std::string& CommandExecutor::getArgument(unsigned int index)
+ {
+ if (index < (CommandExecutor::getEvaluation().commandTokens_.size()))
+ return CommandExecutor::getEvaluation().commandTokens_[index];
+ else
+ return BLANKSTRING;
+ }
+
+ const std::string& CommandExecutor::getLastArgument()
+ {
+ return CommandExecutor::getArgument(CommandExecutor::argumentsGiven() - 1);
+ }
+
+ void CommandExecutor::createListOfPossibleIdentifiers(const std::string& fragment)
+ {
+ CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.clear();
+ const std::string& lowercase = getLowercase(fragment);
+ for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseStringIdentifierMapBegin(); it != Identifier::getLowercaseStringIdentifierMapEnd(); ++it)
+ if (it->second->hasConsoleCommands())
+ if (it->first.find(lowercase) == 0 || fragment.empty())
+ CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.push_back(std::pair<const std::string*, const std::string*>(&it->first, &it->second->getName()));
+ }
+
+ void CommandExecutor::createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier)
+ {
+ CommandExecutor::getEvaluation().listOfPossibleFunctions_.clear();
+ const std::string& lowercase = getLowercase(fragment);
+ if (!identifier)
+ {
+ for (std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMapBegin(); it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd(); ++it)
+ if (it->first.find(lowercase) == 0 || fragment.empty())
+ CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&it->first, &it->second->getName()));
+ }
+ else
+ {
+ for (std::map<std::string, ConsoleCommand*>::const_iterator it = identifier->getLowercaseConsoleCommandMapBegin(); it != identifier->getLowercaseConsoleCommandMapEnd(); ++it)
+ if (it->first.find(lowercase) == 0 || fragment.empty())
+ CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&it->first, &it->second->getName()));
+ }
+ }
+
+ void CommandExecutor::createListOfPossibleArguments(const std::string& fragment, ConsoleCommand* command, unsigned int param)
+ {
+ CommandExecutor::createArgumentCompletionList(command, param);
+
+ CommandExecutor::getEvaluation().listOfPossibleArguments_.clear();
+ const std::string& lowercase = getLowercase(fragment);
+ for (ArgumentCompletionList::const_iterator it = command->getArgumentCompletionListBegin(); it != command->getArgumentCompletionListEnd(); ++it)
+ {
+ if (it->lowercaseComparison())
+ {
+ if (it->getComparable().find(lowercase) == 0 || fragment.empty())
+ CommandExecutor::getEvaluation().listOfPossibleArguments_.push_back(*it);
+ }
+ else
+ {
+ if (it->getComparable().find(fragment) == 0 || fragment.empty())
+ CommandExecutor::getEvaluation().listOfPossibleArguments_.push_back(*it);
+ }
+ }
+ }
+
+ Identifier* CommandExecutor::getPossibleIdentifier(const std::string& name)
+ {
+ const std::string& lowercase = getLowercase(name);
+ std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseStringIdentifierMap().find(lowercase);
+ if ((it != Identifier::getLowercaseStringIdentifierMapEnd()) && it->second->hasConsoleCommands())
+ return it->second;
+
+ return 0;
+ }
+
+ ConsoleCommand* CommandExecutor::getPossibleCommand(const std::string& name, Identifier* identifier)
+ {
+ const std::string& lowercase = getLowercase(name);
+ if (!identifier)
+ {
+ std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMap().find(lowercase);
+ if (it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd())
+ return it->second;
+ }
+ else
+ {
+ std::map<std::string, ConsoleCommand*>::const_iterator it = identifier->getLowercaseConsoleCommandMap().find(lowercase);
+ if (it != identifier->getLowercaseConsoleCommandMapEnd())
+ return it->second;
+ }
+ return 0;
+ }
+
+ const std::string& CommandExecutor::getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param)
+ {
+ CommandExecutor::createArgumentCompletionList(command, param);
+
+ const std::string& lowercase = getLowercase(name);
+ for (ArgumentCompletionList::const_iterator it = command->getArgumentCompletionListBegin(); it != command->getArgumentCompletionListEnd(); ++it)
+ {
+ if (it->lowercaseComparison())
+ {
+ if (it->getComparable() == lowercase)
+ return it->getString();
+ }
+ else
+ {
+ if (it->getComparable() == name)
+ return it->getString();
+ }
+ }
+
+ return BLANKSTRING;
+ }
+
+ void CommandExecutor::createArgumentCompletionList(ConsoleCommand* command, unsigned int param)
+ {
+ std::string params[5];
+
+ unsigned int index = 0;
+ unsigned int lowestIndex = 1 + (CommandExecutor::getEvaluation().functionclass_ != 0);
+
+ for (unsigned int i = CommandExecutor::argumentsGiven() - 1; i >= lowestIndex; --i)
+ {
+ params[index] = CommandExecutor::getArgument(i);
+ ++index;
+ if (index >= 5)
+ break;
+ }
+
+ command->createArgumentCompletionList(param, params[0], params[1], params[2], params[3], params[4]);
+ }
+
+ std::string CommandExecutor::getCommonBegin(const std::list<std::pair<const std::string*, const std::string*> >& list)
+ {
+ if (list.size() == 0)
+ {
+ return "";
+ }
+ else if (list.size() == 1)
+ {
+ return ((*list.begin()->first) + ' ');
+ }
+ else
+ {
+ std::string output;
+ for (unsigned int i = 0; true; i++)
+ {
+ char temp = 0;
+ for (std::list<std::pair<const std::string*, const std::string*> >::const_iterator it = list.begin(); it != list.end(); ++it)
+ {
+ if (it->first->size() > i)
+ {
+ if (it == list.begin())
+ {
+ temp = (*it->first)[i];
+ }
+ else
+ {
+ if (temp != (*it->first)[i])
+ return output;
+ }
+ }
+ else
+ {
+ return output;
+ }
+ }
+ output += temp;
+ }
+ return output;
+ }
+ }
+
+ std::string CommandExecutor::getCommonBegin(const ArgumentCompletionList& list)
+ {
+ if (list.size() == 0)
+ {
+ return "";
+ }
+ else if (list.size() == 1)
+ {
+ return (list.begin()->getComparable() + ' ');
+ }
+ else
+ {
+ std::string output;
+ for (unsigned int i = 0; true; i++)
+ {
+ char tempComparable = 0;
+ char temp = 0;
+ for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
+ {
+ const std::string& argumentComparable = it->getComparable();
+ const std::string& argument = it->getString();
+ if (argument.size() > i)
+ {
+ if (it == list.begin())
+ {
+ tempComparable = argumentComparable[i];
+ temp = argument[i];
+ }
+ else
+ {
+ if (tempComparable != argumentComparable[i])
+ return output;
+ else if (temp != argument[i])
+ temp = tempComparable;
+ }
+ }
+ else
+ {
+ return output;
+ }
+ }
+ output += temp;
+ }
+ return output;
+ }
+ }
+
+ void CommandExecutor::destroyExternalCommands()
+ {
+ for (std::set<ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandExternals_.begin();
+ it != CommandExecutor::getInstance().consoleCommandExternals_.end(); ++it)
+ delete *it;
+ }
+}
Copied: code/branches/consolecommands3/src/libraries/core/command/CommandExecutor.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/CommandExecutor.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/CommandExecutor.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/CommandExecutor.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,115 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _CommandExecutor_H__
+#define _CommandExecutor_H__
+
+#include "CorePrereqs.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "util/MultiType.h"
+#include "CommandEvaluation.h"
+
+// tolua_begin
+namespace orxonox
+{
+ class _CoreExport CommandExecutor
+ {
+// tolua_end
+ public:
+ static bool execute(const std::string& command, bool useTcl = true); // tolua_export
+
+ static MultiType queryMT(const std::string& command, bool* success = 0, bool useTcl = true);
+ static std::string query(const std::string& command, bool* success = 0, bool useTcl = true); // tolua_export
+
+ static std::string complete(const std::string& command);
+ static std::string hint(const std::string& command);
+
+ static CommandEvaluation evaluate(const std::string& command);
+ static const CommandEvaluation& getLastEvaluation();
+
+ static ConsoleCommand& addConsoleCommandShortcut(ConsoleCommand* command, bool bDeleteAtExit = false);
+ static ConsoleCommand* getConsoleCommandShortcut(const std::string& name);
+ static ConsoleCommand* getLowercaseConsoleCommandShortcut(const std::string& name);
+
+ /** @brief Returns the map that stores all console commands. @return The const_iterator */
+ static inline const std::map<std::string, ConsoleCommand*>& getConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_; }
+ /** @brief Returns a const_iterator to the beginning of the map that stores all console commands. @return The const_iterator */
+ static inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_.begin(); }
+ /** @brief Returns a const_iterator to the end of the map that stores all console commands. @return The const_iterator */
+ static inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_.end(); }
+
+ /** @brief Returns the map that stores all console commands with their names in lowercase. @return The const_iterator */
+ static inline const std::map<std::string, ConsoleCommand*>& getLowercaseConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_; }
+ /** @brief Returns a const_iterator to the beginning of the map that stores all console commands with their names in lowercase. @return The const_iterator */
+ static inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.begin(); }
+ /** @brief Returns a const_iterator to the end of the map that stores all console commands with their names in lowercase. @return The const_iterator */
+ static inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end(); }
+
+ static void destroyExternalCommands();
+
+ private:
+ CommandExecutor() {}
+ CommandExecutor(const CommandExecutor& other);
+ ~CommandExecutor() {}
+
+ static CommandExecutor& getInstance();
+ static CommandEvaluation& getEvaluation();
+
+ static void parseIfNeeded(const std::string& command);
+ static void parse(const std::string& command, bool bInitialize = true);
+
+ static unsigned int argumentsFinished();
+ static unsigned int argumentsGiven();
+ static bool enoughArgumentsGiven(ConsoleCommand* command);
+ static const std::string& getArgument(unsigned int index);
+ static const std::string& getLastArgument();
+
+ static void createListOfPossibleIdentifiers(const std::string& fragment);
+ static void createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier = 0);
+ static void createListOfPossibleArguments(const std::string& fragment, ConsoleCommand* command, unsigned int param);
+
+ static Identifier* getPossibleIdentifier(const std::string& name);
+ static ConsoleCommand* getPossibleCommand(const std::string& name, Identifier* identifier = 0);
+ static const std::string& getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param);
+
+ static void createArgumentCompletionList(ConsoleCommand* command, unsigned int param);
+ static std::string getCommonBegin(const std::list<std::pair<const std::string*, const std::string*> >& list);
+ static std::string getCommonBegin(const ArgumentCompletionList& list);
+
+ CommandEvaluation evaluation_;
+ std::map<std::string, ConsoleCommand*> consoleCommandShortcuts_;
+ std::map<std::string, ConsoleCommand*> consoleCommandShortcuts_LC_;
+ std::set<ConsoleCommand*> consoleCommandExternals_;
+ }; // tolua_export
+} // tolua_export
+
+#endif /* _CommandExecutor_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/ConsoleCommand.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/ConsoleCommand.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/ConsoleCommand.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/ConsoleCommand.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,295 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#include "ConsoleCommand.h"
+#include <cassert>
+
+#include "Language.h"
+
+namespace orxonox
+{
+ ConsoleCommand::ConsoleCommand(const FunctorPtr& functor, const std::string& name) : Executor(functor, name)
+ {
+ this->accessLevel_ = AccessLevel::None;
+ this->argumentCompleter_[0] = 0;
+ this->argumentCompleter_[1] = 0;
+ this->argumentCompleter_[2] = 0;
+ this->argumentCompleter_[3] = 0;
+ this->argumentCompleter_[4] = 0;
+
+ this->keybindMode_ = KeybindMode::OnPress;
+ this->inputConfiguredParam_ = -1;
+ }
+
+ ConsoleCommand& ConsoleCommand::argumentCompleter(unsigned int param, ArgumentCompleter* completer)
+ {
+ if (param < 5)
+ this->argumentCompleter_[param] = completer;
+ else
+ {
+ COUT(2) << "Warning: Couldn't add autocompletion-function for param " << param << ": index out of bound." << std::endl;
+ }
+ return (*this);
+ }
+
+ ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int param) const
+ {
+ if (param < 5)
+ return this->argumentCompleter_[param];
+ else
+ return 0;
+ }
+
+ void ConsoleCommand::createArgumentCompletionList(unsigned int param, const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5)
+ {
+ if (param < 5 && this->argumentCompleter_[param])
+ this->argumentList_ = (*this->argumentCompleter_[param])(param1, param2, param3, param4, param5);
+ else
+ this->argumentList_.clear();
+ }
+
+ ConsoleCommand& ConsoleCommand::description(const std::string& description)
+ {
+ this->description_ = std::string("ConsoleCommandDescription::" + this->name_ + "::function");
+ AddLanguageEntry(this->description_, description);
+ return (*this);
+ }
+
+ const std::string& ConsoleCommand::getDescription() const
+ {
+ return GetLocalisation_noerror(this->description_);
+ }
+
+ ConsoleCommand& ConsoleCommand::descriptionParam(unsigned int param, const std::string& description)
+ {
+ if (param < MAX_FUNCTOR_ARGUMENTS)
+ {
+ this->descriptionParam_[param] = std::string("ConsoleCommandDescription::" + this->name_ + "::param" + multi_cast<std::string>(param));
+ AddLanguageEntry(this->descriptionParam_[param], description);
+ }
+ return (*this);
+ }
+
+ const std::string& ConsoleCommand::getDescriptionParam(unsigned int param) const
+ {
+ if (param < MAX_FUNCTOR_ARGUMENTS)
+ return GetLocalisation_noerror(this->descriptionParam_[param]);
+
+ return this->descriptionParam_[0];
+ }
+
+ ConsoleCommand& ConsoleCommand::descriptionReturnvalue(const std::string& description)
+ {
+ this->descriptionReturnvalue_ = std::string("ConsoleCommandDescription::" + this->name_ + "::returnvalue");
+ AddLanguageEntry(this->descriptionReturnvalue_, description);
+ return (*this);
+ }
+
+ const std::string& ConsoleCommand::getDescriptionReturnvalue(int param) const
+ {
+ return GetLocalisation_noerror(this->descriptionReturnvalue_);
+ }
+}
+
+#include "BaseObject.h" // remove this
+
+namespace orxonox
+{
+ _SetConsoleCommand("BaseObject", "setName", &BaseObject::setName, (BaseObject*)0);
+ _ConsoleCommand::_ConsoleCommandManipulator test(_ModifyConsoleCommand("BaseObject", "setName").setFunction(&BaseObject::setActive));
+
+ _ConsoleCommand::_ConsoleCommand(const std::string& group, const std::string& name, const FunctorPtr& functor, bool bInitialized) : Executor(functor, name), functionHeader_(functor->getHeaderIdentifier())
+ {
+ this->bActive_ = true;
+ this->bInitialized_ = bInitialized;
+ _ConsoleCommand::registerCommand(group, name, this);
+ }
+
+ _ConsoleCommand& _ConsoleCommand::addShortcut()
+ {
+ _ConsoleCommand::registerCommand("", this->getName(), this);
+ return *this;
+ }
+
+ _ConsoleCommand& _ConsoleCommand::addShortcut(const std::string& name)
+ {
+ _ConsoleCommand::registerCommand("", name, this);
+ return *this;
+ }
+
+ _ConsoleCommand& _ConsoleCommand::addGroup(const std::string& group)
+ {
+ _ConsoleCommand::registerCommand(group, this->getName(), this);
+ return *this;
+ }
+
+ _ConsoleCommand& _ConsoleCommand::addGroup(const std::string& group, const std::string& name)
+ {
+ _ConsoleCommand::registerCommand(group, name, this);
+ return *this;
+ }
+
+ bool _ConsoleCommand::setFunctor(const FunctorPtr& functor, bool bForce)
+ {
+ if (!functor)
+ {
+ this->bInitialized_ = false;
+ return true;
+ }
+
+ if (!bForce && !this->functionHeaderMatches(functor))
+ {
+ COUT(1) << "Error: Couldn't assign new function to console command with name \"" << this->getName() << "\", headers don't match." << std::endl;
+ return false;
+ }
+
+ this->functor_ = functor;
+ this->bInitialized_ = true;
+ return true;
+ }
+
+ void _ConsoleCommand::pushFunctor(const FunctorPtr& functor, bool bForce)
+ {
+ const FunctorPtr& oldfunctor = this->getFunctor();
+
+ if (this->setFunctor(functor, bForce));
+ this->functorStack_.push(oldfunctor);
+ }
+
+ void _ConsoleCommand::popFunctor()
+ {
+ FunctorPtr newfunctor;
+ if (!this->functorStack_.empty())
+ {
+ newfunctor = this->functorStack_.top();
+ this->functorStack_.pop();
+ }
+ this->setFunctor(newfunctor);
+ }
+
+ const FunctorPtr& _ConsoleCommand::getFunctor() const
+ {
+// if (this->bInitialized_) // FIXME
+ return this->functor_;
+// else
+// return 0;
+ }
+
+ bool _ConsoleCommand::functionHeaderMatches(const FunctorPtr& functor) const
+ {
+ if (!this->functor_)
+ {
+ assert(false);
+ return true;
+ }
+ return (functor->getHeaderIdentifier() == this->functionHeader_);
+ }
+
+ void _ConsoleCommand::setObject(void* object)
+ {
+ if (this->functor_)
+ this->functor_->setRawObjectPointer(object);
+ else if (object)
+ COUT(1) << "Error: Can't set object in console command \"" << this->getName() << "\", no functor set." << std::endl;
+ }
+
+ void _ConsoleCommand::pushObject(void* object)
+ {
+ if (this->functor_)
+ {
+ this->objectStack_.push(this->getObject());
+ this->setObject(object);
+ }
+ else
+ COUT(1) << "Error: Can't set object in console command \"" << this->getName() << "\", no functor set." << std::endl;
+ }
+
+ void _ConsoleCommand::popObject()
+ {
+ void* newobject = 0;
+ if (!this->objectStack_.empty())
+ {
+ newobject = this->objectStack_.top();
+ this->objectStack_.pop();
+ }
+ this->setObject(newobject);
+ }
+
+ void* _ConsoleCommand::getObject() const
+ {
+ if (this->functor_)
+ return this->functor_->getRawObjectPointer();
+ else
+ return 0;
+ }
+
+ /* static */ const _ConsoleCommand* _ConsoleCommand::getCommand(const std::string& group, const std::string& name, bool bPrintError)
+ {
+ std::map<std::string, std::map<std::string, _ConsoleCommand*> >::const_iterator it_group = _ConsoleCommand::getCommandMap().find(group);
+ if (it_group != _ConsoleCommand::getCommandMap().end())
+ {
+ std::map<std::string, _ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
+ if (it_name != it_group->second.end())
+ {
+ return it_name->second;
+ }
+ }
+ if (bPrintError)
+ {
+ if (group == "")
+ COUT(1) << "Error: Couldn't find console command with shortcut \"" << name << "\"" << std::endl;
+ else
+ COUT(1) << "Error: Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << std::endl;
+ }
+ return 0;
+ }
+
+ /* static */ std::map<std::string, std::map<std::string, _ConsoleCommand*> >& _ConsoleCommand::getCommandMap()
+ {
+ static std::map<std::string, std::map<std::string, _ConsoleCommand*> > commandMap;
+ return commandMap;
+ }
+
+ /* static */ void _ConsoleCommand::registerCommand(const std::string& group, const std::string& name, _ConsoleCommand* command)
+ {
+ if (name == "")
+ return;
+
+ if (_ConsoleCommand::getCommand(group, name) != 0)
+ {
+ if (group == "")
+ COUT(2) << "Warning: A console command with shortcut name \"" << name << "\" already exists." << std::endl;
+ else
+ COUT(2) << "Warning: A console command with group \"" << group << "\" and name \"" << name << "\" already exists." << std::endl;
+ }
+ else
+ {
+ _ConsoleCommand::getCommandMap()[group][name] = command;
+ }
+ }
+}
Copied: code/branches/consolecommands3/src/libraries/core/command/ConsoleCommand.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/ConsoleCommand.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/ConsoleCommand.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/ConsoleCommand.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,303 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _ConsoleCommand_H__
+#define _ConsoleCommand_H__
+
+#include "CorePrereqs.h"
+
+#include <stack>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/facilities/expand.hpp>
+
+#include "util/VA_NARGS.h"
+#include "ArgumentCompletionFunctions.h"
+#include "CommandExecutor.h"
+#include "Executor.h"
+#include "Identifier.h"
+
+
+#define SetConsoleCommand(classname, function, bCreateShortcut) \
+ SetConsoleCommandGeneric(classname, function, #function, bCreateShortcut)
+#define SetConsoleCommandAlias(classname, function, name, bCreateShortcut) \
+ SetConsoleCommandGeneric(classname, function, name, bCreateShortcut)
+
+#define SetConsoleCommandGeneric(classname, function, name, bCreateShortcut) \
+ orxonox::ConsoleCommand& BOOST_PP_CAT(classname##function##consolecommand__, __LINE__) = orxonox::ClassIdentifier<classname>::getIdentifier(#classname)->addConsoleCommand(orxonox::createConsoleCommand(orxonox::createFunctor(&classname::function), name), bCreateShortcut)
+
+
+#define SetConsoleCommandShortcut(classname, function) \
+ SetConsoleCommandShortcutAliasGeneric(classname, function, #function)
+#define SetConsoleCommandShortcutAlias(classname, function, name) \
+ SetConsoleCommandShortcutAliasGeneric(classname, function, name)
+#define SetConsoleCommandShortcutAliasGeneric(classname, function, name) \
+ SetConsoleCommandShortcutGeneric(BOOST_PP_CAT(function##consolecommand__, __LINE__), orxonox::createConsoleCommand(orxonox::createFunctor(&classname::function), name))
+
+#define SetConsoleCommandShortcutExtern(function) \
+ SetConsoleCommandShortcutExternAliasGeneric(function, #function)
+#define SetConsoleCommandShortcutExternAlias(function, name) \
+ SetConsoleCommandShortcutExternAliasGeneric(function, name)
+#define SetConsoleCommandShortcutExternAliasGeneric(function, name) \
+ SetConsoleCommandShortcutGeneric(BOOST_PP_CAT(function##consolecommand__, __LINE__), orxonox::createConsoleCommand(orxonox::createFunctor(&function), name))
+
+#define SetConsoleCommandShortcutGeneric(fakevariable, command) \
+ orxonox::ConsoleCommand& fakevariable = orxonox::CommandExecutor::addConsoleCommandShortcut(command, true)
+
+
+namespace orxonox
+{
+ namespace AccessLevel
+ {
+ enum Value
+ {
+ None,
+ User,
+ Admin,
+ Offline,
+ Debug,
+ Disabled
+ };
+ }
+
+ class _CoreExport ConsoleCommand : public Executor
+ {
+ public:
+ ConsoleCommand(const FunctorPtr& functor, const std::string& name = "");
+
+ ConsoleCommand& description(const std::string& description);
+ const std::string& getDescription() const;
+
+ ConsoleCommand& descriptionParam(unsigned int param, const std::string& description);
+ const std::string& getDescriptionParam(unsigned int param) const;
+
+ ConsoleCommand& descriptionReturnvalue(const std::string& description);
+ const std::string& getDescriptionReturnvalue(int param) const;
+
+ inline ConsoleCommand& defaultValues(const MultiType& param1)
+ { this->Executor::setDefaultValues(param1); return (*this); }
+ inline ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2)
+ { this->Executor::setDefaultValues(param1, param2); return (*this); }
+ inline ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
+ { this->Executor::setDefaultValues(param1, param2, param3); return (*this); }
+ inline ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
+ { this->Executor::setDefaultValues(param1, param2, param3, param4); return (*this); }
+ inline ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
+ { this->Executor::setDefaultValues(param1, param2, param3, param4, param5); return (*this); }
+ inline ConsoleCommand& defaultValue(unsigned int index, const MultiType& param)
+ { this->Executor::setDefaultValue(index, param); return (*this); }
+
+ inline ConsoleCommand& accessLevel(AccessLevel::Value level)
+ { this->accessLevel_ = level; return (*this); }
+ inline AccessLevel::Value getAccessLevel() const
+ { return this->accessLevel_; }
+
+ ConsoleCommand& argumentCompleter(unsigned int param, ArgumentCompleter* completer);
+ ArgumentCompleter* getArgumentCompleter(unsigned int param) const;
+
+ void createArgumentCompletionList(unsigned int param, const std::string& param1 = "", const std::string& param2 = "", const std::string& param3 = "", const std::string& param4 = "", const std::string& param5 = "");
+ const ArgumentCompletionList& getArgumentCompletionList() const
+ { return this->argumentList_; }
+ ArgumentCompletionList::const_iterator getArgumentCompletionListBegin() const
+ { return this->argumentList_.begin(); }
+ ArgumentCompletionList::const_iterator getArgumentCompletionListEnd() const
+ { return this->argumentList_.end(); }
+
+ inline ConsoleCommand& setAsInputCommand()
+ {
+ this->keybindMode(KeybindMode::OnHold);
+ this->defaultValue(0, Vector2(0.0f, 0.0f));
+ this->inputConfiguredParam(0);
+ return *this;
+ }
+
+ inline ConsoleCommand& keybindMode(KeybindMode::Value mode)
+ { this->keybindMode_ = mode; return *this; }
+ inline KeybindMode::Value getKeybindMode() const
+ { return this->keybindMode_; }
+
+ inline ConsoleCommand& inputConfiguredParam(int index)
+ { this->inputConfiguredParam_ = index; return *this; }
+ inline int getInputConfiguredParam_() const
+ { return this->inputConfiguredParam_; }
+
+ private:
+ AccessLevel::Value accessLevel_;
+ ArgumentCompleter* argumentCompleter_[5];
+ ArgumentCompletionList argumentList_;
+
+ KeybindMode::Value keybindMode_;
+ int inputConfiguredParam_;
+
+ LanguageEntryLabel description_;
+ LanguageEntryLabel descriptionReturnvalue_;
+ LanguageEntryLabel descriptionParam_[MAX_FUNCTOR_ARGUMENTS];
+ };
+
+ inline ConsoleCommand* createConsoleCommand(const FunctorPtr& functor, const std::string& name = "")
+ {
+ return new ConsoleCommand(functor, name);
+ }
+}
+
+
+#define _SetConsoleCommand(...) \
+ BOOST_PP_EXPAND(BOOST_PP_CAT(_SetConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
+#define _SetConsoleCommand2(name, functionpointer) \
+ _SetConsoleCommandGeneric("", name, orxonox::createFunctor(functionpointer))
+#define _SetConsoleCommand3(group, name, functionpointer) \
+ _SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer))
+#define _SetConsoleCommand4(group, name, functionpointer, object) \
+ _SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer, object))
+
+#define _SetConsoleCommandGeneric(group, name, functor) \
+ orxonox::_ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __LINE__) = (*orxonox::_createConsoleCommand(group, name, functor))
+
+
+#define _DeclareConsoleCommand(...) \
+ BOOST_PP_CAT(_DeclareConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__)
+#define _DeclareConsoleCommand2(name, functionpointer) \
+ _DeclareConsoleCommandGeneric("", name, functionpointer)
+#define _DeclareConsoleCommand3(group, name, functionpointer) \
+ _DeclareConsoleCommandGeneric(group, name, functionpointer)
+
+#define _DeclareConsoleCommandGeneric(group, name, functionpointer) \
+ orxonox::_ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __LINE__) = (*orxonox::_createConsoleCommand(group, name, orxonox::createFunctor(functionpointer), false))
+
+
+#define _ModifyConsoleCommand(...) \
+ orxonox::_ConsoleCommand::getCommand(__VA_ARGS__, true)->getManipulator()
+
+
+namespace orxonox
+{
+ class _CoreExport _ConsoleCommand : protected Executor
+ {
+ friend struct _ConsoleCommandManipulator;
+
+ public:
+ struct _ConsoleCommandManipulator
+ {
+ public:
+ _ConsoleCommandManipulator(const _ConsoleCommand* command) : command_(const_cast<_ConsoleCommand*>(command)) {}
+
+ template <class F>
+ inline _ConsoleCommandManipulator& setFunction(F function, bool bForce = false)
+ { if (this->command_) { this->command_->setFunctor(createFunctor(function), bForce); } return *this; }
+ template <class F, class O>
+ inline _ConsoleCommandManipulator& setFunction(F function, O* object, bool bForce = false)
+ { if (this->command_) { this->command_->setFunctor(createFunctor(function, object), bForce); } return *this; }
+ inline _ConsoleCommandManipulator& setFunction(const FunctorPtr& functor, bool bForce = false)
+ { if (this->command_) { this->command_->setFunctor(functor, bForce); } return *this; }
+
+ template <class F>
+ inline _ConsoleCommandManipulator& pushFunction(F function, bool bForce = false)
+ { if (this->command_) { this->command_->pushFunctor(createFunctor(function), bForce); } return *this; }
+ template <class F, class O>
+ inline _ConsoleCommandManipulator& pushFunction(F function, O* object, bool bForce = false)
+ { if (this->command_) { this->command_->pushFunctor(createFunctor(function, object), bForce); } return *this; }
+ inline _ConsoleCommandManipulator& pushFunction(const FunctorPtr& functor, bool bForce = false)
+ { if (this->command_) { this->command_->pushFunctor(functor, bForce); } return *this; }
+
+ inline _ConsoleCommandManipulator& popFunction()
+ { if (this->command_) { this->command_->popFunctor(); } return *this; }
+
+ inline _ConsoleCommandManipulator& setObject(void* object)
+ { if (this->command_) { this->command_->setObject(object); } return *this; }
+ inline _ConsoleCommandManipulator& pushObject(void* object)
+ { if (this->command_) { this->command_->pushObject(object); } return *this; }
+ inline _ConsoleCommandManipulator& popObject()
+ { if (this->command_) { this->command_->popObject(); } return *this; }
+
+ inline void* getObject() const
+ { if (this->command_) { return this->command_->getObject(); } else { return 0; } }
+
+ inline _ConsoleCommandManipulator& setActive(bool bActive)
+ { if (this->command_) { this->command_->setActive(bActive); } return *this; }
+
+ private:
+ _ConsoleCommand* command_;
+ };
+
+ public:
+ _ConsoleCommand(const std::string& group, const std::string& name, const FunctorPtr& functor, bool bInitialized = true);
+
+ _ConsoleCommand& addShortcut();
+ _ConsoleCommand& addShortcut(const std::string& name);
+ _ConsoleCommand& addGroup(const std::string& group);
+ _ConsoleCommand& addGroup(const std::string& group, const std::string& name);
+
+ inline void setActive(bool bActive)
+ { this->bActive_ = bActive; }
+ inline bool isActive() const
+ { return (this->bActive_ && this->bInitialized_); }
+
+ inline _ConsoleCommandManipulator getManipulator() const
+ { return this; }
+
+ static inline const std::map<std::string, std::map<std::string, _ConsoleCommand*> >& getCommands()
+ { return _ConsoleCommand::getCommandMap(); }
+
+ static inline const _ConsoleCommand* getCommand(const std::string& name, bool bPrintError = false)
+ { return _ConsoleCommand::getCommand("", name, bPrintError); }
+ static const _ConsoleCommand* getCommand(const std::string& group, const std::string& name, bool bPrintError = false);
+
+ private:
+ static std::map<std::string, std::map<std::string, _ConsoleCommand*> >& getCommandMap();
+ static void registerCommand(const std::string& group, const std::string& name, _ConsoleCommand* command);
+
+ bool setFunctor(const FunctorPtr& functor, bool bForce = false);
+ void pushFunctor(const FunctorPtr& functor, bool bForce = false);
+ void popFunctor();
+ const FunctorPtr& getFunctor() const;
+
+ bool functionHeaderMatches(const FunctorPtr& functor) const;
+
+ void setObject(void* object);
+ void pushObject(void* object);
+ void popObject();
+ void* getObject() const;
+
+ bool bActive_;
+ bool bInitialized_;
+ const std::type_info& functionHeader_;
+ std::stack<FunctorPtr> functorStack_;
+ std::stack<void*> objectStack_;
+ };
+
+ inline _ConsoleCommand* _createConsoleCommand(const std::string& name, const FunctorPtr& functor, bool bInitialized = true)
+ {
+ return new _ConsoleCommand("", name, functor, bInitialized);
+ }
+
+ inline _ConsoleCommand* _createConsoleCommand(const std::string& group, const std::string& name, const FunctorPtr& functor, bool bInitialized = true)
+ {
+ return new _ConsoleCommand(group, name, functor, bInitialized);
+ }
+}
+
+#endif /* _ConsoleCommand_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/ConsoleCommandCompilation.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/ConsoleCommandCompilation.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/ConsoleCommandCompilation.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/ConsoleCommandCompilation.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,181 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#include "ConsoleCommandCompilation.h"
+
+#include <fstream>
+#include <set>
+#include <string>
+
+#include "util/Debug.h"
+#include "util/ExprParser.h"
+#include "util/StringUtils.h"
+#include "ConsoleCommand.h"
+
+namespace orxonox
+{
+ SetConsoleCommandShortcutExtern(source).argumentCompleter(0, autocompletion::files());
+ SetConsoleCommandShortcutExtern(echo);
+ SetConsoleCommandShortcutExtern(puts);
+
+ SetConsoleCommandShortcutExtern(read).argumentCompleter(0, autocompletion::files());
+ SetConsoleCommandShortcutExtern(append).argumentCompleter(0, autocompletion::files());
+ SetConsoleCommandShortcutExtern(write).argumentCompleter(0, autocompletion::files());
+
+ SetConsoleCommandShortcutExtern(calculate);
+
+ void source(const std::string& filename)
+ {
+ static std::set<std::string> executingFiles;
+
+ std::set<std::string>::const_iterator it = executingFiles.find(filename);
+ if (it != executingFiles.end())
+ {
+ COUT(1) << "Error: Recurring source command in \"" << filename << "\". Stopped execution." << std::endl;
+ return;
+ }
+
+ // Open the file
+ std::ifstream file;
+ file.open(filename.c_str(), std::fstream::in);
+
+ if (!file.is_open())
+ {
+ COUT(1) << "Error: Couldn't open file \"" << filename << "\"." << std::endl;
+ return;
+ }
+
+ executingFiles.insert(filename);
+
+ // Iterate through the file and put the lines into the CommandExecutor
+ while (file.good() && !file.eof())
+ {
+ std::string line;
+ std::getline(file, line);
+ CommandExecutor::execute(line);
+ }
+
+ executingFiles.erase(filename);
+ file.close();
+ }
+
+ std::string echo(const std::string& text)
+ {
+ return text;
+ }
+
+ void puts(bool newline, const std::string& text)
+ {
+ if (newline)
+ {
+ COUT(0) << stripEnclosingBraces(text) << std::endl;
+ }
+ else
+ {
+ COUT(0) << stripEnclosingBraces(text);
+ }
+ }
+
+ void write(const std::string& filename, const std::string& text)
+ {
+ std::ofstream file;
+ file.open(filename.c_str(), std::fstream::out);
+
+ if (!file.is_open())
+ {
+ COUT(1) << "Error: Couldn't write to file \"" << filename << "\"." << std::endl;
+ return;
+ }
+
+ file << text << std::endl;
+ file.close();
+ }
+
+ void append(const std::string& filename, const std::string& text)
+ {
+ std::ofstream file;
+ file.open(filename.c_str(), std::fstream::app);
+
+ if (!file.is_open())
+ {
+ COUT(1) << "Error: Couldn't append to file \"" << filename << "\"." << std::endl;
+ return;
+ }
+
+ file << text << std::endl;
+ file.close();
+ }
+
+ std::string read(const std::string& filename)
+ {
+ std::ifstream file;
+ file.open(filename.c_str(), std::fstream::in);
+
+ if (!file.is_open())
+ {
+ COUT(1) << "Error: Couldn't read from file \"" << filename << "\"." << std::endl;
+ return "";
+ }
+
+ std::string output;
+ while (file.good() && !file.eof())
+ {
+ std::string line;
+ std::getline(file, line);
+ output += line;
+ output += "\n";
+ }
+
+ file.close();
+
+ return output;
+ }
+
+ float calculate(const std::string& calculation)
+ {
+ ExprParser expr;
+ expr.parse(calculation);
+ if (expr.getSuccess())
+ {
+ if (expr.getResult() == 42.0)
+ {
+ COUT(3) << "Greetings from the restaurant at the end of the universe." << std::endl;
+ }
+ if (!expr.getRemains().empty())
+ {
+ COUT(2) << "Warning: Expression could not be parsed to the end! Remains: '" << expr.getRemains() << '\'' << std::endl;
+ }
+ return static_cast<float>(expr.getResult());
+ }
+ else
+ {
+ COUT(1) << "Error: Cannot calculate expression: Parse error." << std::endl;
+ return 0;
+ }
+ }
+}
Copied: code/branches/consolecommands3/src/libraries/core/command/ConsoleCommandCompilation.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/ConsoleCommandCompilation.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/ConsoleCommandCompilation.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/ConsoleCommandCompilation.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,47 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _ConsoleCommandCompilation_H__
+#define _ConsoleCommandCompilation_H__
+
+#include "CorePrereqs.h"
+
+namespace orxonox
+{
+ _CoreExport void source(const std::string& filename);
+ _CoreExport std::string echo(const std::string& text);
+ _CoreExport void puts(bool newline, const std::string& test);
+
+ _CoreExport void write(const std::string& filename, const std::string& text);
+ _CoreExport void append(const std::string& filename, const std::string& text);
+ _CoreExport std::string read(const std::string& filename);
+
+ _CoreExport float calculate(const std::string& calculation);
+}
+
+#endif /* _ConsoleCommandCompilation_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/Executor.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/Executor.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/Executor.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/Executor.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,237 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ * Inspiration: Executor by Benjamin Grauer
+ */
+
+#include "Executor.h"
+
+#include <algorithm>
+
+#include "util/Convert.h"
+#include "util/Debug.h"
+#include "util/StringUtils.h"
+#include "util/SubString.h"
+
+namespace orxonox
+{
+ Executor::Executor(const FunctorPtr& functor, const std::string& name)
+ {
+ this->functor_ = functor;
+ this->name_ = name;
+ }
+
+ Executor::~Executor()
+ {
+ }
+
+ MultiType Executor::parse(const std::string& params, bool* success, const std::string& delimiter) const
+ {
+ if (success)
+ *success = true;
+
+ unsigned int paramCount = this->functor_->getParamCount();
+
+ if (paramCount == 0)
+ {
+ COUT(5) << "Calling Executor " << this->name_ << " through parser without parameters." << std::endl;
+ return (*this->functor_)();
+ }
+ else if (paramCount == 1)
+ {
+ const std::string& temp = getStripped(params);
+ if (!temp.empty())
+ {
+ COUT(5) << "Calling Executor " << this->name_ << " through parser with one parameter, using whole string: " << params << std::endl;
+ return (*this->functor_)(MultiType(params));
+ }
+ else if (!this->defaultValue_[0].null())
+ {
+ COUT(5) << "Calling Executor " << this->name_ << " through parser with one parameter, using default value: " << this->defaultValue_[0] << std::endl;
+ return (*this->functor_)(this->defaultValue_[0]);
+ }
+ else
+ {
+ COUT(2) << "Warning: Can't call executor " << this->name_ << " through parser: Not enough parameters or default values given (input: " << temp << ")." << std::endl;
+ if (success)
+ *success = false;
+ return MT_Type::Null;
+ }
+ }
+ else
+ {
+ SubString tokens(params, delimiter, SubString::WhiteSpaces, false, '\\', true, '"', true, '(', ')', true, '\0');
+
+ for (unsigned int i = tokens.size(); i < this->functor_->getParamCount(); i++)
+ {
+ if (this->defaultValue_[i].null())
+ {
+ COUT(2) << "Warning: Can't call executor " << this->name_ << " through parser: Not enough parameters or default values given (input:" << params << ")." << std::endl;
+ if (success)
+ *success = false;
+ return MT_Type::Null;
+ }
+ }
+
+ MultiType param[MAX_FUNCTOR_ARGUMENTS];
+ COUT(5) << "Calling Executor " << this->name_ << " through parser with " << paramCount << " parameters, using " << tokens.size() << " tokens (";
+ for (unsigned int i = 0; i < tokens.size() && i < MAX_FUNCTOR_ARGUMENTS; i++)
+ {
+ param[i] = tokens[i];
+ if (i != 0)
+ {
+ COUT(5) << ", ";
+ }
+ COUT(5) << tokens[i];
+ }
+ COUT(5) << ") and " << std::max((int)paramCount - (int)tokens.size(), 0) << " default values (";
+ for (unsigned int i = tokens.size(); i < paramCount; i++)
+ {
+ param[i] = this->defaultValue_[i];
+ if (i != 0)
+ {
+ COUT(5) << ", ";
+ }
+ COUT(5) << this->defaultValue_[i];
+ }
+ COUT(5) << ")." << std::endl;
+
+ if ((tokens.size() > paramCount) && (this->functor_->getTypenameParam(paramCount - 1) == "string"))
+ param[paramCount - 1] = tokens.subSet(paramCount - 1).join();
+
+ switch(paramCount)
+ {
+ case 2:
+ return (*this->functor_)(param[0], param[1]);
+ case 3:
+ return (*this->functor_)(param[0], param[1], param[2]);
+ case 4:
+ return (*this->functor_)(param[0], param[1], param[2], param[3]);
+ case 5:
+ return (*this->functor_)(param[0], param[1], param[2], param[3], param[4]);
+ }
+ }
+
+ return MT_Type::Null;
+ }
+
+ bool Executor::evaluate(const std::string& params, MultiType param[5], const std::string& delimiter) const
+ {
+ unsigned int paramCount = this->functor_->getParamCount();
+
+ if (paramCount == 1)
+ {
+ // only one param: check if there are params given, otherwise try to use default values
+ if (!getStripped(params).empty())
+ {
+ param[0] = params;
+ this->functor_->evaluateParam(0, param[0]);
+ return true;
+ }
+ else if (!this->defaultValue_[0].null())
+ {
+ param[0] = this->defaultValue_[0];
+ this->functor_->evaluateParam(0, param[0]);
+ return true;
+ }
+ return false;
+ }
+ else
+ {
+ // more than one param
+ SubString tokens(params, delimiter, SubString::WhiteSpaces, false, '\\', true, '"', true, '(', ')', true, '\0');
+
+ // if there are not enough params given, check if there are default values
+ for (unsigned int i = tokens.size(); i < this->functor_->getParamCount(); i++)
+ if (this->defaultValue_[i].null())
+ return false;
+
+ // assign all given arguments to the multitypes
+ for (unsigned int i = 0; i < std::min(tokens.size(), MAX_FUNCTOR_ARGUMENTS); i++)
+ param[i] = tokens[i];
+
+ // fill the remaining multitypes with default values
+ for (unsigned int i = tokens.size(); i < std::min(paramCount, MAX_FUNCTOR_ARGUMENTS); i++)
+ param[i] = this->defaultValue_[i];
+
+ // evaluate the param types through the functor
+ for (unsigned int i = 0; i < std::min(paramCount, MAX_FUNCTOR_ARGUMENTS); i++)
+ this->functor_->evaluateParam(i, param[i]);
+
+ return true;
+ }
+ }
+
+ void Executor::setDefaultValues(const MultiType& param1)
+ {
+ this->defaultValue_[0] = param1;
+ }
+
+ void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2)
+ {
+ this->defaultValue_[0] = param1;
+ this->defaultValue_[1] = param2;
+ }
+
+ void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
+ {
+ this->defaultValue_[0] = param1;
+ this->defaultValue_[1] = param2;
+ this->defaultValue_[2] = param3;
+ }
+
+ void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
+ {
+ this->defaultValue_[0] = param1;
+ this->defaultValue_[1] = param2;
+ this->defaultValue_[2] = param3;
+ this->defaultValue_[3] = param4;
+ }
+
+ void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
+ {
+ this->defaultValue_[0] = param1;
+ this->defaultValue_[1] = param2;
+ this->defaultValue_[2] = param3;
+ this->defaultValue_[3] = param4;
+ this->defaultValue_[4] = param5;
+ }
+
+ void Executor::setDefaultValue(unsigned int index, const MultiType& param)
+ {
+ if (index < MAX_FUNCTOR_ARGUMENTS)
+ this->defaultValue_[index] = param;
+ }
+
+ bool Executor::allDefaultValuesSet() const
+ {
+ for (unsigned int i = 0; i < this->functor_->getParamCount(); i++)
+ if (this->defaultValue_[i].null())
+ return false;
+
+ return true;
+ }
+}
Copied: code/branches/consolecommands3/src/libraries/core/command/Executor.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/Executor.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/Executor.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/Executor.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,206 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ * Inspiration: Executor by Benjamin Grauer
+ */
+
+#ifndef _Executor_H__
+#define _Executor_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include "util/MultiType.h"
+#include "Functor.h"
+#include "ExecutorPtr.h"
+
+namespace orxonox
+{
+ class _CoreExport Executor
+ {
+ public:
+ Executor(const FunctorPtr& functor, const std::string& name = "");
+ virtual ~Executor();
+
+ inline MultiType operator()() const
+ { return (*this->functor_)(this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(const MultiType& param1) const
+ { return (*this->functor_)(param1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(const MultiType& param1, const MultiType& param2) const
+ { return (*this->functor_)(param1, param2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(const MultiType& param1, const MultiType& param2, const MultiType& param3) const
+ { return (*this->functor_)(param1, param2, param3, this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) const
+ { return (*this->functor_)(param1, param2, param3, param4, this->defaultValue_[4]); }
+ inline MultiType operator()(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) const
+ { return (*this->functor_)(param1, param2, param3, param4, param5); }
+
+ MultiType parse(const std::string& params, bool* success = 0, const std::string& delimiter = " ") const;
+
+ bool evaluate(const std::string& params, MultiType param[5], const std::string& delimiter = " ") const;
+
+ inline const FunctorPtr& getFunctor() const
+ { return this->functor_; }
+ inline unsigned int getParamCount() const
+ { return this->functor_->getParamCount(); }
+ inline bool hasReturnvalue() const
+ { return this->functor_->hasReturnvalue(); }
+ inline Functor::Type::Enum getType() const
+ { return this->functor_->getType(); }
+ inline std::string getTypenameParam(unsigned int param) const
+ { return this->functor_->getTypenameParam(param); }
+ inline std::string getTypenameReturnvalue() const
+ { return this->functor_->getTypenameReturnvalue(); }
+
+ inline void setName(const std::string& name)
+ { this->name_ = name; }
+ inline const std::string& getName() const
+ { return this->name_; }
+
+ void setDefaultValues(const MultiType& param1);
+ void setDefaultValues(const MultiType& param1, const MultiType& param2);
+ void setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3);
+ void setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4);
+ void setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5);
+ void setDefaultValue(unsigned int index, const MultiType& param);
+
+ inline MultiType getDefaultValue(unsigned int index) const
+ {
+ if (index < MAX_FUNCTOR_ARGUMENTS)
+ return this->defaultValue_[index];
+
+ return MT_Type::Null;
+ }
+
+ bool allDefaultValuesSet() const;
+ inline bool defaultValueSet(unsigned int index) const
+ {
+ if (index < MAX_FUNCTOR_ARGUMENTS)
+ return !this->defaultValue_[index].null();
+
+ return false;
+ }
+
+ protected:
+ FunctorPtr functor_;
+ std::string name_;
+ MultiType defaultValue_[MAX_FUNCTOR_ARGUMENTS];
+ };
+
+ class _CoreExport ExecutorStatic : public Executor
+ {
+ public:
+ ExecutorStatic(const FunctorStaticPtr& functor, const std::string& name = "") : Executor(functor, name) {}
+ virtual ~ExecutorStatic() {}
+ };
+
+ template <class T>
+ class ExecutorMember : public Executor
+ {
+ public:
+ ExecutorMember(const FunctorMemberPtr<T>& functor, const std::string& name = "") : Executor(functor, name), functorMember_(functor) {}
+ virtual ~ExecutorMember() {}
+
+ using Executor::operator();
+
+ inline MultiType operator()(T* object) const
+ { return (*this->functorMember_)(object, this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(T* object, const MultiType& param1) const
+ { return (*this->functorMember_)(object, param1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2) const
+ { return (*this->functorMember_)(object, param1, param2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3) const
+ { return (*this->functorMember_)(object, param1, param2, param3, this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) const
+ { return (*this->functorMember_)(object, param1, param2, param3, param4, this->defaultValue_[4]); }
+ inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) const
+ { return (*this->functorMember_)(object, param1, param2, param3, param4, param5); }
+
+
+ inline MultiType operator()(const T* object) const
+ { return (*this->functorMember_)(object, this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(const T* object, const MultiType& param1) const
+ { return (*this->functorMember_)(object, param1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2) const
+ { return (*this->functorMember_)(object, param1, param2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3) const
+ { return (*this->functorMember_)(object, param1, param2, param3, this->defaultValue_[3], this->defaultValue_[4]); }
+ inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) const
+ { return (*this->functorMember_)(object, param1, param2, param3, param4, this->defaultValue_[4]); }
+ inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) const
+ { return (*this->functorMember_)(object, param1, param2, param3, param4, param5); }
+
+ inline void setObject(T* object) const
+ { this->functorMember_->setObject(object); }
+ inline void setObject(const T* object) const
+ { this->functorMember_->setObject(object); }
+
+ using Executor::parse;
+
+ MultiType parse(T* object, const std::string& params, bool* success = 0, const std::string& delimiter = " ") const
+ {
+ const typename FunctorMember<T>::Objects& objects = this->functorMember_->getObjects();
+
+ this->functorMember_->setObject(object);
+ const MultiType& result = this->Executor::parse(params, success, delimiter);
+ this->functorMember_->setObjects(objects);
+
+ return result;
+ }
+
+ MultiType parse(const T* object, const std::string& params, bool* success = 0, const std::string& delimiter = " ") const
+ {
+ const typename FunctorMember<T>::Objects& objects = this->functorMember_->getObjects();
+
+ this->functorMember_->setObject(object);
+ const MultiType& result = this->Executor::parse(params, success, delimiter);
+ this->functorMember_->setObjects(objects);
+
+ return result;
+ }
+
+ protected:
+ FunctorMemberPtr<T> functorMember_;
+ };
+
+ inline ExecutorPtr createExecutor(const FunctorPtr& functor, const std::string& name = "")
+ {
+ return new Executor(functor, name);
+ }
+
+ template <class T>
+ inline ExecutorMemberPtr<T> createExecutor(const FunctorMemberPtr<T>& functor, const std::string& name = "")
+ {
+ return new ExecutorMember<T>(functor, name);
+ }
+
+ inline ExecutorStaticPtr createExecutor(const FunctorStaticPtr& functor, const std::string& name = "")
+ {
+ return new ExecutorStatic(functor, name);
+ }
+}
+
+#endif /* _Executor_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/ExecutorPtr.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/ExecutorPtr.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/ExecutorPtr.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/ExecutorPtr.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,51 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _ExecutorPtr_H__
+#define _ExecutorPtr_H__
+
+#include "CorePrereqs.h"
+#include "SharedPtr.h"
+
+namespace orxonox
+{
+ typedef SharedPtr<Executor> ExecutorPtr;
+
+ typedef SharedChildPtr<ExecutorStatic, ExecutorPtr> ExecutorStaticPtr;
+
+ template <class T>
+ class ExecutorMemberPtr : public SharedChildPtr<ExecutorMember<T>, ExecutorPtr>
+ {
+ public:
+ inline ExecutorMemberPtr() : SharedChildPtr<ExecutorMember<T>, ExecutorPtr>() {}
+ inline ExecutorMemberPtr(ExecutorMember<T>* pointer) : SharedChildPtr<ExecutorMember<T>, ExecutorPtr>(pointer) {}
+ inline ExecutorMemberPtr(const SharedPtr<ExecutorMember<T> >& other) : SharedChildPtr<ExecutorMember<T>, ExecutorPtr>(other) {}
+ };
+}
+
+#endif /* _ExecutorPtr_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/Functor.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/Functor.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/Functor.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/Functor.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,589 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ * Inspiration: Functor by Benjamin Grauer
+ */
+
+#ifndef _Functor_H__
+#define _Functor_H__
+
+#include <typeinfo>
+
+#include "CorePrereqs.h"
+
+#include "util/Convert.h"
+#include "util/Debug.h"
+#include "util/MultiType.h"
+#include "FunctorPtr.h"
+
+namespace orxonox
+{
+ const unsigned int MAX_FUNCTOR_ARGUMENTS = 5;
+
+ template <class T>
+ inline std::string typeToString() { return "unknown"; }
+
+#define CreateTypeToStringTemplate(type) \
+ template <> \
+ inline std::string typeToString<type>() { return #type; } \
+ template <> \
+ inline std::string typeToString<type&>() { return #type; } \
+ template <> \
+ inline std::string typeToString<const type>() { return #type; } \
+ template <> \
+ inline std::string typeToString<const type&>() { return #type; }
+
+ CreateTypeToStringTemplate(int);
+ CreateTypeToStringTemplate(unsigned int);
+ CreateTypeToStringTemplate(char);
+ CreateTypeToStringTemplate(unsigned char);
+ CreateTypeToStringTemplate(short);
+ CreateTypeToStringTemplate(unsigned short);
+ CreateTypeToStringTemplate(long);
+ CreateTypeToStringTemplate(unsigned long);
+ CreateTypeToStringTemplate(long long);
+ CreateTypeToStringTemplate(unsigned long long);
+ CreateTypeToStringTemplate(float);
+ CreateTypeToStringTemplate(double);
+ CreateTypeToStringTemplate(long double);
+ CreateTypeToStringTemplate(bool);
+ CreateTypeToStringTemplate(Vector2);
+ CreateTypeToStringTemplate(Vector3);
+ CreateTypeToStringTemplate(Quaternion);
+ CreateTypeToStringTemplate(ColourValue);
+ CreateTypeToStringTemplate(Radian);
+ CreateTypeToStringTemplate(Degree);
+
+ template <>
+ inline std::string typeToString<std::string>() { return "string"; }
+ template <>
+ inline std::string typeToString<std::string&>() { return "string"; }
+ template <>
+ inline std::string typeToString<const std::string>() { return "string"; }
+ template <>
+ inline std::string typeToString<const std::string&>() { return "string"; }
+
+ class _CoreExport Functor
+ {
+ public:
+ struct Type
+ {
+ enum Enum
+ {
+ Member,
+ ConstMember,
+ Static,
+ Lua
+ };
+ };
+
+ public:
+ Functor() {}
+ virtual ~Functor() {}
+
+ virtual MultiType 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;
+
+ virtual Type::Enum getType() const = 0;
+ virtual unsigned int getParamCount() const = 0;
+ virtual bool hasReturnvalue() const = 0;
+
+ virtual std::string getTypenameParam(unsigned int param) const = 0;
+ virtual std::string getTypenameReturnvalue() const = 0;
+
+ virtual void evaluateParam(unsigned int index, MultiType& param) const = 0;
+
+ virtual void setRawObjectPointer(void* object) {}
+ virtual void* getRawObjectPointer() const { return 0; }
+
+ virtual const std::type_info& getHeaderIdentifier() const = 0;
+ };
+
+ class _CoreExport FunctorStatic : public Functor
+ {
+ public:
+ virtual ~FunctorStatic() {}
+ virtual MultiType 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;
+ };
+
+ template <class T>
+ class FunctorMember : public Functor
+ {
+ public:
+ FunctorMember()
+ {
+ this->object_ = 0;
+ this->constObject_ = 0;
+ }
+ virtual ~FunctorMember() {}
+
+ virtual MultiType 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;
+ virtual MultiType 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;
+
+ virtual MultiType 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)
+ {
+ if (this->object_)
+ return (*this)(this->object_, param1, param2, param3, param4, param5);
+ else if (this->constObject_)
+ return (*this)(this->constObject_, param1, param2, param3, param4, param5);
+ else
+ {
+ COUT(1) << "An error occurred in Functor.h:" << std::endl;
+ COUT(1) << "Error: No object set." << std::endl;
+ return MT_Type::Null;
+ }
+ }
+
+ inline FunctorMember<T>* setObject(T* object)
+ {
+ this->object_ = object;
+ this->constObject_ = 0;
+ return this;
+ }
+
+ inline FunctorMember<T>* setObject(const T* object)
+ {
+ this->object_ = 0;
+ this->constObject_ = object;
+ return this;
+ }
+
+ void setRawObjectPointer(void* object)
+ {
+ this->object_ = (T*)object;
+ this->constObject_ = 0;
+ }
+
+ void* getRawObjectPointer() const
+ {
+ if (this->object_)
+ return (void*)this->object_;
+ else
+ return (void*)this->constObject_;
+ }
+
+ typedef std::pair<T*, const T*> Objects;
+
+ inline Objects getObjects() const
+ {
+ return Objects(this->object_, this->constObject_);
+ }
+
+ inline void setObjects(const Objects& objects)
+ {
+ this->object_ = objects.first;
+ this->constObject_ = objects.second;
+ }
+
+ private:
+ T* object_;
+ const T* constObject_;
+ };
+
+
+
+ template <class R, class P1, class P2, class P3, class P4, class P5>
+ struct FunctorHeaderIdentifier {};
+
+
+
+ inline const FunctorPtr& createFunctor(const FunctorPtr& functor)
+ {
+ return functor;
+ }
+
+
+
+#define FUNCTOR_TEMPLATE(ismember, returnvalue, numparams, additionalobject) FUNCTOR_TEMPLATE##ismember##returnvalue##numparams(additionalobject)
+#define FUNCTOR_TEMPLATE000(additionalobject)
+#define FUNCTOR_TEMPLATE001(additionalobject) template <class P1>
+#define FUNCTOR_TEMPLATE002(additionalobject) template <class P1, class P2>
+#define FUNCTOR_TEMPLATE003(additionalobject) template <class P1, class P2, class P3>
+#define FUNCTOR_TEMPLATE004(additionalobject) template <class P1, class P2, class P3, class P4>
+#define FUNCTOR_TEMPLATE005(additionalobject) template <class P1, class P2, class P3, class P4, class P5>
+#define FUNCTOR_TEMPLATE010(additionalobject) template <class R>
+#define FUNCTOR_TEMPLATE011(additionalobject) template <class R, class P1>
+#define FUNCTOR_TEMPLATE012(additionalobject) template <class R, class P1, class P2>
+#define FUNCTOR_TEMPLATE013(additionalobject) template <class R, class P1, class P2, class P3>
+#define FUNCTOR_TEMPLATE014(additionalobject) template <class R, class P1, class P2, class P3, class P4>
+#define FUNCTOR_TEMPLATE015(additionalobject) template <class R, class P1, class P2, class P3, class P4, class P5>
+#define FUNCTOR_TEMPLATE100(additionalobject) template <class T FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE101(additionalobject) template <class T, class P1 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE102(additionalobject) template <class T, class P1, class P2 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE103(additionalobject) template <class T, class P1, class P2, class P3 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE104(additionalobject) template <class T, class P1, class P2, class P3, class P4 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE105(additionalobject) template <class T, class P1, class P2, class P3, class P4, class P5 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE110(additionalobject) template <class T, class R FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE111(additionalobject) template <class T, class R, class P1 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE112(additionalobject) template <class T, class R, class P1, class P2 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE113(additionalobject) template <class T, class R, class P1, class P2, class P3 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE114(additionalobject) template <class T, class R, class P1, class P2, class P3, class P4 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+#define FUNCTOR_TEMPLATE115(additionalobject) template <class T, class R, class P1, class P2, class P3, class P4, class P5 FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) >
+
+
+
+#define FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT(additionalobject) FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT##additionalobject
+#define FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT0
+#define FUNCTOR_TEMPLATE_ADDITIONAL_OBJECT1 , class O
+
+
+
+#define FUNCTOR_TEMPLATE_CLASSES(ismember, returnvalue, numparams) FUNCTOR_TEMPLATE_CLASSES##ismember##returnvalue##numparams
+#define FUNCTOR_TEMPLATE_CLASSES000
+#define FUNCTOR_TEMPLATE_CLASSES001 <P1>
+#define FUNCTOR_TEMPLATE_CLASSES002 <P1, P2>
+#define FUNCTOR_TEMPLATE_CLASSES003 <P1, P2, P3>
+#define FUNCTOR_TEMPLATE_CLASSES004 <P1, P2, P3, P4>
+#define FUNCTOR_TEMPLATE_CLASSES005 <P1, P2, P3, P4, P5>
+#define FUNCTOR_TEMPLATE_CLASSES010 <R>
+#define FUNCTOR_TEMPLATE_CLASSES011 <R, P1>
+#define FUNCTOR_TEMPLATE_CLASSES012 <R, P1, P2>
+#define FUNCTOR_TEMPLATE_CLASSES013 <R, P1, P2, P3>
+#define FUNCTOR_TEMPLATE_CLASSES014 <R, P1, P2, P3, P4>
+#define FUNCTOR_TEMPLATE_CLASSES015 <R, P1, P2, P3, P4, P5>
+#define FUNCTOR_TEMPLATE_CLASSES100 <T>
+#define FUNCTOR_TEMPLATE_CLASSES101 <T, P1>
+#define FUNCTOR_TEMPLATE_CLASSES102 <T, P1, P2>
+#define FUNCTOR_TEMPLATE_CLASSES103 <T, P1, P2, P3>
+#define FUNCTOR_TEMPLATE_CLASSES104 <T, P1, P2, P3, P4>
+#define FUNCTOR_TEMPLATE_CLASSES105 <T, P1, P2, P3, P4, P5>
+#define FUNCTOR_TEMPLATE_CLASSES110 <T, R>
+#define FUNCTOR_TEMPLATE_CLASSES111 <T, R, P1>
+#define FUNCTOR_TEMPLATE_CLASSES112 <T, R, P1, P2>
+#define FUNCTOR_TEMPLATE_CLASSES113 <T, R, P1, P2, P3>
+#define FUNCTOR_TEMPLATE_CLASSES114 <T, R, P1, P2, P3, P4>
+#define FUNCTOR_TEMPLATE_CLASSES115 <T, R, P1, P2, P3, P4, P5>
+
+
+
+#define FUNCTOR_TYPENAME_PARAM(numparams) FUNCTOR_TYPENAME_PARAM##numparams
+#define FUNCTOR_TYPENAME_PARAM0 \
+ return BLANKSTRING
+#define FUNCTOR_TYPENAME_PARAM1 \
+ if (param == 0) { return typeToString<P1>(); } \
+ else { return BLANKSTRING; }
+#define FUNCTOR_TYPENAME_PARAM2 \
+ if (param == 0) { return typeToString<P1>(); } \
+ else if (param == 1) { return typeToString<P2>(); } \
+ else { return BLANKSTRING; }
+#define FUNCTOR_TYPENAME_PARAM3 \
+ if (param == 0) { return typeToString<P1>(); } \
+ else if (param == 1) { return typeToString<P2>(); } \
+ else if (param == 2) { return typeToString<P3>(); } \
+ else { return BLANKSTRING; }
+#define FUNCTOR_TYPENAME_PARAM4 \
+ if (param == 0) { return typeToString<P1>(); } \
+ else if (param == 1) { return typeToString<P2>(); } \
+ else if (param == 2) { return typeToString<P3>(); } \
+ else if (param == 3) { return typeToString<P4>(); } \
+ else { return BLANKSTRING; }
+#define FUNCTOR_TYPENAME_PARAM5 \
+ if (param == 0) { return typeToString<P1>(); } \
+ else if (param == 1) { return typeToString<P2>(); } \
+ else if (param == 2) { return typeToString<P3>(); } \
+ else if (param == 3) { return typeToString<P4>(); } \
+ else if (param == 4) { return typeToString<P5>(); } \
+ else { return BLANKSTRING; }
+
+#define FUNCTOR_TYPENAME_RETURN(returnvalue) FUNCTOR_TYPENAME_RETURN##returnvalue
+#define FUNCTOR_TYPENAME_RETURN0 BLANKSTRING
+#define FUNCTOR_TYPENAME_RETURN1 typeToString<R>()
+
+
+
+#define FUNCTOR_FUNCTION_PARAMS(numparams) FUNCTOR_FUNCTION_PARAMS##numparams
+#define FUNCTOR_FUNCTION_PARAMS0
+#define FUNCTOR_FUNCTION_PARAMS1 P1 param1
+#define FUNCTOR_FUNCTION_PARAMS2 P1 param1, P2 param2
+#define FUNCTOR_FUNCTION_PARAMS3 P1 param1, P2 param2, P3 param3
+#define FUNCTOR_FUNCTION_PARAMS4 P1 param1, P2 param2, P3 param3, P4 param4
+#define FUNCTOR_FUNCTION_PARAMS5 P1 param1, P2 param2, P3 param3, P4 param4, P5 param5
+
+#define FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) FUNCTOR_FUNCTION_RETURNVALUE##returnvalue
+#define FUNCTOR_FUNCTION_RETURNVALUE0 void
+#define FUNCTOR_FUNCTION_RETURNVALUE1 R
+
+
+
+#define FUNCTOR_FUNCTION_CALL(numparams) FUNCTOR_FUNCTION_CALL##numparams
+#define FUNCTOR_FUNCTION_CALL0
+#define FUNCTOR_FUNCTION_CALL1 param1
+#define FUNCTOR_FUNCTION_CALL2 param1, param2
+#define FUNCTOR_FUNCTION_CALL3 param1, param2, param3
+#define FUNCTOR_FUNCTION_CALL4 param1, param2, param3, param4
+#define FUNCTOR_FUNCTION_CALL5 param1, param2, param3, param4, param5
+
+#define FUNCTOR_STORE_RETURNVALUE(returnvalue, functioncall) FUNCTOR_STORE_RETURNVALUE##returnvalue(functioncall)
+#define FUNCTOR_STORE_RETURNVALUE0(functioncall) functioncall; return MT_Type::Null
+#define FUNCTOR_STORE_RETURNVALUE1(functioncall) return functioncall
+
+
+
+#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES(returnvalue, numparams) FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES##numparams(returnvalue)
+#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES0(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), void, void, void, void, void>
+#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES1(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), P1, void, void, void, void>
+#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES2(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), P1, P2, void, void, void>
+#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES3(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), P1, P2, P3, void, void>
+#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES4(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), P1, P2, P3, P4, void>
+#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES5(returnvalue) <FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue), P1, P2, P3, P4, P5>
+
+#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE(returnvalue) FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE##returnvalue
+#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE0 void
+#define FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES_RETURNVALUE1 R
+
+
+
+#define FUNCTOR_EVALUATE_PARAM(numparams) FUNCTOR_EVALUATE_PARAM##numparams
+#define FUNCTOR_EVALUATE_PARAM0
+#define FUNCTOR_EVALUATE_PARAM1 \
+ if (index == 0) { param.convert<P1>(); }
+#define FUNCTOR_EVALUATE_PARAM2 \
+ if (index == 0) { param.convert<P1>(); } \
+ else if (index == 1) { param.convert<P2>(); }
+#define FUNCTOR_EVALUATE_PARAM3 \
+ if (index == 0) { param.convert<P1>(); } \
+ else if (index == 1) { param.convert<P2>(); } \
+ else if (index == 2) { param.convert<P3>(); }
+#define FUNCTOR_EVALUATE_PARAM4 \
+ if (index == 0) { param.convert<P1>(); } \
+ else if (index == 1) { param.convert<P2>(); } \
+ else if (index == 2) { param.convert<P3>(); } \
+ else if (index == 3) { param.convert<P4>(); }
+#define FUNCTOR_EVALUATE_PARAM5 \
+ if (index == 0) { param.convert<P1>(); } \
+ else if (index == 1) { param.convert<P2>(); } \
+ else if (index == 2) { param.convert<P3>(); } \
+ else if (index == 3) { param.convert<P4>(); } \
+ else if (index == 4) { param.convert<P5>(); }
+
+
+
+
+#define CREATE_STATIC_FUNCTOR(returnvalue, numparams) \
+ FUNCTOR_TEMPLATE(0, returnvalue, numparams, 0) \
+ class FunctorStatic##returnvalue##numparams : public FunctorStatic \
+ { \
+ public: \
+ FunctorStatic##returnvalue##numparams(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams))) \
+ { \
+ this->functionPointer_ = functionPointer; \
+ } \
+ \
+ MultiType 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) \
+ { \
+ FUNCTOR_STORE_RETURNVALUE(returnvalue, (*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
+ } \
+ \
+ void evaluateParam(unsigned int index, MultiType& param) const \
+ { \
+ FUNCTOR_EVALUATE_PARAM(numparams); \
+ } \
+ \
+ Functor::Type::Enum getType() const { return Functor::Type::Static; } \
+ unsigned int getParamCount() const { return numparams; } \
+ bool hasReturnvalue() const { return returnvalue; } \
+ std::string getTypenameParam(unsigned int param) const { FUNCTOR_TYPENAME_PARAM(numparams); } \
+ std::string getTypenameReturnvalue() const { return FUNCTOR_TYPENAME_RETURN(returnvalue); } \
+ \
+ const std::type_info& getHeaderIdentifier() const \
+ { \
+ return typeid(FunctorHeaderIdentifier FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES(returnvalue, numparams)); \
+ } \
+ \
+ private: \
+ FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (*functionPointer_)(FUNCTOR_FUNCTION_PARAMS(numparams)); \
+ }; \
+ \
+ \
+ FUNCTOR_TEMPLATE(0, returnvalue, numparams, 0) \
+ inline SharedChildPtr<FunctorStatic##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(0, returnvalue, numparams), FunctorStaticPtr> createFunctor(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams))) \
+ { \
+ return new FunctorStatic##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(0, returnvalue, numparams) (functionPointer); \
+ }
+
+
+
+
+
+#define CREATE_MEMBER_FUNCTOR(returnvalue, numparams) \
+ FUNCTOR_TEMPLATE(1, returnvalue, numparams, 0) \
+ class FunctorMember##returnvalue##numparams : public FunctorMember<T> \
+ { \
+ public: \
+ FunctorMember##returnvalue##numparams(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams))) \
+ { \
+ this->functionPointer_ = functionPointer; \
+ } \
+ \
+ MultiType 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) \
+ { \
+ FUNCTOR_STORE_RETURNVALUE(returnvalue, (*object.*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
+ } \
+ \
+ MultiType 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) \
+ { \
+ COUT(1) << "An error occurred in Functor.h:" << std::endl; \
+ COUT(1) << "Error: Function is not const." << std::endl; \
+ return MT_Type::Null; \
+ } \
+ \
+ void evaluateParam(unsigned int index, MultiType& param) const \
+ { \
+ FUNCTOR_EVALUATE_PARAM(numparams); \
+ } \
+ \
+ Functor::Type::Enum getType() const { return Functor::Type::Member; } \
+ unsigned int getParamCount() const { return numparams; } \
+ bool hasReturnvalue() const { return returnvalue; } \
+ std::string getTypenameParam(unsigned int param) const { FUNCTOR_TYPENAME_PARAM(numparams); } \
+ std::string getTypenameReturnvalue() const { return FUNCTOR_TYPENAME_RETURN(returnvalue); } \
+ \
+ const std::type_info& getHeaderIdentifier() const \
+ { \
+ return typeid(FunctorHeaderIdentifier FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES(returnvalue, numparams)); \
+ } \
+ \
+ private: \
+ FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer_)(FUNCTOR_FUNCTION_PARAMS(numparams)); \
+ }; \
+ \
+ \
+ FUNCTOR_TEMPLATE(1, returnvalue, numparams, 0) \
+ class FunctorConstMember##returnvalue##numparams : public FunctorMember<T> \
+ { \
+ public: \
+ FunctorConstMember##returnvalue##numparams(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams)) const) \
+ { \
+ this->functionPointer_ = functionPointer; \
+ } \
+ \
+ MultiType 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) \
+ { \
+ FUNCTOR_STORE_RETURNVALUE(returnvalue, (*object.*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
+ } \
+ \
+ MultiType 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) \
+ { \
+ FUNCTOR_STORE_RETURNVALUE(returnvalue, (*object.*this->functionPointer_)(FUNCTOR_FUNCTION_CALL(numparams))); \
+ } \
+ \
+ void evaluateParam(unsigned int index, MultiType& param) const \
+ { \
+ FUNCTOR_EVALUATE_PARAM(numparams); \
+ } \
+ \
+ Functor::Type::Enum getType() const { return Functor::Type::ConstMember; } \
+ unsigned int getParamCount() const { return numparams; } \
+ bool hasReturnvalue() const { return returnvalue; } \
+ std::string getTypenameParam(unsigned int param) const { FUNCTOR_TYPENAME_PARAM(numparams); } \
+ std::string getTypenameReturnvalue() const { return FUNCTOR_TYPENAME_RETURN(returnvalue); } \
+ \
+ const std::type_info& getHeaderIdentifier() const \
+ { \
+ return typeid(FunctorHeaderIdentifier FUNCTOR_HEADER_IDENTIFIER_TEMPLATE_CLASSES(returnvalue, numparams)); \
+ } \
+ \
+ private: \
+ FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer_)(FUNCTOR_FUNCTION_PARAMS(numparams)) const; \
+ }; \
+ \
+ \
+ FUNCTOR_TEMPLATE(1, returnvalue, numparams, 0) \
+ inline SharedChildPtr<FunctorMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams), FunctorMemberPtr<T> > createFunctor(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams))) \
+ { \
+ return new FunctorMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams) (functionPointer); \
+ } \
+ \
+ \
+ FUNCTOR_TEMPLATE(1, returnvalue, numparams, 0) \
+ inline SharedChildPtr<FunctorConstMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams), FunctorMemberPtr<T> > createFunctor(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams)) const) \
+ { \
+ return new FunctorConstMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams) (functionPointer); \
+ } \
+ \
+ FUNCTOR_TEMPLATE(1, returnvalue, numparams, 1) \
+ inline SharedChildPtr<FunctorMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams), FunctorMemberPtr<T> > createFunctor(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams)), O* object) \
+ { \
+ FunctorMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams)* functor = new FunctorMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams) (functionPointer); \
+ functor->setObject(object); \
+ return functor; \
+ } \
+ \
+ \
+ FUNCTOR_TEMPLATE(1, returnvalue, numparams, 1) \
+ inline SharedChildPtr<FunctorConstMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams), FunctorMemberPtr<T> > createFunctor(FUNCTOR_FUNCTION_RETURNVALUE(returnvalue) (T::*functionPointer)(FUNCTOR_FUNCTION_PARAMS(numparams)) const, O* object) \
+ { \
+ FunctorConstMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams)* functor = new FunctorConstMember##returnvalue##numparams FUNCTOR_TEMPLATE_CLASSES(1, returnvalue, numparams) (functionPointer); \
+ functor->setObject(object); \
+ return functor; \
+ }
+
+
+
+// disable annoying warning about forcing value to boolean
+#ifdef ORXONOX_COMPILER_MSVC
+#pragma warning(push)
+#pragma warning(disable:4100 4800)
+#endif
+
+#define CREATE_ALL_STATIC_FUNCTORS() \
+ CREATE_STATIC_FUNCTOR(0, 0); \
+ CREATE_STATIC_FUNCTOR(0, 1); \
+ CREATE_STATIC_FUNCTOR(0, 2); \
+ CREATE_STATIC_FUNCTOR(0, 3); \
+ CREATE_STATIC_FUNCTOR(0, 4); \
+ CREATE_STATIC_FUNCTOR(0, 5); \
+ CREATE_STATIC_FUNCTOR(1, 0); \
+ CREATE_STATIC_FUNCTOR(1, 1); \
+ CREATE_STATIC_FUNCTOR(1, 2); \
+ CREATE_STATIC_FUNCTOR(1, 3); \
+ CREATE_STATIC_FUNCTOR(1, 4); \
+ CREATE_STATIC_FUNCTOR(1, 5)
+
+
+#define CREATE_ALL_MEMBER_FUNCTORS() \
+ CREATE_MEMBER_FUNCTOR(0, 0); \
+ CREATE_MEMBER_FUNCTOR(0, 1); \
+ CREATE_MEMBER_FUNCTOR(0, 2); \
+ CREATE_MEMBER_FUNCTOR(0, 3); \
+ CREATE_MEMBER_FUNCTOR(0, 4); \
+ CREATE_MEMBER_FUNCTOR(0, 5); \
+ CREATE_MEMBER_FUNCTOR(1, 0); \
+ CREATE_MEMBER_FUNCTOR(1, 1); \
+ CREATE_MEMBER_FUNCTOR(1, 2); \
+ CREATE_MEMBER_FUNCTOR(1, 3); \
+ CREATE_MEMBER_FUNCTOR(1, 4); \
+ CREATE_MEMBER_FUNCTOR(1, 5)
+
+
+ CREATE_ALL_STATIC_FUNCTORS();
+ CREATE_ALL_MEMBER_FUNCTORS();
+}
+
+#ifdef ORXONOX_COMPILER_MSVC
+#pragma warning(pop)
+#endif
+
+#endif /* _Functor_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/FunctorPtr.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/FunctorPtr.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/FunctorPtr.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/FunctorPtr.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,51 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _FunctorPtr_H__
+#define _FunctorPtr_H__
+
+#include "CorePrereqs.h"
+#include "SharedPtr.h"
+
+namespace orxonox
+{
+ typedef SharedPtr<Functor> FunctorPtr;
+
+ typedef SharedChildPtr<FunctorStatic, FunctorPtr> FunctorStaticPtr;
+
+ template <class T>
+ class FunctorMemberPtr : public SharedChildPtr<FunctorMember<T>, FunctorPtr>
+ {
+ public:
+ inline FunctorMemberPtr() : SharedChildPtr<FunctorMember<T>, FunctorPtr>() {}
+ inline FunctorMemberPtr(FunctorMember<T>* pointer) : SharedChildPtr<FunctorMember<T>, FunctorPtr>(pointer) {}
+ inline FunctorMemberPtr(const SharedPtr<FunctorMember<T> >& other) : SharedChildPtr<FunctorMember<T>, FunctorPtr>(other) {}
+ };
+}
+
+#endif /* _FunctorPtr_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/IOConsole.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/IOConsole.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/IOConsole.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/IOConsole.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,799 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Oliver Scheuss
+ * Reto Grieder
+ * Co-authors:
+ * ...
+ *
+ */
+
+#include "IOConsole.h"
+
+#include <iomanip>
+#include <iostream>
+
+#include "util/Clock.h"
+#include "util/Math.h"
+#include "Game.h"
+#include "input/InputBuffer.h"
+
+// ##########################
+// ### Mutual methods ###
+// ##########################
+namespace orxonox
+{
+ IOConsole* IOConsole::singletonPtr_s = NULL;
+
+ // ###############################
+ // ### ShellListener methods ###
+ // ###############################
+
+ //! Called if all output-lines have to be reprinted
+ void IOConsole::linesChanged()
+ {
+ // Method only gets called upon start to draw all the lines
+ // or when scrolling. But scrolling is disabled and the output
+ // is already in std::cout when we start the IOConsole
+ }
+
+ //! Called if a command is about to be executed
+ void IOConsole::executed()
+ {
+ this->shell_->addOutput(this->promptString_ + this->shell_->getInput() + '\n', Shell::Command);
+ }
+
+ //! Called if the console gets closed
+ void IOConsole::exit()
+ {
+ // Exit is not an option, just do nothing (Shell doesn't really exit too)
+ }
+}
+
+#ifdef ORXONOX_PLATFORM_UNIX
+// ###############################
+// ### Unix Implementation ###
+// ###############################
+
+#include <termios.h>
+#include <sys/ioctl.h>
+
+namespace orxonox
+{
+ namespace EscapeMode
+ {
+ enum Value
+ {
+ None,
+ First,
+ Second
+ };
+ }
+
+ IOConsole::IOConsole()
+ : shell_(new Shell("IOConsole", false))
+ , buffer_(shell_->getInputBuffer())
+ , cout_(std::cout.rdbuf())
+ , promptString_("orxonox # ")
+ , bStatusPrinted_(false)
+ , originalTerminalSettings_(0)
+ {
+ this->setTerminalMode();
+ this->shell_->registerListener(this);
+
+ // Manually set the widths of the individual status lines
+ this->statusLineWidths_.push_back(29);
+ this->statusLineMaxWidth_ = 29;
+
+ this->getTerminalSize();
+ this->lastTerminalWidth_ = this->terminalWidth_;
+ this->lastTerminalHeight_ = this->terminalHeight_;
+
+ // Disable standard std::cout logging
+ OutputHandler::getInstance().disableCout();
+ // Redirect std::cout to an ostringstream
+ // (Other part is in the initialiser list)
+ std::cout.rdbuf(this->origCout_.rdbuf());
+
+ // Make sure we make way for the status lines
+ this->preUpdate(Game::getInstance().getGameClock());
+ }
+
+ IOConsole::~IOConsole()
+ {
+ // Process output written to std::cout in the meantime
+ std::cout.flush();
+ if (!this->origCout_.str().empty())
+ this->shell_->addOutput(this->origCout_.str(), Shell::None);
+ // Erase input and status lines
+ this->cout_ << "\033[1G\033[J";
+ // Move cursor to the bottom
+ this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B';
+ // Scroll terminal to compensate for erased lines
+ this->cout_ << "\033[" << this->statusLineWidths_.size() << 'T';
+
+ resetTerminalMode();
+ this->shell_->destroy();
+
+ // Restore this->cout_ redirection
+ std::cout.rdbuf(this->cout_.rdbuf());
+ // Enable standard std::cout logging again
+ OutputHandler::getInstance().enableCout();
+ }
+
+ void IOConsole::preUpdate(const Clock& time)
+ {
+ unsigned char c;
+ std::string escapeSequence;
+ EscapeMode::Value escapeMode = EscapeMode::None;
+ while (std::cin.good())
+ {
+ c = std::cin.get();
+ if (!std::cin.good())
+ break;
+
+ if (escapeMode == EscapeMode::First && (c == '[' || c=='O') )
+ escapeMode = EscapeMode::Second;
+ // Get Alt+Tab combination when switching applications
+ else if (escapeMode == EscapeMode::First && c == '\t')
+ {
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::Tab, '\t', KeyboardModifier::Alt));
+ escapeMode = EscapeMode::None;
+ }
+ else if (escapeMode == EscapeMode::Second)
+ {
+ escapeSequence += c;
+ escapeMode = EscapeMode::None;
+ if (escapeSequence == "A")
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::Up, 0, 0));
+ else if (escapeSequence == "B")
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::Down, 0, 0));
+ else if (escapeSequence == "C")
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::Right, 0, 0));
+ else if (escapeSequence == "D")
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::Left, 0, 0));
+ else if (escapeSequence == "1~" || escapeSequence == "H")
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::Home, 0, 0));
+ else if (escapeSequence == "2~")
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::Insert, 0, 0));
+ else if (escapeSequence == "3~")
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::Delete, 0, 0));
+ else if (escapeSequence == "4~" || escapeSequence == "F")
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::End, 0, 0));
+ else if (escapeSequence == "5~")
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::PageUp, 0, 0));
+ else if (escapeSequence == "6~")
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::PageDown, 0, 0));
+ else
+ // Waiting for sequence to complete
+ // If the user presses ESC and then '[' or 'O' while the loop is not
+ // running (for instance while loading), the whole sequence gets dropped
+ escapeMode = EscapeMode::Second;
+ }
+ else // not in an escape sequence OR user might have pressed just ESC
+ {
+ if (escapeMode == EscapeMode::First)
+ {
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, c, 0));
+ escapeMode = EscapeMode::None;
+ }
+ if (c == '\033')
+ {
+ escapeMode = EscapeMode::First;
+ escapeSequence.clear();
+ }
+ else
+ {
+ KeyCode::ByEnum code;
+ switch (c)
+ {
+ case '\n' : case '\r': code = KeyCode::Return; break;
+ case '\177': case '\b': code = KeyCode::Back; break;
+ case '\t' : code = KeyCode::Tab; break;
+ default:
+ // We don't encode the key code (would be a very large switch)
+ // because the InputBuffer will only insert the text anyway
+ // Replacement character is simply KeyCode::A
+ code = KeyCode::A;
+ }
+ this->buffer_->buttonPressed(KeyEvent(code, c, 0));
+ }
+ }
+ }
+ // Reset error flags in std::cin
+ std::cin.clear();
+
+ // If there is still an escape key pending (escape key ONLY), then
+ // it sure isn't an escape sequence anymore
+ if (escapeMode == EscapeMode::First)
+ this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, '\033', 0));
+
+ // Determine terminal width and height
+ this->lastTerminalWidth_ = this->terminalWidth_;
+ this->lastTerminalHeight_ = this->terminalHeight_;
+ this->getTerminalSize();
+
+ int heightDiff = this->terminalHeight_ - this->lastTerminalHeight_;
+ if (this->bStatusPrinted_ && heightDiff < 0)
+ {
+ // Terminal width has shrunk. The cursor will still be on the input line,
+ // but that line might very well be the last
+ int newLines = std::min((int)this->statusLineWidths_.size(), -heightDiff);
+ // Scroll terminal to create new lines
+ this->cout_ << "\033[" << newLines << 'S';
+ }
+
+ if (!this->bStatusPrinted_ && this->willPrintStatusLines())
+ {
+ // Scroll console to make way for status lines
+ this->cout_ << "\033[" << this->statusLineWidths_.size() << 'S';
+ this->bStatusPrinted_ = true;
+ }
+
+ // We always assume that the cursor is on the input line.
+ // But we cannot always be sure about that, esp. if we scroll the console
+ this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B';
+ this->cout_ << "\033[" << this->statusLineWidths_.size() << 'A';
+
+ // Erase status and input lines
+ this->cout_ << "\033[1G\033[J";
+ this->printInputLine();
+ this->printStatusLines();
+ this->cout_.flush();
+
+ // Process output written to std::cout
+ std::cout.flush();
+ if (!this->origCout_.str().empty())
+ {
+ this->shell_->addOutput(this->origCout_.str(), Shell::None);
+ this->origCout_.str("");
+ }
+ }
+
+ void IOConsole::printOutputLine(const std::string& text, Shell::LineType type)
+ {
+/*
+ // Colour line
+ switch (type)
+ {
+ case Shell::None: this->cout_ << "\033[37m"; break;
+ case Shell::Error: this->cout_ << "\033[91m"; break;
+ case Shell::Warning: this->cout_ << "\033[31m"; break;
+ case Shell::Info: this->cout_ << "\033[34m"; break;
+ case Shell::Debug: this->cout_ << "\033[36m"; break;
+ case Shell::Verbose: this->cout_ << "\033[35m"; break;
+ case Shell::Ultra: this->cout_ << "\033[37m"; break;
+ default: break;
+ }
+*/
+
+ // Print output line
+ this->cout_ << text;
+
+ // Reset colour to white
+// this->cout_ << "\033[37m";
+ }
+
+ void IOConsole::printInputLine()
+ {
+ // Set cursor to the beginning of the line and erase the line
+ this->cout_ << "\033[1G\033[K";
+ // Indicate a command prompt
+ this->cout_ << this->promptString_;
+ // Save cursor position
+ this->cout_ << "\033[s";
+ // Print command line buffer
+ this->cout_ << this->shell_->getInput();
+ // Restore cursor position and move it to the right
+ this->cout_ << "\033[u";
+ if (this->buffer_->getCursorPosition() > 0)
+ this->cout_ << "\033[" << this->buffer_->getCursorPosition() << 'C';
+ }
+
+ void IOConsole::printStatusLines()
+ {
+ if (this->willPrintStatusLines())
+ {
+ // Save cursor position
+ this->cout_ << "\033[s";
+ // Move cursor down (don't create a new line here because the buffer might flush then!)
+ this->cout_ << "\033[1B\033[1G";
+ this->cout_ << std::fixed << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgFPS() << " fps, ";
+ this->cout_ << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgTickTime() << " ms tick time";
+ // Restore cursor position
+ this->cout_ << "\033[u";
+ this->bStatusPrinted_ = true;
+ }
+ else
+ this->bStatusPrinted_ = false;
+ }
+
+ void IOConsole::setTerminalMode()
+ {
+ termios new_settings;
+ this->originalTerminalSettings_ = new termios();
+
+ tcgetattr(0, this->originalTerminalSettings_);
+ new_settings = *this->originalTerminalSettings_;
+ new_settings.c_lflag &= ~(ICANON | ECHO);
+ //new_settings.c_lflag |= (ISIG | IEXTEN);
+ new_settings.c_cc[VTIME] = 0;
+ new_settings.c_cc[VMIN] = 0;
+ tcsetattr(0, TCSANOW, &new_settings);
+ atexit(&IOConsole::resetTerminalMode);
+ }
+
+ /*static*/ void IOConsole::resetTerminalMode()
+ {
+ if (IOConsole::singletonPtr_s && IOConsole::singletonPtr_s->originalTerminalSettings_)
+ {
+ tcsetattr(0, TCSANOW, IOConsole::singletonPtr_s->originalTerminalSettings_);
+ delete IOConsole::singletonPtr_s->originalTerminalSettings_;
+ IOConsole::singletonPtr_s->originalTerminalSettings_ = 0;
+ }
+ }
+
+ void IOConsole::getTerminalSize()
+ {
+#ifdef TIOCGSIZE
+ struct ttysize win;
+ if (!ioctl(STDIN_FILENO, TIOCGSIZE, &win))
+ {
+ this->terminalWidth_ = win.ts_cols;
+ this->terminalHeight_ = win.ts_lines;
+ return;
+ }
+#elif defined TIOCGWINSZ
+ struct winsize win;
+ if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &win))
+ {
+ this->terminalWidth_ = win.ws_col;
+ this->terminalHeight_ = win.ws_row;
+ return;
+ }
+#else
+ const char* s = getenv("COLUMNS");
+ this->terminalWidth_ = s ? strtol(s, NULL, 10) : 80;
+ s = getenv("LINES");
+ this->terminalHeight_ = s ? strtol(s, NULL, 10) : 24;
+ return;
+#endif
+ this->terminalWidth_ = 80;
+ this->terminalHeight_ = 24;
+ }
+
+ inline bool IOConsole::willPrintStatusLines()
+ {
+ return !this->statusLineWidths_.empty()
+ && this->terminalWidth_ >= this->statusLineMaxWidth_
+ && this->terminalHeight_ >= this->minOutputLines_ + (int)this->statusLineWidths_.size();
+ }
+
+ // ###############################
+ // ### ShellListener methods ###
+ // ###############################
+
+ //! Called if only the last output-line has changed
+ void IOConsole::onlyLastLineChanged()
+ {
+ // Save cursor position and move it to the beginning of the first output line
+ this->cout_ << "\033[s\033[1A\033[1G";
+ // Erase the line
+ this->cout_ << "\033[K";
+ // Reprint the last output line
+ this->printOutputLine(this->shell_->getNewestLineIterator()->first, this->shell_->getNewestLineIterator()->second);
+ // Restore cursor
+ this->cout_ << "\033[u";
+ this->cout_.flush();
+ }
+
+ //! Called if a new output-line was added
+ void IOConsole::lineAdded()
+ {
+ int newLines = this->shell_->getNewestLineIterator()->first.size() / this->terminalWidth_ + 1;
+ // Create new lines by scrolling the screen
+ this->cout_ << "\033[" << newLines << 'S';
+ // Move cursor to the beginning of the new (last) output line
+ this->cout_ << "\033[" << newLines << "A\033[1G";
+ // Erase screen from here
+ this->cout_ << "\033[J";
+ // Print the new output lines
+ for (int i = 0; i < newLines; ++i)
+ {
+ Shell::LineList::const_iterator it = this->shell_->getNewestLineIterator();
+ this->printOutputLine(it->first.substr(i*this->terminalWidth_, this->terminalWidth_), it->second);
+ }
+ // Move cursor down
+ this->cout_ << "\033[1B\033[1G";
+ // Print status and input lines
+ this->printInputLine();
+ this->printStatusLines();
+ this->cout_.flush();
+ }
+
+ //! Called if the text in the input-line has changed
+ void IOConsole::inputChanged()
+ {
+ this->printInputLine();
+ this->cout_.flush();
+ }
+
+ //! Called if the position of the cursor in the input-line has changed
+ void IOConsole::cursorChanged()
+ {
+ this->printInputLine();
+ this->cout_.flush();
+ }
+}
+
+#elif defined(ORXONOX_PLATFORM_WINDOWS)
+// ##################################
+// ### Windows Implementation ###
+// ##################################
+
+#include <windows.h>
+
+namespace orxonox
+{
+ //! Redirects std::cout, creates the corresponding Shell and changes the terminal mode
+ IOConsole::IOConsole()
+ : shell_(new Shell("IOConsole", false))
+ , buffer_(shell_->getInputBuffer())
+ , cout_(std::cout.rdbuf())
+ , promptString_("orxonox # ")
+ , inputLineHeight_(1)
+ , statusLines_(1)
+ , lastOutputLineHeight_(0)
+ {
+ // Disable standard this->cout_ logging
+ OutputHandler::getInstance().disableCout();
+ // Redirect std::cout to an ostringstream
+ // (Other part is in the initialiser list)
+ std::cout.rdbuf(this->origCout_.rdbuf());
+
+ this->setTerminalMode();
+ CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
+ GetConsoleScreenBufferInfo(this->stdOutHandle_, &screenBufferInfo);
+ this->terminalWidth_ = screenBufferInfo.dwSize.X;
+ this->terminalHeight_ = screenBufferInfo.dwSize.Y;
+ // Determines where we are in respect to output already written with std::cout
+ this->inputLineRow_ = screenBufferInfo.dwCursorPosition.Y;
+/*
+ this->lastTerminalWidth_ = this->terminalWidth_;
+ this->lastTerminalHeight_ = this->terminalHeight_;
+*/
+
+ // Cursor already at the end of the screen buffer?
+ // (assuming the current input line height is 1)
+ if (this->inputLineRow_ >= this->terminalHeight_ - this->statusLines_)
+ SetConsoleCursorPosition(this->stdOutHandle_, makeCOORD(0, this->terminalHeight_ - this->statusLines_));
+
+ // Prevent input line from overflowing
+ int maxInputLength = (this->terminalHeight_ - this->statusLines_) * this->terminalWidth_ - 1 - this->promptString_.size();
+ // Consider that the echo of a command might include the command plus some other characters (assumed max 80)
+ // Also put a minimum so the config file parser is not overwhelmed with the command history
+ this->buffer_->setMaxLength(std::min(8192, (maxInputLength - 80) / 2));
+
+ // Print input and status line and position cursor
+ this->inputChanged();
+ this->cursorChanged();
+ this->lastRefreshTime_ = Game::getInstance().getGameClock().getRealMicroseconds();
+ this->preUpdate(Game::getInstance().getGameClock());
+
+ this->shell_->registerListener(this);
+ }
+
+ //! Resets std::cout redirection and restores the terminal mode
+ IOConsole::~IOConsole()
+ {
+ // Process output written to std::cout in the meantime
+ std::cout.flush();
+ if (!this->origCout_.str().empty())
+ this->shell_->addOutput(this->origCout_.str(), Shell::None);
+
+ this->shell_->unregisterListener(this);
+
+ // Erase input and status lines
+ COORD pos = {0, this->inputLineRow_};
+ this->writeText(std::string((this->inputLineHeight_ + this->statusLines_) * this->terminalWidth_, ' '), pos);
+ // Move cursor to the beginning of the line
+ SetConsoleCursorPosition(stdOutHandle_, pos);
+
+ // Restore this->cout_ redirection
+ std::cout.rdbuf(this->cout_.rdbuf());
+ // Enable standard this->cout_ logging again
+ OutputHandler::getInstance().enableCout();
+
+ resetTerminalMode();
+ this->shell_->destroy();
+ }
+
+ //! Processes the pending input key strokes, refreshes the status lines and handles std::cout (redirected)
+ void IOConsole::preUpdate(const Clock& time)
+ {
+ // Process input
+ while (true)
+ {
+ DWORD count;
+ INPUT_RECORD inrec;
+ PeekConsoleInput(this->stdInHandle_, &inrec, 1, &count);
+ if (count == 0)
+ break;
+ ReadConsoleInput(this->stdInHandle_, &inrec, 1, &count);
+ if (inrec.EventType == KEY_EVENT && inrec.Event.KeyEvent.bKeyDown)
+ {
+ // Process keyboard modifiers (Ctrl, Alt and Shift)
+ DWORD modifiersIn = inrec.Event.KeyEvent.dwControlKeyState;
+ int modifiersOut = 0;
+ if ((modifiersIn & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0)
+ modifiersOut |= KeyboardModifier::Alt;
+ if ((modifiersIn & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
+ modifiersOut |= KeyboardModifier::Ctrl;
+ if ((modifiersIn & SHIFT_PRESSED) != 0)
+ modifiersOut |= KeyboardModifier::Shift;
+
+ // ASCII character (0 for special keys)
+ char asciiChar = inrec.Event.KeyEvent.uChar.AsciiChar;
+
+ // Process special keys and if not found, use Key::A as dummy (InputBuffer uses the ASCII text anyway)
+ switch (inrec.Event.KeyEvent.wVirtualKeyCode)
+ {
+ case VK_BACK: this->buffer_->buttonPressed(KeyEvent(KeyCode::Back, asciiChar, modifiersOut)); break;
+ case VK_TAB: this->buffer_->buttonPressed(KeyEvent(KeyCode::Tab, asciiChar, modifiersOut)); break;
+ case VK_RETURN: this->buffer_->buttonPressed(KeyEvent(KeyCode::Return, asciiChar, modifiersOut)); break;
+ case VK_PAUSE: this->buffer_->buttonPressed(KeyEvent(KeyCode::Pause, asciiChar, modifiersOut)); break;
+ case VK_ESCAPE: this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, asciiChar, modifiersOut)); break;
+ case VK_SPACE: this->buffer_->buttonPressed(KeyEvent(KeyCode::Space, asciiChar, modifiersOut)); break;
+ case VK_PRIOR: this->buffer_->buttonPressed(KeyEvent(KeyCode::PageUp, asciiChar, modifiersOut)); break;
+ case VK_NEXT: this->buffer_->buttonPressed(KeyEvent(KeyCode::PageDown, asciiChar, modifiersOut)); break;
+ case VK_END: this->buffer_->buttonPressed(KeyEvent(KeyCode::End, asciiChar, modifiersOut)); break;
+ case VK_HOME: this->buffer_->buttonPressed(KeyEvent(KeyCode::Home, asciiChar, modifiersOut)); break;
+ case VK_LEFT: this->buffer_->buttonPressed(KeyEvent(KeyCode::Left, asciiChar, modifiersOut)); break;
+ case VK_UP: this->buffer_->buttonPressed(KeyEvent(KeyCode::Up, asciiChar, modifiersOut)); break;
+ case VK_RIGHT: this->buffer_->buttonPressed(KeyEvent(KeyCode::Right, asciiChar, modifiersOut)); break;
+ case VK_DOWN: this->buffer_->buttonPressed(KeyEvent(KeyCode::Down, asciiChar, modifiersOut)); break;
+ case VK_INSERT: this->buffer_->buttonPressed(KeyEvent(KeyCode::Insert, asciiChar, modifiersOut)); break;
+ case VK_DELETE: this->buffer_->buttonPressed(KeyEvent(KeyCode::Delete, asciiChar, modifiersOut)); break;
+ default: this->buffer_->buttonPressed(KeyEvent(KeyCode::A, asciiChar, modifiersOut));
+ }
+ }
+ }
+
+ // TODO: Respect screen buffer size changes
+/*
+ // The user can manually adjust the screen buffer size on Windows
+ // And we don't want to screw the console because of that
+ this->lastTerminalWidth_ = this->terminalWidth_;
+ this->lastTerminalHeight_ = this->terminalHeight_;
+ this->getTerminalSize(); // Also sets this->inputLineRow_ according to the cursor position
+ // Is there still enough space below the cursor for the status line(s)?
+ if (this->inputLineRow_ >= this->terminalHeight_ - this->statusLines_)
+ this->moveCursor(0, -this->inputLineRow_ + this->terminalHeight_ - this->statusLines_ - 1);
+*/
+
+ // Refresh status line 5 times per second
+ if (time.getMicroseconds() > this->lastRefreshTime_ + 1000000)
+ {
+ this->printStatusLines();
+ this->lastRefreshTime_ = time.getMicroseconds();
+ }
+
+ // Process output written to std::cout
+ std::cout.flush();
+ if (!this->origCout_.str().empty())
+ {
+ this->shell_->addOutput(this->origCout_.str(), Shell::None);
+ this->origCout_.str("");
+ }
+ }
+
+ //! Prints output text. Similar to writeText, but sets the colour according to the output level
+ void IOConsole::printOutputLine(const std::string& text, Shell::LineType type, const COORD& pos)
+ {
+ // Colour line
+ WORD colour = 0;
+ switch (type)
+ {
+ case Shell::Error: colour = FOREGROUND_INTENSITY | FOREGROUND_RED; break;
+ case Shell::Warning: colour = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED; break;
+ case Shell::Info:
+ case Shell::Debug:
+ case Shell::Verbose:
+ case Shell::Ultra: colour = FOREGROUND_INTENSITY ; break;
+ case Shell::Command: colour = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
+ case Shell::Hint: colour = FOREGROUND_GREEN | FOREGROUND_RED ; break;
+ default: colour = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE; break;
+ }
+
+ // Print output line
+ this->writeText(text, pos, colour);
+ }
+
+ //! Prints all status lines with current content
+ void IOConsole::printStatusLines()
+ {
+ // Prepare text to be written
+ std::ostringstream oss;
+ oss << std::fixed << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgFPS() << " fps, ";
+ oss << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgTickTime() << " ms tick time";
+ // Clear rest of the line by inserting spaces
+ oss << std::string(this->terminalWidth_ - oss.str().size(), ' ');
+ this->writeText(oss.str(), makeCOORD(0, this->inputLineRow_ + this->inputLineHeight_), FOREGROUND_GREEN);
+ }
+
+ //! Changes the console parameters for unbuffered input
+ void IOConsole::setTerminalMode()
+ {
+ // Set the console mode to no-echo, raw input, and no window or mouse events
+ this->stdOutHandle_ = GetStdHandle(STD_OUTPUT_HANDLE);
+ this->stdInHandle_ = GetStdHandle(STD_INPUT_HANDLE);
+ if (this->stdInHandle_ == INVALID_HANDLE_VALUE
+ || !GetConsoleMode(this->stdInHandle_, &this->originalTerminalSettings_)
+ || !SetConsoleMode(this->stdInHandle_, 0))
+ {
+ COUT(1) << "Error: Could not set Windows console settings" << std::endl;
+ return;
+ }
+ FlushConsoleInputBuffer(this->stdInHandle_);
+ }
+
+ //! Restores the console parameters
+ void IOConsole::resetTerminalMode()
+ {
+ SetConsoleMode(this->stdInHandle_, this->originalTerminalSettings_);
+ }
+
+ //! Sets this->terminalWidth_ and this->terminalHeight_
+ void IOConsole::getTerminalSize()
+ {
+ CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
+ GetConsoleScreenBufferInfo(this->stdOutHandle_, &screenBufferInfo);
+ this->terminalWidth_ = screenBufferInfo.dwSize.X;
+ this->terminalHeight_ = screenBufferInfo.dwSize.Y;
+ }
+
+ //! Writes arbitrary text to the console with a certain colour and screen buffer position
+ void IOConsole::writeText(const std::string& text, const COORD& coord, WORD attributes)
+ {
+ DWORD count;
+ WriteConsoleOutputCharacter(stdOutHandle_, text.c_str(), text.size(), coord, &count);
+ FillConsoleOutputAttribute(stdOutHandle_, attributes, text.size(), coord, &count);
+ }
+
+ /** Scrolls the console screen buffer to create empty lines above the input line.
+ @details
+ If the input and status lines are already at the bottom of the screen buffer
+ the whole output gets scrolled up. In the other case the input and status
+ lines get scrolled down.
+ In any case the status and input lines get scrolled down as far as possible.
+ @param lines
+ Number of lines to be inserted. Behavior for negative values is undefined.
+ */
+ void IOConsole::createNewOutputLines(int lines)
+ {
+ CHAR_INFO fillChar = {{' '}, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED};
+ // Lines to scroll input/status down (if possible)
+ int linesDown = clamp(terminalHeight_ - inputLineRow_ - inputLineHeight_ - statusLines_, 0, lines);
+ if (linesDown > 0)
+ {
+ // Scroll input and status lines down
+ SMALL_RECT oldRect = {0, this->inputLineRow_,
+ this->terminalWidth_ - 1, this->inputLineRow_ + this->inputLineHeight_ + this->statusLines_ - 1};
+ this->inputLineRow_ += linesDown;
+ ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, makeCOORD(0, this->inputLineRow_), &fillChar);
+ // Move cursor down to the new bottom so the user can see the status lines
+ COORD pos = {0, this->inputLineRow_ + this->inputLineHeight_ - 1 + this->statusLines_};
+ SetConsoleCursorPosition(stdOutHandle_, pos);
+ // Get cursor back to the right position
+ this->cursorChanged();
+ }
+ // Check how many lines we still have to scroll up the output
+ if (lines - linesDown > 0)
+ {
+ // Scroll output up
+ SMALL_RECT oldRect = {0, lines - linesDown, this->terminalWidth_ - 1, this->inputLineRow_ - 1};
+ ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, makeCOORD(0, 0), &fillChar);
+ }
+ }
+
+ // ###############################
+ // ### ShellListener methods ###
+ // ###############################
+
+ //! Called if the text in the input line has changed
+ void IOConsole::inputChanged()
+ {
+ int newInputLineLength = this->promptString_.size() + this->shell_->getInput().size();
+ int newInputLineHeight = 1 + newInputLineLength / this->terminalWidth_;
+ int newLines = newInputLineHeight - this->inputLineHeight_;
+ if (newLines > 0)
+ {
+ // Abuse this function to scroll the console
+ this->createNewOutputLines(newLines);
+ // Either Compensate for side effects (input/status lines scrolled down)
+ // or we have to do this anyway (output scrolled up)
+ this->inputLineRow_ -= newLines;
+ }
+ else if (newLines < 0)
+ {
+ // Scroll status lines up
+ int statusLineRow = this->inputLineRow_ + this->inputLineHeight_;
+ SMALL_RECT oldRect = {0, statusLineRow, this->terminalWidth_ - 1, statusLineRow + this->statusLines_};
+ CHAR_INFO fillChar = {{' '}, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED};
+ ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, makeCOORD(0, statusLineRow + newLines), &fillChar);
+ // Clear potential leftovers
+ if (-newLines - this->statusLines_ > 0)
+ {
+ COORD pos = {0, this->inputLineRow_ + newInputLineHeight + this->statusLines_};
+ this->writeText(std::string((-newLines - this->statusLines_) * this->terminalWidth_, ' '), pos);
+ }
+ }
+ this->inputLineHeight_ = newInputLineHeight;
+
+ // Print the whole line, including spaces that erase leftovers
+ std::string inputLine = this->promptString_ + this->shell_->getInput();
+ inputLine += std::string(this->terminalWidth_ - newInputLineLength % this->terminalWidth_, ' ');
+ this->writeText(inputLine, makeCOORD(0, this->inputLineRow_), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
+ // If necessary, move cursor
+ if (newLines != 0)
+ this->cursorChanged();
+ }
+
+ //! Called if the position of the cursor in the input-line has changed
+ void IOConsole::cursorChanged()
+ {
+ int rawCursorPos = this->promptString_.size() + this->buffer_->getCursorPosition();
+ // Compensate for cursor further to the right than the terminal width
+ COORD pos;
+ pos.X = rawCursorPos % this->terminalWidth_;
+ pos.Y = this->inputLineRow_ + rawCursorPos / this->terminalWidth_;
+ SetConsoleCursorPosition(stdOutHandle_, pos);
+ }
+
+ //! Called if only the last output-line has changed
+ void IOConsole::onlyLastLineChanged()
+ {
+ int newLineHeight = 1 + this->shell_->getNewestLineIterator()->first.size() / this->terminalWidth_;
+ // Compute the number of new lines needed
+ int newLines = newLineHeight - this->lastOutputLineHeight_;
+ this->lastOutputLineHeight_ = newLineHeight;
+ // Scroll console if necessary
+ if (newLines > 0) // newLines < 0 is assumed impossible
+ this->createNewOutputLines(newLines);
+ Shell::LineList::const_iterator it = this->shell_->getNewestLineIterator();
+ this->printOutputLine(it->first, it->second, makeCOORD(0, this->inputLineRow_ - newLineHeight));
+ }
+
+ //! Called if a new output line was added
+ void IOConsole::lineAdded()
+ {
+ Shell::LineList::const_iterator it = this->shell_->getNewestLineIterator();
+ // Scroll console
+ this->lastOutputLineHeight_ = 1 + it->first.size() / this->terminalWidth_;
+ this->createNewOutputLines(this->lastOutputLineHeight_);
+ // Write the text
+ COORD pos = {0, this->inputLineRow_ - this->lastOutputLineHeight_};
+ this->printOutputLine(it->first, it->second, pos);
+ }
+}
+
+#endif /* ORXONOX_PLATFORM_UNIX */
Copied: code/branches/consolecommands3/src/libraries/core/command/IOConsole.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/IOConsole.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/IOConsole.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/IOConsole.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,128 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Oliver Scheuss
+ * Reto Grieder
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _IOConsole_H__
+#define _IOConsole_H__
+
+#include "CorePrereqs.h"
+
+#include <sstream>
+#include <string>
+#include <vector>
+#include "util/Singleton.h"
+#include "Shell.h"
+
+#ifdef ORXONOX_PLATFORM_UNIX
+struct termios;
+#elif defined(ORXONOX_PLATFORM_WINDOWS)
+#define WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
+namespace orxonox
+{
+ class _CoreExport IOConsole : public Singleton<IOConsole>, public ShellListener
+ {
+ friend class Singleton<IOConsole>;
+
+ public:
+ IOConsole();
+ ~IOConsole();
+
+ void preUpdate(const Clock& time);
+
+ private:
+ void setTerminalMode();
+ void getTerminalSize();
+ void printStatusLines();
+ static int extractLogLevel(std::string* text);
+
+ // Methods from ShellListener
+ void linesChanged();
+ void onlyLastLineChanged();
+ void lineAdded();
+ void inputChanged();
+ void cursorChanged();
+ void executed();
+ void exit();
+
+ Shell* shell_;
+ InputBuffer* buffer_;
+ std::ostream cout_;
+ std::ostringstream origCout_;
+ int terminalWidth_;
+ int terminalHeight_;
+ int lastTerminalWidth_;
+ int lastTerminalHeight_;
+ const std::string promptString_;
+
+#ifdef ORXONOX_PLATFORM_UNIX
+ bool willPrintStatusLines();
+ void printInputLine();
+ void printOutputLine(const std::string& line, Shell::LineType type);
+ static void resetTerminalMode();
+
+ bool bPrintStatusLine_;
+ bool bStatusPrinted_;
+ std::vector<int> statusLineWidths_;
+ int statusLineMaxWidth_;
+ static const int minOutputLines_ = 3;
+ termios* originalTerminalSettings_;
+
+#elif defined(ORXONOX_PLATFORM_WINDOWS)
+ void resetTerminalMode();
+ void moveCursor(int dx, int dy);
+ void writeText(const std::string& text, const COORD& pos, WORD attributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
+ void createNewOutputLines(int lines);
+ void printOutputLine(const std::string& line, Shell::LineType type, const COORD& pos);
+
+ static inline COORD makeCOORD(int x, int y)
+ {
+ COORD val = {x, y};
+ return val;
+ }
+
+ DWORD originalTerminalSettings_;
+ HANDLE stdInHandle_;
+ HANDLE stdOutHandle_;
+ int inputLineRow_;
+ int inputLineHeight_;
+ const int statusLines_;
+ int lastOutputLineHeight_;
+ uint64_t lastRefreshTime_;
+#endif
+
+ static IOConsole* singletonPtr_s;
+ };
+}
+
+#endif /* _IOConsole_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/IRC.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/IRC.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/IRC.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/IRC.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,137 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#include "IRC.h"
+
+#include <cpptcl/cpptcl.h>
+
+#include "util/Convert.h"
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "ConsoleCommand.h"
+#include "CoreIncludes.h"
+#include "TclThreadManager.h"
+
+namespace orxonox
+{
+ static const unsigned int IRC_TCL_THREADID = 1421421421;
+
+ SetConsoleCommand(IRC, say, true).accessLevel(AccessLevel::User);
+ SetConsoleCommand(IRC, msg, false).accessLevel(AccessLevel::User);
+ SetConsoleCommand(IRC, nick, false).accessLevel(AccessLevel::User);
+
+ IRC::IRC()
+ {
+ RegisterRootObject(IRC);
+ this->interpreter_ = 0;
+ }
+
+ void IRC::initialize()
+ {
+ unsigned int threadID = IRC_TCL_THREADID;
+ this->interpreter_ = TclThreadManager::createWithId(threadID);
+
+ try
+ {
+ this->interpreter_->def("::orxonox::irc::say", IRC::tcl_say, Tcl::variadic());
+ this->interpreter_->def("::orxonox::irc::privmsg", IRC::tcl_privmsg, Tcl::variadic());
+ this->interpreter_->def("::orxonox::irc::action", IRC::tcl_action, Tcl::variadic());
+ this->interpreter_->def("::orxonox::irc::info", IRC::tcl_info, Tcl::variadic());
+ }
+ catch (Tcl::tcl_error const &e)
+ { COUT(1) << "Tcl (IRC) error: " << e.what(); }
+
+ this->nickname_ = "orx" + multi_cast<std::string>(static_cast<unsigned int>(rand()));
+ TclThreadManager::execute(threadID, "set nickname " + this->nickname_);
+ TclThreadManager::execute(threadID, "source irc.tcl");
+ }
+
+ IRC& IRC::getInstance()
+ {
+ static IRC instance;
+ return instance;
+ }
+
+ bool IRC::eval(const std::string& command)
+ {
+ if (!IRC::getInstance().interpreter_)
+ {
+ IRC::getInstance().initialize();
+ COUT(1) << "Error: IRC client wasn't yet initialized, please try again." << std::endl;
+ return false;
+ }
+
+ try
+ {
+ IRC::getInstance().interpreter_->eval(command);
+ return true;
+ }
+ catch (Tcl::tcl_error const &e)
+ { COUT(1) << "Tcl (IRC) error: " << e.what(); }
+
+ return false;
+ }
+
+ void IRC::say(const std::string& message)
+ {
+ if (IRC::eval("irk::say $conn #orxonox {" + message + '}'))
+ IRC::tcl_say(Tcl::object(), Tcl::object(IRC::getInstance().nickname_), Tcl::object(message));
+ }
+
+ void IRC::msg(const std::string& channel, const std::string& message)
+ {
+ if (IRC::eval("irk::say $conn " + channel + " {" + message + '}'))
+ IRC::tcl_privmsg(Tcl::object(channel), Tcl::object(IRC::getInstance().nickname_), Tcl::object(message));
+ }
+
+ void IRC::nick(const std::string& nickname)
+ {
+ if (IRC::eval("irk::nick $conn " + nickname))
+ IRC::getInstance().nickname_ = nickname;
+ }
+
+ void IRC::tcl_say(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args)
+ {
+ COUT(0) << "IRC> " << nick.get() << ": " << stripEnclosingBraces(args.get()) << std::endl;
+ }
+
+ void IRC::tcl_privmsg(Tcl::object const &query, Tcl::object const &nick, Tcl::object const &args)
+ {
+ COUT(0) << "IRC (" << query.get() << ")> " << nick.get() << ": " << stripEnclosingBraces(args.get()) << std::endl;
+ }
+
+ void IRC::tcl_action(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args)
+ {
+ COUT(0) << "IRC> * " << nick.get() << ' ' << stripEnclosingBraces(args.get()) << std::endl;
+ }
+
+ void IRC::tcl_info(Tcl::object const &channel, Tcl::object const &args)
+ {
+ COUT(0) << "IRC> --> " << stripEnclosingBraces(args.get()) << std::endl;
+ }
+}
Copied: code/branches/consolecommands3/src/libraries/core/command/IRC.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/IRC.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/IRC.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/IRC.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,66 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _IRC_H__
+#define _IRC_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include "OrxonoxClass.h"
+
+namespace orxonox
+{
+ class _CoreExport IRC : public OrxonoxClass
+ {
+ public:
+ static IRC& getInstance();
+
+ static void say(const std::string& message);
+ static void msg(const std::string& channel, const std::string& message);
+ static void nick(const std::string& nickname);
+
+ static void tcl_say(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args);
+ static void tcl_privmsg(Tcl::object const &query, Tcl::object const &nick, Tcl::object const &args);
+ static void tcl_action(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args);
+ static void tcl_info(Tcl::object const &channel, Tcl::object const &args);
+
+ private:
+ static bool eval(const std::string& command);
+ void initialize();
+
+ IRC();
+ IRC(const IRC& other);
+ ~IRC() {}
+
+ Tcl::interpreter* interpreter_;
+ std::string nickname_;
+ };
+}
+
+#endif /* _IRC_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/Shell.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/Shell.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/Shell.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/Shell.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,469 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * Reto Grieder
+ *
+ */
+
+#include "Shell.h"
+
+#include "util/OutputHandler.h"
+#include "util/StringUtils.h"
+#include "util/SubString.h"
+#include "CommandExecutor.h"
+#include "CoreIncludes.h"
+#include "ConfigFileManager.h"
+#include "ConfigValueIncludes.h"
+#include "ConsoleCommand.h"
+
+namespace orxonox
+{
+ SetConsoleCommandShortcut(OutputHandler, log);
+ SetConsoleCommandShortcut(OutputHandler, error);
+ SetConsoleCommandShortcut(OutputHandler, warning);
+ SetConsoleCommandShortcut(OutputHandler, info);
+ SetConsoleCommandShortcut(OutputHandler, debug);
+
+ Shell::Shell(const std::string& consoleName, bool bScrollable)
+ : OutputListener(consoleName)
+ , inputBuffer_(new InputBuffer())
+ , consoleName_(consoleName)
+ , bScrollable_(bScrollable)
+ {
+ RegisterRootObject(Shell);
+
+ this->scrollPosition_ = 0;
+ this->maxHistoryLength_ = 100;
+ this->historyPosition_ = 0;
+ this->historyOffset_ = 0;
+ this->bFinishedLastLine_ = true;
+
+ this->clearOutput();
+ this->configureInputBuffer();
+
+ // Specify file for the command history
+ ConfigFileManager::getInstance().setFilename(ConfigFileType::CommandHistory, "commandHistory.ini");
+
+ // Use a stringstream object to buffer the output
+ this->outputStream_ = &this->outputBuffer_;
+
+ this->setConfigValues();
+
+ // Get the previous output and add it to the Shell
+ for (OutputHandler::OutputVectorIterator it = OutputHandler::getInstance().getOutputVectorBegin();
+ it != OutputHandler::getInstance().getOutputVectorEnd(); ++it)
+ {
+ if (it->first <= this->getSoftDebugLevel())
+ {
+ this->outputBuffer_ << it->second;
+ this->outputChanged(it->first);
+ }
+ }
+
+ // Register the shell as output listener
+ OutputHandler::getInstance().registerOutputListener(this);
+ }
+
+ Shell::~Shell()
+ {
+ OutputHandler::getInstance().unregisterOutputListener(this);
+ this->inputBuffer_->destroy();
+ }
+
+ void Shell::setConfigValues()
+ {
+ SetConfigValue(maxHistoryLength_, 100)
+ .callback(this, &Shell::commandHistoryLengthChanged);
+ SetConfigValue(historyOffset_, 0)
+ .callback(this, &Shell::commandHistoryOffsetChanged);
+ setConfigValueGeneric(this, &commandHistory_, ConfigFileType::CommandHistory, "Shell", "commandHistory_", std::vector<std::string>());
+
+#ifdef ORXONOX_RELEASE
+ const unsigned int defaultLevel = 1;
+#else
+ const unsigned int defaultLevel = 3;
+#endif
+ SetConfigValueExternal(softDebugLevel_, "OutputHandler", "softDebugLevel" + this->consoleName_, defaultLevel)
+ .description("The maximal level of debug output shown in the Shell");
+ this->setSoftDebugLevel(this->softDebugLevel_);
+ }
+
+ void Shell::commandHistoryOffsetChanged()
+ {
+ if (this->historyOffset_ >= this->maxHistoryLength_)
+ this->historyOffset_ = 0;
+ }
+
+ void Shell::commandHistoryLengthChanged()
+ {
+ this->commandHistoryOffsetChanged();
+
+ while (this->commandHistory_.size() > this->maxHistoryLength_)
+ {
+ unsigned int index = this->commandHistory_.size() - 1;
+ this->commandHistory_.erase(this->commandHistory_.begin() + index);
+ ModifyConfigValue(commandHistory_, remove, index);
+ }
+ }
+
+ void Shell::configureInputBuffer()
+ {
+ this->inputBuffer_->registerListener(this, &Shell::inputChanged, true);
+ this->inputBuffer_->registerListener(this, &Shell::execute, '\r', false);
+ this->inputBuffer_->registerListener(this, &Shell::execute, '\n', false);
+ this->inputBuffer_->registerListener(this, &Shell::hintAndComplete, '\t', true);
+ this->inputBuffer_->registerListener(this, &Shell::backspace, '\b', true);
+ this->inputBuffer_->registerListener(this, &Shell::backspace, '\177', true);
+ this->inputBuffer_->registerListener(this, &Shell::exit, '\033', true); // escape
+ this->inputBuffer_->registerListener(this, &Shell::deleteChar, KeyCode::Delete);
+ this->inputBuffer_->registerListener(this, &Shell::cursorRight, KeyCode::Right);
+ this->inputBuffer_->registerListener(this, &Shell::cursorLeft, KeyCode::Left);
+ this->inputBuffer_->registerListener(this, &Shell::cursorEnd, KeyCode::End);
+ this->inputBuffer_->registerListener(this, &Shell::cursorHome, KeyCode::Home);
+ this->inputBuffer_->registerListener(this, &Shell::historyUp, KeyCode::Up);
+ this->inputBuffer_->registerListener(this, &Shell::historyDown, KeyCode::Down);
+ if (this->bScrollable_)
+ {
+ this->inputBuffer_->registerListener(this, &Shell::scrollUp, KeyCode::PageUp);
+ this->inputBuffer_->registerListener(this, &Shell::scrollDown, KeyCode::PageDown);
+ }
+ else
+ {
+ this->inputBuffer_->registerListener(this, &Shell::historySearchUp, KeyCode::PageUp);
+ this->inputBuffer_->registerListener(this, &Shell::historySearchDown, KeyCode::PageDown);
+ }
+ }
+
+ /*
+ void Shell::history()
+ {
+ Shell& instance = Shell::getInstance();
+
+ for (unsigned int i = instance.historyOffset_; i < instance.commandHistory_.size(); ++i)
+ instance.addOutput(instance.commandHistory_[i] + '\n', -1);
+ for (unsigned int i = 0; i < instance.historyOffset_; ++i)
+ instance.addOutput(instance.commandHistory_[i] + '\n', -1);
+ }
+ */
+
+ void Shell::registerListener(ShellListener* listener)
+ {
+ this->listeners_.push_back(listener);
+ }
+
+ void Shell::unregisterListener(ShellListener* listener)
+ {
+ for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+ {
+ if ((*it) == listener)
+ it = this->listeners_.erase(it);
+ else
+ ++it;
+ }
+ }
+
+ void Shell::setCursorPosition(unsigned int cursor)
+ {
+ this->inputBuffer_->setCursorPosition(cursor);
+ this->updateListeners<&ShellListener::cursorChanged>();
+ }
+
+ void Shell::addOutput(const std::string& text, LineType type)
+ {
+ this->outputBuffer_ << text;
+ this->outputChanged(type);
+ }
+
+ void Shell::clearOutput()
+ {
+ this->outputLines_.clear();
+ this->scrollIterator_ = this->outputLines_.begin();
+
+ this->scrollPosition_ = 0;
+ this->bFinishedLastLine_ = true;
+
+ this->updateListeners<&ShellListener::linesChanged>();
+ }
+
+ Shell::LineList::const_iterator Shell::getNewestLineIterator() const
+ {
+ if (this->scrollPosition_)
+ return this->scrollIterator_;
+ else
+ return this->outputLines_.begin();
+ }
+
+ Shell::LineList::const_iterator Shell::getEndIterator() const
+ {
+ return this->outputLines_.end();
+ }
+
+ void Shell::addToHistory(const std::string& command)
+ {
+ if (command == "")
+ return;
+
+ size_t previous_offset = mod(this->historyOffset_ - 1, this->maxHistoryLength_);
+ if (previous_offset < this->commandHistory_.size() && command == this->commandHistory_[previous_offset])
+ return;
+
+ ModifyConfigValue(commandHistory_, set, this->historyOffset_, command);
+ this->historyPosition_ = 0;
+ ModifyConfigValue(historyOffset_, set, (this->historyOffset_ + 1) % this->maxHistoryLength_);
+ }
+
+ const std::string& Shell::getFromHistory() const
+ {
+ unsigned int index = mod(static_cast<int>(this->historyOffset_) - static_cast<int>(this->historyPosition_), this->maxHistoryLength_);
+ if (index < this->commandHistory_.size() && this->historyPosition_ != 0)
+ return this->commandHistory_[index];
+ else
+ return BLANKSTRING;
+ }
+
+ void Shell::outputChanged(int lineType)
+ {
+ bool newline = false;
+ do
+ {
+ std::string output;
+ std::getline(this->outputBuffer_, output);
+
+ bool eof = this->outputBuffer_.eof();
+ bool fail = this->outputBuffer_.fail();
+ if (eof)
+ this->outputBuffer_.flush();
+ if (eof || fail)
+ this->outputBuffer_.clear();
+ newline = (!eof && !fail);
+
+ if (!newline && output.empty())
+ break;
+
+ if (this->bFinishedLastLine_)
+ {
+ this->outputLines_.push_front(std::make_pair(output, static_cast<LineType>(lineType)));
+
+ if (this->scrollPosition_)
+ this->scrollPosition_++;
+ else
+ this->scrollIterator_ = this->outputLines_.begin();
+
+ this->bFinishedLastLine_ = newline;
+
+ if (!this->scrollPosition_)
+ this->updateListeners<&ShellListener::lineAdded>();
+ }
+ else
+ {
+ this->outputLines_.front().first += output;
+ this->bFinishedLastLine_ = newline;
+ this->updateListeners<&ShellListener::onlyLastLineChanged>();
+ }
+ this->bFinishedLastLine_ = newline;
+
+ } while (newline);
+ }
+
+ void Shell::clearInput()
+ {
+ this->inputBuffer_->clear();
+ this->historyPosition_ = 0;
+ this->updateListeners<&ShellListener::inputChanged>();
+ this->updateListeners<&ShellListener::cursorChanged>();
+ }
+
+ void Shell::setPromptPrefix(const std::string& str)
+ {
+ }
+
+
+ // ##########################################
+ // ### InputBuffer callback functions ###
+ // ##########################################
+
+ void Shell::inputChanged()
+ {
+ this->updateListeners<&ShellListener::inputChanged>();
+ this->updateListeners<&ShellListener::cursorChanged>();
+ }
+
+ void Shell::execute()
+ {
+ this->addToHistory(this->inputBuffer_->get());
+ this->updateListeners<&ShellListener::executed>();
+
+ bool success;
+ const std::string& result = CommandExecutor::query(this->inputBuffer_->get(), &success);
+ if (!success)
+ {
+ this->outputBuffer_ << "Error: Can't execute \"" << this->inputBuffer_->get() << "\"." << std::endl;
+ this->outputChanged(Error);
+ }
+ else if (result != "")
+ {
+ this->outputBuffer_ << result << std::endl;
+ this->outputChanged(Command);
+ }
+
+ this->clearInput();
+ }
+
+ void Shell::hintAndComplete()
+ {
+ this->inputBuffer_->set(CommandExecutor::complete(this->inputBuffer_->get()));
+ this->outputBuffer_ << CommandExecutor::hint(this->inputBuffer_->get()) << std::endl;
+ this->outputChanged(Hint);
+
+ this->inputChanged();
+ }
+
+ void Shell::backspace()
+ {
+ this->inputBuffer_->removeBehindCursor();
+ this->updateListeners<&ShellListener::inputChanged>();
+ this->updateListeners<&ShellListener::cursorChanged>();
+ }
+
+ void Shell::exit()
+ {
+ if (this->inputBuffer_->getSize() > 0)
+ {
+ this->clearInput();
+ return;
+ }
+
+ this->clearInput();
+ this->scrollPosition_ = 0;
+ this->scrollIterator_ = this->outputLines_.begin();
+
+ this->updateListeners<&ShellListener::exit>();
+ }
+
+ void Shell::deleteChar()
+ {
+ this->inputBuffer_->removeAtCursor();
+ this->updateListeners<&ShellListener::inputChanged>();
+ }
+
+ void Shell::cursorRight()
+ {
+ this->inputBuffer_->increaseCursor();
+ this->updateListeners<&ShellListener::cursorChanged>();
+ }
+
+ void Shell::cursorLeft()
+ {
+ this->inputBuffer_->decreaseCursor();
+ this->updateListeners<&ShellListener::cursorChanged>();
+ }
+
+ void Shell::cursorEnd()
+ {
+ this->inputBuffer_->setCursorToEnd();
+ this->updateListeners<&ShellListener::cursorChanged>();
+ }
+
+ void Shell::cursorHome()
+ {
+ this->inputBuffer_->setCursorToBegin();
+ this->updateListeners<&ShellListener::cursorChanged>();
+ }
+
+ void Shell::historyUp()
+ {
+ if (this->historyPosition_ < this->commandHistory_.size())
+ {
+ this->historyPosition_++;
+ this->inputBuffer_->set(this->getFromHistory());
+ }
+ }
+
+ void Shell::historyDown()
+ {
+ if (this->historyPosition_ > 0)
+ {
+ this->historyPosition_--;
+ this->inputBuffer_->set(this->getFromHistory());
+ }
+ }
+
+ void Shell::historySearchUp()
+ {
+ if (this->historyPosition_ == this->historyOffset_)
+ return;
+ unsigned int cursorPosition = this->getCursorPosition();
+ const std::string& input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning of the inputline until the cursor position
+ for (unsigned int newPos = this->historyPosition_ + 1; newPos <= this->historyOffset_; newPos++)
+ {
+ if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // search case insensitive
+ {
+ this->historyPosition_ = newPos;
+ this->inputBuffer_->set(this->getFromHistory());
+ this->setCursorPosition(cursorPosition);
+ return;
+ }
+ }
+ }
+
+ void Shell::historySearchDown()
+ {
+ if (this->historyPosition_ == 0)
+ return;
+ unsigned int cursorPosition = this->getCursorPosition();
+ const std::string& input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning
+ for (unsigned int newPos = this->historyPosition_ - 1; newPos > 0; newPos--)
+ {
+ if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // sear$
+ {
+ this->historyPosition_ = newPos;
+ this->inputBuffer_->set(this->getFromHistory());
+ this->setCursorPosition(cursorPosition);
+ return;
+ }
+ }
+ }
+
+ void Shell::scrollUp()
+ {
+ if (this->scrollIterator_ != this->outputLines_.end())
+ {
+ ++this->scrollIterator_;
+ ++this->scrollPosition_;
+
+ this->updateListeners<&ShellListener::linesChanged>();
+ }
+ }
+
+ void Shell::scrollDown()
+ {
+ if (this->scrollIterator_ != this->outputLines_.begin())
+ {
+ --this->scrollIterator_;
+ --this->scrollPosition_;
+
+ this->updateListeners<&ShellListener::linesChanged>();
+ }
+ }
+}
Copied: code/branches/consolecommands3/src/libraries/core/command/Shell.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/Shell.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/Shell.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/Shell.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,172 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * Reto Grieder
+ *
+ */
+
+#ifndef _Shell_H__
+#define _Shell_H__
+
+#include "CorePrereqs.h"
+
+#include <list>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "util/OutputHandler.h"
+#include "OrxonoxClass.h"
+#include "input/InputBuffer.h"
+
+namespace orxonox
+{
+ class _CoreExport ShellListener
+ {
+ friend class Shell;
+
+ public:
+ virtual ~ShellListener() {}
+
+ private:
+ virtual void linesChanged() {}
+ virtual void onlyLastLineChanged() {}
+ virtual void lineAdded() {}
+ virtual void inputChanged() {}
+ virtual void cursorChanged() {}
+ virtual void executed() {}
+ virtual void exit() {}
+ };
+
+
+ class _CoreExport Shell : virtual public OrxonoxClass, public OutputListener
+ {
+ public:
+ enum LineType
+ {
+ None = OutputLevel::None,
+ Warning = OutputLevel::Warning,
+ Error = OutputLevel::Error,
+ Info = OutputLevel::Info,
+ Debug = OutputLevel::Debug,
+ Verbose = OutputLevel::Verbose,
+ Ultra = OutputLevel::Ultra,
+ Input,
+ Command,
+ Hint
+ };
+
+ Shell(const std::string& consoleName, bool bScrollable);
+ ~Shell();
+
+ void setConfigValues();
+ void commandHistoryOffsetChanged();
+ void commandHistoryLengthChanged();
+
+ void registerListener(ShellListener* listener);
+ void unregisterListener(ShellListener* listener);
+
+ inline InputBuffer* getInputBuffer()
+ { return this->inputBuffer_; }
+
+ void setCursorPosition(unsigned int cursor);
+ inline unsigned int getCursorPosition() const
+ { return this->inputBuffer_->getCursorPosition(); }
+
+ inline const std::string& getInput() const
+ { return this->inputBuffer_->get(); }
+
+ typedef std::list<std::pair<std::string, LineType> > LineList;
+ LineList::const_iterator getNewestLineIterator() const;
+ LineList::const_iterator getEndIterator() const;
+
+ void addOutput(const std::string& text, LineType type = None);
+ void clearOutput();
+
+ inline unsigned int getNumLines() const
+ { return this->outputLines_.size(); }
+ inline unsigned int getScrollPosition() const
+ { return this->scrollPosition_; }
+
+ inline const std::string& getPromptPrefix() const { return this->promptPrefix_; }
+ void setPromptPrefix(const std::string& str);
+
+ private:
+ Shell(const Shell& other);
+
+ void addToHistory(const std::string& command);
+ const std::string& getFromHistory() const;
+ void clearInput();
+ // OutputListener
+ void outputChanged(int level);
+
+ void configureInputBuffer();
+
+ // InputBuffer callbacks
+ void inputChanged();
+ void execute();
+ void hintAndComplete();
+ void backspace();
+ void deleteChar();
+ void cursorRight();
+ void cursorLeft();
+ void cursorEnd();
+ void cursorHome();
+ void historyUp();
+ void historyDown();
+ void historySearchUp();
+ void historySearchDown();
+ void scrollUp();
+ void scrollDown();
+ void exit();
+
+ template <void (ShellListener::*F)()>
+ void updateListeners()
+ {
+ for (std::list<ShellListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+ ((*(it++))->*F)();
+ }
+
+ std::list<ShellListener*> listeners_;
+ InputBuffer* inputBuffer_;
+ std::stringstream outputBuffer_;
+ bool bFinishedLastLine_;
+ LineList outputLines_;
+ LineList::const_iterator scrollIterator_;
+ unsigned int scrollPosition_;
+ unsigned int historyPosition_;
+
+ std::string promptPrefix_;
+ const std::string consoleName_;
+ const bool bScrollable_;
+
+ // Config values
+ unsigned int maxHistoryLength_;
+ unsigned int historyOffset_;
+ std::vector<std::string> commandHistory_;
+ int softDebugLevel_;
+ };
+}
+
+#endif /* _Shell_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/TclBind.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/TclBind.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/TclBind.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/TclBind.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,198 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#include "TclBind.h"
+
+#include <exception>
+#include <string>
+#include <cpptcl/cpptcl.h>
+
+#include "SpecialConfig.h"
+#include "util/Debug.h"
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "CommandExecutor.h"
+#include "ConsoleCommand.h"
+#include "PathConfig.h"
+#include "TclThreadManager.h"
+
+namespace orxonox
+{
+ SetConsoleCommandShortcut(TclBind, tcl);
+ SetConsoleCommandShortcut(TclBind, bgerror);
+
+ TclBind* TclBind::singletonPtr_s = 0;
+
+ TclBind::TclBind(const std::string& datapath)
+ {
+ this->interpreter_ = 0;
+ this->bSetTclDataPath_ = false;
+ this->setDataPath(datapath);
+ }
+
+ TclBind::~TclBind()
+ {
+ if (this->interpreter_)
+ delete this->interpreter_;
+ }
+
+ void TclBind::setDataPath(const std::string& datapath)
+ {
+ // String has POSIX slashes
+ this->tclDataPath_ = datapath + "tcl" + '/';
+ this->bSetTclDataPath_ = true;
+
+ this->initializeTclInterpreter();
+ }
+
+ void TclBind::initializeTclInterpreter()
+ {
+ if (this->bSetTclDataPath_ && !this->interpreter_)
+ {
+ this->interpreter_ = this->createTclInterpreter();
+
+ this->interpreter_->def("::orxonox::query", TclBind::tcl_query, Tcl::variadic());
+ this->interpreter_->def("::orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
+ this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
+ this->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
+
+ try
+ {
+ this->interpreter_->eval("proc query {args} { ::orxonox::query $args }");
+ this->interpreter_->eval("proc crossquery {id args} { ::orxonox::crossquery 0 $id $args }");
+ this->interpreter_->eval("proc crossexecute {id args} { ::orxonox::crossquery 0 $id $args }");
+ this->interpreter_->eval("proc running {} { return 1 }");
+ this->interpreter_->eval("set id 0");
+ this->interpreter_->eval("rename exit ::tcl::exit; proc exit {} { execute exit }");
+ }
+ catch (Tcl::tcl_error const &e)
+ { COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl; }
+ }
+ }
+
+ Tcl::interpreter* TclBind::createTclInterpreter()
+ {
+ Tcl::interpreter* interpreter = new Tcl::interpreter();
+ const std::string& libpath = TclBind::getTclLibraryPath();
+
+ try
+ {
+ if (!libpath.empty())
+ interpreter->eval("set tcl_library \"" + libpath + '"');
+
+ Tcl_Init(interpreter->get());
+
+ interpreter->eval("source \"" + TclBind::getInstance().tclDataPath_ + "/init.tcl\"");
+ }
+ catch (Tcl::tcl_error const &e)
+ { COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl; COUT(1) << "Error: Tcl isn't properly initialized. Orxonox might possibly not work like that." << std::endl; }
+
+ return interpreter;
+ }
+
+ std::string TclBind::getTclLibraryPath()
+ {
+#ifdef DEPENDENCY_PACKAGE_ENABLE
+ if (PathConfig::isDevelopmentRun())
+ return (std::string(specialConfig::dependencyLibraryDirectory) + "/tcl");
+ else
+ return (PathConfig::getRootPathString() + "lib/tcl");
+#else
+ return "";
+#endif
+ }
+
+ std::string TclBind::tcl_query(Tcl::object const &args)
+ {
+ COUT(4) << "Tcl_query: " << args.get() << std::endl;
+
+ const std::string& command = stripEnclosingBraces(args.get());
+
+ bool success;
+ const std::string& result = CommandExecutor::query(command, &success, false);
+ if (!success)
+ {
+ COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
+ }
+
+ return result;
+ }
+
+ void TclBind::tcl_execute(Tcl::object const &args)
+ {
+ COUT(4) << "Tcl_execute: " << args.get() << std::endl;
+ const std::string& command = stripEnclosingBraces(args.get());
+
+ if (!CommandExecutor::execute(command, false))
+ {
+ COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
+ }
+ }
+
+ std::string TclBind::tcl(const std::string& tclcode)
+ {
+ if (TclBind::getInstance().interpreter_)
+ {
+ try
+ {
+ const std::string& output = TclBind::getInstance().interpreter_->eval("uplevel #0 " + tclcode);
+ if (!output.empty())
+ {
+ COUT(0) << "tcl> " << output << std::endl;
+ }
+ return output;
+ }
+ catch (Tcl::tcl_error const &e)
+ { COUT(1) << "tcl> Error: " << e.what() << std::endl; }
+ }
+
+ return "";
+ }
+
+ void TclBind::bgerror(const std::string& error)
+ {
+ COUT(1) << "Tcl background error: " << stripEnclosingBraces(error) << std::endl;
+ }
+
+ std::string TclBind::eval(const std::string& tclcode, bool* success)
+ {
+ if (success)
+ *success = true;
+
+ try
+ {
+ return TclBind::getInstance().interpreter_->eval(tclcode);
+ }
+ catch (Tcl::tcl_error const &e)
+ { COUT(1) << "Tcl error: " << e.what() << std::endl; }
+
+ if (success)
+ *success = false;
+ return "";
+ }
+}
Copied: code/branches/consolecommands3/src/libraries/core/command/TclBind.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/TclBind.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/TclBind.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/TclBind.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,74 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _TclBind_H__
+#define _TclBind_H__
+
+#include "CorePrereqs.h"
+
+#include <cassert>
+#include <string>
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+ class _CoreExport TclBind : public Singleton<TclBind>
+ {
+ friend class Singleton<TclBind>;
+ public:
+ TclBind(const std::string& datapath);
+ ~TclBind();
+
+ static std::string tcl(const std::string& tclcode);
+ static void bgerror(const std::string& error);
+
+ void setDataPath(const std::string& datapath);
+ const std::string& getTclDataPath() const { return this->tclDataPath_; }
+ static std::string getTclLibraryPath();
+
+ void initializeTclInterpreter();
+ static Tcl::interpreter* createTclInterpreter();
+ Tcl::interpreter* getTclInterpreter() const { return this->interpreter_; }
+
+ static std::string tcl_query(Tcl::object const &args);
+ static void tcl_execute(Tcl::object const &args);
+
+ static std::string eval(const std::string& tclcode, bool* success = 0);
+
+ private:
+ TclBind(const TclBind& other);
+
+ Tcl::interpreter* interpreter_;
+ std::string tclDataPath_;
+ bool bSetTclDataPath_;
+
+ static TclBind* singletonPtr_s;
+ };
+}
+
+#endif /* _TclBind_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/TclThreadList.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/TclThreadList.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/TclThreadList.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/TclThreadList.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,263 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _TclThreadList_H__
+#define _TclThreadList_H__
+
+#include "CorePrereqs.h"
+
+#include <list>
+
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
+
+namespace orxonox
+{
+ template <class T>
+ class TclThreadList
+ {
+ public:
+ void push_front(const T& value);
+ void push_back(const T& value);
+ template <class InputIterator> void insert(typename std::list<T>::iterator position, InputIterator begin, InputIterator end);
+
+ void wait_and_pop_front(T* value);
+ void wait_and_pop_back(T* value);
+ bool try_pop_front(T* value);
+ bool try_pop_back(T* value);
+ void clear();
+
+ size_t size() const;
+ bool empty() const;
+ bool is_in(const T& value) const;
+
+ /**
+ @brief Returns a reference to the list. Don't forget to lock the mutex (see @ref getMutex).
+ */
+ inline std::list<T>& getList()
+ { return this->list_; }
+
+ /**
+ @brief Returns a reference to the list. Don't forget to lock the mutex (see @ref getMutex).
+ */
+ inline const std::list<T>& getList() const
+ { return this->list_; }
+
+ /**
+ @brief Returns a reference to the mutex which might be useful if you want to iterate through the list (see @ref begin and @ref end).
+ */
+ inline boost::shared_mutex& getMutex() const
+ { return this->mutex_; }
+
+ private:
+ std::list<T> list_; ///< A standard list for type T
+ mutable boost::shared_mutex mutex_; ///< A mutex to grant exclusive access to the list
+ boost::condition_variable_any condition_; ///< A condition variable to wake threads waiting for the mutex to become ready
+ };
+
+ /**
+ @brief Pushes a new element to the front of the list. A unique_lock is needed.
+ */
+ template <class T>
+ void TclThreadList<T>::push_front(const T& value)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+ this->list_.push_front(value);
+ lock.unlock(); // unlock the mutex...
+ this->condition_.notify_all(); // ...then call notify_all to wake threads waiting in wait_and_pop_front/back
+ }
+
+ /**
+ @brief Pushes a new element to the back of the list. A unique_lock is needed.
+ */
+ template <class T>
+ void TclThreadList<T>::push_back(const T& value)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+ this->list_.push_back(value);
+ lock.unlock(); // unlock the mutex...
+ this->condition_.notify_all(); // ...then call notify_all to wake threads waiting in wait_and_pop_front/back
+ }
+
+ /**
+ @brief Inserts new elements into the list. A unique_lock is needed.
+ */
+ template <class T>
+ template <class InputIterator> void TclThreadList<T>::insert(typename std::list<T>::iterator position, InputIterator begin, InputIterator end)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+ this->list_.insert(position, begin, end);
+ lock.unlock(); // unlock the mutex...
+ this->condition_.notify_all(); // ...then call notify_all to wake threads waiting in wait_and_pop_front/back
+ }
+
+ /**
+ @brief Waits until the list contains at least one element and then pops and returns the front element.
+ @param value The front value will be stored in the variable referenced by this pointer.
+ */
+ template <class T>
+ void TclThreadList<T>::wait_and_pop_front(T* value)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+
+ while (this->list_.empty()) // check if there's an element in the list
+ this->condition_.wait(lock); // wait until the condition becomes true (a notification comes from push_front, push_back or insert
+
+ *value = this->list_.front();
+ this->list_.pop_front();
+ }
+
+ /**
+ @brief Waits until the list contains at least one element and then pops and returns the back element.
+ @param value The back value will be stored in the variable referenced by this pointer.
+ */
+ template <class T>
+ void TclThreadList<T>::wait_and_pop_back(T* value)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+
+ while (this->list_.empty()) // check if there's an element in the list
+ this->condition_.wait(lock); // wait until the condition becomes true (a notification comes from push_front, push_back or insert
+
+ *value = this->list_.back();
+ this->list_.pop_back();
+ }
+
+ /**
+ @brief Pops and returns the front element if there's at least one element in the list.
+ @param value The front value will be stored in the variable referenced by this pointer.
+ @return Returns true if there was at least one element in the list (which got poped). If the list was empty, false is returned immediately.
+
+ Needs a unique_lock if there's an element to pop. If not, shared_lock is sufficient.
+ */
+ template <class T>
+ bool TclThreadList<T>::try_pop_front(T* value)
+ {
+ boost::upgrade_lock<boost::shared_mutex> lock(this->mutex_); // gain shared lock
+
+ if (this->list_.empty())
+ {
+ // No elements - return immediately
+ return false;
+ }
+ else
+ {
+ // At least one element - write it into the passed variable and pop it from the list
+ boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); // upgrade to unique lock to modify the list
+ *value = this->list_.front();
+ this->list_.pop_front();
+ }
+ return true;
+ }
+
+ /**
+ @brief Pops and returns the back element if there's at least one element in the list.
+ @param value The back value will be stored in the variable referenced by this pointer.
+ @return Returns true if there was at least one element in the list (which got poped). If the list was empty, false is returned immediately.
+
+ Needs a unique_lock if there's an element to pop. If not, shared_lock is sufficient.
+ */
+ template <class T>
+ bool TclThreadList<T>::try_pop_back(T* value)
+ {
+ boost::upgrade_lock<boost::shared_mutex> lock(this->mutex_); // gain shared lock
+
+ if (this->list_.empty())
+ {
+ // No elements - return immediately
+ return false;
+ }
+ else
+ {
+ // At least one element - write it into the passed variable and pop it from the list
+ boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); // upgrade to unique lock to modify the list
+ *value = this->list_.back();
+ this->list_.pop_back();
+ }
+ return true;
+ }
+
+ /**
+ @brief Clears the list. A unique_lock is needed.
+ */
+ template <class T>
+ void TclThreadList<T>::clear()
+ {
+ boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+ this->list_.clear();
+ }
+
+ /**
+ @brief Returns the size of the list. A shared_lock is needed.
+
+ Warning: Don't change the list based on the result of size(). Use an atomic function instead. Other threads may change the list
+ beween your call to size() and your further actions, so be careful and use this function only if you really want nothing else than
+ just the size of the list.
+ */
+ template <class T>
+ size_t TclThreadList<T>::size() const
+ {
+ boost::shared_lock<boost::shared_mutex> lock(this->mutex_);
+ return this->list_.size();
+ }
+
+ /**
+ @brief Returns true if the list is empty, false otherwise. A shared_lock is needed.
+
+ Warning: Don't change the list based on the result of empty(). Use an atomic function instead. Other threads may change the list
+ beween your call to empty() and your further actions, so be careful and use this function only if you really want nothing else than
+ just if the list is empty or not.
+ */
+ template <class T>
+ bool TclThreadList<T>::empty() const
+ {
+ boost::shared_lock<boost::shared_mutex> lock(this->mutex_);
+ return this->list_.empty();
+ }
+
+ /**
+ @brief Returns true if a given element is in the list, false otherwise. A shared_lock is needed.
+
+ Warning: The result of this function might be wrong just one instruction after the call. Use this function just to get information
+ about a temporary snapshot and don't change the list based on the result of this function.
+ */
+ template <class T>
+ bool TclThreadList<T>::is_in(const T& value) const
+ {
+ boost::shared_lock<boost::shared_mutex> lock(this->mutex_);
+
+ for (typename std::list<T>::const_iterator it = this->list_.begin(); it != this->list_.end(); ++it)
+ if (*it == value)
+ return true;
+
+ return false;
+ }
+}
+
+#endif /* _TclThreadList_H__ */
Copied: code/branches/consolecommands3/src/libraries/core/command/TclThreadManager.cc (from rev 7201, code/branches/consolecommands3/src/libraries/core/TclThreadManager.cc)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/TclThreadManager.cc (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/TclThreadManager.cc 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,669 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#include "TclThreadManager.h"
+
+#include <boost/bind.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <OgreTimer.h>
+#include <cpptcl/cpptcl.h>
+
+#include "util/Clock.h"
+#include "util/Convert.h"
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "CommandExecutor.h"
+#include "ConsoleCommand.h"
+#include "CoreIncludes.h"
+#include "TclBind.h"
+#include "TclThreadList.h"
+
+namespace orxonox
+{
+ const float TCLTHREADMANAGER_MAX_CPU_USAGE = 0.50f;
+
+ SetConsoleCommandShortcutAlias(TclThreadManager, execute, "tclexecute").argumentCompleter(0, autocompletion::tclthreads());
+ SetConsoleCommandShortcutAlias(TclThreadManager, query, "tclquery" ).argumentCompleter(0, autocompletion::tclthreads());
+ SetConsoleCommand(TclThreadManager, create, false);
+ SetConsoleCommand(TclThreadManager, destroy, false).argumentCompleter(0, autocompletion::tclthreads());
+ SetConsoleCommand(TclThreadManager, execute, false).argumentCompleter(0, autocompletion::tclthreads());
+ SetConsoleCommand(TclThreadManager, query, false).argumentCompleter(0, autocompletion::tclthreads());
+ SetConsoleCommand(TclThreadManager, source, false).argumentCompleter(0, autocompletion::tclthreads());
+
+ /**
+ @brief A struct containing all information about a Tcl-interpreter
+ */
+ struct TclInterpreterBundle
+ {
+ TclInterpreterBundle()
+ {
+ this->lock_ = new boost::unique_lock<boost::mutex>(this->mutex_, boost::defer_lock);
+ this->bRunning_ = true;
+ }
+
+ ~TclInterpreterBundle()
+ {
+ delete this->lock_;
+ }
+
+ unsigned int id_; ///< The id of the interpreter
+ Tcl::interpreter* interpreter_; ///< The Tcl-interpreter
+ boost::mutex mutex_; ///< A mutex to lock the interpreter while it's being used
+ boost::unique_lock<boost::mutex>* lock_; ///< The corresponding lock for the mutex
+ TclThreadList<std::string> queue_; ///< The command queue for commands passed by execute(command)
+ TclThreadList<unsigned int> queriers_; ///< A list containing the id's of all other threads sending a query to this interpreter (to avoid circular queries and deadlocks)
+ bool bRunning_; ///< This variable stays true until destroy() gets called
+ };
+
+ TclThreadManager* TclThreadManager::singletonPtr_s = 0;
+
+ /**
+ @brief Constructor
+ @param interpreter A pointer to the standard Tcl-interpreter (see @ref TclBind)
+ */
+ TclThreadManager::TclThreadManager(Tcl::interpreter* interpreter)
+ {
+ RegisterRootObject(TclThreadManager);
+
+ this->numInterpreterBundles_ = 0;
+
+ this->interpreterBundlesMutex_ = new boost::shared_mutex();
+ this->mainInterpreterMutex_ = new boost::mutex();
+ this->messageQueue_ = new TclThreadList<std::string>();
+
+ TclInterpreterBundle* newbundle = new TclInterpreterBundle();
+ newbundle->id_ = 0;
+ newbundle->interpreter_ = interpreter;
+ newbundle->lock_->lock();
+
+ {
+ boost::unique_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
+ this->interpreterBundles_[0] = newbundle;
+ }
+ }
+
+ /**
+ @brief Destructor
+ */
+ TclThreadManager::~TclThreadManager()
+ {
+ delete this->interpreterBundlesMutex_;
+// delete this->mainInterpreterMutex_; // <-- temporary disabled to avoid crash if a thread is still actively queriyng
+ delete this->messageQueue_;
+ }
+
+ /**
+ @brief The "main loop" of the TclThreadManager. Creates new threads if needed and handles queries and queued commands for the main interpreter.
+ */
+ void TclThreadManager::preUpdate(const Clock& time)
+ {
+ // Get the bundle of the main interpreter (0)
+ TclInterpreterBundle* bundle = this->getInterpreterBundle(0);
+ if (bundle)
+ {
+ // Unlock the mutex to allow other threads accessing the main interpreter
+ bundle->lock_->unlock();
+
+ // Lock the main interpreter mutex once to synchronize with threads that want to query the main interpreter
+ {
+ boost::unique_lock<boost::mutex> lock(*this->mainInterpreterMutex_);
+ }
+
+ // Lock the mutex again to gain exclusive access to the interpreter for the rest of the mainloop
+ bundle->lock_->lock();
+
+ // Execute commands in the queues of the threaded interpreters
+ {
+ boost::shared_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
+ for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
+ {
+ if (it->first == 0)
+ continue; // We'll handle the default interpreter later (and without threads of course)
+
+ TclInterpreterBundle* bundle = it->second;
+ if (!bundle->queue_.empty())
+ {
+ // There are commands in the queue
+ try
+ {
+ if (!bundle->lock_->owns_lock() && bundle->lock_->try_lock())
+ {
+ // We sucessfully obtained a lock for the interpreter
+ std::string command;
+ if (bundle->queue_.try_pop_front(&command))
+ {
+ // Start a thread to execute the command
+ boost::thread(boost::bind(&tclThread, bundle, command));
+ }
+ else
+ {
+ // Somehow the queue become empty (maybe multiple consumers) - unlock the mutex
+ bundle->lock_->unlock();
+ }
+ }
+ }
+ catch (...)
+ {
+ // A lock error occurred - this is possible if the lock gets locked between !bundle->lock_->owns_lock() and bundle->lock_->try_lock()
+ // This isn't too bad, just continue
+ }
+ }
+ }
+ }
+
+ // Execute commands in the message queue
+ if (!this->messageQueue_->empty())
+ {
+ std::string command;
+ while (true)
+ {
+ // Pop the front value from the list (break the loop if there are no elements in the list)
+ if (!this->messageQueue_->try_pop_front(&command))
+ break;
+
+ // Execute the command
+ CommandExecutor::execute(command, false);
+ }
+ }
+
+ // Execute commands in the queue of the main interpreter
+ if (!bundle->queue_.empty())
+ {
+ // Calculate the time we have until we reach the maximal cpu usage
+ unsigned long maxtime = (unsigned long)(time.getDeltaTime() * 1000000 * TCLTHREADMANAGER_MAX_CPU_USAGE);
+
+ Ogre::Timer timer;
+ std::string command;
+
+ while (timer.getMicroseconds() < maxtime)
+ {
+ // Pop the front value from the list (break the loop if there are no elements in the list)
+ if (!bundle->queue_.try_pop_front(&command))
+ break;
+
+ // Execute the command
+ CommandExecutor::execute(command, false);
+ }
+ }
+ }
+ }
+
+ /**
+ @brief Creates a new Tcl-interpreter.
+ */
+ unsigned int TclThreadManager::create()
+ {
+ TclThreadManager::getInstance().numInterpreterBundles_++;
+ TclThreadManager::createWithId(TclThreadManager::getInstance().numInterpreterBundles_);
+ COUT(0) << "Created new Tcl-interpreter with ID " << TclThreadManager::getInstance().numInterpreterBundles_ << std::endl;
+ return TclThreadManager::getInstance().numInterpreterBundles_;
+ }
+
+ /**
+ @brief Creates a new Tcl-interpreter with a given id.
+
+ Use with caution - if the id collides with an already existing interpreter, this call will fail.
+ This will also be a problem, if the auto-numbered interpreters (by using create()) reach an id
+ which was previously used in this function. Use high numbers to be safe.
+ */
+ Tcl::interpreter* TclThreadManager::createWithId(unsigned int id)
+ {
+ TclInterpreterBundle* newbundle = new TclInterpreterBundle();
+ newbundle->id_ = id;
+ newbundle->interpreter_ = TclBind::createTclInterpreter();
+
+ TclThreadManager::initialize(newbundle);
+
+ {
+ // Add the new bundle to the map
+ boost::unique_lock<boost::shared_mutex> lock(*TclThreadManager::getInstance().interpreterBundlesMutex_);
+ TclThreadManager::getInstance().interpreterBundles_[id] = newbundle;
+ }
+
+ return newbundle->interpreter_;
+ }
+
+ void TclThreadManager::initialize(TclInterpreterBundle* bundle)
+ {
+ const std::string& id_string = getConvertedValue<unsigned int, std::string>(bundle->id_);
+
+ // Initialize the new interpreter
+ try
+ {
+ // Define the functions which are implemented in C++
+ bundle->interpreter_->def("::orxonox::execute", TclThreadManager::tcl_execute, Tcl::variadic());
+ bundle->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
+ bundle->interpreter_->def("::orxonox::query", TclThreadManager::tcl_query, Tcl::variadic());
+ bundle->interpreter_->def("::orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
+ bundle->interpreter_->def("::orxonox::running", TclThreadManager::tcl_running);
+
+ // Create threadspecific shortcuts for the functions above
+ bundle->interpreter_->def("execute", TclThreadManager::tcl_execute, Tcl::variadic());
+ bundle->interpreter_->def("crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
+ bundle->interpreter_->eval("proc query {args} { ::orxonox::query " + id_string + " $args }");
+ bundle->interpreter_->eval("proc crossquery {id args} { ::orxonox::crossquery " + id_string + " $id $args }");
+ bundle->interpreter_->eval("proc running {} { return [::orxonox::running " + id_string + "] }");
+
+ // Define a variable containing the thread id
+ bundle->interpreter_->eval("set id " + id_string);
+
+ // Use our own exit function to avoid shutting down the whole program instead of just the interpreter
+ bundle->interpreter_->eval("rename exit ::tcl::exit");
+ bundle->interpreter_->eval("proc exit {} { execute TclThreadManager destroy " + id_string + " }");
+
+ // Redefine some native functions
+ bundle->interpreter_->eval("rename while ::tcl::while");
+ bundle->interpreter_->eval("rename ::orxonox::while while");
+ bundle->interpreter_->eval("rename for ::tcl::for");
+ bundle->interpreter_->eval("rename ::orxonox::for for");
+ }
+ catch (const Tcl::tcl_error& e)
+ { bundle->interpreter_ = 0; COUT(1) << "Tcl error while creating Tcl-interpreter (" << id_string << "): " << e.what() << std::endl; }
+ }
+
+ /**
+ @brief Stops and destroys a given Tcl-interpreter
+ */
+ void TclThreadManager::destroy(unsigned int id)
+ {
+ // TODO
+ // Not yet implemented
+ TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(id);
+ if (bundle)
+ {
+ bundle->bRunning_ = false;
+ }
+ }
+
+ /**
+ @brief Sends a command to the queue of a given Tcl-interpreter
+ @param id The id of the target interpreter
+ @param command The command to be sent
+ */
+ void TclThreadManager::execute(unsigned int target_id, const std::string& command)
+ {
+ TclThreadManager::getInstance()._execute(target_id, command);
+ }
+
+ /**
+ @brief This function can be called from Tcl to execute a console command.
+
+ Commands which shall be executed are put into a queue and processed as soon as the
+ main thread feels ready to do so. The queue may also be full which results in a temporary
+ suspension of the calling thread until the queue gets ready again.
+ */
+ void TclThreadManager::tcl_execute(const Tcl::object& args)
+ {
+ TclThreadManager::getInstance()._execute(0, stripEnclosingBraces(args.get()));
+ }
+
+ /**
+ @brief This function can be called from Tcl to send a command to the queue of any interpreter.
+ @param target_id The id of the target thread
+ */
+ void TclThreadManager::tcl_crossexecute(int target_id, const Tcl::object& args)
+ {
+ TclThreadManager::getInstance()._execute(static_cast<unsigned int>(target_id), stripEnclosingBraces(args.get()));
+ }
+
+ /**
+ @brief Sends a command to the queue of a given Tcl-interpreter
+ @param id The id of the target interpreter
+ @param command The command to be sent
+ */
+ void TclThreadManager::_execute(unsigned int target_id, const std::string& command)
+ {
+ TclInterpreterBundle* bundle = this->getInterpreterBundle(target_id);
+ if (bundle)
+ bundle->queue_.push_back(command);
+ }
+
+
+ /**
+ @brief Sends a query to a given Tcl-interpreter and waits for the result
+ @param id The id of the target interpreter
+ @param command The command to be sent
+ @return The result of the command
+ */
+ std::string TclThreadManager::query(unsigned int target_id, const std::string& command)
+ {
+ return TclThreadManager::getInstance()._query(0, target_id, command);
+ }
+
+ /**
+ @brief This function can be called from Tcl to send a query to the main thread.
+ @param source_id The id of the calling thread
+
+ A query waits for the result of the command. This means, the calling thread will be blocked until
+ the main thread answers the query. In return, the main thread sends the result of the console
+ command back to Tcl.
+ */
+ std::string TclThreadManager::tcl_query(int source_id, const Tcl::object& args)
+ {
+ return TclThreadManager::getInstance()._query(static_cast<unsigned int>(source_id), 0, stripEnclosingBraces(args.get()), true);
+ }
+
+ /**
+ @brief This function can be called from Tcl to send a query to another thread.
+ @param source_id The id of the calling thread
+ @param target_id The id of the target thread
+ */
+ std::string TclThreadManager::tcl_crossquery(int source_id, int target_id, const Tcl::object& args)
+ {
+ return TclThreadManager::getInstance()._query(static_cast<unsigned int>(source_id), static_cast<unsigned int>(target_id), stripEnclosingBraces(args.get()));
+ }
+
+ /**
+ @brief This function performs a query to any Tcl interpreter
+ @param source_id The id of the calling thread
+ @param target_id The id of the target thread
+ @param command The command to send as a query
+ @param bUseCommandExecutor Only used if the target_id is 0 (which references the main interpreter). In this case it means if the command should be passed to the CommandExecutor (true) or to the main Tcl interpreter (false). This is true when called by tcl_query and false when called by tcl_crossquery.
+ */
+ std::string TclThreadManager::_query(unsigned int source_id, unsigned int target_id, const std::string& command, bool bUseCommandExecutor)
+ {
+ TclInterpreterBundle* source_bundle = this->getInterpreterBundle(source_id);
+ TclInterpreterBundle* target_bundle = this->getInterpreterBundle(target_id);
+ std::string output;
+
+ if (source_bundle && target_bundle)
+ {
+ // At this point we assume the mutex of source_bundle to be locked (because it's executing this query right now an waits for the return value)
+ // We can safely use it's querier list (because there's no other place in the code using the list except this query - and the interpreter can't start more than one query)
+
+ if ((source_bundle->id_ == target_bundle->id_) || source_bundle->queriers_.is_in(target_bundle->id_))
+ {
+ // This query would lead to a deadlock - return with an error
+ TclThreadManager::error("Error: Circular query (" + this->dumpList(source_bundle->queriers_.getList()) + ' ' + getConvertedValue<unsigned int, std::string>(source_bundle->id_) \
+ + " -> " + getConvertedValue<unsigned int, std::string>(target_bundle->id_) \
+ + "), couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target_bundle->id_) \
+ + " from other interpreter with ID " + getConvertedValue<unsigned int, std::string>(source_bundle->id_) + '.');
+ }
+ else
+ {
+ boost::unique_lock<boost::mutex> lock(target_bundle->mutex_, boost::try_to_lock);
+ boost::unique_lock<boost::mutex> mainlock(*this->mainInterpreterMutex_, boost::defer_lock);
+
+ if (!lock.owns_lock() && source_bundle->id_ != 0)
+ {
+ // We couldn't obtain the try_lock immediately and we're not the main interpreter - wait until the lock becomes possible (note: the main interpreter won't wait and instead returns an error - see below)
+ if (target_bundle->id_ == 0)
+ {
+ // We're querying the main interpreter - use the main interpreter mutex to synchronize
+ mainlock.lock();
+ lock.lock();
+ }
+ else
+ {
+ // We're querying a threaded interpreter - no synchronization needed
+ lock.lock();
+ }
+ }
+
+ if (lock.owns_lock())
+ {
+ // Now the mutex of target_bundle is also locked an we can update the querier list
+ target_bundle->queriers_.insert(target_bundle->queriers_.getList().begin(), source_bundle->queriers_.getList().begin(), source_bundle->queriers_.getList().end());
+ target_bundle->queriers_.push_back(source_bundle->id_);
+
+ // Perform the query (note: this happens in the main thread because we need the returnvalue)
+ if (target_bundle->id_ == 0 && bUseCommandExecutor)
+ {
+ // It's a query to the CommandExecutor
+ TclThreadManager::debug("TclThread_query -> CE: " + command);
+ bool success;
+ output = CommandExecutor::query(command, &success, false);
+ if (!success)
+ TclThreadManager::error("Error: Can't execute command \"" + command + "\"!");
+ }
+ else
+ {
+ // It's a query to a Tcl interpreter
+ TclThreadManager::debug("TclThread_query: " + command);
+
+ output = TclThreadManager::eval(target_bundle, command, "query");
+ }
+
+ // Clear the queriers list of the target
+ target_bundle->queriers_.clear();
+
+ // Unlock the mutex of the target_bundle
+ lock.unlock();
+
+ // Finally unlock the main interpreter lock if necessary
+ if (mainlock.owns_lock())
+ mainlock.unlock();
+ }
+ else
+ {
+ // This happens if the main thread tries to query a busy interpreter
+ // To avoid a lock of the main thread, we simply don't proceed with the query in this case
+ TclThreadManager::error("Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target_bundle->id_) + ", interpreter is busy right now.");
+ }
+ }
+
+ }
+
+ return output;
+ }
+
+ /**
+ @brief Creates a non-interactive Tcl-interpreter which executes a file.
+ */
+ void TclThreadManager::source(const std::string& file)
+ {
+ boost::thread(boost::bind(&sourceThread, file));
+ }
+
+ /**
+ @brief This function can be called from Tcl to ask if the thread is still suposed to be running.
+ @param id The id of the thread in question
+ */
+ bool TclThreadManager::tcl_running(int id)
+ {
+ TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(static_cast<unsigned int>(id));
+ if (bundle)
+ return bundle->bRunning_;
+ else
+ return false;
+ }
+
+ /**
+ @brief Returns the interpreter bundle with the given id.
+ @param id The id of the interpreter
+ @return The interpreter or 0 if the id doesn't exist
+ */
+ TclInterpreterBundle* TclThreadManager::getInterpreterBundle(unsigned int id)
+ {
+ boost::shared_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
+
+ std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = this->interpreterBundles_.find(id);
+ if (it != this->interpreterBundles_.end())
+ {
+ return it->second;
+ }
+ else
+ {
+ TclThreadManager::error("Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(id) + " existing.");
+ return 0;
+ }
+ }
+
+ /**
+ @brief Returns a string containing all elements of a unsigned-integer-list separated by spaces.
+ */
+ std::string TclThreadManager::dumpList(const std::list<unsigned int>& list)
+ {
+ std::string output;
+ for (std::list<unsigned int>::const_iterator it = list.begin(); it != list.end(); ++it)
+ {
+ if (it != list.begin())
+ output += ' ';
+
+ output += getConvertedValue<unsigned int, std::string>(*it);
+ }
+ return output;
+ }
+
+ /**
+ @brief Returns a list with the numbers of all existing Tcl-interpreters.
+
+ This function is used by the auto completion function.
+ */
+ std::list<unsigned int> TclThreadManager::getThreadList() const
+ {
+ boost::shared_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
+
+ std::list<unsigned int> threads;
+ for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
+ if (it->first > 0 && it->first <= this->numInterpreterBundles_) // only list autonumbered interpreters (created with create()) - exclude the default interpreter 0 and all manually numbered interpreters)
+ threads.push_back(it->first);
+ return threads;
+ }
+
+ /**
+ @brief A helper function to print errors in a thread safe manner.
+ */
+ void TclThreadManager::error(const std::string& error)
+ {
+ TclThreadManager::getInstance().messageQueue_->push_back("error " + error);
+ }
+
+ /**
+ @brief A helper function to print debug information in a thread safe manner.
+ */
+ void TclThreadManager::debug(const std::string& error)
+ {
+ TclThreadManager::getInstance().messageQueue_->push_back("debug " + error);
+ }
+
+ /**
+ @brief Evaluates a Tcl command without throwing exceptions (which may rise problems on certain machines).
+ @return The Tcl return value
+
+ Errors are reported through the @ref error function.
+ */
+ std::string TclThreadManager::eval(TclInterpreterBundle* bundle, const std::string& command, const std::string& action)
+ {
+ Tcl_Interp* interpreter = bundle->interpreter_->get();
+ int cc = Tcl_Eval(interpreter, command.c_str());
+
+ Tcl::details::result result(interpreter);
+
+ if (cc != TCL_OK)
+ {
+ TclThreadManager::error("Tcl error (" + action + ", ID " + getConvertedValue<unsigned int, std::string>(bundle->id_) + "): " + static_cast<std::string>(result));
+ return "";
+ }
+ else
+ {
+ return result;
+ }
+ }
+
+ ////////////////
+ // The Thread //
+ ////////////////
+
+ /**
+ @brief The main function of the thread. Executes a Tcl command.
+ @param bundle The interpreter bundle containing all necessary variables
+ @param command the Command to execute
+ */
+ void tclThread(TclInterpreterBundle* bundle, const std::string& command)
+ {
+ TclThreadManager::debug("TclThread_execute: " + command);
+
+ TclThreadManager::eval(bundle, command, "execute");
+
+ bundle->lock_->unlock();
+ }
+
+ /**
+ @brief The main function of a non-interactive source thread. Executes the file.
+ @param file The name of the file that should be executed by the non-interactive interpreter.
+ */
+ void sourceThread(const std::string& file)
+ {
+ TclThreadManager::debug("TclThread_source: " + file);
+
+ // Prepare the command-line arguments
+ const int argc = 2;
+ char* argv[argc];
+ argv[0] = const_cast<char*>("tclthread");
+ argv[1] = const_cast<char*>(file.c_str());
+
+ // Start the Tcl-command Tcl_Main with the Tcl_OrxonoxAppInit hook
+ Tcl_Main(argc, argv, Tcl_OrxonoxAppInit);
+
+// Tcl::object object(file);
+// int cc = Tcl_FSEvalFile(bundle->interpreter_->get(), object.get_object());
+// Tcl::details::result result(bundle->interpreter_->get());
+// if (cc != TCL_OK)
+// TclThreadManager::error("Tcl error (source, ID " + getConvertedValue<unsigned int, std::string>(bundle->id_) + "): " + static_cast<std::string>(result));
+//
+// // Unlock the mutex
+// bundle->lock_->unlock();
+ }
+
+ /**
+ @brief A tcl-init hook to inject the non-interactive Tcl-interpreter into the TclThreadManager.
+ */
+ int Tcl_OrxonoxAppInit(Tcl_Interp* interp)
+ {
+ // Create a new interpreter bundle
+ unsigned int id = TclThreadManager::create();
+ TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(id);
+
+ // Replace the default interpreter in the bundle with the non-interactive one (passed as an argument to this function)
+ if (bundle->interpreter_)
+ delete bundle->interpreter_;
+ bundle->interpreter_ = new Tcl::interpreter(interp, true);
+
+ // Initialize the non-interactive interpreter (like in @ref TclBind::createTclInterpreter but exception safe)
+ const std::string& libpath = TclBind::getTclLibraryPath();
+ if (!libpath.empty())
+ TclThreadManager::eval(bundle, "set tcl_library \"" + libpath + '"', "source");
+ int cc = Tcl_Init(interp);
+ TclThreadManager::eval(bundle, "source \"" + TclBind::getInstance().getTclDataPath() + "/init.tcl\"", "source");
+
+ // Initialize the non-interactive interpreter also with the thread-specific stuff
+ TclThreadManager::initialize(bundle);
+
+ // Lock the mutex (this will be locked until the thread finishes - no chance to interact with the interpreter)
+ bundle->lock_->lock();
+
+ // Return to Tcl_Main
+ if (!bundle->interpreter_)
+ return TCL_ERROR;
+ else
+ return cc;
+ }
+}
Copied: code/branches/consolecommands3/src/libraries/core/command/TclThreadManager.h (from rev 7201, code/branches/consolecommands3/src/libraries/core/TclThreadManager.h)
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/TclThreadManager.h (rev 0)
+++ code/branches/consolecommands3/src/libraries/core/command/TclThreadManager.h 2010-08-22 22:54:08 UTC (rev 7202)
@@ -0,0 +1,102 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Fabian 'x3n' Landau
+ * Co-authors:
+ * ...
+ *
+ */
+
+#ifndef _TclThreadManager_H__
+#define _TclThreadManager_H__
+
+#include "CorePrereqs.h"
+
+#include <cassert>
+#include <list>
+#include <map>
+#include <string>
+
+#include "util/Singleton.h"
+#include "OrxonoxClass.h"
+
+struct Tcl_Interp;
+
+namespace orxonox
+{
+ class _CoreExport TclThreadManager : public Singleton<TclThreadManager>, public OrxonoxClass
+ {
+ friend class Singleton<TclThreadManager>;
+ friend class TclBind;
+ friend _CoreExport void tclThread(TclInterpreterBundle* bundle, const std::string& command);
+ friend _CoreExport void sourceThread(const std::string& file);
+ friend _CoreExport int Tcl_OrxonoxAppInit(Tcl_Interp* interp);
+
+ public:
+ TclThreadManager(Tcl::interpreter* interpreter);
+ virtual ~TclThreadManager();
+
+ static unsigned int create();
+ static Tcl::interpreter* createWithId(unsigned int id);
+ static void destroy(unsigned int id);
+ static void execute(unsigned int target_id, const std::string& command);
+ static std::string query(unsigned int target_id, const std::string& command);
+ static void source(const std::string& file);
+
+ static void error(const std::string& error);
+ static void debug(const std::string& error);
+
+ void preUpdate(const Clock& time);
+
+ std::list<unsigned int> getThreadList() const;
+
+ private:
+ static void tcl_execute(const Tcl::object& args);
+ static void tcl_crossexecute(int target_id, const Tcl::object& args);
+ static std::string tcl_query(int source_id, const Tcl::object& args);
+ static std::string tcl_crossquery(int source_id, int target_id, const Tcl::object& args);
+ static bool tcl_running(int id);
+
+ void _execute(unsigned int target_id, const std::string& command);
+ std::string _query(unsigned int source_id, unsigned int target_id, const std::string& command, bool bUseCommandExecutor = false);
+
+ TclInterpreterBundle* getInterpreterBundle(unsigned int id);
+ std::string dumpList(const std::list<unsigned int>& list);
+
+ static void initialize(TclInterpreterBundle* bundle);
+ static std::string eval(TclInterpreterBundle* bundle, const std::string& command, const std::string& action);
+
+ static TclThreadManager* singletonPtr_s; ///< Singleton pointer
+
+ unsigned int numInterpreterBundles_; ///< Number of created Tcl-interpreters (only used for auto-numbered interpreters, not affected by @ref createWithId)
+ std::map<unsigned int, TclInterpreterBundle*> interpreterBundles_; ///< A map containing all Tcl-interpreters
+ boost::shared_mutex* interpreterBundlesMutex_; ///< A mutex used to synchronize threads when accessing @ref interpreterBundles_
+ TclThreadList<std::string>* messageQueue_; ///< A queue to pass messages from Tcl-threads to the main thread
+ boost::mutex* mainInterpreterMutex_; ///< A mutex to synchronize queries to the main interpreter
+ };
+
+ _CoreExport void tclThread(TclInterpreterBundle* bundle, const std::string& command);
+ _CoreExport void sourceThread(const std::string& file);
+ _CoreExport int Tcl_OrxonoxAppInit(Tcl_Interp* interp);
+}
+
+#endif /* _TclThreadManager_H__ */
More information about the Orxonox-commit
mailing list