Browse Source

Fixed one of the leaks.

Fixed some more Lua errors that remained when I converted Python to Lua

Added a 'Shutdown' function for the plugin, so that all of the elements can be garbage collected from Lua before they get destroyed by the other plugins.

Fixed Log.Message

Created the functions for AddEventListener on both Context and Element.

Fixed the LuaEventListener lua function composition to actually compile AND run the string. It works now.
Nate Starkey 13 years ago
parent
commit
c615b0b190

+ 1 - 0
Include/Rocket/Core/Lua/Interpreter.h

@@ -26,6 +26,7 @@ public:
     static lua_State* GetLuaState();
     static lua_State* GetLuaState();
 
 
     static void Initialise();
     static void Initialise();
+	static void Shutdown();
     
     
     //From Plugin
     //From Plugin
     virtual int GetEventClasses();
     virtual int GetEventClasses();

+ 2 - 1
Samples/luainvaders/data/main_menu.rml

@@ -22,7 +22,8 @@ MainMenu = MainMenu or {}
 
 
 function MainMenu.CloseLogo(document)
 function MainMenu.CloseLogo(document)
 	if document.context then
 	if document.context then
-		document.context.documents['logo']:Close()
+		--context.documents seems to be empty
+		--document.context.documents['logo']:Close()
     end
     end
 end
 end
 		</script>
 		</script>

+ 6 - 6
Samples/luainvaders/data/options.rml

@@ -31,14 +31,14 @@ Options = Options or {}
 function Options.LoadOptions(document)
 function Options.LoadOptions(document)
     local f = io.open('options.dat', 'r')
     local f = io.open('options.dat', 'r')
     --create the function below
     --create the function below
-    local options = cPickle.loads(''.join(f:lines()))
+    local options = nil --cPickle.loads(''.join(f:lines()))
     
     
     document:GetElementById(options['graphics']).checked = true
     document:GetElementById(options['graphics']).checked = true
     document:GetElementById('reverb').checked = options['reverb']
     document:GetElementById('reverb').checked = options['reverb']
     document:GetElementById('3d').checked = options['3d']
     document:GetElementById('3d').checked = options['3d']
 end
 end
 
 
-function Options.SaveOptions(event, document):
+function Options.SaveOptions(event)
     if event.parameters['button'] == 'cancel' then
     if event.parameters['button'] == 'cancel' then
         return
         return
     end
     end
@@ -51,11 +51,11 @@ function Options.SaveOptions(event, document):
     
     
     local f = io.open('options.dat', 'w+')
     local f = io.open('options.dat', 'w+')
     --need the below function
     --need the below function
-    f:write(cPickle.dumps(options))
+    --f:write(cPickle.dumps(options))
     f:close()
     f:close()
 end
 end
 		
 		
-function Options.DisplayBadGraphics(document, display):
+function Options.DisplayBadGraphics(document, display)
 	if display then
 	if display then
 		document:GetElementById('bad_warning').style.display = 'block'
 		document:GetElementById('bad_warning').style.display = 'block'
 	else
 	else
@@ -66,13 +66,13 @@ end
 	</script>
 	</script>
 	</head>
 	</head>
 	<body template="luawindow" onload="Window.OnWindowLoad(element) Options.LoadOptions(document)">
 	<body template="luawindow" onload="Window.OnWindowLoad(element) Options.LoadOptions(document)">
-		<form onsubmit="Options.SaveOptions(event, document) Window.LoadMenu('main_menu')">
+		<form onsubmit="Options.SaveOptions(event) Window.LoadMenu('main_menu',document)">
 			<div>
 			<div>
 				<p>
 				<p>
 					Graphics:<br />
 					Graphics:<br />
 					<input id="good" type="radio" name="graphics" value="good"/> Good<br />
 					<input id="good" type="radio" name="graphics" value="good"/> Good<br />
 					<input id="ok" type="radio" name="graphics" value="ok" checked="true"/> OK<br />
 					<input id="ok" type="radio" name="graphics" value="ok" checked="true"/> OK<br />
-					<input id="bad" type="radio" name="graphics" value="bad" onchange="DisplayBadGraphics(document, self.checked)" /> Bad<br />
+					<input id="bad" type="radio" name="graphics" value="bad" onchange="Options.DisplayBadGraphics(document, true)" /> Bad<br />
 				</p>
 				</p>
 				<p id="bad_warning" style="display: none;">Are you sure about this? Bad graphics are just plain <em>bad.</em></p>
 				<p id="bad_warning" style="display: none;">Are you sure about this? Bad graphics are just plain <em>bad.</em></p>
 				<p>
 				<p>

+ 3 - 7
Samples/luainvaders/lua/start.lua

@@ -1,12 +1,8 @@
 
 
 function Startup()
 function Startup()
