I've just setup my Irrlicht project with a Singleton, and from the research I've done, Singletons are great, but overuse of them is a bad idea. This article outlines the problems with them quite well.
http://www.softwarereality.com/design/singleton.jsp
The best thing I found was to put only the things that will be required everywhere in the project into Singletons, namely the Engine. I have a Singleton template class, which I use to inherit from when I want to make a singleton.
Code: Select all
// Singleton Template
// Taken from http://geeklab.wikidot.com/cpp-singleton-template
// Author : Rodrigo Varas
#ifndef SINGLETON_H
#define SINGLETON_H
template<class T>
class Singleton
{
private:
// Static current instance
static T* CurrentInstance;
public:
// Current instance retriever
static T* Current()
{
if (Singleton<T>::CurrentInstance == NULL)
{
Singleton<T>::CurrentInstance = new T;
}
return Singleton<T>::CurrentInstance;
}
//Delete current instance
static void DeleteCurrent()
{
if (Singleton<T>::CurrentInstance != NULL)
{
delete Singleton<T>::CurrentInstance;
Singleton<T>::CurrentInstance = NULL;
}
}
};
// Initialize the static member CurrentInstance
template<class T>
T* Singleton<T>::CurrentInstance = NULL;
#endif // SINGLETON_H
My Irrlicht singleton header looks like this
Code: Select all
#ifndef IRRSINGLETON_H
#define IRRSINGLETON_H
// IrrSingleton.h
// Created 22/11/08
// Author : James Murchison
// A singleton class for handling the Irrlicht Engine
#include "stdafx.h"
#include "Singleton.h"
class IrrSingleton : public Singleton<IrrSingleton>
{
public:
IrrSingleton(void);
~IrrSingleton(void);
// Initializes the Irrlicht engine
bool Init();
// Called every frame to update
void Update();
// Functions for retrieving the main Irrlicht devices
IrrlichtDevice* GetDevice(){return m_pDevice;}
video::IVideoDriver* GetVideoDriver(){return m_pDriver;}
scene::ISceneManager* GetSceneManager(){return m_pSmgr;}
gui::IGUIEnvironment* GetGUIEnvironment(){return m_pGUIEnv;}
// Functions to create engine objects
scene::ICameraSceneNode* CreateStandardCamera(core::vector3df _vPos, core::vector3df _vLookAt);
scene::ICameraSceneNode* CreateFPSCamera(core::vector3df _vPos, core::vector3df _vLookAt);
private:
// Irrlicht Device, used to create just about everything
IrrlichtDevice *m_pDevice;
// Video driver, interface for 2D/3D graphics functions
video::IVideoDriver *m_pDriver;
// Scene Manager, manages scene nodes, mesh resources, cameras, etc.
scene::ISceneManager *m_pSmgr;
// GUI Environment, factory and manager of all GUI elements
gui::IGUIEnvironment *m_pGUIEnv;
};
// Definition of macro, makes calling the singleton a little easier
#define IrrEngine IrrSingleton::Current()
#endif // IRRSINGLETON_H
By doing this I have access to the engine where ever I am in my project, as long as I include the IrrSingleton header. If your code is structured properly, you shouldn't really have to make anything else a singleton.
Also the macro definition down the bottom of the header is nice, means I only type "IrrEngine" to get the singleton, rather than "IrrSingleton::Current()".