#ifndef __GRAPHICS_SYSTEM_H__
#define __GRAPHICS_SYSTEM_H__

// base class
#include "XML.h"

// ogre
#include "OgrePrerequisites.h"
#include "OgreGpuCommandBufferFlush.h"
#include <OgreMaterialManager.h>
#include "OgreFrameListener.h"
#include "OgreWindowEventUtilities.h"
using namespace Ogre;

// game
#include "ShadowQualityType.h"
#include "TerrainQualityType.h"
#include "TextureQualityType.h"

// std
#include <vector>

// constants
const float DEFAULT_BRIGHTNESS = 0.5f;

// prototype
class SPZipArchiveFactory;
class TextureArchiveFactory;
struct SDL_Window;

class GraphicsSystem : public XML, FrameListener, WindowEventListener
{

   //
   // System Singleton
   //
public:
   GraphicsSystem();
   ~GraphicsSystem();

   // Create the singleton instance
   static void Create();
   static GraphicsSystem* GetSingleton() { return s_pSingleton; }

private:
   // There can only be one instance of a singleton
   static GraphicsSystem* s_pSingleton;


   //
   // Lifecycle
   //
public:
   void Init();
   void Tick( float i_fSecFrame );

private:   
   // Loads data from graphics.xml at game start-up
   // - note:  we have 2 grahpics.xml files:
   //   1.  spreadsheet/graphics.xml, which contains static data like our m_mapTextureQualityOverride.
   //   2.  SETTINGS_FOLDER/graphics.xml, which contains any graphics settings the player has set in UIGraphics.
   void LoadXML( XMLNode& i_node );


   //
   // Load/Save Settings
   //
public:
   // Restore settings from the last session, like shadow quality.
   // - note:  most settings are actually saved in the ogre.cfg file, but we have a few extra
   //   settings that don't fit in there.
   void LoadSettings();
   void SaveSettings();


   //
   // Ogre (Rendering) objects
   //
public:
   Root* GetOgreRoot() const;
   RenderWindow* GetRenderWindow() const;
   SceneManager* CreateSceneManager( SceneTypeMask i_eSceneType, const String& i_strName );
   void DestroySceneManager( SceneManager* i_pSceneMgr );