-    local escape = rocket.key_identifier["ESCAPE"]
-    if escape ~= nil then
-        maincontext = rocket.contexts()["main"]
-        maincontext:LoadDocument("data/background.rml"):Show()
-        local doc = maincontext:LoadDocument("data/main_menu.rml")
-        doc:Show()
-    end
+	maincontext = rocket.contexts()["main"]
+	maincontext:LoadDocument("data/background.rml"):Show()
+	maincontext:LoadDocument("data/main_menu.rml"):Show()
 end
 end
 
 
 Startup()
 Startup()

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

@@ -133,6 +133,7 @@ int main(int, char**)
 	
 	
 	// Shutdown Python before we shut down Rocket.
 	// Shutdown Python before we shut down Rocket.
 	//PythonInterface::Shutdown();
 	//PythonInterface::Shutdown();
+	Rocket::Core::Lua::Interpreter::Shutdown();
 
 
 	// Shut down the game singletons.
 	// Shut down the game singletons.
 	HighScores::Shutdown();
 	HighScores::Shutdown();

+ 38 - 1
Source/Core/Lua/Context.cpp

@@ -2,6 +2,8 @@
 #include "Context.h"
 #include "Context.h"
 #include <Rocket/Core/Context.h>
 #include <Rocket/Core/Context.h>
 #include <Rocket/Core/ElementDocument.h>
 #include <Rocket/Core/ElementDocument.h>
