changeset 2682:776f049ffaf5 feature-particleuniverse

refs #34: Replaced Ogre Particle System with Particle Universe and improved particle handling in general
author Stefan Stammberger <some.fusion@gmail.com>
date Thu, 20 Mar 2014 19:20:41 +0100
parents bb4609184777
children e6e38155c234
files CMakeLists.txt CMakeModules/FindParticleUniverse.cmake src/core/sumwarshelper.cpp src/gui/application.cpp src/gui/default_resources.cfg.inc.in src/gui/graphicmanager.cpp src/gui/graphicmanager.h src/gui/graphicobject.cpp src/gui/graphicobject.h src/gui/mainmenu.cpp
diffstat 10 files changed, 249 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Thu Mar 20 18:08:50 2014 +0000
+++ b/CMakeLists.txt	Thu Mar 20 19:20:41 2014 +0100
@@ -195,6 +195,7 @@
 FIND_PACKAGE(Vorbis REQUIRED)
 FIND_PACKAGE(PhysFS REQUIRED)
 FIND_PACKAGE(Threads REQUIRED)
+FIND_PACKAGE(ParticleUniverse REQUIRED)
 
 if(WIN32)
   set(Boost_USE_STATIC_LIBS ON)
@@ -225,6 +226,7 @@
 ADD_DEFINITIONS(-DGUSSOUND_STANDALONE)
 INCLUDE_DIRECTORIES(${OGRE_INCLUDE_DIRS})
 INCLUDE_DIRECTORIES(${OGRE_RTShaderSystem_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${OGRE_Overlay_INCLUDE_DIR})
 IF (WIN32)
   Message(STATUS "Adding boost include: ${BoostOGRE_INCLUDE_DIR}")
   INCLUDE_DIRECTORIES(${BoostOGRE_INCLUDE_DIR})
@@ -241,6 +243,7 @@
 INCLUDE_DIRECTORIES(${VORBIS_INCLUDE_DIR})
 INCLUDE_DIRECTORIES(${PHYSFS_INCLUDE_DIR})
 INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(${PARTICLE_UNIVERSE_INCLUDE_DIRS})
 
 IF(SUMWARS_NO_TINYXML)
   INCLUDE_DIRECTORIES(${TINYXML_INCLUDE_DIR})
@@ -511,6 +514,7 @@
   ${OGRE_LIBRARIES}
   ${OGRE_Terrain_LIBRARY}
   ${OGRE_RTShaderSystem_LIBRARY}
+  ${OGRE_Overlay_LIBRARY}
   ${OIS_LIBRARIES} 
   ${CEGUI_LIBRARY} 
   ${CEGUIOGRE_LIBRARY}
@@ -523,6 +527,7 @@
   ${Boost_LIBRARIES}
   ${CMAKE_THREAD_LIBS_INIT}
   ${CPPNETLIB_LIBS}
+  ${PARTICLE_UNIVERSE_LIBRARIES}
   )
   
 IF(SUMWARS_BUILD_WITH_ONLINE_SERVICE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CMakeModules/FindParticleUniverse.cmake	Thu Mar 20 19:20:41 2014 +0100
@@ -0,0 +1,41 @@
+# - Try to find Particle Universe
+#  	Once done this will define
+#
+#	On Windows, this script will look for Particle Universe using the environment variable PUDIR
+#	The variable should point to the install directory
+#  
+#	PARTICLE_UNIVERSE_FOUND - System has ParticleUniverse
+#	PARTICLE_UNIVERSE_INCLUDE_DIRS - The ParticleUniverse include directories
+#	PARTICLE_UNIVERSE_LIBRARIES - The libraries needed to use Particle Universe
+#	PARTICLE_UNIVERSE_LIBRARIES_REL - The libraries needed to use Particle Universe
+#	PARTICLE_UNIVERSE_LIBRARIES_DEBUG - The libraries needed to use Particle Universe
+#	PARTICLE_UNIVERSE_DEFINITIONS - Compiler switches required for using Particle Universe
+
+include(FindPkgMacros)
+include(PreprocessorUtils)
+findpkg_begin(ParticleUniverse)
+
+STRING(REGEX REPLACE "\\\\" "/" PU_INSTALL_DIR $ENV{PUDIR})
+
+find_path(PARTICLE_UNIVERSE_INCLUDE_DIR ParticleUniversePlugin.h
+			HINTS ${PU_INSTALL_DIR}/include
+)
+
+find_library(PARTICLE_UNIVERSE_LIBRARY_REL NAMES Plugin_ParticleUniverse libPlugin_ParticleUniverse
+             HINTS ${PC_PARTICLE_UNIVERSE_LIBDIR} ${PC_PARTICLE_UNIVERSE_LIBRARY_DIRS} ${PU_INSTALL_DIR}/lib/Release ${PU_INSTALL_DIR}/lib/RelWithDebInfo ${PU_INSTALL_DIR}/lib/MinSizeRel )
+			 
+find_library(PARTICLE_UNIVERSE_LIBRARY_DEBUG NAMES Plugin_ParticleUniverse_d libPlugin_ParticleUniverse_d
+             HINTS ${PC_PARTICLE_UNIVERSE_LIBDIR} ${PC_PARTICLE_UNIVERSE_LIBRARY_DIRS} ${PU_INSTALL_DIR}/lib/Debug)
+
+set(PARTICLE_UNIVERSE_LIBRARIES ${PARTICLE_UNIVERSE_LIBRARY_REL} ${PARTICLE_UNIVERSE_LIBRARY_DEBUG})
+set(PARTICLE_UNIVERSE_LIBRARIES_REL ${PARTICLE_UNIVERSE_LIBRARY_REL}  )
+set(PARTICLE_UNIVERSE_LIBRARIES_DEBUG ${PARTICLE_UNIVERSE_LIBRARY_DEBUG} )
+set(PARTICLE_UNIVERSE_INCLUDE_DIRS ${PARTICLE_UNIVERSE_INCLUDE_DIR} )
+
+include(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set PARTICLE_UNIVERSE_FOUND to TRUE
+# if all listed variables are TRUE
+find_package_handle_standard_args(ParticleUniverse  DEFAULT_MSG
+                                  PARTICLE_UNIVERSE_LIBRARY_REL PARTICLE_UNIVERSE_LIBRARY_DEBUG PARTICLE_UNIVERSE_INCLUDE_DIR)
+
+mark_as_advanced(PARTICLE_UNIVERSE_INCLUDE_DIR PARTICLE_UNIVERSE_LIBRARY_REL PARTICLE_UNIVERSE_LIBRARY_DEBUG )
\ No newline at end of file
--- a/src/core/sumwarshelper.cpp	Thu Mar 20 18:08:50 2014 +0000
+++ b/src/core/sumwarshelper.cpp	Thu Mar 20 19:20:41 2014 +0100
@@ -153,7 +153,7 @@
 #ifdef _WIN32
         "Plugin=RenderSystem_Direct3D9" SUMWARS_DEBUG_POSTFIX "\n"
 #endif
-        "Plugin=Plugin_ParticleFX" SUMWARS_DEBUG_POSTFIX "\n"
+        "Plugin=Plugin_ParticleUniverse" SUMWARS_DEBUG_POSTFIX "\n"
         "Plugin=Plugin_OctreeSceneManager" SUMWARS_DEBUG_POSTFIX "\n";
 
 #include "default_resources.cfg.inc"
--- a/src/gui/application.cpp	Thu Mar 20 18:08:50 2014 +0000
+++ b/src/gui/application.cpp	Thu Mar 20 19:20:41 2014 +0100
@@ -42,7 +42,7 @@
 
 
 #include "OgreConfigFile.h"
-#include <OgreParticleSystemManager.h>
+#include <ParticleUniverseSystemManager.h>
 
 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 #include "../winicon/resource.h"
@@ -1146,7 +1146,7 @@
 		Ogre::ResourceGroupManager::getSingleton().loadResourceGroup("Particles");
 		if (m_running)
 		{
-			files = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("Particles","*.particle");
+            /*files = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("Particles","*.particle");
 			for (it = files->begin(); it != files->end(); ++it)
 			{
 				try
@@ -1155,14 +1155,14 @@
 					DEBUGX("loading script file %s",file.c_str());
 					Ogre::DataStreamPtr filehandle;
 					filehandle = Ogre::ResourceGroupManager::getSingleton().openResource(file);
-					Ogre::ParticleSystemManager::getSingleton().parseScript(filehandle,"Particles" ); 
+                    ParticleUniverse::ParticleSystemManager::getSingleton().parseScript(filehandle,"Particles" );
 					updateStartScreen(0.36);
 				}
 				catch (Ogre::Exception& e)
 				{
 					SW_DEBUG("failed with exception %s",e.what());
 				}
-			}
+            }*/
 		}
 	}
 	updateStartScreen(0.4);
@@ -1375,12 +1375,7 @@
 	}
 	
 	if (datagroups & World::DATA_PARTICLESYSTEMS)
