Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/resource2/src/core/LuaState.cc @ 5663

Last change on this file since 5663 was 5661, checked in by rgrieder, 15 years ago

Cleaned out the lua script files for the GUI.
Also replaced "require" function to support resources.
Fixed a problem with the return value of doFile, includeFile and require being discarded because the tolua binding is for a C++ function returning void.

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