Browse Source

Fixed the LuaEventListener so that it will actually have a function at the top of the stack.

After fixing the above, and making an EventInstancer for the sample, it is now crashing. This is a good thing.

Changed the Log::__call to Log::Message for Lua, because the metamethod for __call would not have been called.
Nate Starkey 13 years ago
parent
commit
14392479d7

+ 18 - 2
Samples/luainvaders/PyRocketInvaders.vcproj

@@ -54,7 +54,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="RocketCore_d.lib RocketDebugger_d.lib RocketControls_d.lib opengl32.lib RocketLua_d.lib"
+				AdditionalDependencies="RocketCore_d.lib RocketDebugger_d.lib RocketControls_d.lib opengl32.lib RocketLua_d.lib lua51.lib"
 				OutputFile="..\..\bin\$(ProjectName)_d.exe"
 				AdditionalLibraryDirectories="..\..\bin;..\..\..\support\lib"
 				GenerateDebugInformation="true"
@@ -124,7 +124,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="RocketCore.lib RocketDebugger.lib RocketControls.lib opengl32.lib boost_python-vc90-mt-1_44.lib"
+				AdditionalDependencies="RocketCore.lib RocketDebugger.lib RocketControls.lib opengl32.lib RocketLua.lib lua51.lib"
 				OutputFile="..\..\bin\$(ProjectName).exe"
 				AdditionalLibraryDirectories="..\..\bin;..\..\..\support\lib"
 				GenerateDebugInformation="true"
@@ -177,6 +177,14 @@
 				RelativePath=".\src\ElementGame.h"
 				>
 			</File>
+			<File
+				RelativePath=".\src\ElementGameInstancer.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\ElementGameInstancer.h"
+				>
+			</File>
 			<File
 				RelativePath=".\src\Game.cpp"
 				>
@@ -274,6 +282,14 @@
 				>
 			</File>
 		</Filter>
+		<File
+			RelativePath=".\src\LuaInterface.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\LuaInterface.h"
+			>
+		</File>
 		<File
 			RelativePath=".\src\main.cpp"
 			>

+ 28 - 0
Samples/luainvaders/src/ElementGameInstancer.cpp

@@ -0,0 +1,28 @@
+#include "ElementGameInstancer.h"
+#include "ElementGame.h"
+
+ElementGameInstancer::~ElementGameInstancer()
+{
+}
+	
+// Instances an element given the tag name and attributes
+Rocket::Core::Element* ElementGameInstancer::InstanceElement(Rocket::Core::Element* /*parent*/, const Rocket::Core::String& tag, const Rocket::Core::XMLAttributes& /*attributes*/)
+{
+	return new ElementGame(tag);
+}
+
+
+
+// Releases the given element
+void ElementGameInstancer::ReleaseElement(Rocket::Core::Element* element)
+{
+	delete element;
+}
+
+
+
+// Release the instancer
+void ElementGameInstancer::Release()
+{
+	delete this;
+}

+ 23 - 0
Samples/luainvaders/src/ElementGameInstancer.h

@@ -0,0 +1,23 @@
+#ifndef ELEMENTGAMEINSTANCER_H
+#define ELEMENTGAMEINSTANCER_H
+#include <Rocket/Core/ElementInstancer.h>
+
+class ElementGameInstancer : public Rocket::Core::ElementInstancer
+{
+public:
+	virtual ~ElementGameInstancer();
+	
+	/// Instances an element given the tag name and attributes
+	/// @param tag Name of the element to instance
+	/// @param attributes vector of name value pairs
+    virtual Rocket::Core::Element* InstanceElement(Rocket::Core::Element* parent, const Rocket::Core::String& tag, const Rocket::Core::XMLAttributes& attributes);
+
+	/// Releases the given element
+	/// @param element to release
+	virtual void ReleaseElement(Rocket::Core::Element* element);
+
+	/// Release the instancer
+	virtual void Release();
+};
+
+#endif

+ 117 - 0
Samples/luainvaders/src/LuaInterface.cpp