   // Ok, here's something fun.
   // I sent a build to gamestop.  It crashed on startup for him.
   // The game has been played on a TON of different computers, and this is new, and of course strikes when a distributor is evaluating the build.
   //
   // I'm going to document the debugging process I went through, and why it led to the creation of the IsDeviceLost() function below.
   //
   // So, I got the .dmp and .log files back for this crash.
   // The stack was kinda mangled and had bits and pieces of various different functions.  But this bit ended up being the important stuff:
   //     >	RenderSystem_Direct3D9.dll!Ogre::D3D9RenderSystem::_getDepthStencilFormatFor(_D3DFORMAT fmt=D3DFMT_A8R8G8B8)  Line 3726	C++
   //       RenderSystem_Direct3D9.dll!Ogre::D3D9RenderSystem::_getDepthStencilFor(_D3DFORMAT fmt=D3DFMT_A8R8G8B8, _D3DMULTISAMPLE_TYPE multisample=D3DMULTISAMPLE_NONE, unsigned long multisample_quality=0, unsigned int width=128, unsigned int height=128)  Line 3762 + 0xb bytes	C++
   //       RenderSystem_Direct3D9.dll!Ogre::D3D9RenderSystem::_setRenderTarget(Ogre::RenderTarget * target=0x083e70d8)  Line 2750 + 0x31 bytes	C++
   //       RenderSystem_Direct3D9.dll!Ogre::D3D9RenderSystem::_setViewport(Ogre::Viewport * vp=0x0400af60)  Line 2786	C++
   //
   // I also did a diff between a log file from my machine, and the crashy log file.
   // The important difference was this:
   //       D3D9 Device 0x[04F9A5E0] entered lost state
   //
   // I got 2 crash logs, and in both the device lost notice was in the same place:
   //
   //       [GAME_MSG]: SoundSystem::Init
   //       ... a crap ton of Parsing scripts stuff here ...
   //       D3D9 Device 0x[04F9A5E0] entered lost state
   //       [GAME_MSG]: PhysicsSystem::Init
   //       [GAME_MSG]: PhysicsFactory::Init
   //       [GAME_MSG]: StationFactory::Init
   //       ... a bunch of system inits ...
   //       [GAME_MSG]: Parsing text localization file: wormhole_loc.xml
   //       [GAME_MSG]: Parsing text localization file: layout_loc.xml
   //       [GAME_MSG]: UISystem::Init
   //       Texture: _cegui_ogre_0: Loading 1 faces(PF_A8B8G8R8,512x512x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,512x512x1.
   //       Texture: _cegui_ogre_1: Loading 1 faces(PF_A8B8G8R8,2048x1024x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,2048x1024x1.
   //       Texture: _cegui_ogre_2: Loading 1 faces(PF_A8B8G8R8,1024x1024x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,1024x1024x1.
   //       Texture: _cegui_ogre_3: Loading 1 faces(PF_A8B8G8R8,128x1024x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,128x1024x1.
   //       Texture: _cegui_ogre_4: Loading 1 faces(PF_A8B8G8R8,128x1024x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,128x1024x1.
   //       Texture: _cegui_ogre_5: Loading 1 faces(PF_A8B8G8R8,128x1024x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,128x1024x1.
   //       Texture: _cegui_ogre_6: Loading 1 faces(PF_A8B8G8R8,128x1024x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,128x1024x1.
   //       Texture: _cegui_ogre_7: Loading 1 faces(PF_A8B8G8R8,256x512x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,256x512x1.
   //       Texture: _cegui_ogre_8: Loading 1 faces(PF_A8B8G8R8,1024x128x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,1024x128x1.
   //       Texture: _cegui_ogre_9: Loading 1 faces(PF_A8B8G8R8,512x256x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,512x256x1.
   //       Texture: _cegui_ogre_10: Loading 1 faces(PF_B8G8R8,256x256x1) with 0 generated mipmaps from Image. Internal format is PF_X8R8G8B8,256x256x1.
   //       Unloading unused resources in resource group General
   //       Finished unloading unused resources in resource group General
   //       Texture: _cegui_ogre_11: Loading 1 faces(PF_A8B8G8R8,2048x1024x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,2048x1024x1.
   //       Texture: _cegui_ogre_12: Loading 1 faces(PF_A8B8G8R8,256x256x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,256x256x1.
   //       Texture: _cegui_ogre_13: Loading 1 faces(PF_A8B8G8R8,256x256x1) with 0 generated mipmaps from Image. Internal format is PF_A8R8G8B8,256x256x1.
   //
   //       --- end of log ---
   //
   // There is no device restored / device reset messages, as we normally get when a device is lost.
   //
   // So both the log, and the stack indicate a bunch of CEGUI stuff is going on, but I *think* this is a false trail.
   // The real problem appears to be a bug in Ogre where we crash if trying to create a viewport while in a device lost state.
   // This is somewhat confirmed by a related bug report I found:
   // - http://www.ogre3d.org/mantis/bug_view_advanced_page.php?bug_id=478
   // - this bug is unresolved at the time of writing this comment
   // - this bug reports the same crash stack, and cites device lost as the issue as well.
   // - this bug also identifies the problem as dereferencing a null variable in the Ogre code in OgreD3D9RenderSystem.cpp, function D3D9RenderSystem::_getDepthStencilFormatFor
   // - this corresponds to the crash stack I got.
   //
   // I now theorize that the crash is occuring as follows:
   // 1.  Game starts up
   // 2.  We have the device lost notification in the log during initialization  
   //     - unusual, doesn't happen on my machine
   //     - maybe a dual-monitor specific issue?  (guessing)  --- nope, the crashy machine was single monitor, Win7 64, ATI 6850 video
   // 3.  We get to the last stage of GameSystem::InitializeSystems, where we call UISys()->ActivateScreen( SlideShow_UIScreenType, ... );
   // 4.  UISlideShow::Activate gets called
   // 5.  UISlideShow::CreateViewport gets called
   // 6.  Ogre code crashes, see above stack, following the call to D3D9RenderSystem::_setViewport
   //
   // I also am able to reproduce this crash on my machine, by hitting <windows key>-L during startup.
   // - this causes a "lock terminal" thing, which causes a device lost.
   //
   // So, I have 2 options:
   // 1.  Fix the ogre code
   // 2.  Detect a device lost state from my own code, and hold off activating UISlideShow until it is restored.
   //
   // I've ended up doing both.
   // (1) - I added a pointer check in the ogre code, although I don't know if this will cause ogre to gracefully handle the device lost situation, 
   //       or if we'll just run into another issue again further on in the ogre code.
   //     - This has the advantage of potentially helping for ALL device lost crashes, rather than just the UISlideShow one.
   // (2) - resulted in this function below.
   //     - used in GameSystem::InitializeSystems
   //     - we now wait until we have a valid (non-lost) device before kicking off UISlideShow
   //     - I'm more confident about this fix, but has the disadvantage of only handling the specific crash at startup.
   //     - It won't help if we have other device lost / create viewport crashes elsewhere in the code.
   //
   // I did both so I'd be more sure to fix the known crash, and have the backup in ogre code for these potential other crashes.
   // 
   // UPDATE:
   // CRAP!  I can still get things to crash with both the above fixes.
   // Ok, I've reverted (1), and changed (2) so we check IsDeviceLost every tick from GameSystem::Tick.  This seems to solve the problem.
   // A good thing is that this new fix should hopefully help in all situations, rather than limiting our fix to handling a device lost 
   // during the initialization stage.
   //
   // CRITIQUE OF IMPLEMENTATION:
   // One crappy thing about this IsDeviceLost fix is that I had to include, and link to some DirectX9 specific code.
   // - we now link to RenderSystem_Direct3D9.lib
   // - we now include a bunch of OgreD3D9* headers in GraphicsSystem.cpp
   // - we have D3D9 specific code in the IsDeviceLost function
   // - this obviously isn't portable, and also it's sloppy to tunnel through Ogre's render system abstractions to D3D9 code.
   //
   // If we port to opengl (linux, max), we can probably just preproc out all this code
   // - I believe I read somewhere that device lost is a DX specific issue, so there will be nothing needed for opengl, the function can just return false.
   bool IsDeviceLost() const;

private:
   Root* m_pOgreRoot;
   RenderWindow* m_pWindow;
   String m_strDefaultRenderSystem;

public:
   // Making this a public, static var so our exception handler in main.cpp
   // can access this value in as simple of way as possible.
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
   static HWND m_hwnd;
#endif


