diff options
author | Eugene Sandulenko | 2010-07-29 19:53:02 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2010-10-12 21:38:20 +0000 |
commit | a683a420a9e43705c972b5e74d55e319729e1a81 (patch) | |
tree | bde6e4abd417bdfaec120aa951da9a19be36b654 /engines/sword25/script/luacallback.cpp | |
parent | 7723d91c957d07205c51be32498d45cd0a78568f (diff) | |
download | scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.tar.gz scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.tar.bz2 scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.zip |
SWORD25: Importing original sources
svn-id: r53171
Diffstat (limited to 'engines/sword25/script/luacallback.cpp')
-rwxr-xr-x | engines/sword25/script/luacallback.cpp | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/engines/sword25/script/luacallback.cpp b/engines/sword25/script/luacallback.cpp new file mode 100755 index 0000000000..09103d5467 --- /dev/null +++ b/engines/sword25/script/luacallback.cpp @@ -0,0 +1,203 @@ +// ----------------------------------------------------------------------------- +// This file is part of Broken Sword 2.5 +// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer +// +// Broken Sword 2.5 is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Broken Sword 2.5 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Broken Sword 2.5; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "luacallback.h" +#include "luabindhelper.h" + +extern "C" +{ + #include <lua.h> + #include <lauxlib.h> +} + +#define BS_LOG_PREFIX "LUA" + +// ----------------------------------------------------------------------------- + +namespace +{ + const char * CALLBACKTABLE_NAME = "__CALLBACKS"; +} + +// ----------------------------------------------------------------------------- + +BS_LuaCallback::BS_LuaCallback(lua_State * L) +{ + // Callbacktabelle erstellen. + lua_newtable(L); + lua_setglobal(L, CALLBACKTABLE_NAME); +} + +// ----------------------------------------------------------------------------- + +BS_LuaCallback::~BS_LuaCallback() +{ +} + +// ----------------------------------------------------------------------------- + +void BS_LuaCallback::RegisterCallbackFunction(lua_State * L, unsigned int ObjectHandle) +{ + BS_ASSERT(lua_isfunction(L, -1)); + EnsureObjectCallbackTableExists(L, ObjectHandle); + + // Funktion in der Objekt-Callbacktabelle speichern. + lua_pushvalue(L, -2); + luaL_ref(L, -2); + + // Funktion und Objekt-Callbacktabelle vom Stack poppen. + lua_pop(L, 2); +} + +// ----------------------------------------------------------------------------- + +void BS_LuaCallback::UnregisterCallbackFunction(lua_State * L, unsigned int ObjectHandle) +{ + BS_ASSERT(lua_isfunction(L, -1)); + EnsureObjectCallbackTableExists(L,ObjectHandle); + + // Über alle Elemente der Objekt-Callbacktabelle iterieren und die Funktion daraus entfernen. + lua_pushnil(L); + while (lua_next(L, -2) != 0) + { + // Der Wert des aktuellen Elementes liegt oben auf dem Stack, darunter der Index. + + // Falls der Wert identisch mit dem Funktionsparameter ist, wird sie aus der Tabelle entfernt. + if (lua_equal(L, -1, -4)) + { + lua_pushvalue(L, -2); + lua_pushnil(L); + lua_settable(L, -5); + + // Die Funktion wurde gefunden, die Iteration kann abgebrochen werden. + lua_pop(L, 2); + break; + } + else + { + // Wert vom Stack poppen. Der Index liegt dann oben für den nächsten Aufruf von lua_next(). + lua_pop(L, 1); + } + } + + // Funktion und Objekt-Callbacktabelle vom Stack poppen. + lua_pop(L, 2); +} + +// ----------------------------------------------------------------------------- + +void BS_LuaCallback::RemoveAllObjectCallbacks(lua_State * L, unsigned int ObjectHandle) +{ + PushCallbackTable(L); + + // Objekt-Callbacktabelle aus der Callbacktabelle entfernen. + lua_pushnumber(L, ObjectHandle); + lua_pushnil(L); + lua_settable(L, -3); + + lua_pop(L, 1); +} + +// ----------------------------------------------------------------------------- + +void BS_LuaCallback::InvokeCallbackFunctions(lua_State * L, unsigned int ObjectHandle) +{ + EnsureObjectCallbackTableExists(L, ObjectHandle); + + // Über die Tabelle iterieren und alle Callbacks ausführen. + lua_pushnil(L); + while (lua_next(L, -2) != 0) + { + // Der Wert des aktuellen Elementes liegt oben auf dem Stack, darunter der Index. + + // Falls der Wert eine Funktion ist, wird sie ausgeführt. + if (lua_type(L, -1) == LUA_TFUNCTION) + { + // Pre-Funktion aufrufen. + // Abgeleitete Klassen könnten in dieser Funktion Parameter auf den Stack schieben. + // Der Rückgabewert gibt die Anzahl der Parameter zurück. + int ArgumentCount = PreFunctionInvokation(L); + + // lua_pcall poppt die Funktion und die Parameter selber vom Stack. + if (lua_pcall(L, ArgumentCount, 0, 0) != 0) + { + // Ein Fehler ist aufgetreten. + BS_LOG_ERRORLN("An error occured executing a callback function: %s", lua_tostring(L, -1)); + + // Fehlernachricht vom Stack poppen. + lua_pop(L, 1); + } + } + else + { + // Wert vom Stack poppen. Der Index liegt dann oben für den nächsten Aufruf von lua_next(). + lua_pop(L, 1); + } + } +} + +// ----------------------------------------------------------------------------- + +void BS_LuaCallback::EnsureObjectCallbackTableExists(lua_State * L, unsigned int ObjectHandle) +{ + PushObjectCallbackTable(L, ObjectHandle); + + // Falls die Tabelle nil ist, muss sie zunächst erstellt werden. + if (lua_isnil(L, -1)) + { + // Nil vom Stack poppen. + lua_pop(L, 1); + + PushCallbackTable(L); + + // Neue Tabelle unter dem Index ObjectHandle in der Callbacktabelle ablegen. + lua_newtable(L); + lua_pushnumber(L, ObjectHandle); + lua_pushvalue(L, -2); + lua_settable(L, -4); + + // Callbacktabelle vom Stack entfernen, Objekt-Callbacktabelle aber dort lassen. + lua_remove(L, -2); + } +} + +// ----------------------------------------------------------------------------- + +void BS_LuaCallback::PushCallbackTable(lua_State * L) +{ + lua_getglobal(L, CALLBACKTABLE_NAME); +} + +// ----------------------------------------------------------------------------- + +void BS_LuaCallback::PushObjectCallbackTable(lua_State * L, unsigned int ObjectHandle) +{ + PushCallbackTable(L); + + // Objekt-Callbacktabelle auf den Stack legen. + lua_pushnumber(L, ObjectHandle); + lua_gettable(L, -2); + + // Callbacktabelle vom Stack entfernen, Objekt-Callbacktabelle aber dort lassen. + lua_remove(L, -2); +} |