@@ -0,0 +1,117 @@
+#include "LuaInterface.h"
+#include <Rocket/Core/Lua/LuaType.h>
+#include <Rocket/Core/Lua/lua.hpp>
+#include "Game.h"
+#include "GameDetails.h"
+#include <Rocket/Core/Log.h>
+#include <Shell.h>
+#include <Rocket/Core/Factory.h>
+#include "HighScores.h"
+#include <Rocket/Core/Types.h>
+#include "ElementGameInstancer.h"
+
+//we have to create the binding ourselves, and these are the functions that will be
+//called. It has to match the function signature of int (*ftnptr)(lua_State*)
+int GameShutdown(lua_State* L);
+int GameSetPaused(lua_State* L);
+int GameSetDifficulty(lua_State* L);
+int GameSetDefenderColour(lua_State* L);
+int GameSubmitHighScore(lua_State* L);
+int GameSetHighScoreName(lua_State* L);
+
+void LuaInterface::Initialise(lua_State* L)
+{
+    InitGame(L);
+    Rocket::Core::Factory::RegisterElementInstancer("game",new ElementGameInstancer())->RemoveReference();
+}
+
+void LuaInterface::InitGame(lua_State *L)
+{
+    luaL_dostring(L,"Game = Game or {}"); //doing this in Lua because it would be 10+ lines in C++
+    lua_getglobal(L,"Game");
+    int game = lua_gettop(L);
+
+    if(lua_isnil(L,game))
+    {
+        Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Error creating the Game table from C++ in LuaInterface::InitGame");
+        return;
+    }
+    
+    //this can be done in a loop similar to the implementation of LuaType::_regfunctions, but I am
+    //defining them explicitly so that there is no black magic
+    lua_pushcfunction(L,GameShutdown);
+    lua_setfield(L, game, "Shutdown");
+
+    lua_pushcfunction(L,GameSetPaused);
+    lua_setfield(L,game,"SetPaused");
+
+    lua_pushcfunction(L,GameSetDifficulty);
+    lua_setfield(L,game,"SetDifficulty");
+
+    lua_pushcfunction(L,GameSetDefenderColour);
+    lua_setfield(L,game,"SetDefenderColour");
+
+    lua_pushcfunction(L,GameSubmitHighScore);
+    lua_setfield(L,game,"SubmitHighScore");
+
+    lua_pushcfunction(L,GameSetHighScoreName);
+    lua_setfield(L,game,"SetHighScoreName");
+
+    lua_newtable(L);
+    lua_pushinteger(L,GameDetails::HARD);
+    lua_setfield(L,-2,"HARD");
+
+    lua_pushinteger(L,GameDetails::EASY);
+    lua_setfield(L,-2,"EASY");
+
+    lua_setfield(L,game,"difficulty"); //Game.difficulty = {HARD,EASY}
+
+    lua_pop(L,2); //pop both Game.difficulty and Game
+}
+
+int GameShutdown(lua_State* L)
+{
+    Shell::RequestExit();
+    return 0;
+}
+
+int GameSetPaused(lua_State* L)
+{
+    bool paused = CHECK_BOOL(L,1); //CHECK_BOOL defined in LuaType.h
+    GameDetails::SetPaused(paused);
+    return 0;
+}
+
+int GameSetDifficulty(lua_State* L)
+{
+    int difficulty = luaL_checkint(L,1);
+    GameDetails::SetDifficulty((GameDetails::Difficulty)difficulty);
+    return 0;
+}
+
+int GameSetDefenderColour(lua_State* L)
+{
+    Rocket::Core::Colourb* colour = Rocket::Core::Lua::LuaType<Rocket::Core::Colourb>::check(L,1);
+    GameDetails::SetDefenderColour(*colour);
+    return 0;
+}
+
+int GameSubmitHighScore(lua_State* L)
+{
+    int score = GameDetails::GetScore();
+    if(score > 0)
+    {
+        // Submit the score the player just got to the high scores chart.
+        HighScores::SubmitScore(GameDetails::GetDefenderColour(),GameDetails::GetWave(), GameDetails::GetScore());
+        // Reset the score so the chart won't get confused next time we enter.
+        GameDetails::ResetScore();
+    }
+    return 0;
+}
+
+int GameSetHighScoreName(lua_State* L)
+{
+    const char* name = luaL_checkstring(L,1);
+    HighScores::SubmitName(name);
+    return 0;
+}