+#include <Rocket/Core/Factory.h>
+#include "LuaEventListener.h"
 
 
 namespace Rocket {
 namespace Rocket {
 namespace Core {
 namespace Core {
@@ -12,6 +14,38 @@ typedef Rocket::Core::ElementDocument Document;
 int ContextAddEventListener(lua_State* L, Context* obj)
 int ContextAddEventListener(lua_State* L, Context* obj)
 {
 {
    //need to make an EventListener for Lua before I can do anything else
    //need to make an EventListener for Lua before I can do anything else
+	LUACHECKOBJ(obj);
+	const char* evt = luaL_checkstring(L,1); //event
+	Element* element = NULL;
+	bool capturephase = false;
+	//get the rest of the stuff needed to construct the listener
+	if(lua_gettop(L) > 2)
+	{
+		if(!lua_isnoneornil(L,3))
+			element = LuaType<Element>::check(L,3);
+		if(!lua_isnoneornil(L,4))
+			capturephase = CHECK_BOOL(L,4);
+
+	}
+	int type = lua_type(L,2);
+	if(type == LUA_TFUNCTION)
+	{
+		if(element)
+			element->AddEventListener(evt, new LuaEventListener(L,2,element), capturephase);
+		else
+			obj->AddEventListener(evt, new LuaEventListener(L,2,NULL), capturephase);
+	}
+	else if(type == LUA_TSTRING)
+	{
+		if(element)
+			element->AddEventListener(evt, new LuaEventListener(luaL_checkstring(L,2),element), capturephase);
+		else
+			obj->AddEventListener(evt, new LuaEventListener(luaL_checkstring(L,2),NULL), capturephase);
+	}
+	else
+	{
+		Log::Message(Log::LT_WARNING, "Lua Context:AddEventLisener's 2nd argument can only be a Lua function or a string, you passed in a %s", lua_typename(L,type));
+	}
     return 0;
     return 0;
 }
 }
 
 
@@ -31,6 +65,8 @@ int ContextCreateDocument(lua_State* L, Context* obj)
         tag = luaL_checkstring(L,1);
         tag = luaL_checkstring(L,1);
     Document* doc = obj->CreateDocument(tag);
     Document* doc = obj->CreateDocument(tag);
     LuaType<Document>::push(L,doc,true);
     LuaType<Document>::push(L,doc,true);
+	//for debugging
+	int count = doc->GetReferenceCount();
     return 1;
     return 1;
 }
 }
 
 
@@ -38,7 +74,8 @@ int ContextLoadDocument(lua_State* L, Context* obj)
 {
 {
     const char* path = luaL_checkstring(L,1);
     const char* path = luaL_checkstring(L,1);
     Document* doc = obj->LoadDocument(path);
     Document* doc = obj->LoadDocument(path);
-    LuaType<Document>::push(L,doc,true);
+    LuaType<Document>::push(L,doc,false);
+	doc->RemoveReference();
     return 1;
     return 1;
 }
 }
 
 

+ 10 - 2
Source/Core/Lua/Context.h

@@ -3,12 +3,12 @@
     This defines a Context type in the Lua global namespace
     This defines a Context type in the Lua global namespace
 
 
     //methods
     //methods
-    Context:AddEventListener --NYI
+    noreturn Context:AddEventListener(string event, function | string listener, [Element element, bool capture]) --see note at the bottom
     noreturn Context:AddMouseCursor(Document cursor_document)
     noreturn Context:AddMouseCursor(Document cursor_document)
     Document Context:CreateDocument([string tag]) --tag defaults to "body"
     Document Context:CreateDocument([string tag]) --tag defaults to "body"
     Document Context:LoadDocument(string path)
     Document Context:LoadDocument(string path)
     Document Context:LoadMouseCursor(string path)
     Document Context:LoadMouseCursor(string path)
-    bool Context:Render
+    bool Context:Render()
     noreturn Context:ShowMouseCursor(bool show)
     noreturn Context:ShowMouseCursor(bool show)
     noreturn Context:UnloadAllDocuments()
     noreturn Context:UnloadAllDocuments()
     noreturn Context:UnloadAllMouseCursors()
     noreturn Context:UnloadAllMouseCursors()
@@ -27,6 +27,14 @@
     //setters
     //setters
     Context.dimensions = Vector2i
     Context.dimensions = Vector2i
 
 
+	--note 1
+	--[[
+	Context:AddEventListener has 2 'unusuals'. The first is that the 2nd argument can be either a string or a function;
+	see footnote 1 in Element.h for more info
+	The second is the optional parameters. If you pass in an element (anything not nil), then it will actually call 
+	element->AddEventListener and will call context->AddEventListener otherwise. capture will default to false
+	]]
+
 */
 */
 #include "LuaType.h"
 #include "LuaType.h"
 #include "lua.hpp"
 #include "lua.hpp"

+ 8 - 6
Source/Core/Lua/Element.cpp

@@ -13,10 +13,10 @@ typedef ElementDocument Document;
 int ElementAddEventListener(lua_State* L, Element* obj)
 int ElementAddEventListener(lua_State* L, Element* obj)
 {
 {
     int top = lua_gettop(L);
     int top = lua_gettop(L);
-    bool capture;
+    bool capture = false;
     //default false if they didn't pass it in
     //default false if they didn't pass it in
-    if (top < 3) capture = false;
-    else capture = CHECK_BOOL(L,3);
+    if (top > 3)
+		capture = CHECK_BOOL(L,3);
 
 
     const char* event = luaL_checkstring(L,1);
     const char* event = luaL_checkstring(L,1);
 
 
@@ -24,15 +24,17 @@ int ElementAddEventListener(lua_State* L, Element* obj)
     int type = lua_type(L,2);
     int type = lua_type(L,2);
     if(type == LUA_TFUNCTION)
     if(type == LUA_TFUNCTION)
     {
     {
-        lua_pushvalue(L,2);
-        int ref = lua_ref(L,true);
-        listener = new LuaEventListener(ref,obj);
+        listener = new LuaEventListener(L,2,obj);
     }
     }
     else if(type == LUA_TSTRING)
     else if(type == LUA_TSTRING)
     {
     {
         const char* code = luaL_checkstring(L,2);
         const char* code = luaL_checkstring(L,2);
         listener = new LuaEventListener(code,obj);
         listener = new LuaEventListener(code,obj);
     }
     }
+	else
+	{
+		Log::Message(Log::LT_WARNING, "Lua Context:AddEventLisener's 2nd argument can only be a Lua function or a string, you passed in a %s", lua_typename(L,type));
+	}
 
 
     if(listener != NULL)
     if(listener != NULL)
     {
     {

+ 7 - 1
Source/Core/Lua/Interpreter.cpp

@@ -163,7 +163,8 @@ void Interpreter::OnInitialise()
 
 
 void Interpreter::OnShutdown()
 void Interpreter::OnShutdown()
 {
 {
-    lua_close(_L);
+	//causing crashes
+    //lua_close(_L);
 }
 }
 
 
 void Interpreter::Initialise()
 void Interpreter::Initialise()
@@ -171,6 +172,11 @@ void Interpreter::Initialise()
     Rocket::Core::RegisterPlugin(new Interpreter());
     Rocket::Core::RegisterPlugin(new Interpreter());
 }
 }
 
 
+void Interpreter::Shutdown()
+{
+	lua_close(_L);
+}
+
 }
 }
 }
 }
 }
 }

+ 1 - 0
Source/Core/Lua/Interpreter.h

@@ -26,6 +26,7 @@ public:
     static lua_State* GetLuaState();
     static lua_State* GetLuaState();
 
 
     static void Initialise();
     static void Initialise();
+	static void Shutdown();
     
     
     //From Plugin
     //From Plugin
     virtual int GetEventClasses();
     virtual int GetEventClasses();

+ 27 - 15
Source/Core/Lua/LuaEventListener.cpp

@@ -35,16 +35,32 @@ LuaEventListener::LuaEventListener(const String& code, Element* element) : Event
     lua_pop(L,1); //pop the EVENTLISTENERFUNCTIONS table
     lua_pop(L,1); //pop the EVENTLISTENERFUNCTIONS table
 
 
     attached = element;
     attached = element;
