Browse Source

Core::Lua Plugin now deletes itself on Core::Shutdown.

Michael Ragazzon 6 years ago
parent
commit
e21b962117

+ 37 - 43
Include/RmlUi/Core/Lua/Interpreter.h

@@ -37,6 +37,9 @@ namespace Rml {
 namespace Core {
 namespace Core {
 namespace Lua {
 namespace Lua {
 
 
+class LuaDocumentElementInstancer;
+class LuaEventListenerInstancer;
+
 /**
 /**
     This initializes the Lua interpreter, and has functions to load the scripts or
     This initializes the Lua interpreter, and has functions to load the scripts or
     call functions that exist in Lua.
     call functions that exist in Lua.
@@ -46,6 +49,24 @@ namespace Lua {
 class RMLUILUA_API Interpreter : public Plugin
 class RMLUILUA_API Interpreter : public Plugin
 {
 {
 public:
 public:
+	/** Creates the plugin.
+	@remark This is equivilent to calling Initialise(nullptr). */
+	static void Initialise();
+
+	/** Creates the plugin and adds RmlUi to an existing Lua state if one is provided.
+	 @remark If nullptr is passed as an argument, the plugin will automatically create the lua state during initialisation
+	   and close the state during the call to Rml::Core::Shutdown(). Otherwise, if a Lua state is provided, the user is 
+	   responsible for closing the provided Lua state. The state must then be closed after the call to Rml::Core::Shutdown().
+	 @remark The plugin registers the "body" tag to generate a LuaDocument rather than a Rml::Core::ElementDocument. */
+	static void Initialise(lua_State* L);
+
+	/**
+	@return The lua_State that the Interpreter created in Interpreter::Startup()
+	@remark This class lacks a SetLuaState for a reason. If you have to use a seperate Lua binding and want to keep the types
+	from RmlUi, then use this lua_State; it will already have all of the libraries loaded, and all of the types defined.
+	Alternatively, you can call RegisterCoreTypes(lua_State*) with your own Lua state if you need them defined in it. */
+	static lua_State* GetLuaState();
+
     /** This function calls luaL_loadfile and then lua_pcall, reporting the errors (if any)
     /** This function calls luaL_loadfile and then lua_pcall, reporting the errors (if any)
     @param[in] file Fully qualified file name to execute.
     @param[in] file Fully qualified file name to execute.
     @remark Somewhat misleading name if you are used to the Lua meaning of "load file". It behaves
     @remark Somewhat misleading name if you are used to the Lua meaning of "load file". It behaves
@@ -77,53 +98,26 @@ public:
     /** removes 'res' number of items from the stack
     /** removes 'res' number of items from the stack
     @param[in] res Number of results to remove from the stack.   */
     @param[in] res Number of results to remove from the stack.   */
     static void EndCall(int res = 0);
     static void EndCall(int res = 0);
-
-    /** This will populate the global Lua table with all of the Lua core types by calling LuaType<T>::Register
-    @param[in] L The lua_State to use to register the types
-    @remark This is called automatically inside of Interpreter::Startup(), so you do not have to 
-    call this function upon initialization of the Interpreter. If you are using RmlControlsLua, then you
-    \em will need to call Rml::Controls::Lua::RegisterTypes(lua_State*)     */
-    static void RegisterCoreTypes(lua_State* L);
-
-    /** 
-    @return The lua_State that the Interpreter created in Interpreter::Startup()
-    @remark This class lacks a SetLuaState for a reason. If you have to use a seperate Lua binding and want to keep the types
-    from RmlUi, then use this lua_State; it will already have all of the libraries loaded, and all of the types defined.
-    Alternatively, you can call RegisterCoreTypes(lua_State*) with your own Lua state if you need them defined in it. */
-    static lua_State* GetLuaState();
-
-    /** Creates the plugin. 
-	@remark This is equivilent to calling Initialise(nullptr).
-      */
-    static void Initialise();
-    /** Creates the plugin and adds RmlUi to an existing Lua context if one is provided.
-	 @remark Call this function only once, and special care must be taken when destroying the lua_State passed to this method.
-	 Interpreter::Shutdown() calles lua_close on the lua_State pointer provided here, do not call Interpreter::Shutdown if you
-	 must call lua_close yourself or if you need to continue to use the lua_State pointer provided here.  Internally, it calls
-	 Interpreter::Startup() and registers the "body" tag to generate a LuaDocument rather than a Rml::Core::ElementDocument.
-	 If the argument provided is nullptr, a Lua context is created automatically instead. */
-    static void Initialise(lua_State *_L);
-
-    /** Stops the plugin by calling lua_close
-	 @remark Shutdown calls lua_Close on the lua_State associated with the Interpreter.  If a lua_State was provided in the
-	 original call to Initialise, Shutdown should not be called OR you must not call lua_Close from within your code. */
-	static void Shutdown();
     
     
-    /** @sa Rml::Core::Plugin::GetEventClasses */
-    virtual int GetEventClasses();
-    /** @sa Rml::Core::Plugin::OnInitialise */
-    virtual void OnInitialise();
-    /** Currently does nothing. You must call Interpreter::Shutdown yourself at the appropriate time.
-    @sa Rml::Core::Plugin::OnShutdown    */
-    virtual void OnShutdown();
 private:
 private:
-    /** Creates a lua_State for @var _L and calls luaL_openlibs, then calls Interpreter::RegisterCoreTypes(lua_State*)
-    @remark called by Interpreter::Initialise()    */
-    void Startup();
+    int GetEventClasses() override;
+    
+	void OnInitialise() override;
+    
+	void OnShutdown() override;
+
+	/** This will populate the global Lua table with all of the Lua core types by calling LuaType<T>::Register
+	@param[in] L The lua_State to use to register the types
+	@remark This is called automatically inside of Interpreter::Startup(), so you do not have to
+	call this function upon initialization of the Interpreter. If you are using RmlControlsLua, then you
+	\em will need to call Rml::Controls::Lua::RegisterTypes(lua_State*)     */
+	static void RegisterCoreTypes(lua_State* L);
 
 
-    /** Lua state that Interpreter::Initialise() creates.    */
-    static lua_State* _L;
+	LuaDocumentElementInstancer* lua_document_element_instancer = nullptr;
+	LuaEventListenerInstancer* lua_event_listener_instancer = nullptr;
+	bool owns_lua_state = false;
 };
 };
+
 }
 }
 }
 }
 }
 }

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

