Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/LuaState.cc @ 5967

Last change on this file since 5967 was 5929, checked in by rgrieder, 15 years ago

Merged core5 branch back to the trunk.
Key features include clean level unloading and an extended XML event system.

Two important notes:
Delete your keybindings.ini files! * or you will still get parser errors when loading the key bindings.
Delete build_dir/lib/modules/libgamestates.module! * or orxonox won't start.
Best thing to do is to delete the build folder ;)

  • Property svn:eol-style set to native
File size: 9.1 KB
RevLine 
[1959]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Benjamin Knecht
[5654]24 *      Reto Grieder
[1959]25 *   Co-authors:
26 *      ...
27 *
28 */
29
[5654]30#include "LuaState.h"
[1959]31
[5654]32#include <tolua/tolua++.h>
[2710]33extern "C" {
[5654]34#include <lua.h>
[2710]35#include <lualib.h>
36}
37
[3196]38#include "util/Debug.h"
[5781]39#include "Resource.h"
[5655]40#include "ToluaBindCore.h"
[1959]41
42namespace orxonox
43{
[5654]44    LuaState::ToluaInterfaceMap LuaState::toluaInterfaces_s;
45    std::vector<LuaState*> LuaState::instances_s;
[1959]46
[5655]47    // Do this after declaring toluaInterfaces_s and instances_s to avoid larger problems
48    DeclareToluaInterface(Core);
49
[5654]50    LuaState::LuaState()
51        : bIsRunning_(false)
52        , includeParseFunction_(NULL)
53    {
54        // Create new lua state and configure it
55        luaState_ = lua_open();
[1959]56#if LUA_VERSION_NUM == 501
[5654]57        luaL_openlibs(luaState_);
[1959]58#else
[5654]59        luaopen_base(luaState_);
60        luaopen_string(luaState_);
61        luaopen_table(luaState_);
62        luaopen_math(luaState_);
63        luaopen_io(luaState_);
64        luaopen_debug(luaState_);
[1959]65#endif
[3370]66
[5654]67        // Open all available tolua interfaces
68        this->openToluaInterfaces(luaState_);
[3370]69
[5654]70        // Create dummy file info
71        sourceFileInfo_.reset(new ResourceInfo());
[5781]72        sourceFileInfo_->group = "General";
73        sourceFileInfo_->size = 0;
[1959]74
[5759]75        // Push 'this' pointer
[5654]76        tolua_pushusertype(luaState_, static_cast<void*>(this), "orxonox::LuaState");
77        lua_setglobal(luaState_, "luaState");
[3370]78
[5654]79        // Parse init script
[5660]80        this->doFile("LuaStateInit.lua");
[5654]81    }
[1959]82
[5654]83    LuaState::~LuaState()
84    {
85        lua_close(luaState_);
86    }
[2710]87
[5781]88    shared_ptr<ResourceInfo> LuaState::getFileInfo(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
[5654]89    {
90        shared_ptr<ResourceInfo> sourceInfo;
[5781]91        if (resourceGroup != "NoResourceGroupProvided")
92            sourceInfo = Resource::getInfo(filename, resourceGroup);
[1959]93
[5654]94        // Continue search if not explicitely forbidden
95        if (bSearchOtherPaths && sourceInfo == NULL)
96        {
97            // Call might be relative to the file currently being processed
[5781]98            sourceInfo = Resource::getInfo(sourceFileInfo_->path + filename, sourceFileInfo_->group);
[5654]99            if (sourceInfo == NULL)
100            {
101                // Maybe find something in the same group but in the root path
[5781]102                sourceInfo = Resource::getInfo(filename, sourceFileInfo_->group);
[5654]103            }
104        }
105        return sourceInfo;
106    }
107
[5781]108    void LuaState::includeFile(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
[1959]109    {
[5781]110        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename, resourceGroup, bSearchOtherPaths);
[5654]111        if (sourceInfo != NULL)
[5781]112            this->includeString(Resource::open(sourceInfo->filename, sourceInfo->group)->getAsString(), sourceInfo);
[5654]113        else
[5781]114            COUT(2) << "LuaState: Cannot include file '" << filename << "' in resource group '"
115                    << (resourceGroup == "NoResourceGroupProvided" ? sourceFileInfo_->group : resourceGroup) << "': group not found." << std::endl;
[1959]116    }
117
[5654]118    void LuaState::includeString(const std::string& code, shared_ptr<ResourceInfo> sourceFileInfo)
119    {
120        // Parse string with provided include parser (otherwise don't preparse at all)
121        std::string luaInput;
122        if (includeParseFunction_ != NULL)
123            luaInput = (*includeParseFunction_)(code);
124        else
125            luaInput = code;
[1959]126
[5654]127        this->doString(luaInput, sourceFileInfo);
128    }
129
[5781]130    void LuaState::doFile(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
[1959]131    {
[5781]132        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename, resourceGroup, bSearchOtherPaths);
[5654]133        if (sourceInfo != NULL)
[5781]134            this->doString(Resource::open(sourceInfo->filename, sourceInfo->group)->getAsString(), sourceInfo);
[5654]135        else
[5781]136            COUT(2) << "LuaState: Cannot do file '" << filename << "' in resource group '"
137                << (resourceGroup == "NoResourceGroupProvided" ? sourceFileInfo_->group : resourceGroup) << "': group not found." << std::endl;
[1959]138    }
139
[5654]140    void LuaState::doString(const std::string& code, shared_ptr<ResourceInfo> sourceFileInfo)
141    {
142        // Save the oold source file info
143        shared_ptr<ResourceInfo> oldSourceFileInfo = sourceFileInfo_;
144        // Only override if sourceFileInfo provides useful information
145        if (sourceFileInfo != NULL)
146            sourceFileInfo_ = sourceFileInfo;
[1959]147
[5654]148        int error = 0;
[1959]149#if LUA_VERSION_NUM != 501
[5654]150        LoadS ls;
151        ls.s = code.c_str();
152        ls.size = code.size();
153        error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, code.c_str());
154#else
155        error = luaL_loadstring(luaState_, code.c_str());
[1959]156#endif
[5654]157
158        // execute the chunk
159        if (error == 0)
[5661]160            error = lua_pcall(luaState_, 0, 1, 0);
[5654]161        if (error != 0)
162        {
163            std::string origin;
164            if (sourceFileInfo != NULL)
165                origin = " originating from " + sourceFileInfo_->filename;
166            COUT(2) << "Error in Lua-script" << origin << ": " << lua_tostring(luaState_, -1) << std::endl;
[5661]167            // return value is nil
168            lua_pushnil(luaState_);
[5654]169        }
[5661]170        // push return value because it will get lost since the return value of this function is void
171        lua_setglobal(luaState_, "LuaStateReturnValue");
[5654]172
173        // Load the old info again
174        sourceFileInfo_ = oldSourceFileInfo;
[1959]175    }
[5654]176
177    void LuaState::luaPrint(const std::string& str)
[1959]178    {
[5654]179        output_ << str;
[1959]180    }
181
[5654]182    void LuaState::luaLog(unsigned int level, const std::string& message)
[1959]183    {
[5654]184        OutputHandler::getOutStream().setOutputLevel(level) << message << std::endl;
[1959]185    }
[5654]186
[5781]187    bool LuaState::fileExists(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
[5661]188    {
[5781]189        shared_ptr<ResourceInfo> info =  this->getFileInfo(filename, resourceGroup, bSearchOtherPaths);
[5661]190        if (info == NULL)
191            return false;
192        else
193            return true;
194    }
195
[5654]196#if LUA_VERSION_NUM != 501
197    const char * LuaState::lua_Chunkreader(lua_State *L, void *data, size_t *size)
[1959]198    {
[5654]199        LoadS* ls = static_cast<LoadS*>(data);
200        if (ls->size == 0)
201            return NULL;
202        *size = ls->size;
203        ls->size = 0;
204        return ls->s;
[1959]205    }
[5654]206#endif
[1959]207
[5654]208    /*static*/ bool LuaState::addToluaInterface(int (*function)(lua_State*), const std::string& name)
[1959]209    {
[5654]210        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
[1959]211        {
[5654]212            if (it->first == name || it->second == function)
213            {
214                COUT(2) << "Warning: Trying to add a Tolua interface with the same name or function." << std::endl;
215                return true;
216            }
[1959]217        }
[5654]218        toluaInterfaces_s[name] = function;
219
220        // Open interface in all LuaStates
221        for (std::vector<LuaState*>::const_iterator it = instances_s.begin(); it != instances_s.end(); ++it)
222            (*function)((*it)->luaState_);
223
224        // Return dummy bool
225        return true;
[1959]226    }
227
[5654]228    /*static*/ bool LuaState::removeToluaInterface(const std::string& name)
[1959]229    {
[5654]230        ToluaInterfaceMap::iterator it = toluaInterfaces_s.find(name);
231        if (it == toluaInterfaces_s.end())
[1959]232        {
[5654]233            COUT(2) << "Warning: Cannot remove Tolua interface '" << name << "': Not found" << std::endl;
234            return true;
[1959]235        }
236
[5654]237        // Close interface in all LuaStates
238        for (std::vector<LuaState*>::const_iterator itState = instances_s.begin(); itState != instances_s.end(); ++itState)
[1959]239        {
[5654]240            lua_pushnil((*itState)->luaState_);
241            lua_setglobal((*itState)->luaState_, it->first.c_str());
[1959]242        }
243
[5654]244        // Remove entry
245        toluaInterfaces_s.erase(it);
246
247        // Return dummy bool
248        return true;
[1959]249    }
250
[5654]251    /*static*/ void LuaState::openToluaInterfaces(lua_State* state)
252    {
253        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
254            (*it->second)(state);
255    }
[1959]256
[5654]257    /*static*/ void LuaState::closeToluaInterfaces(lua_State* state)
[3370]258    {
[5654]259        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
260        {
261            lua_pushnil(state);
262            lua_setglobal(state, it->first.c_str());
263        }
[3370]264    }
[1959]265}
Note: See TracBrowser for help on using the repository browser.