-	{
-		//Ogre::ResourceGroupManager::getSingleton().unloadResourceGroup("Particles", true);
-		// delete all the templates from the ParticleSystemManager
-		Ogre::ParticleSystemManager& pmgr = Ogre::ParticleSystemManager::getSingleton();
-		pmgr.removeAllTemplates();
-		
+    {
 		GraphicManager::clearParticlePool();
 		DEBUGX("deleting particlesystems");
 	}
--- a/src/gui/default_resources.cfg.inc.in	Thu Mar 20 18:08:50 2014 +0000
+++ b/src/gui/default_resources.cfg.inc.in	Thu Mar 20 19:20:41 2014 +0100
@@ -64,7 +64,7 @@
 "FileSystem=@SUMWARS_PREFIX@/@SUMWARS_SHARE_DIR@/resources/materials/textures\n"
 "\n"
 "[Particles]\n"
-"FileSystem=@SUMWARS_PREFIX@/@SUMWARS_SHARE_DIR@/resources/particle/ogre_1_6\n"
+"FileSystem=@SUMWARS_PREFIX@/@SUMWARS_SHARE_DIR@/resources/particle/universe\n"
 "\n"
 "[GUI]\n"
 "FileSystem=@SUMWARS_PREFIX@/@SUMWARS_SHARE_DIR@/resources/gui_common/imagesets\n"
--- a/src/gui/graphicmanager.cpp	Thu Mar 20 18:08:50 2014 +0000
+++ b/src/gui/graphicmanager.cpp	Thu Mar 20 19:20:41 2014 +0100
@@ -16,6 +16,8 @@
 #include "graphicmanager.h"
 #include "debug.h"
 #include "elementattrib.h"
+#include "ParticleUniverseSystemManager.h"
+#include "config.h"
 
 double GraphicManager::g_global_scale = 1;
 
@@ -23,7 +25,7 @@
 Ogre::SceneManager* GraphicManager::m_scene_manager;
 std::map<std::string, GraphicObject::Type> GraphicManager::m_graphic_mapping;
 StencilOpQueueListener* GraphicManager::m_stencil_listener;
-std::multimap<std::string, Ogre::ParticleSystem*> GraphicManager::m_particle_system_pool;
+std::multimap<std::string, ParticleUniverse::ParticleSystem*> GraphicManager::m_particle_system_pool;
 std::string GraphicManager::m_filename;
 
 std::map<std::string, GraphicObject*> GraphicManager::m_graphic_objects;
@@ -100,13 +102,59 @@
 	} 
 } 
 
