Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gamestate/src/libraries/core/LuaState.cc @ 6626

Last change on this file since 6626 was 6626, checked in by rgrieder, 14 years ago

Modified Debugger.lua so we can debug any Lua files from our Resources.
Debugging strings loaded with loadstring() cannot be debugged (not supported by Debugger.lua, it always assumes files).

  • Property svn:eol-style set to native
File size: 9.2 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 "Resource.h"
40#include "ToluaBindCore.h"
41
42namespace orxonox
43{
44    LuaState::ToluaInterfaceMap LuaState::toluaInterfaces_s;
45    std::vector<LuaState*> LuaState::instances_s;
46
47    // Do this after declaring toluaInterfaces_s and instances_s to avoid larger problems
48    DeclareToluaInterface(Core);
49
50    LuaState::LuaState()
51        : bIsRunning_(false)
52        , includeParseFunction_(NULL)
53    {
54        // Create new lua state and configure it
55        luaState_ = lua_open();
56#if LUA_VERSION_NUM == 501
57        luaL_openlibs(luaState_);
58#else
59        luaopen_base(luaState_);
60        luaopen_string(luaState_);
61        luaopen_table(luaState_);
62        luaopen_math(luaState_);
63        luaopen_io(luaState_);
64        luaopen_debug(luaState_);
65#endif
66
67        // Open all available tolua interfaces
68        this->openToluaInterfaces(luaState_);
69
70        // Create dummy file info
71        sourceFileInfo_.reset(new ResourceInfo());
72        sourceFileInfo_->group = "General";
73        sourceFileInfo_->size = 0;
74
75        // Push 'this' pointer
76        tolua_pushusertype(luaState_, static_cast<void*>(this), "orxonox::LuaState");
77        lua_setglobal(luaState_, "luaState");
78
79        // Parse init script
80        this->doFile("LuaStateInit.lua");
81    }
82
83    LuaState::~LuaState()
84    {
85        lua_close(luaState_);
86    }
87
88    shared_ptr<ResourceInfo> LuaState::getFileInfo(const std::string& filename)
89    {
90        // Look in the current directory first
91        shared_ptr<ResourceInfo> sourceInfo = Resource::getInfo(sourceFileInfo_->path + filename);
92        // Continue search in root directories
93        if (sourceInfo == NULL && !sourceFileInfo_->path.empty())
94            sourceInfo = Resource::getInfo(filename);
95        return sourceInfo;
96    }
97
98    void LuaState::includeFile(const std::string& filename)
99    {
100        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename);
101        if (sourceInfo != NULL)
102            this->includeString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
103        else
104            COUT(2) << "LuaState: Cannot include file '" << filename << "'." << std::endl;
105    }
106
107    void LuaState::includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
108    {
109        // Parse string with provided include parser (otherwise don't preparse at all)
110        std::string luaInput;
111        if (includeParseFunction_ != NULL)
112            luaInput = (*includeParseFunction_)(code);
113        else
114            luaInput = code;
115
116        this->doString(luaInput, sourceFileInfo);
117    }
118
119    void LuaState::doFile(const std::string& filename)
120    {
121        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename);
122        if (sourceInfo != NULL)
123            this->doString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
124        else
125            COUT(2) << "LuaState: Cannot do file '" << filename << "'." << std::endl;
126    }
127
128    void LuaState::doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
129    {
130        // Save the old source file info
131        shared_ptr<ResourceInfo> oldSourceFileInfo = sourceFileInfo_;
132        // Only override if sourceFileInfo provides useful information
133        if (sourceFileInfo != NULL)
134            sourceFileInfo_ = sourceFileInfo;
135
136        std::string chunkname;
137        if (sourceFileInfo != NULL)
138        {
139            // Provide lua_load with the filename for debug purposes
140            // The '@' is a Lua convention to identify the chunk name as filename
141            chunkname = '@' + sourceFileInfo->filename;
142        }
143        else
144        {
145            // Use the code string to identify the chunk
146            chunkname = code;
147        }
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, chunkname.c_str());
155#else
156        error = luaL_loadbuffer(luaState_, code.c_str(), code.size(), chunkname.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(1) << "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(level) << message << std::endl;
186    }
187
188    bool LuaState::fileExists(const std::string& filename)
189    {
190        shared_ptr<ResourceInfo> info = this->getFileInfo(filename);
191        if (info == NULL)
192            return false;
193        else
194            return true;
195    }
196
197    //! Returns the content of a file
198    std::string LuaState::getSourceCode(const std::string& filename)
199    {
200        shared_ptr<ResourceInfo> info = Resource::getInfo(filename);
201        if (info == NULL)
202            return "";
203        else
204            return Resource::open(info)->getAsString();
205    }
206
207#if LUA_VERSION_NUM != 501
208    const char * LuaState::lua_Chunkreader(lua_State *L, void *data, size_t *size)
209    {
210        LoadS* ls = static_cast<LoadS*>(data);
211        if (ls->size == 0)
212            return NULL;
213        *size = ls->size;
214        ls->size = 0;
215        return ls->s;
216    }
217#endif
218
219    /*static*/ bool LuaState::addToluaInterface(int (*function)(lua_State*), const std::string& name)
220    {
221        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
222        {
223            if (it->first == name || it->second == function)
224            {
225                COUT(2) << "Warning: Trying to add a Tolua interface with the same name or function." << std::endl;
226                return true;
227            }
228        }
229        toluaInterfaces_s[name] = function;
230
231        // Open interface in all LuaStates
232        for (std::vector<LuaState*>::const_iterator it = instances_s.begin(); it != instances_s.end(); ++it)
233            (*function)((*it)->luaState_);
234
235        // Return dummy bool
236        return true;
237    }
238
239    /*static*/ bool LuaState::removeToluaInterface(const std::string& name)
240    {
241        ToluaInterfaceMap::iterator it = toluaInterfaces_s.find(name);
242        if (it == toluaInterfaces_s.end())
243        {
244            COUT(2) << "Warning: Cannot remove Tolua interface '" << name << "': Not found" << std::endl;
245            return true;
246        }
247
248        // Close interface in all LuaStates
249        for (std::vector<LuaState*>::const_iterator itState = instances_s.begin(); itState != instances_s.end(); ++itState)
250        {
251            lua_pushnil((*itState)->luaState_);
252            lua_setglobal((*itState)->luaState_, it->first.c_str());
253        }
254
255        // Remove entry
256        toluaInterfaces_s.erase(it);
257
258        // Return dummy bool
259        return true;
260    }
261
262    /*static*/ void LuaState::openToluaInterfaces(lua_State* state)
263    {
264        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
265            (*it->second)(state);
266    }
267
268    /*static*/ void LuaState::closeToluaInterfaces(lua_State* state)
269    {
270        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
271        {
272            lua_pushnil(state);
273            lua_setglobal(state, it->first.c_str());
274        }
275    }
276
277
278    LuaFunctor::LuaFunctor(const std::string& code, LuaState* luaState)
279    {
280        this->code_ = code;
281        this->lua_ = luaState;
282    }
283
284    void LuaFunctor::operator()(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
285    {
286        lua_->doString(this->code_);
287    }
288}
Note: See TracBrowser for help on using the repository browser.