Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/buildsystem2/src/ceguilua-0.6.1/ceguilua/CEGUILua.cpp @ 2576

Last change on this file since 2576 was 2509, checked in by rgrieder, 16 years ago

Merged revisions 1875-2278 of the buildsystem branch to buildsystem2.

  • Property svn:eol-style set to native
File size: 10.7 KB
Line 
1/***********************************************************************
2        filename: CEGUILua.cpp
3        created:  16/3/2005
4        author:   Tomas Lindquist Olsen
5
6        purpose:  Implementation for LuaScriptModule class
7*************************************************************************/
8/***************************************************************************
9 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
10 *
11 *   Permission is hereby granted, free of charge, to any person obtaining
12 *   a copy of this software and associated documentation files (the
13 *   "Software"), to deal in the Software without restriction, including
14 *   without limitation the rights to use, copy, modify, merge, publish,
15 *   distribute, sublicense, and/or sell copies of the Software, and to
16 *   permit persons to whom the Software is furnished to do so, subject to
17 *   the following conditions:
18 *
19 *   The above copyright notice and this permission notice shall be
20 *   included in all copies or substantial portions of the Software.
21 *
22 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 *   OTHER DEALINGS IN THE SOFTWARE.
29 ***************************************************************************/
30#ifdef HAVE_CONFIG_H
31#   include "config.h"
32#endif
33
34#include "CEGUI.h"
35#include "CEGUIConfig.h"
36#include "CEGUIPropertyHelper.h"
37#include "CEGUILua.h"
38#include "CEGUILuaFunctor.h"
39#include <vector>
40
41// include Lua libs and tolua++
42extern "C" {
43#include "lua.h"
44#include "lualib.h"
45#include "lauxlib.h"
46}
47
48#include "tolua++.h"
49
50// prototype for bindings initialisation function
51int tolua_CEGUI_open(lua_State* tolua_S);
52
53
54// Start of CEGUI namespace section
55namespace CEGUI
56{
57
58/*************************************************************************
59        Constructor (creates Lua state)
60*************************************************************************/
61LuaScriptModule::LuaScriptModule()
62{
63    #if LUA_VERSION_NUM >= 501
64        static const luaL_Reg lualibs[] = {
65            {"", luaopen_base},
66            {LUA_LOADLIBNAME, luaopen_package},
67            {LUA_TABLIBNAME, luaopen_table},
68            {LUA_IOLIBNAME, luaopen_io},
69            {LUA_OSLIBNAME, luaopen_os},
70            {LUA_STRLIBNAME, luaopen_string},
71            {LUA_MATHLIBNAME, luaopen_math},
72        #if defined(DEBUG) || defined (_DEBUG)
73                {LUA_DBLIBNAME, luaopen_debug},
74        #endif
75            {0, 0}
76        };
77    #endif /* CEGUI_LUA_VER >= 51 */
78
79    // create a lua state
80    d_ownsState = true;
81    d_state = lua_open();
82
83    // init all standard libraries
84    #if LUA_VERSION_NUM >= 501
85            const luaL_Reg *lib = lualibs;
86            for (; lib->func; lib++)
87            {
88                lua_pushcfunction(d_state, lib->func);
89                lua_pushstring(d_state, lib->name);
90                lua_call(d_state, 1, 0);
91            }
92    #else /* CEGUI_LUA_VER >= 51 */
93        luaopen_base(d_state);
94        luaopen_io(d_state);
95        luaopen_string(d_state);
96        luaopen_table(d_state);
97        luaopen_math(d_state);
98        #if defined(DEBUG) || defined (_DEBUG)
99            luaopen_debug(d_state);
100        #endif
101    #endif /* CEGUI_LUA_VER >= 51 */
102
103    setModuleIdentifierString();
104}
105
106
107/*************************************************************************
108        Constructor (uses given Lua state)
109*************************************************************************/
110LuaScriptModule::LuaScriptModule(lua_State* state)
111{
112        // just use the given state
113        d_ownsState = false;
114        d_state = state;
115
116        setModuleIdentifierString();
117}
118
119
120/*************************************************************************
121        Destructor
122*************************************************************************/
123LuaScriptModule::~LuaScriptModule()
124{
125        if ( d_ownsState && d_state )
126        {
127                lua_close( d_state );
128        }
129}
130
131
132/*************************************************************************
133        Execute script file
134*************************************************************************/
135void LuaScriptModule::executeScriptFile(const String& filename, const String& resourceGroup)
136{
137        // load file
138        RawDataContainer raw;
139        System::getSingleton().getResourceProvider()->loadRawDataContainer(filename,
140        raw, resourceGroup.empty() ? d_defaultResourceGroup : resourceGroup);
141
142        // load code into lua
143        int top = lua_gettop(d_state);
144        int loaderr = luaL_loadbuffer(d_state, (char*)raw.getDataPtr(), raw.getSize(), filename.c_str());
145        System::getSingleton().getResourceProvider()->unloadRawDataContainer( raw );
146        if (loaderr)
147        {
148            String errMsg = lua_tostring(d_state,-1);
149                lua_settop(d_state,top);
150                throw ScriptException("Unable to execute Lua script file: '"+filename+"'\n\n"+errMsg+"\n");
151        }
152
153    // call it
154        if (lua_pcall(d_state,0,0,0))
155        {
156            String errMsg = lua_tostring(d_state,-1);
157                lua_settop(d_state,top);
158                throw ScriptException("Unable to execute Lua script file: '"+filename+"'\n\n"+errMsg+"\n");
159        }
160
161        lua_settop(d_state,top); // just in case :P
162}
163
164
165/*************************************************************************
166        Execute global script function
167*************************************************************************/
168int     LuaScriptModule::executeScriptGlobal(const String& function_name)
169{
170    int top = lua_gettop(d_state);
171
172    // get the function from lua
173    lua_getglobal(d_state, function_name.c_str());
174
175    // is it a function
176    if (!lua_isfunction(d_state,-1))
177    {
178        lua_settop(d_state,top);
179        throw ScriptException("Unable to get Lua global: '"+function_name+"' as name not represent a global Lua function" );
180    }
181
182    // call it
183    int error = lua_pcall(d_state,0,1,0);
184
185    // handle errors
186    if (error)
187    {
188        String errMsg = lua_tostring(d_state,-1);
189        lua_pop(d_state,1);
190        throw ScriptException("Unable to evaluate Lua global: '"+function_name+"\n\n"+errMsg+"\n");
191    }
192
193    // get return value
194    if (!lua_isnumber(d_state,-1))
195    {
196        // log that return value is invalid. return -1 and move on.
197        lua_settop(d_state,top);
198        ScriptException("Unable to get Lua global : '"+function_name+"' return value as it's not a number" );
199        return -1;
200    }
201
202    int ret = (int)lua_tonumber(d_state,-1);
203    lua_pop(d_state,1);
204
205    // return it
206    return ret;
207}
208
209
210/*************************************************************************
211        Execute scripted event handler
212*************************************************************************/
213bool LuaScriptModule::executeScriptedEventHandler(const String& handler_name, const EventArgs& e)
214{
215
216        LuaFunctor::pushNamedFunction(d_state, handler_name);
217
218        ScriptWindowHelper* helper = 0;
219        //If this is an event that was triggered by a window then make a "this" pointer to the window for the script.
220        if(e.d_hasWindow)
221        {
222                WindowEventArgs& we = (WindowEventArgs&)e;
223                helper = new ScriptWindowHelper(we.window);
224                lua_pushlightuserdata(d_state,(void*)helper);
225                lua_setglobal(d_state,"this");
226        } // if(e.d_hasWindow)
227
228    // push EventArgs as the first parameter
229    tolua_pushusertype(d_state,(void*)&e,"const CEGUI::EventArgs");
230
231    // call it
232    int error = lua_pcall(d_state,1,0,0);
233
234    // handle errors
235    if (error)
236    {
237        String errStr(lua_tostring(d_state,-1));
238        lua_pop(d_state,1);
239                //cleanup the helper object if any
240                if(helper)
241                {
242                        delete helper;
243                        helper = 0;
244                }
245        throw ScriptException("Unable to evaluate the Lua event handler: '"+handler_name+"'\n\n"+errStr+"\n");
246    } // if (error)
247
248        if(helper)
249        {
250                delete helper;
251                helper = 0;
252        }
253
254    return true;
255}
256
257
258/*************************************************************************
259        Execute script code string
260*************************************************************************/
261void LuaScriptModule::executeString(const String& str)
262{
263    int top = lua_gettop(d_state);
264
265    // load code into lua and call it
266    int error = luaL_loadbuffer(d_state, str.c_str(), str.length(), str.c_str()) || lua_pcall(d_state,0,0,0);
267
268    // handle errors
269    if (error)
270    {
271        String errMsg = lua_tostring(d_state,-1);
272        lua_settop(d_state,top);
273        throw ScriptException("Unable to execute Lua script string: '"+str+"'\n\n"+errMsg+"\n");
274    }
275}
276
277
278/*************************************************************************
279        Create Lua bindings
280*************************************************************************/
281void LuaScriptModule::createBindings(void)
282{
283        CEGUI::Logger::getSingleton().logEvent( "---- Creating Lua bindings ----" );
284        // init CEGUI module
285        tolua_CEGUI_open(d_state);
286}
287
288
289/*************************************************************************
290        Destroy Lua bindings
291*************************************************************************/
292void LuaScriptModule::destroyBindings(void)
293{
294        CEGUI::Logger::getSingleton().logEvent( "---- Destroying Lua bindings ----" );
295        // is this ok ?
296        lua_pushnil(d_state);
297        lua_setglobal(d_state,"CEGUI");
298}
299
300
301/*************************************************************************
302        Set the ID string for the module
303*************************************************************************/
304void LuaScriptModule::setModuleIdentifierString()
305{
306    // set ID string
307    d_identifierString = "CEGUI::LuaScriptModule - Official Lua based scripting module for CEGUI";
308        d_language = "Lua";
309}
310
311
312/*************************************************************************
313        Subscribe to a scripted event handler
314*************************************************************************/
315Event::Connection LuaScriptModule::subscribeEvent(EventSet* target, const String& event_name, const String& subscriber_name)
316{
317    // do the real subscription
318    LuaFunctor functor(d_state,subscriber_name,LUA_NOREF);
319    Event::Connection con = target->subscribeEvent(event_name, Event::Subscriber(functor));
320    // make sure we don't release the reference we just made when this call returns
321    functor.index = LUA_NOREF;
322
323    // return the event connection
324    return con;
325}
326
327
328/*************************************************************************
329        Subscribe to a scripted event handler
330*************************************************************************/
331Event::Connection LuaScriptModule::subscribeEvent(EventSet* target, const String& event_name, Event::Group group, const String& subscriber_name)
332{
333    // do the real subscription
334    LuaFunctor functor(d_state,subscriber_name,LUA_NOREF);
335    Event::Connection con = target->subscribeEvent(event_name, group, Event::Subscriber(functor));
336
337    // return the event connection
338    return con;
339}
340
341} // namespace CEGUI
Note: See TracBrowser for help on using the repository browser.