+template<> ParticleEventHandler* Ogre::Singleton<ParticleEventHandler>::SUMWARS_OGRE_SINGLETON = 0;
+
+ParticleEventHandler::ParticleEventHandler()
+{
+	m_temp_node = Ogre::Root::getSingleton().getSceneManager("DefaultSceneManager")->getRootSceneNode()->createChildSceneNode("ParticleEventHandler::TempNode");
+}
+
+void ParticleEventHandler::addParticleSystem(ParticleUniverse::ParticleSystem *sys, Ogre::SceneNode *n)
+{
+	if(!Ogre::Root::getSingleton().getSceneManager("DefaultSceneManager")->hasSceneNode("ParticleEventHandler::TempNode") || !m_temp_node)
+		m_temp_node = Ogre::Root::getSingleton().getSceneManager("DefaultSceneManager")->getRootSceneNode()->createChildSceneNode("ParticleEventHandler::TempNode");
+
+    if(!m_particle_systems[sys->getName()])
+    {
+        m_particle_systems[sys->getName()] = sys;
+		m_temp_node->addChild(n);
+		sys->stopFade();
+    }
+}
+
+void ParticleEventHandler::handleParticleSystemEvent(ParticleUniverse::ParticleSystem *particleSystem, ParticleUniverse::ParticleUniverseEvent &particleUniverseEvent)
+{
+    if(particleUniverseEvent.eventType == ParticleUniverse::PU_EVT_SYSTEM_STOPPED)
+    {
+			ParticleUniverse::ParticleSystem* psys = m_particle_systems[particleSystem->getName()];
+            if(psys)
+			{
+				Ogre::SceneNode *n = dynamic_cast<Ogre::SceneNode*>(particleSystem->getParentNode());
+				m_particle_systems.erase(psys->getName());
+                GraphicManager::putBackParticleSystem(psys);
+			}
+
+    }
+}
+
+ParticleEventHandler &ParticleEventHandler::getSingleton()
+{
+	assert( SUMWARS_OGRE_SINGLETON );
+	return ( *SUMWARS_OGRE_SINGLETON );
+}
+
+ParticleEventHandler *ParticleEventHandler::getSingletonPtr()
+{
+	return SUMWARS_OGRE_SINGLETON;
+}
+
 void GraphicManager::init()
 {
 	m_scene_manager = Ogre::Root::getSingleton().getSceneManager("DefaultSceneManager");
 	m_stencil_listener = new StencilOpQueueListener;
 	
 	m_scene_manager->addRenderQueueListener(m_stencil_listener);
-
+	new ParticleEventHandler();
 }
 
 void GraphicManager::cleanup()