@@ -129,11 +129,6 @@ int main(int, char**)
 
 
 	Shell::EventLoop(GameLoop);	
 	Shell::EventLoop(GameLoop);	
 
 
-	Rml::Core::RemoveContext(context->GetName());
-
-	// Shutdown Lua before we shut down RmlUi.
-	Rml::Core::Lua::Interpreter::Shutdown();
-
 	// Shut down the game singletons.
 	// Shut down the game singletons.
 	HighScores::Shutdown();
 	HighScores::Shutdown();
 
 

+ 3 - 3
Source/Core/Element.cpp

@@ -1269,10 +1269,10 @@ bool Element::Focus()
 
 
 	// Update the focus chain up the hierarchy.
 	// Update the focus chain up the hierarchy.
 	Element* element = this;
 	Element* element = this;
-	while (element->GetParentNode())
+	while (Element* parent = element->GetParentNode())
 	{
 	{
-		element->GetParentNode()->focus = element;
-		element = element->GetParentNode();
+		parent->focus = element;
+		element = parent;
 	}
 	}
 
 
 	return true;
 	return true;

+ 90 - 87
Source/Core/Lua/Interpreter.cpp

@@ -60,50 +60,29 @@
 namespace Rml {
 namespace Rml {
 namespace Core {
 namespace Core {
 namespace Lua {
 namespace Lua {
-lua_State* Interpreter::_L = nullptr;
+
+static lua_State* g_L = nullptr;
+
 //typedefs for nicer Lua names
 //typedefs for nicer Lua names
 typedef Rml::Core::ElementDocument Document;
 typedef Rml::Core::ElementDocument Document;
 
 
-void Interpreter::Startup()
+
+void Interpreter::Initialise()
 {
 {
-	if(_L == nullptr)
-	{
-		Log::Message(Log::LT_INFO, "Loading Lua interpreter");
-		_L = luaL_newstate();
-		luaL_openlibs(_L);
-	}
-    RegisterCoreTypes(_L);
+	Rml::Core::Lua::Interpreter::Initialise(nullptr);
 }
 }
 
 
-
-void Interpreter::RegisterCoreTypes(lua_State* L)
+void Interpreter::Initialise(lua_State* luaStatePointer)
 {
 {
-    LuaType<Vector2i>::Register(L);
-    LuaType<Vector2f>::Register(L);
-    LuaType<Colourf>::Register(L);
-    LuaType<Colourb>::Register(L);
-    LuaType<Log>::Register(L);
-    LuaType<ElementStyleProxy>::Register(L);
-    LuaType<Element>::Register(L);
-        //things that inherit from Element
-        LuaType<Document>::Register(L);
-        LuaType<ElementText>::Register(L);
-    LuaType<ElementPtr>::Register(L);
-    LuaType<Event>::Register(L);
-    LuaType<Context>::Register(L);
-    LuaType<LuaRmlUi>::Register(L);
-    LuaType<ElementInstancer>::Register(L);
-    //Proxy tables
-    LuaType<ContextDocumentsProxy>::Register(L);
-    LuaType<EventParametersProxy>::Register(L);
-    LuaType<ElementAttributesProxy>::Register(L);
-    LuaType<ElementChildNodesProxy>::Register(L);
-    LuaType<RmlUiContextsProxy>::Register(L);
-    OverrideLuaGlobalFunctions(L);
-    //push the global variable "rmlui" to use the "RmlUi" methods
-    LuaRmlUiPushrmluiGlobal(L);
+	RMLUI_ASSERT(g_L == nullptr);
+	g_L = luaStatePointer;
+	Rml::Core::RegisterPlugin(new Interpreter());
 }
 }
 
 
+lua_State* Interpreter::GetLuaState() 
+{
+	return g_L;
+}
 
 
 
 
 void Interpreter::LoadFile(const String& file)
 void Interpreter::LoadFile(const String& file)
@@ -112,27 +91,27 @@ void Interpreter::LoadFile(const String& file)
     Rml::Core::FileInterface* file_interface = Rml::Core::GetFileInterface();
     Rml::Core::FileInterface* file_interface = Rml::Core::GetFileInterface();
     Rml::Core::FileHandle handle = file_interface->Open(file);
     Rml::Core::FileHandle handle = file_interface->Open(file);
     if(handle == 0) {
     if(handle == 0) {
-        lua_pushfstring(_L, "LoadFile: Unable to open file: %s", file.c_str());
-        Report(_L);
+        lua_pushfstring(g_L, "LoadFile: Unable to open file: %s", file.c_str());
+        Report(g_L);
         return;
         return;
     }
     }
 
 
     size_t size = file_interface->Length(handle);
     size_t size = file_interface->Length(handle);
     if(size == 0) {
     if(size == 0) {
-        lua_pushfstring(_L, "LoadFile: File is 0 bytes in size: %s", file.c_str());
-        Report(_L);
+        lua_pushfstring(g_L, "LoadFile: File is 0 bytes in size: %s", file.c_str());
+        Report(g_L);
         return;
         return;
     }
     }
     char* file_contents = new char[size];
     char* file_contents = new char[size];
     file_interface->Read(file_contents,size,handle);
     file_interface->Read(file_contents,size,handle);
     file_interface->Close(handle);
     file_interface->Close(handle);
 
 
-    if(luaL_loadbuffer(_L,file_contents,size,file.c_str()) != 0)
-        Report(_L); 
+    if(luaL_loadbuffer(g_L,file_contents,size,file.c_str()) != 0)
+        Report(g_L); 
     else //if there were no errors loading, then the compiled function is on the top of the stack
     else //if there were no errors loading, then the compiled function is on the top of the stack
     {
     {
-        if(lua_pcall(_L,0,0,0) != 0)
-            Report(_L);
+        if(lua_pcall(g_L,0,0,0) != 0)
+            Report(g_L);
     }
     }
 
 
     delete[] file_contents;
     delete[] file_contents;
@@ -141,34 +120,34 @@ void Interpreter::LoadFile(const String& file)
 
 
 void Interpreter::DoString(const Rml::Core::String& code, const Rml::Core::String& name)
 void Interpreter::DoString(const Rml::Core::String& code, const Rml::Core::String& name)
 {
 {
-    if(luaL_loadbuffer(_L,code.c_str(),code.length(), name.c_str()) != 0)
-        Report(_L);
+    if(luaL_loadbuffer(g_L,code.c_str(),code.length(), name.c_str()) != 0)
+        Report(g_L);
     else
     else
     {
     {
-        if(lua_pcall(_L,0,0,0) != 0)
-            Report(_L);
+        if(lua_pcall(g_L,0,0,0) != 0)
+            Report(g_L);
     }
     }
 }
 }
 
 
 void Interpreter::LoadString(const Rml::Core::String& code, const Rml::Core::String& name)
 void Interpreter::LoadString(const Rml::Core::String& code, const Rml::Core::String& name)
 {
 {
-    if(luaL_loadbuffer(_L,code.c_str(),code.length(), name.c_str()) != 0)
-        Report(_L);
+    if(luaL_loadbuffer(g_L,code.c_str(),code.length(), name.c_str()) != 0)
+        Report(g_L);
 }
 }
 
 
 
 
 void Interpreter::BeginCall(int funRef)
 void Interpreter::BeginCall(int funRef)
 {
 {
-    lua_settop(_L,0); //empty stack
-    //lua_getref(_L,funRef);
-    lua_rawgeti(_L, LUA_REGISTRYINDEX, (int)funRef);
+    lua_settop(g_L,0); //empty stack
+    //lua_getref(g_L,funRef);
+    lua_rawgeti(g_L, LUA_REGISTRYINDEX, (int)funRef);
 }
 }
 
 
 bool Interpreter::ExecuteCall(int params, int res)
 bool Interpreter::ExecuteCall(int params, int res)
 {
 {
     bool ret = true;
     bool ret = true;
-    int top = lua_gettop(_L);
-    if(lua_type(_L,top-params) != LUA_TFUNCTION)
+    int top = lua_gettop(g_L);
+    if(lua_type(g_L,top-params) != LUA_TFUNCTION)
     {
     {
         ret = false;
         ret = false;
         //stack cleanup
         //stack cleanup
@@ -176,16 +155,16 @@ bool Interpreter::ExecuteCall(int params, int res)
         {
         {
             for(int i = top; i >= (top-params); i--)
             for(int i = top; i >= (top-params); i--)
             {
             {
-                if(!lua_isnone(_L,i))
-                    lua_remove(_L,i);
+                if(!lua_isnone(g_L,i))
+                    lua_remove(g_L,i);
             }
             }
         }
         }
     }
     }
     else
     else
     {
     {
-        if(lua_pcall(_L,params,res,0) != 0)
+        if(lua_pcall(g_L,params,res,0) != 0)
         {
         {
-            Report(_L);
+            Report(g_L);
             ret = false;
             ret = false;
         }
         }
     }
     }
@@ -197,13 +176,11 @@ void Interpreter::EndCall(int res)
     //stack cleanup
     //stack cleanup
     for(int i = res; i > 0; i--)
     for(int i = res; i > 0; i--)
     {
     {
-        if(!lua_isnone(_L,res))
-            lua_remove(_L,res);
+        if(!lua_isnone(g_L,res))
+            lua_remove(g_L,res);
     }
     }
 }
 }
 
 
-lua_State* Interpreter::GetLuaState() { return _L; }
-
 
 
 //From Plugin
 //From Plugin
 int Interpreter::GetEventClasses()
 int Interpreter::GetEventClasses()
@@ -211,46 +188,72 @@ int Interpreter::GetEventClasses()
     return EVT_BASIC;
     return EVT_BASIC;
 }
 }
 
 
-static LuaDocumentElementInstancer* g_lua_document_element_instancer = nullptr;
-static LuaEventListenerInstancer* g_lua_event_listener_instancer = nullptr;
-
 void Interpreter::OnInitialise()
 void Interpreter::OnInitialise()
 {
 {
-    Startup();
-	g_lua_document_element_instancer = new LuaDocumentElementInstancer();
-	g_lua_event_listener_instancer = new LuaEventListenerInstancer();
-    Factory::RegisterElementInstancer("body", g_lua_document_element_instancer);
-	Factory::RegisterEventListenerInstancer(g_lua_event_listener_instancer);
+	if (g_L == nullptr)
+	{
+		Log::Message(Log::LT_INFO, "Loading Lua interpreter");
+		g_L = luaL_newstate();
+		luaL_openlibs(g_L);
+		owns_lua_state = true;
+	}
+	else
+	{
+		owns_lua_state = false;
+	}
+	RegisterCoreTypes(g_L);
+
+	lua_document_element_instancer = new LuaDocumentElementInstancer();
+	lua_event_listener_instancer = new LuaEventListenerInstancer();
+    Factory::RegisterElementInstancer("body", lua_document_element_instancer);
+	Factory::RegisterEventListenerInstancer(lua_event_listener_instancer);
 }
 }
 
 
 void Interpreter::OnShutdown()
 void Interpreter::OnShutdown()
 {
 {
-	delete g_lua_document_element_instancer;
-	delete g_lua_event_listener_instancer;
-	g_lua_document_element_instancer = nullptr;
-	g_lua_event_listener_instancer = nullptr;
-}
+	delete lua_document_element_instancer;
+	delete lua_event_listener_instancer;
+	lua_document_element_instancer = nullptr;
+	lua_event_listener_instancer = nullptr;
 
 
-void Interpreter::Initialise()
-{
-    Rml::Core::Lua::Interpreter::Initialise(nullptr);
-}
+	if (owns_lua_state)
+		lua_close(g_L);
+	
+	g_L = nullptr;
 
 
-void Interpreter::Initialise(lua_State *luaStatePointer)
-{
-	Interpreter *iPtr = new Interpreter();
-	iPtr->_L = luaStatePointer;
-	Rml::Core::RegisterPlugin(iPtr);
+	delete this;
 }
 }
 
 
-void Interpreter::Shutdown()
+void Interpreter::RegisterCoreTypes(lua_State* L)
 {
 {
-	lua_close(_L);
+	LuaType<Vector2i>::Register(L);
+	LuaType<Vector2f>::Register(L);
+	LuaType<Colourf>::Register(L);
+	LuaType<Colourb>::Register(L);
+	LuaType<Log>::Register(L);
+	LuaType<ElementStyleProxy>::Register(L);
+	LuaType<Element>::Register(L);
+	//things that inherit from Element
+	LuaType<Document>::Register(L);
+	LuaType<ElementText>::Register(L);
+	LuaType<ElementPtr>::Register(L);
+	LuaType<Event>::Register(L);
+	LuaType<Context>::Register(L);
+	LuaType<LuaRmlUi>::Register(L);
+	LuaType<ElementInstancer>::Register(L);
+	//Proxy tables
+	LuaType<ContextDocumentsProxy>::Register(L);
+	LuaType<EventParametersProxy>::Register(L);
+	LuaType<ElementAttributesProxy>::Register(L);
+	LuaType<ElementChildNodesProxy>::Register(L);
+	LuaType<RmlUiContextsProxy>::Register(L);
+	OverrideLuaGlobalFunctions(L);
+	//push the global variable "rmlui" to use the "RmlUi" methods
+	LuaRmlUiPushrmluiGlobal(L);
 }
 }
 
 
 
 
 
 
-
 }
 }
 }
 }
 }
 }