   //
   // Video Card
   //
public:
   GPUVendor GetGPUVendor() const;

   //
   // Resources
   //
public:
   // This must be called after GraphicsSystem::Init()
   // Method where you can perform resource group loading.
   // Must at least do ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
   void LoadResources();
   // This function loads just enough resources that we can put up our loading screen.
   // Loading our full resources takes a long time, and we don't want to have a blank screen
   // that long, which would be the case if we didn't put up the loading screen until after
   // it was done.
   void LoadIntroResources();

private:
   // Method which will define the source of resources (other than current folder).
   // This data is read from resources.cfg
   void SetupResources();
   // Helper for SetupResources() 
   // e.g. SetupResources( "resources.cfg" );
   void SetupResources( const String& i_strConfigFile );
   // Determines the aspect ratio of the desktop / monitor.
   // E.g. widescreen will be 1.6
   void RetrieveDesktopAspectRatio();
   // Reads the graphics options from ogre.cfg
   void ConfigureGraphics();
   // Ensures the rendering device specified in ogre.cfg is valid.
   // It may not be, say if the user changes his video card.
   void VerifyRenderingDevice();
   // If we're in full screen mode, ensures the video resolution in ogre.cfg matches the aspect ratio
   // of the desktop.  
   // Note:  "screen resolution" and "video mode" are somewhat synonymous in our usage here.
   void VerifyScreenResolution();
   // When configuring our graphics, we commonly have to set a config option out of a list of
   // possible values.  See Ogre::ConfigOption for more details.
   // This function merely checks to see if i_strOption exists in the option list, i_vecOption.
   bool IsValidOption( const String& i_strOption, const Ogre::StringVector& i_vecOption );
   // Does the same thing as IsValidOption, but we need to handle Video Mode specially.
   bool IsValidVideoMode( const String& i_strVideoMode, const Ogre::StringVector& i_vecVideoMode );
   // Helper function for VerifyScreenResolution, to select a valid video mode 
   // of the specified aspect ratio.
   void SelectNewVideoMode( float i_fAspectRatio, const Ogre::StringVector& i_vecValidMode );
   // Helper function to retrieve a specific config option, such as:
   // "Full Screen", "Rendering Device", "VSync", "Video Mode".
   // See ogre.cfg
   ConfigOption* GetConfigOption( const String& i_strOption ) const;
   String GetConfigOptionCurrentValue( const String& i_strOption ) const;
   void SetConfigOption( const String& i_strOption, const String& i_strValue ) const;
   // Checks to see whether the file ogre.cfg exists
   bool OgreConfigFileExists() const;
   // Opens the ogre configuration dialog that comes stock with ogre3d.
   // This is not part of the expected pathway, but might be used to help work around some technical problems.
   void ShowOgreConfigurationDialog();
   // Ensures the proper shader model is supported by the user's video card, and exits with an error message if not.
   void VerifyShaderModel();
   // In case we fail to get Ogre3D up and running, we'll exit the program with a message box telling the user 
   // what went wrong.
   void ExitWithNonRecoverableErrorMessageBox( const String& i_strMsg ) const;