@@ -241,7 +289,7 @@
 
 void GraphicManager::clearParticlePool()
 {
-	std::multimap<std::string, Ogre::ParticleSystem*>::iterator pt;
+    std::multimap<std::string, ParticleUniverse::ParticleSystem*>::iterator pt;
 	for (pt = m_particle_system_pool.begin(); pt != m_particle_system_pool.end(); ++pt)
 	{
 		m_scene_manager->destroyMovableObject(pt->second);
@@ -468,7 +516,7 @@
 	}
 	else if (info.m_type == MovableObjectInfo::PARTICLE_SYSTEM)
 	{
-		Ogre::ParticleSystem* part =0;
+		ParticleUniverse::ParticleSystem* part =0;
 		try
 		{
 			part = getParticleSystem(info.m_source);
@@ -491,14 +539,7 @@
 
 void GraphicManager::destroyMovableObject(Ogre::MovableObject* obj)
 {
-	if (obj->getMovableType() == "ParticleSystem")
-	{
-		putBackParticleSystem(static_cast<Ogre::ParticleSystem*>(obj));
-	}
-	else
-	{
-		m_scene_manager->destroyMovableObject(obj);
-	}
+    m_scene_manager->destroyMovableObject(obj);
 }
 
 std::string GraphicManager::getDropSound(std::string objecttype)
@@ -882,13 +923,13 @@
 	return "";
 }
 
-Ogre::ParticleSystem* GraphicManager::getParticleSystem(std::string type)
+ParticleUniverse::ParticleSystem* GraphicManager::getParticleSystem(std::string type)
 {
 	// search the pool for a fitting particle system
-	std::multimap<std::string, Ogre::ParticleSystem*>::iterator it;
+    std::multimap<std::string, ParticleUniverse::ParticleSystem*>::iterator it;
 	it = m_particle_system_pool.find(type);
 
-	Ogre::ParticleSystem* part=0;
+    ParticleUniverse::ParticleSystem* part=0;
 	static int count =0;
 
 	if (it == m_particle_system_pool.end())
@@ -898,7 +939,9 @@
 		name << "ParticleSystem"<<count;
 		count ++;
 
-		part = m_scene_manager->createParticleSystem(name.str(), type);
+        ParticleUniverse::ParticleSystemManager* pManager = ParticleUniverse::ParticleSystemManager::getSingletonPtr();
+		part = pManager->createParticleSystem(name.str(), type.c_str(), m_scene_manager);
+        part->addParticleSystemListener(ParticleEventHandler::getSingletonPtr());
 		// type is stored in the OGRE any Attribute
 		part->setUserAny(Ogre::Any(type));
 		DEBUGX("created particlesystem %p %s for type %s",part, name.str().c_str(), type.c_str());
@@ -911,11 +954,11 @@
 		DEBUGX("took particlesystem %s for type %s",part->getName().c_str(), type.c_str());
 	}
 
-	part->clear();
+	part->stop();
 	return part;
 }
 
-void GraphicManager::putBackParticleSystem(Ogre::ParticleSystem* part)
+void GraphicManager::putBackParticleSystem(ParticleUniverse::ParticleSystem* part)
 {
 	// store type of the particle system in OGRE any
 	std::string type;
--- a/src/gui/graphicmanager.h	Thu Mar 20 18:08:50 2014 +0000
+++ b/src/gui/graphicmanager.h	Thu Mar 20 19:20:41 2014 +0100
@@ -19,8 +19,8 @@
 
 #include "OgreSceneManager.h"
 #include "OgreRoot.h"
-#include "OgreParticleSystem.h"
 #include "OgreEntity.h"
+#include "ParticleUniverseSystem.h"
 #include "OgreMovableObject.h"
 #include "OgreStaticGeometry.h"
 #include "graphicobject.h"
@@ -58,6 +58,42 @@
 
 }; 
 
+class ParticleEventHandler : public ParticleUniverse::ParticleSystemListener, public Ogre::Singleton<ParticleEventHandler>
+{
+    // ParticleSystemListener interface
+public:
+
+    ParticleEventHandler();
+
+    /**
+     * @brief Adds a particle system to be destroyed when all particles have expired
+     * @param sys The particle system that is about to be deleted
+     */
+    void addParticleSystem(ParticleUniverse::ParticleSystem *sys, Ogre::SceneNode *n);
+
+    /**
+     * @brief handleParticleSystemEvent
+     * @param particleSystem
+     * @param particleUniverseEvent
+     */
+    void handleParticleSystemEvent(ParticleUniverse::ParticleSystem *particleSystem, ParticleUniverse::ParticleUniverseEvent &particleUniverseEvent);
+
+    static ParticleEventHandler& getSingleton();
+    static ParticleEventHandler* getSingletonPtr();
+
+private:
+    /**
+     * @brief objects Holds the objects that are about to be deleted
+     */
+    std::map<Ogre::String, ParticleUniverse::ParticleSystem*> m_particle_systems;
+
+
+    /**
+     * @brief This node holds the particle systems that will be removed from scene when all particles are gone
+     */
+    Ogre::SceneNode* m_temp_node;
+};
+
 /**
  * \brief Graphic object creation and destruction class
  * Class that manages creation and destruction of Graphicobject and Ogre::Movableobject objects. 
@@ -245,22 +281,22 @@
 		 */
 		static void loadRenderInfo(TiXmlNode* node, GraphicRenderInfo* info);
 		
+        /**
+         * \brief Returns an ParticleUniverse Particlesystem with the requested type
+         * \param type Type of a Particlesystem
+         * The particle system is taken from the particle pool. A new particle system is only created if there is none of the requested type in the pool
+         */
+        static ParticleUniverse::ParticleSystem* getParticleSystem(std::string type);
+
+        /**
+         * \brief Inserts the particle system into the particle pool
+         * \param part particle system
+        */
+        static void putBackParticleSystem(ParticleUniverse::ParticleSystem* part);
+
+
 	private:
-		
-		
-		/**
-		 * \brief Returns an OGRE Particlesystem with the requested type
-		 * \param type Type of a Particlesystem
-		 * The particle system is taken from the particle pool. A new particle system is only created if there is none of the requested type in the pool
-		 */
-		static Ogre::ParticleSystem* getParticleSystem(std::string type);
-	
-		/**
-		 * \brief Inserts the particle system into the particle pool
-		 * \param part particle system
-	 	*/
-		static void putBackParticleSystem(Ogre::ParticleSystem* part);
-		
+
 		/**
 		 * \brief Adds all entities in the subtree below the given scene node to the static geometry
 		 * \param node Top node of the scene subtree
@@ -316,7 +352,7 @@
 		/**
 		 * \brief internal pool of Particle system
 		 */
-		static std::multimap<std::string, Ogre::ParticleSystem*> m_particle_system_pool;
+        static std::multimap<std::string, ParticleUniverse::ParticleSystem*> m_particle_system_pool;
 		
 		/**
 		 * \brief Name of XML file being read at the moment
--- a/src/gui/graphicobject.cpp	Thu Mar 20 18:08:50 2014 +0000
+++ b/src/gui/graphicobject.cpp	Thu Mar 20 19:20:41 2014 +0100
@@ -34,6 +34,7 @@
 	
 	m_highlight = false;
 	m_exact_animations = false; // as default ?
+    m_delete_node = true;
 
 	initContent();
 }
@@ -75,7 +76,11 @@
 	{
 		removeMovableObject(m_dependencies.begin()->first);
 	}
-	m_top_node->getCreator()->destroySceneNode(m_top_node->getName());
+
+    if(m_delete_node)
+	{
+        m_top_node->getCreator()->destroySceneNode(m_top_node->getName());
+	}
 }
 
 void GraphicObject::invalidateRenderInfo()
@@ -330,7 +335,7 @@
 
 		m_soundobjects[object.m_objectname] = SoundObject (name);
 		//m_soundobjects[object.m_objectname] = name;
-		SW_DEBUG ("setting soundobject with name [%s] to: (%s)", object.m_objectname.c_str (), name.c_str ());
+		//SW_DEBUG ("setting soundobject with name [%s] to: (%s)", object.m_objectname.c_str (), name.c_str ());
 	}
 	else 
 	{
@@ -363,17 +368,52 @@
 		Ogre::TagPoint* tag =0;
 		Ogre::Entity* ent =0;
 		
-		// attach object to new Node
-		Ogre::SceneNode* snode = GraphicManager::getSceneManager()->getRootSceneNode()->createChildSceneNode();
-		snode->getParent()->removeChild(snode);
-		snode->setInheritScale(true);
-		snode->attachObject(obj);
+		Ogre::SceneNode* snode;
+		if(obj->getMovableType() == "PUParticleSystem")
+		{
+			ParticleUniverse::ParticleSystem* particle_system = static_cast<ParticleUniverse::ParticleSystem*>(obj);
+			snode = obj->getParentSceneNode();
+            m_delete_node = false;
+		
+			if(snode == 0)
+			{
+				// attach object to new Node
+				snode = GraphicManager::getSceneManager()->getRootSceneNode()->createChildSceneNode();
+				snode->getParent()->removeChild(snode);
+				snode->setInheritScale(true);
+				snode->attachObject(obj);
+			}
+			else
+			{
+				snode->getParentSceneNode()->removeChild(snode);
+			}
+
+			// need to start the particle system
+            particle_system->start();
+		}
+		else
+		{
+			// attach object to new Node
+			snode = GraphicManager::getSceneManager()->getRootSceneNode()->createChildSceneNode();
+			snode->getParent()->removeChild(snode);
+			snode->setInheritScale(true);
+			snode->attachObject(obj);
+		}
+
+
 		node = snode;
 		
 		if (object.m_bone == "")
 		{
 			// attach to Topnode
-			getTopNode()->addChild(node);
+			try
+			{
+				getTopNode()->addChild(node);
+			}
+			catch(Ogre::InvalidParametersException e)
+			{
+				SW_DEBUG(e.what());
+			}
 			DEBUGX("node %p parent %p",node,m_top_node );
 			m_attached_objects[object.m_objectname].m_tag_trackpoint = 0;
 		}
@@ -470,10 +510,20 @@
 		Ogre::Node* node = obj->getParentNode();
 		Ogre::SceneNode* snode = dynamic_cast<Ogre::SceneNode*>(node);
 		Ogre::TagPoint* tag = dynamic_cast<Ogre::TagPoint*>(node);
-		GraphicManager::detachMovableObject(obj);
-		
-		GraphicManager::destroyMovableObject(obj);
-		
+
+		if (obj->getMovableType() == "PUParticleSystem")
+		{
+			ParticleUniverse::ParticleSystem* sys = static_cast<ParticleUniverse::ParticleSystem*>(obj);
+			snode->getParentSceneNode()->removeChild(snode->getName());
+			ParticleEventHandler::getSingleton().addParticleSystem(sys, snode);
+		}
+		else
+		{
+			GraphicManager::detachMovableObject(obj);
+			snode->getCreator()->destroySceneNode(snode->getName());
+			GraphicManager::destroyMovableObject(obj);
+		}
+
 		// remove Highlight Entity
 		obj = getHighlightObject(name);
 		if (obj != 0)
@@ -483,7 +533,6 @@
 			GraphicManager::destroyMovableObject(obj);
 		}
 		
-		snode->getCreator()->destroySceneNode(snode->getName());
 		std::map<std::string, AttachedMovableObject>::iterator it;
 		it = m_attached_objects.find(name);
 		
--- a/src/gui/graphicobject.h	Thu Mar 20 18:08:50 2014 +0000
+++ b/src/gui/graphicobject.h	Thu Mar 20 19:20:41 2014 +0100
@@ -519,6 +519,11 @@
 		 * \brief Signals if the objects Renderinfo is still valid
 		 */
 		bool m_render_info_valid;
+
+        /**
+         * @brief Signals if the scene node should be deleted. Nodes of particle system are reused
+         */
+        bool m_delete_node;
 };
 
 