+ 27 - 0
Samples/luainvaders/src/LuaInterface.h

@@ -0,0 +1,27 @@
+#ifndef LUAINTERFACE_H
+#define LUAINTERFACE_H 
+/*
+    This will define the "Game" global table in Lua and some functions with it.
+
+    In Lua, the skeleton definition of Game with the fake function definitions (because it calls c++ code) would look something like
+
+    Game = Game or {} --so if something else made a "Game" table, we would save the previous table, and just add on to it
+    Game.Shutdown = function() Shell::RequestExit() end
+    Game.SetPaused = function(paused) GameDetails::SetPaused(paused) end --where paused is a bool
+    Game.SetDifficulty = function(difficulty) GameDetails::SetDifficulty(difficulty) end --difficulty is a value from Game.difficulty
+    Game.SetDefenderColour = function(colour) GameDetails::SetDefenderColour(colour) end --colour is of type Colourb
+    Game.SubmitHighScore = function() HighScores::SubmitScore(stuff from GameDetails) end
+    Game.SetHighScoreName = function(name) HighScore::SubmitName(name) end -- name is a string
+    Game.difficulty = { "HARD" = GameDetails::HARD, "EASY" = GameDetails::EASY }
+*/
+
+struct lua_State;
+class Game;
+class LuaInterface
+{
+public:
+    static void Initialise(lua_State* L);
+    static void InitGame(lua_State* L);
+};
+
+#endif

+ 1 - 0
Samples/luainvaders/src/main.cpp

@@ -122,6 +122,7 @@ int main(int, char**)
 
 	// Fire off the startup script.
 	//PythonInterface::Import("autoexec");
+    //LuaInterface::Initialise(Interpreter::GetLuaState());
     Rocket::Core::Lua::Interpreter::LoadFile(Rocket::Core::String(APP_PATH).Append("lua/start.lua"));
 
 	Shell::EventLoop(GameLoop);	

+ 1 - 1
Source/Core/Lua/Log.cpp

@@ -9,7 +9,7 @@ namespace Lua {
 
 
 
-int Log__call(lua_State* L)
+int LogMessage(lua_State* L)
 {
     Log::Type type = Log::Type((int)luaL_checkinteger(L,1));
     const char* str = luaL_checkstring(L,2);

+ 3 - 4
Source/Core/Lua/Log.h

@@ -4,9 +4,8 @@
 /*
     Declares "Log" in the global Lua namespace.
 
-    //It is not nessecarry to call it on a "Log" object, just
-    //call it on the Log table
-    Log(logtype type, string message)
+    //method, not called from a "Log" object, just from the Log table
+    Log.Message(logtype type, string message)
 
     where logtype is defined in Log.logtype, and can be:
     logtype.always
@@ -22,7 +21,7 @@ namespace Core {
 namespace Lua {
 
 template<> void LuaType<Log>::extra_init(lua_State* L, int metatable_index);
-int Log__call(lua_State* L);
+int LogMessage(lua_State* L);
 
 RegType<Log> LogMethods[];
 luaL_reg LogGetters[];

+ 2 - 2
Source/Core/Lua/LuaEventListener.cpp

@@ -10,9 +10,9 @@ typedef Rocket::Core::ElementDocument Document;
 
 LuaEventListener::LuaEventListener(const String& code, Element* element) : EventListener()
 {
-    String function = "function (event,element,document) ";
+    String function = "return function (event,element,document) ";
     function.Append(code);
-    function.Append("end");
+    function.Append(" end");
 
     lua_State* L = Interpreter::GetLuaState();
 

+ 2 - 2
Source/Core/Lua/LuaTypeTemplateSpec.inl

@@ -278,8 +278,8 @@ template<> void LuaType<Log>::extra_init(lua_State* L, int metatable_index)
     //directly below the metatable
     int method_index = metatable_index - 1;
 
-    lua_pushcfunction(L,Log__call);
-    lua_setfield(L,metatable_index, "__call");
+    lua_pushcfunction(L,LogMessage);
+    lua_setfield(L,metatable_index, "Message");
 
     //construct the "logtype" table, so that we can use the Rocket::Core::Log::Type enum like Log.logtype.always in Lua for Log::LT_ALWAYS
     lua_newtable(L);