   //
   // Video Mode
   //
public:
   // Returns a list of supported video modes.
   // We ignore 16-bit colour modes.
   // param i_bShowAllResolutions:  If false, we'll only show resolutions which match the monitor size.
   std::list< std::pair<int,int> > GetVideoModes( bool i_bShowAllResolutions = true ) const;
   // Checks if the current video mode matches the specified dimensions.
   // i_bCheckConfigValue - Used by UIGraphics, see comments for IsFullscreen in this file.
   bool IsCurrentVideoMode( int i_nWidth, int i_nHeight, bool i_bCheckConfigValue = false ) const;
   void GetCurrentVideoMode( int& o_nWidth, int& o_nHeight, bool i_bCheckConfigValue = false ) const;
   // Sets the video mode (screen dimensions) to the specified values.
   void SetVideoMode( int i_nWidth, int i_nHeight );
   // E.g. widescreen will return 1.6
   float GetDesktopAspectRatio() const;
   // Parses out the width and height from the "Video Mode" config string (ogre.cfg).
   bool ParseWidthHeightFromVideoModeString( const String& i_strVideoMode, int& o_nWidth, int& o_nHeight ) const;

private:
   float m_fDesktopAspectRatio;


   //
   // Brightness
   //
public:
   // Brightness is [0,1], where:
   //   0.5 is "normal brightness"
   //   0 is darkest
   //   1 is brightest
   // This way, the brightness value matches the range of our brightness slider in UIGraphics
   float GetBrightness() const;
   void SetBrightness( float i_fBrightness );
   void SetBrightnessToDefault();
   // We use a compositor to adjust the brightness.  This has some effect on framerate.  But we don't
   // need the compositor if the brightness is set to default.  This is where this function comes in.
   bool IsDefaultBrightness() const;

private:
   float m_fBrightness;


   //
   // Anti Aliasing
   //
public:
   Ogre::StringVector GetAntiAliasingModes() const;
   bool IsCurrentAntiAliasingMode( const String& i_strMode );
   void SetAntiAliasingMode( const String& i_strMode );
   

   //
   // VSync
   //
public:
   // Note:  This will get/set the VSync configuration.
   // It requires a restart for this change to take effect.
   // So, for example, GetVSync can return true if the user changed the setting in the graphics UI,
   // but VSync won't actually be enabled yet (until a restart).
   // A dialog is used to inform the user a restart is necessary.
   void SetVSync( bool i_bVSync );
   bool IsVSync() const;


   //
   // Max FPS
   //
private:
   // Used to support OptionSystem::GetMaxFPS()
   void LimitMaxFPS();

private:
   unsigned long m_msLastFrame;


   //
   // FullScreen
   //
public:
   // Note:  This will get/set the FullScreen configuration.
   // It requires a restart for this change to take effect.
   // A dialog is used to inform the user a restart is necessary.
   void SetFullScreen( bool i_bFullScreen );
   // if i_bCheckConfigValue is true, then instead of checking the current fullscreen state,
   // we will instead check what our current _configuration_ (i.e. for next reboot) is.
   // This is useful for UIGraphics, where we can change the fullscreen checkbox, but this
   // config option doesn't change until next restart.  Without this, if we opened UIGraphics,
   // checked the fullscreen checkbox, then closed and opened UIGraphics again, our change
   // (the fullscreen checkmark) would be lost.
   bool IsFullScreen( bool i_bCheckConfigValue = false ) const;