--- a/src/gui/mainmenu.cpp	Thu Mar 20 18:08:50 2014 +0000
+++ b/src/gui/mainmenu.cpp	Thu Mar 20 19:20:41 2014 +0100
@@ -18,7 +18,7 @@
 #include <OgreRenderWindow.h>
 #include <OgreSubEntity.h>
 #include <OgreMeshManager.h>
-#include <OgreParticleSystem.h>
+#include <ParticleUniverseSystemManager.h>
 #include "listitem.h"
 #include "savegamelist.h"
 #include "messageboxes.h"
@@ -394,6 +394,12 @@
 		// we need a scene to display the character, so set the savegame now
 		m_saveGameList->selectDefaultSavegame();
 	}
+    else
+    {
+        ParticleUniverse::ParticleSystem *p = ParticleUniverse::ParticleSystemManager::getSingleton().getParticleSystem("mainMen_Particle#0");
+        p->start();
+    }
+
 	m_saveGameList->update();
 
 	root->getAutoCreatedWindow()->getViewport(0)->setCamera(m_mainMenuCamera);
@@ -420,6 +426,8 @@
     if (m_sceneCreated)
 	{
 		root->getAutoCreatedWindow()->getViewport(0)->setCamera(m_gameCamera);
+        ParticleUniverse::ParticleSystem *p = ParticleUniverse::ParticleSystemManager::getSingleton().getParticleSystem("mainMen_Particle#0");
+        p->stop();
 	}
 	CEGUIUtility::getWindowForLoadedLayoutEx (m_window, "MainMenuRoot")->setAlpha(1);
 
