Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Aug 17, 2009, 4:37:10 PM (15 years ago)
Author:
rgrieder
Message:
  • Implemented file management via resource manager and loading of resource locations via XML. Changes made:
    • SoundManager loads via memory stream rather than via file
    • Loader uses LuaState::includeFile() to load an XML file and passes the lua tag remover function to its LuaState.
    • ConfigFileManager still loads with hard paths because the files are required before Ogre gets created
  • Renamed LuaBind to LuaState, deSingletonised it and added new features:
    • doFile(), doString(), includeFile(), includeString() where include will preparse the string with a function provided with LuaState::setIncludeParser
    • Moved lua tags replace function to Loader (since it's actually an XML related task)
    • Using data_path/lua/LuaInitScript.lua to provide the following functions
      • logMessage(level, message)
      • doFile, dofile, include (all working with relative paths but within the same resource group)
  • Modified Script class to work with LuaState and fixed its XML Loader
  • Adjusted all level and include files (both "include" and "dofile" lua commands)
File:
1 moved

Legend:

Unmodified
Added
Removed
  • code/branches/resource2/src/core/LuaState.cc

    r5645 r5654  
    2222 *   Author:
    2323 *      Benjamin Knecht
     24 *      Reto Grieder
    2425 *   Co-authors:
    2526 *      ...
     
    2728 */
    2829
    29 #include "LuaBind.h"
    30 
    31 #include <fstream>
    32 #include <map>
     30#include "LuaState.h"
     31
     32#include <tolua/tolua++.h>
    3333extern "C" {
     34#include <lua.h>
    3435#include <lualib.h>
    3536}
    36 #include <tolua/tolua++.h>
    37 #include <boost/filesystem.hpp>
    3837
    3938#include "util/Debug.h"
    40 #include "util/StringUtils.h"
    4139#include "Core.h"
     40#include "Resource.h"
    4241
    4342namespace orxonox
    4443{
    45   LuaBind* LuaBind::singletonPtr_s = NULL;
    46 
    47   LuaBind::LuaBind()
    48   {
    49     this->includePath_ = Core::getDataPathString();
    50 
    51     luaState_ = lua_open();
    52     luaSource_ = "";
     44    LuaState::ToluaInterfaceMap LuaState::toluaInterfaces_s;
     45    std::vector<LuaState*> LuaState::instances_s;
     46
     47    LuaState::LuaState()
     48        : bIsRunning_(false)
     49        , includeParseFunction_(NULL)
     50    {
     51        // Create new lua state and configure it
     52        luaState_ = lua_open();
    5353#if LUA_VERSION_NUM == 501
    54     luaL_openlibs(luaState_);
     54        luaL_openlibs(luaState_);
    5555#else
    56     luaopen_base(luaState_);
    57     luaopen_string(luaState_);
    58     luaopen_table(luaState_);
    59     luaopen_math(luaState_);
    60     luaopen_io(luaState_);
    61     luaopen_debug(luaState_);
     56        luaopen_base(luaState_);
     57        luaopen_string(luaState_);
     58        luaopen_table(luaState_);
     59        luaopen_math(luaState_);
     60        luaopen_io(luaState_);
     61        luaopen_debug(luaState_);
    6262#endif
    6363
    64     // Open all available tolua interfaces
    65     this->openToluaInterfaces(luaState_);
    66 
    67     output_ = "";
    68     isRunning_ = false;
    69   }
    70 
    71   LuaBind::~LuaBind()
    72   {
    73     this->closeToluaInterfaces(luaState_);
    74   };
    75 
    76   void LuaBind::luaPrint(const std::string& str)
    77   {
    78     output_ += str;
    79 //    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
    80     COUT(5) << str;
    81   }
    82 
    83   /**
    84       @brief Loads the specified file line by line
    85       @param filename The filename of the file
    86       @param luaTags if true, the loaded file gets stripped off luaTags
    87   */
    88   void LuaBind::loadFile(const std::string& filename, bool luaTags)
    89   {
    90     boost::filesystem::path filepath(filename);
    91 
    92     output_ = "";
    93     std::ifstream file;
    94     file.open(filepath.string().c_str(), std::fstream::in);
    95 
    96     if (!file.is_open())
    97     {
    98       // some error msg
    99     }
    100 
    101     std::string levelString = "";
    102 
    103     while (file.good() && !file.eof())
    104     {
    105       std::string line;
    106       std::getline(file, line);
    107       levelString += line;
    108       levelString += "\n";
    109     }
    110 
    111     file.close();
    112     //std::string output;
    113 
    114     if (luaTags)
    115       luaSource_ = replaceLuaTags(levelString);
    116     else
    117       luaSource_ = levelString;
    118     COUT(5) << "ParsedSourceCode: " << luaSource_ << std::endl;
    119   }
    120 
    121   void LuaBind::loadString(const std::string& code)
    122   {
    123     luaSource_ = code;
    124     output_ = "";
    125   }
    126 
     64        // Open all available tolua interfaces
     65        this->openToluaInterfaces(luaState_);
     66
     67        // Create dummy file info
     68        sourceFileInfo_.reset(new ResourceInfo());
     69        sourceFileInfo_->group = "General";
     70        sourceFileInfo_->size = 0;
     71
     72        // Push this pointer
     73        tolua_pushusertype(luaState_, static_cast<void*>(this), "orxonox::LuaState");
     74        lua_setglobal(luaState_, "luaState");
     75
     76        // Parse init script
     77        // Note: We have to use a hard coded path because the script is required for the resource loading
     78        this->doString("dofile(\"" + Core::getDataPathString() + "lua/LuaStateInit.lua\")");
     79    }
     80
     81    LuaState::~LuaState()
     82    {
     83        lua_close(luaState_);
     84    }
     85
     86    shared_ptr<ResourceInfo> LuaState::getFileInfo(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
     87    {
     88        shared_ptr<ResourceInfo> sourceInfo;
     89        if (resourceGroup != "NoResourceGroupProvided")
     90            sourceInfo = Resource::getInfo(filename, resourceGroup);
     91
     92        // Continue search if not explicitely forbidden
     93        if (bSearchOtherPaths && sourceInfo == NULL)
     94        {
     95            // Call might be relative to the file currently being processed
     96            sourceInfo = Resource::getInfo(sourceFileInfo_->path + filename, sourceFileInfo_->group);
     97            if (sourceInfo == NULL)
     98            {
     99                // Maybe find something in the same group but in the root path
     100                sourceInfo = Resource::getInfo(filename, sourceFileInfo_->group);
     101            }
     102        }
     103        return sourceInfo;
     104    }
     105
     106    void LuaState::includeFile(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
     107    {
     108        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename, resourceGroup, bSearchOtherPaths);
     109        if (sourceInfo != NULL)
     110            this->includeString(Resource::open(sourceInfo->filename, sourceInfo->group)->getAsString(), sourceInfo);
     111        else
     112            COUT(2) << "LuaState: Cannot include file '" << filename << "' in resource group '"
     113                    << (resourceGroup == "NoResourceGroupProvided" ? sourceFileInfo_->group : resourceGroup) << "': group not found." << std::endl;
     114    }
     115
     116    void LuaState::includeString(const std::string& code, shared_ptr<ResourceInfo> sourceFileInfo)
     117    {
     118        // Parse string with provided include parser (otherwise don't preparse at all)
     119        std::string luaInput;
     120        if (includeParseFunction_ != NULL)
     121            luaInput = (*includeParseFunction_)(code);
     122        else
     123            luaInput = code;
     124
     125        this->doString(luaInput, sourceFileInfo);
     126    }
     127
     128    void LuaState::doFile(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
     129    {
     130        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename, resourceGroup, bSearchOtherPaths);
     131        if (sourceInfo != NULL)
     132            this->doString(Resource::open(sourceInfo->filename, sourceInfo->group)->getAsString(), sourceInfo);
     133        else
     134            COUT(2) << "LuaState: Cannot do file '" << filename << "' in resource group '"
     135                << (resourceGroup == "NoResourceGroupProvided" ? sourceFileInfo_->group : resourceGroup) << "': group not found." << std::endl;
     136    }
     137
     138    void LuaState::doString(const std::string& code, shared_ptr<ResourceInfo> sourceFileInfo)
     139    {
     140        // Save the oold source file info
     141        shared_ptr<ResourceInfo> oldSourceFileInfo = sourceFileInfo_;
     142        // Only override if sourceFileInfo provides useful information
     143        if (sourceFileInfo != NULL)
     144            sourceFileInfo_ = sourceFileInfo;
     145
     146        //if (!bIsRunning_)
     147        //{
     148        //    bIsRunning_ = true;
     149
     150        int error = 0;
    127151#if LUA_VERSION_NUM != 501
    128   const char * LuaBind::lua_Chunkreader(lua_State *L, void *data, size_t *size)
    129   {
    130     LoadS* ls = static_cast<LoadS*>(data);
    131     if (ls->size == 0) return NULL;
    132     *size = ls->size;
    133     ls->size = 0;
    134     return ls->s;
    135   }
     152        LoadS ls;
     153        ls.s = code.c_str();
     154        ls.size = code.size();
     155        error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, code.c_str());
     156#else
     157        error = luaL_loadstring(luaState_, code.c_str());
    136158#endif
    137   void LuaBind::run()
    138   {
    139     if (!isRunning_)
    140     {
    141       isRunning_ = true;
    142       int error = 0;
    143       std::string init =
    144          "local scr = orxonox.LuaBind:getInstance()\n \
    145           local debug = print\n \
    146           print = function(s)\n \
    147               scr:luaPrint(s)\n \
    148           end\n \
    149           include = function(f)\n \
    150               file = assert(io.open(\"" + this->includePath_ + "\"..\"/\"..f))\n \
    151               content = file:read(\"*a\")\n \
    152               file:close()\n \
    153               source = scr:replaceLuaTags(content)\n \
    154               assert(loadstring(source))()\n \
    155           end\n";
    156       init += luaSource_;
    157   #if LUA_VERSION_NUM == 501
    158       error = luaL_loadstring(luaState_, init.c_str());
    159   #else
    160       LoadS ls;
    161       ls.s = init.c_str();
    162       ls.size = init.size();
    163       error = lua_load(luaState_, &orxonox::LuaBind::lua_Chunkreader, &ls, init.c_str());
    164   #endif
    165       if (error == 0)
    166       {
    167         error = lua_pcall(luaState_, 0, 0, 0);
    168       }
    169       if (error != 0)
    170       {
    171         COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
    172       }
    173       isRunning_ = false;
    174     }
    175     else
    176     {
    177       COUT(2) << "Warning: Lua's run is called while running!" << std::endl;
    178     }
    179   }
    180 
    181   std::string LuaBind::replaceLuaTags(const std::string& text)
    182   {
    183     // chreate map with all Lua tags
    184     std::map<size_t, bool> luaTags;
    185     {
    186       size_t pos = 0;
    187       while ((pos = text.find("<?lua", pos)) != std::string::npos)
    188         luaTags[pos++] = true;
    189     }
    190     {
    191       size_t pos = 0;
    192       while ((pos = text.find("?>", pos)) != std::string::npos)
    193         luaTags[pos++] = false;
    194     }
    195 
    196     // erase all tags from the map that are between two quotes
    197     {
    198       std::map<size_t, bool>::iterator it = luaTags.begin();
    199       std::map<size_t, bool>::iterator it2 = it;
    200       bool bBetweenQuotes = false;
    201       size_t pos = 0;
    202       while ((pos = getNextQuote(text, pos)) != std::string::npos)
    203       {
    204         while ((it != luaTags.end()) && (it->first < pos))
    205         {
    206           if (bBetweenQuotes) {
    207             it2++;
    208             if(it->second && !(it2->second) && it2->first < pos)
    209               it = ++it2;
    210             else
    211               luaTags.erase(it++);
    212           }
    213           else
    214             ++it;
    215         }
    216         bBetweenQuotes = !bBetweenQuotes;
    217         pos++;
    218       }
    219     }
    220 
    221     // check whether on every opening <?lua tag a closing ?> tag follows
    222     {
    223       bool expectedValue = true;
    224       for (std::map<size_t, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
    225       {
    226         if (it->second == expectedValue)
    227           expectedValue = !expectedValue;
    228         else
    229         {
    230           expectedValue = false;
    231           break;
    232         }
    233       }
    234       if (!expectedValue) {
    235         COUT(2) << "Warning: Error in level file" << std::endl;
    236         // todo: errorhandling
    237         return "";
    238       }
    239     }
    240 
    241     // cut the original string into pieces and put them together with print() instead of lua tags
    242     std::string output;
    243     {
    244       std::map<size_t, bool>::iterator it = luaTags.begin();
    245       bool bInPrintFunction = true;
    246       size_t start = 0;
    247       size_t end = 0;
    248 
    249       do
    250       {
    251         if (it != luaTags.end())
    252           end = (*(it++)).first;
    253         else
    254           end = std::string::npos;
    255 
    256         unsigned int equalSignCounter = 0;
    257 
    258         if (bInPrintFunction)
    259         {
    260           // count ['='[ and ]'='] and replace tags with print([[ and ]])
    261           std::string temp = text.substr(start, end - start);
    262           {
    263             size_t pos = 0;
    264             while ((pos = temp.find('[', pos)) != std::string::npos)
     159
     160        // execute the chunk
     161        if (error == 0)
     162            error = lua_pcall(luaState_, 0, 0, 0);
     163        if (error != 0)
     164        {
     165            std::string origin;
     166            if (sourceFileInfo != NULL)
     167                origin = " originating from " + sourceFileInfo_->filename;
     168            COUT(2) << "Error in Lua-script" << origin << ": " << lua_tostring(luaState_, -1) << std::endl;
     169        }
     170
     171        //    bIsRunning_ = false;
     172        //}
     173        //else
     174        //{
     175        //    COUT(2) << "Warning: LuaState do function called while running!" << std::endl;
     176        //}
     177
     178        // Load the old info again
     179        sourceFileInfo_ = oldSourceFileInfo;
     180    }
     181
     182    void LuaState::luaPrint(const std::string& str)
     183    {
     184        output_ << str;
     185    }
     186
     187    void LuaState::luaLog(unsigned int level, const std::string& message)
     188    {
     189        OutputHandler::getOutStream().setOutputLevel(level) << message << std::endl;
     190    }
     191
     192#if LUA_VERSION_NUM != 501
     193    const char * LuaState::lua_Chunkreader(lua_State *L, void *data, size_t *size)
     194    {
     195        LoadS* ls = static_cast<LoadS*>(data);
     196        if (ls->size == 0)
     197            return NULL;
     198        *size = ls->size;
     199        ls->size = 0;
     200        return ls->s;
     201    }
     202#endif
     203
     204    /*static*/ bool LuaState::addToluaInterface(int (*function)(lua_State*), const std::string& name)
     205    {
     206        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
     207        {
     208            if (it->first == name || it->second == function)
    265209            {
    266               unsigned int tempCounter = 1;
    267               size_t tempPos = pos++;
    268               while(temp[++tempPos] == '=') {
    269                 tempCounter++;
    270               }
    271               if(temp[tempPos] != '[') {
    272                 tempCounter = 0;
    273               }
    274               else if(tempCounter == 0) {
    275                 tempCounter = 1;
    276               }
    277               if (tempCounter > equalSignCounter)
    278                 equalSignCounter = tempCounter;
     210                COUT(2) << "Warning: Trying to add a Tolua interface with the same name or function." << std::endl;
     211                return true;
    279212            }
    280           }
    281           {
    282             size_t pos = 0;
    283             while ((pos = temp.find(']', pos)) != std::string::npos)
    284             {
    285               unsigned int tempCounter = 1;
    286               size_t tempPos = pos++;
    287               while(temp[++tempPos] == '=') {
    288                 tempCounter++;
    289               }
    290               if(temp[tempPos] != ']') {
    291                 tempCounter = 0;
    292               }
    293               else if(tempCounter == 0) {
    294                 tempCounter = 1;
    295               }
    296               if (tempCounter > equalSignCounter)
    297                 equalSignCounter = tempCounter;
    298             }
    299           }
    300           std::string equalSigns = "";
    301           for(unsigned int i = 0; i < equalSignCounter; i++) {
    302             equalSigns += "=";
    303           }
    304           output += "print([" + equalSigns + "[" + temp + "]" + equalSigns +"])";
    305           start = end + 5;
    306         }
    307         else
    308         {
    309           output += text.substr(start, end - start);
    310           start = end + 2;
    311         }
    312 
    313         bInPrintFunction = !bInPrintFunction;
    314       }
    315       while (end != std::string::npos);
    316     }
    317 
    318     return output;
    319   }
    320 
    321   void LuaBind::addToluaInterface(int (*function)(lua_State*), const std::string& name)
    322   {
    323     toluaInterfaces_.push_back(std::make_pair(name, function));
    324     // Apply changes to our own lua state as well
    325     (*function)(luaState_);
    326   }
    327 
    328   void LuaBind::openToluaInterfaces(lua_State* state)
    329   {
    330     for (unsigned int i = 0; i < toluaInterfaces_.size(); ++i)
    331       (*toluaInterfaces_[i].second)(state);
    332   }
    333 
    334   void LuaBind::closeToluaInterfaces(lua_State* state)
    335   {
    336     for (unsigned int i = 0; i < toluaInterfaces_.size(); ++i)
    337     {
    338       lua_pushnil(state);
    339       lua_setglobal(state, toluaInterfaces_[i].first.c_str());
    340     }
    341   }
    342 
     213        }
     214        toluaInterfaces_s[name] = function;
     215
     216        // Open interface in all LuaStates
     217        for (std::vector<LuaState*>::const_iterator it = instances_s.begin(); it != instances_s.end(); ++it)
     218            (*function)((*it)->luaState_);
     219
     220        // Return dummy bool
     221        return true;
     222    }
     223
     224    /*static*/ bool LuaState::removeToluaInterface(const std::string& name)
     225    {
     226        ToluaInterfaceMap::iterator it = toluaInterfaces_s.find(name);
     227        if (it == toluaInterfaces_s.end())
     228        {
     229            COUT(2) << "Warning: Cannot remove Tolua interface '" << name << "': Not found" << std::endl;
     230            return true;
     231        }
     232
     233        // Close interface in all LuaStates
     234        for (std::vector<LuaState*>::const_iterator itState = instances_s.begin(); itState != instances_s.end(); ++itState)
     235        {
     236            lua_pushnil((*itState)->luaState_);
     237            lua_setglobal((*itState)->luaState_, it->first.c_str());
     238        }
     239
     240        // Remove entry
     241        toluaInterfaces_s.erase(it);
     242
     243        // Return dummy bool
     244        return true;
     245    }
     246
     247    /*static*/ void LuaState::openToluaInterfaces(lua_State* state)
     248    {
     249        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
     250            (*it->second)(state);
     251    }
     252
     253    /*static*/ void LuaState::closeToluaInterfaces(lua_State* state)
     254    {
     255        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
     256        {
     257            lua_pushnil(state);
     258            lua_setglobal(state, it->first.c_str());
     259        }
     260    }
    343261}
Note: See TracChangeset for help on using the changeset viewer.