   //
   // Viewports
   //
public:
   // This is a hook where we can apply our TerrainQuality material scheme,
   // when a new viewport is created.
   void ApplyMaterialScheme( Viewport* i_pViewport );
   // This function destroys all viewports in the game by calling Ogre::RenderWindow::removeAllViewports()
   // Several different game system classes have viewports and viewport pointers.  I used to call
   // RenderWindow::removeAllViewports() from these classes, but this introduced a potential bug by leaving
   // invalid Viewport* pointers in some of the other classes.
   // This class savely wraps RenderWindow::removeAllViewports() by zeroing out all viewport pointers in the game.
   // As a future design consideration, think about moving the viewport pointer(s) to this class.
   void RemoveAllViewports();


   //
   // Terrain Quality
   //
public:
   // Affects the shader we use to render the terrain.
   // High quality uses an expensive shader with normal, spec, and parallax.
   // Medium quality uses a more lightweight shader with just diffuse lighting.
   // See TerrainMaterialGeneratorCustom.h/cpp
   TerrainQualityType GetTerrainQuality() const;
   void SetTerrainQuality( TerrainQualityType i_eQuality );
   // We'll adjust the MaxPixelError setting on our terrain based on the TerrainQualityType setting.
   int GetTerrainMaxPixelError() const;

private:
   TerrainQualityType m_eTerrainQuality;


   //
   // Texture Quality
   //
public:
   // Uses the TextureArchive class to impact the size of our textures.
   // Reducing the TextureQualityType is important on video cards with lower VRam, so that all
   // of our textures (and other graphical assets) fit in VRAM.
   TextureQualityType GetTextureQuality() const;
   void SetTextureQuality( TextureQualityType i_eQuality );
   // Called by TextureArchive to determine how many mipmaps of a dds to skip.
   // This will be based on:
   // 1. the current m_eTextureQuality setting.
   // and either:
   // 2a.  the size of the texture
   // or:
   // 2b.  the specific data in m_mapTextureQualitySetting
   //
   // Note that not every texture needs a setting in m_mapTextureQualityOverride, because we have a basic algorithm
   // which reduces mipmaps based on the size of the texture, which should be good for the general case.  But sometimes
   // we may want to override this.  For example, maybe we want the textures on playable characters to stay larger, 
   // even on lower TextureQualitySettings
   int GetNumMipMapsToSkip( const String& i_strResourceName, int i_width, int i_height );

private:
   TextureQualityType m_eTextureQuality;
   TextureArchiveFactory* m_pTextureArchiveFactory;

   class TextureQualitySetting : public XML
   {
   public:
      TextureQualitySetting();
      void LoadXML( XMLNode& i_node );

   public:
      // number of mipmaps to skip on high texture quality setting.
      int m_nMipMapSkipHigh;
      // number of mipmaps to skip on medium texture quality setting.
      int m_nMipMapSkipMedium;
      // number of mipmaps to skip on low texture quality setting.
      int m_nMipMapSkipLow;
   };

   // See notes for GetNumMipMapsToSkip(..)
   // key:  name of texture
   // value:  TextureQualitySetting data, which tells us how many mipmaps to skip 
   //         at the various TextureQualityType values.
   std::map< String, TextureQualitySetting > m_mapTextureQualityOverride;


   //
   // SPZipArchive
   //
private:
   // Loads our .spar archive files
   // See comments in tool/sparify_data.pl for more info about .spar files
   SPZipArchiveFactory* m_pSPZipArchiveFactory;


   //
   // Shadow Quality
   //
public:
   // Affects the size of the textures used for our shadows.
   // See Scene::UpdateShadowQuality()
   ShadowQualityType GetShadowQuality() const;
   void SetShadowQuality( ShadowQualityType i_eQuality );

private:
   ShadowQualityType m_eShadowQuality;