@@ -497,7 +505,7 @@
     {
 		try
 		{
-			m_mainNode = m_sceneMgr->getRootSceneNode()->createChildSceneNode("MainMenuMainNode");
+            m_mainNode = m_sceneMgr->getRootSceneNode()->createChildSceneNode("MainMenuMainNode");
 			m_mainNode->setPosition(Ogre::Vector3::ZERO);
 
 			m_mainMenuCamera->setPosition(Ogre::Vector3(-12.2126, 0.597, -14.1));
@@ -507,7 +515,7 @@
 			Ogre::SceneNode *n = m_mainNode->createChildSceneNode();
 			Ogre::Entity *e;
 			Ogre::MeshPtr ptrMesh; // 2014.01.12: re-added.
-			Ogre::ParticleSystem *p;
+            ParticleUniverse::ParticleSystem *p;
 			Ogre::Light *l;
 
 			m_sceneMgr->setAmbientLight(Ogre::ColourValue(0.1, 0.1, 0.3, 2));
@@ -805,9 +813,10 @@
 			n->setScale(Ogre::Vector3(1, 1, 1));
 			n->setOrientation(Ogre::Quaternion(1, 0, 0, 0));
 
-			p = m_sceneMgr->createParticleSystem("mainMen_Particle#0","CampFire");
+            p = ParticleUniverse::ParticleSystemManager::getSingleton().createParticleSystem("mainMen_Particle#0","CampFire", m_sceneMgr);
 			n = m_mainNode->createChildSceneNode();
-			n->attachObject(p);
+            n->attachObject(p);
+            p->start();
 			n->setPosition(Ogre::Vector3(-10.5017, 0.150328, -21.4926));
 			n->setScale(Ogre::Vector3(1, 1, 1));
 			n->setOrientation(Ogre::Quaternion(1, 0, 0, 0));
@@ -963,7 +972,7 @@
 		std::string act = pl->getActionString();
 		float perc = m_savegame_player_action.m_elapsed_time / m_savegame_player_action.m_time;
 		
-		m_savegame_player_object->updateAction(act,perc);
+        m_savegame_player_object->updateAction(act,perc);
 		m_savegame_player_object->update(0);
 		
 		pl->setAction(actsave);