-    parent = element->GetOwnerDocument();
+	if(element)
+		parent = element->GetOwnerDocument();
+	else
+		parent = NULL;
     strFunc = function;
     strFunc = function;
 }
 }
 
 
-//if it is created from a Lua Element
-LuaEventListener::LuaEventListener(int ref, Element* element)
+//if it is passed in a Lua function
+LuaEventListener::LuaEventListener(lua_State* L, int narg, Element* element)
 {
 {
-    luaFuncRef = ref;
-    attached = element;
-    parent = element->GetOwnerDocument();
+    lua_getglobal(L,"EVENTLISTENERFUNCTIONS");
+	if(lua_isnoneornil(L,-1))
+	{
+		lua_newtable(L);
+		lua_setglobal(L,"EVENTLISTENERFUNCTIONS");
+		lua_pop(L,1); //pop the unsucessful getglobal
+		lua_getglobal(L,"EVENTLISTENERFUNCTIONS");
+	}
+	lua_pushvalue(L,narg);
+	luaFuncRef = luaL_ref(L,-2); //put the funtion as a ref in to that table
+	lua_pop(L,1); //pop the EVENTLISTENERFUNCTIONS table
+	attached = element;
+	if(element)
+		parent = element->GetOwnerDocument();
+	else
+		parent = NULL;
 }
 }
 
 
 LuaEventListener::~LuaEventListener()
 LuaEventListener::~LuaEventListener()
@@ -61,19 +77,15 @@ void LuaEventListener::ProcessEvent(Event& event)
     //not sure if this is the right place to do this, but if the element we are attached to isn't a document, then
     //not sure if this is the right place to do this, but if the element we are attached to isn't a document, then
     //the 'parent' variable will be NULL, because element->ower_document hasn't been set on the construction. We should
     //the 'parent' variable will be NULL, because element->ower_document hasn't been set on the construction. We should
     //correct that
     //correct that
-    if(!parent) parent = attached->GetOwnerDocument();
+    if(!parent && attached) parent = attached->GetOwnerDocument();
     lua_State* L = Interpreter::GetLuaState();
     lua_State* L = Interpreter::GetLuaState();
-    String strtype;
     int top = lua_gettop(L); 
     int top = lua_gettop(L); 
     //push the arguments
     //push the arguments
     lua_getglobal(L,"EVENTLISTENERFUNCTIONS");
     lua_getglobal(L,"EVENTLISTENERFUNCTIONS");
-    int table = lua_gettop(L); //needed for lua_remove
-    strtype = lua_typename(L,lua_type(L,table));
-    lua_rawgeti(L,table,luaFuncRef);
-    strtype = lua_typename(L,lua_type(L,-1));
-    strtype = lua_typename(L,lua_type(L,LuaType<Event>::push(L,&event,false)));
-    strtype = lua_typename(L,lua_type(L,LuaType<Element>::push(L,attached,false)));
-    strtype = lua_typename(L,lua_type(L,LuaType<Document>::push(L,parent,false)));
+    lua_rawgeti(L,-1,luaFuncRef);
+    LuaType<Event>::push(L,&event,false);
+	LuaType<Element>::push(L,attached,false);
+    LuaType<Document>::push(L,parent,false);
     
     
     Interpreter::ExecuteCall(3,0); //call the function at the top of the stack with 3 arguments
     Interpreter::ExecuteCall(3,0); //call the function at the top of the stack with 3 arguments
 
 

+ 2 - 1
Source/Core/Lua/LuaEventListener.h

@@ -17,7 +17,8 @@ public:
     //This is called from a Lua Element if in element:AddEventListener it passes a function in as the 2nd
     //This is called from a Lua Element if in element:AddEventListener it passes a function in as the 2nd
     //parameter rather than a string. We don't wrap the function in an anonymous function, so the user
     //parameter rather than a string. We don't wrap the function in an anonymous function, so the user
     //should take care to have the proper order. The order is event,element,document.
     //should take care to have the proper order. The order is event,element,document.
-    LuaEventListener(int ref, Element* element);
+	//narg is the position on the stack
+    LuaEventListener(lua_State* L, int narg, Element* element);
 
 
     virtual ~LuaEventListener();
     virtual ~LuaEventListener();
 
 

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

@@ -293,7 +293,7 @@ template<> void LuaType<Log>::extra_init(lua_State* L, int metatable_index)
     int method_index = metatable_index - 1;
     int method_index = metatable_index - 1;
 
 
     lua_pushcfunction(L,LogMessage);
     lua_pushcfunction(L,LogMessage);
-    lua_setfield(L,metatable_index, "Message");
+    lua_setfield(L,method_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
     //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);
     lua_newtable(L);