   //
   // Wormhole Graphics
   //
public:
   // The cubic_reflection used in material WormholeCylinder looks cool, but is fairly "flashy/blinky" which some players
   // have said causes a bit of eye strain.  We'll add a graphics option to use this material instead, which does not use
   // a cubic_reflection.
   bool UseSimpleWormholeGraphics() const;
   void SetUseSimpleWormholeGraphics( bool i_bUseSimple );

private:
   bool m_bUseSimpleWormholeGraphics;


   //
   // Flush GPU Buffer
   //
public:
   // see:  http://www.ogre3d.org/wiki/index.php/FlushGPUBuffer
   GpuCommandBufferFlush& GetGpuCommandBufferFlush();

private:
   GpuCommandBufferFlush m_gpuBufferFlush;


   //
   // Frame Listener
   //
public:
   bool frameRenderingQueued(const FrameEvent& evt);


   //
   // Window Event Listener
   //
public:
   void windowResized( RenderWindow* rw );
   bool windowClosing(RenderWindow* rw);
   
   //
   // Multiple SceneManager Bugfix
   //
public:
   // http://www.ogre3d.org/forums/viewtopic.php?f=1&t=40839
   // http://www.ogre3d.org/mantis/view.php?id=130

   /* Copy and paste from the mantis bug report linked to above:

   Summary:  Multiple SceneManagers and changing pass hashes 

   Description:
   See http://www.ogre3d.org/phpBB2/viewtopic.php?p=189032#189032 [^]

   Hmm, actually multiple scene managers could cause a problem here.

   It's during RenderQueue::clear() that dirty hashes are removed from the queue, so that when they are put back, 
   it will be with the updated hash. However, because this is called from SceneManager::_renderScene, the whole sequence 
   of checking and then clearing the dirty list is done within one SceneManager, so when the render queue is cleared 
   for the other one the passes are no longer marked as dirty.

   What is needed is the sequence:

   - SM1 clear render queue
   - SM2 clear render queue
   - Process pending pass updates
   - render..

   However this is rather difficult to engineer generically given how the SceneManager might be invoked. 
   We'd have to move the process of clearing the queues and processing the updates outside of the SceneManager itself, 
   perhaps into Root somewhere. Hmm. 

   Notes:

   For the moment, we're advising users to use the workaround in frameStarted:

   sm1->getRenderQueue()->clear();
   sm2->getRenderQueue()->clear();
   .. all other SMs
   Pass::processPendingPassUpdates();

   We will look at resolving this issue more elegantly in v2.0 with the SceneManager redesign. 
   */
   void ClearSceneManagerPassMaps();
   
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
   //
   // SDL
   //
public:
   // See header comments for OptionSystem::UseSDLVideo()
   
   // This should be called instead of GraphicsSystem::Init if we're using SDL
   void InitSDL();
   SDL_Window* GetSDLWindow();
   bool HasSDLWindow() const;

private:
   SDL_Window* m_pSDLWindow;
#endif
};




class GlowMaterialListener : public Ogre::MaterialManager::Listener
{
protected:
   Ogre::MaterialPtr mBlackMat;
public:
   GlowMaterialListener()
   {
      mBlackMat = Ogre::MaterialManager::getSingleton().create("mGlowBlack", "Internal");
      mBlackMat->getTechnique(0)->getPass(0)->setDiffuse(0,0,0,0);
      mBlackMat->getTechnique(0)->getPass(0)->setSpecular(0,0,0,0);
      mBlackMat->getTechnique(0)->getPass(0)->setAmbient(0,0,0);
      mBlackMat->getTechnique(0)->getPass(0)->setSelfIllumination(0,0,0);
      mBlackMat->getTechnique(0)->getPass(0)->setFog( true, FOG_NONE );
   }

   Ogre::Technique *handleSchemeNotFound(unsigned short, const Ogre::String& schemeName, Ogre::Material*mat, unsigned short, const Ogre::Renderable*)
   {
      if (schemeName == "glow")
      {
         //LogManager::getSingleton().logMessage(">> adding glow to material: "+mat->getName());
         return mBlackMat->getTechnique(0);
      }
      return NULL;
   }
};


// Syntactic convenience function.
inline GraphicsSystem* GraphicsSys()
{
   return GraphicsSystem::GetSingleton();
}

#endif // __GRAPHICS_SYSTEM_H__
