/********************************************************************

  Module: TitanUI

  Author: Jon Wiesman

  Description:

  TODO

  Copyright 2006 Sony Online Entertainment.  All rights reserved.

*********************************************************************/

#include ".\TitanUI.h"
#include ".\SyScene.h"

#include "SyScene.h"
#include "SyHavok.h"
#include "SyPerformanceStats.h"
#include "SyESFParse.h"
#include "SyTime.h"
#include "SyPlatformMisc.h"
#include "SyTime.h"
#include "SyParameterValidator.h"
#include "SyBuildVersion.h"
#include "SyDirectory.h"
#include "SyDebug.h"
#include "SyMemory.h"
#include "HttpFileDownload.h"
#include "debugoverlay.h"
#include "TitanFXScriptDriver.h"

#ifdef SNTUNER
#include "libsntuner.h"
#endif

#include "InputConsole.h"
#include "RecordingInputConsole.h"
#include "RawController.h"

#include "tinyxml/tinyxml.h"

#include "TiUI.h"
#include "TiUIControl.h"
#include "TiStartWindow.h"
#include "TiGameWindow.h"
#include "TiCommandMessage.h"
#include "TiStartMessage.h"
#include "TiSceneController.h"
#include "TitanOptions.h"
#include "TiInstaller.h"
#include "TiConsoleWindow.h"
#include "TitanApp.h"
#include "SyPlatformMisc.h"

// returns -1 if __x is not true
#define CHECK_RESULT(__x) if ( !(__x) ) { SyAssert( !#__x ); return -1; }

#define OPTION_CONTROLLER       "controller"
#define OPTION_FRAMERATE        "framerate"
#define OPTION_LEVEL            "level"
#define OPTION_MOVIE            "movie"
#define OPTION_NET              "net"
#define OPTION_PLAYBACK         "playback"
#define OPTION_RECORD           "record"
#define OPTION_NO_TITLE_SCREEN  "no_title_screen"
#define OPTION_TVSTANDARD       "tvstandard"
#define OPTION_STATS            "stats"
#ifdef WIN32
#define OPTION_RESOLUTION       "resolution"
#define OPTION_FULLSCREEN       "fullscreen"
#elif __CELLOS_LV2__
#define OPTION_ROOT             "root"
#define OPTION_INSTALL          "install"
#define OPTION_INSTALL_MAIN     "install_main"
#define OPTION_LIST             "list"
#endif // WIN32

TitanUI *TitanUI::sm_pSingleton = NULL;

void TitanUI::InitParameterValidator( SyParameterValidator* parameterValidator )
{
  mpParameters = parameterValidator;
  mpTitan->InitParameterValidator( parameterValidator );

  // please alphabetize
  parameterValidator->AddStringOption(  OPTION_CONTROLLER,      "c", "select the controller button mapping airflo/logitech/ps2" );
  parameterValidator->AddIntegerOption( OPTION_FRAMERATE,       "f", "set game to run at a fixed logical frame rate" );
  parameterValidator->AddStringOption(  OPTION_LEVEL,           "l", "name of level to load (.lvl or .xml)" );
  parameterValidator->AddStringOption(  OPTION_MOVIE,           "",  "write every frame to a file to make a movie" );
  parameterValidator->AddSwitch(        OPTION_NET,             "n", "operate in network mode" );
  parameterValidator->AddBooleanOption( OPTION_STATS,           "",  "enable/disable performance display" );
  parameterValidator->AddStringOption(  OPTION_PLAYBACK,        "p", "playback a previously recorded session" );
  parameterValidator->AddStringOption(  OPTION_RECORD,          "r", "record session input to a file for playback later" );
  parameterValidator->AddSwitch(        OPTION_NO_TITLE_SCREEN, "",  "Bypass the title screen" );
  parameterValidator->AddStringOption(  OPTION_TVSTANDARD,      "",  "select a tv standard ntsc/480p/720p/1080i/1080p" );
#ifdef WIN32
  parameterValidator->AddSwitch(        OPTION_FULLSCREEN,      "f", "this parameter causes the game window to cover the entire display (Windows only) (cannot be used with \"video\")" );
  parameterValidator->AddStringOption(  OPTION_RESOLUTION,      "",  "set the resolution (ignored on tv devices)" );
#elif __CELLOS_LV2__
  parameterValidator->AddStringOption(  OPTION_ROOT,            "",  "set root directory" );
  parameterValidator->AddSwitch(        OPTION_INSTALL,         "",  "mirror root to hdd, run from hdd" );
  parameterValidator->AddSwitch(        OPTION_INSTALL_MAIN,    "",  "copy main.elf to the hdd" );
  parameterValidator->AddSwitch(        OPTION_LIST,            "",  "list all files under root" );
#endif // WIN32

  // these parameters are obsoloete
  // delete after 2006-05-12
  parameterValidator->AddSwitch( "no_stats", "",  "" );
}

void ProgressCallback( void* pData )
{
  static SyTime lastTime    = 0;
  TitanUI* pTitanUI         = static_cast<TitanUI*>(pData);
  TiUI* pUI                 = pTitanUI->GetUI();
  SyScene* pScene           = pTitanUI->GetScene();
  SyRaster* pRaster         = pScene->GetRasterDev();
  SyDictionary* pDictionary = pScene->GetDictionary();

  // update time
  pTitanUI->UpdateInputConsole();
  SyTime time = pTitanUI->GetTime();
  if( time - lastTime < 16 )
  {
    return;
  }
  lastTime = time;

  // draw screen
  pRaster->BeginScene();
  pRaster->Begin2D();

  // some art
  const char8* pScreen = "loadscreen_sewers_1.tga";
  const char8* pBG = "loadscreen_bg_sewers_1.tga";
  const char8* pBlade = "loadscreen_blade.tga";
  SyVect2I offset(0,0);
  SyVect2I size(1280,684);

  // stretch as needed
  int32 w = pRaster->GetScreenWidth();
  int32 h = pRaster->GetScreenHeight();
  SyVect2I screenLoc, screenSize;
  if( size.X > w && size.Y > h )
  {
    screenLoc( 0, 0 );
    screenSize( w, h );
  }
  else if( size.X > w )
  {
    screenSize.X = w;
    screenSize.Y = w * size.Y / size.X;

    screenLoc.X = 0;
    screenLoc.Y = (h>>1) - (screenSize.Y>>1);
  }
  else if( size.Y > h )
  {
    screenSize.X = h * size.X / size.Y;
    screenSize.Y = h;

    screenLoc.X = (w>>1) - (screenSize.X>>1);
    screenLoc.Y = 0;
  }
  else
  {
    screenSize = size;
    screenLoc.X = (w>>1) - (screenSize.X>>1);
    screenLoc.Y = (h>>1) - (screenSize.Y>>1);
  }

  int32 hSurface = 0;

  // background
  if( pDictionary->FindTyped( SyHashResourceID(pBG), SYRESOURCETYPE_SURFACE, hSurface ) != 0 )
  {
    static int v0 = 0;
    pUI->Blit( hSurface, 0, SyVect2I(0,0), SyVect2I(v0,0), SyVect2I(w,256), SYALPHABLENDMODE_AVG, 1.f );
    v0 += 3;

    static int v1 = 0;
    pUI->Blit( hSurface, 0, SyVect2I(0,h-256), SyVect2I(v1,0), SyVect2I(w,256), SYALPHABLENDMODE_AVG, 1.f );
    v1 -= 3;
  }

  // blades
  if( pDictionary->FindTyped( SyHashResourceID(pBlade), SYRESOURCETYPE_SURFACE, hSurface ) != 0 )
  {
    pUI->StretchBlit( hSurface, 0, SyVect2I(0,0), SyVect2I(w,67), SyVect2I(0,0), SyVect2I(1280,67), SYALPHABLENDMODE_AVG, 1.f );
    pUI->StretchBlit( hSurface, SYRASTER_BLITFLAG_FLIP_VERTICAL, SyVect2I(0,h-67), SyVect2I(w,67), SyVect2I(0,0), SyVect2I(1280,67), SYALPHABLENDMODE_AVG, 1.f );
  }

  // main image
  if( pDictionary->FindTyped( SyHashResourceID(pScreen), SYRESOURCETYPE_SURFACE, hSurface ) != 0 )
  {
    pUI->StretchBlit( hSurface, 0, SyVect2I(0,0)/*screenLoc*/, SyVect2I(w,h)/*screenSize*/, offset, size, SYALPHABLENDMODE_AVG, 1.f );
  }

  pUI->FlushDeferred2D();
  pRaster->End2D();
  pRaster->EndScene();
}

TitanUI::TitanUI() :
mRawController(0),
mpInputConsole(0),
mpScene(0),
mpRaster(0),
mpDictionary(0),
mpCollide(0),
mpSoundDevice(0),
mpWaterSystem(0),
#ifdef HAVOK_ENABLED
mpPhysics(0),
#endif
mBloomEffectHandle(-1),
mFontHandle(-1),
mpPerformanceStats(0),
mbHardPause(0),
mbStabilizeHavokObjects(0),
mbExitAfterStabilize(0),
mpAtlasMaterial(0),
mAtlasMaterialHandle(-1),
mAtlasSurfaceHandle(-1),
mpTitanApp(0),
mpUI(NULL),
mpStats(NULL),
mpGameWindow(NULL),
mpStartWindow(NULL),
m_pConsoleWindow(NULL),
m_eLetterbox(LM_Normal),
m_fLetterboxProgress(0.f),
m_eFade(FM_Normal),
m_fFadeProgress(0.f),
m_fFadeTransition(0.f),
m_eFadeAndExit(FAE_Normal),
m_fFAEWaitTime(0.f),
m_fFAEFadeTime(0.f),
m_fFAEProgress(0.f),
mMovieFrame(0),
mShowStats(false),
mShowVersion(false),
mShowUI(true),
mShowPlayerPos(false),
m_nGameToLoad( -1 )
{
  // don't do any file I/O in this constructor
  // file system may not have been mounted yet 

  mpTitan = TitanI::Create( this );
  mpParameters = 0;
  mMode = kGameModeNone;
  mDesiredMode = kGameModeNone;
  mpSceneControl = 0;
  mpESFParser = 0;
  mpOptions = 0;

  // ok, I know these are frowned on, but there really should only 
  // be one UI object.  It's a purely client-side object, no?
  sm_pSingleton = this;
}

TitanUI::~TitanUI()
{
  mpTitan->Close();
  delete mpTitan;

  std::map<int,TitanController*>::iterator i = mControllers.begin();
  while ( i != mControllers.end() )
  {
    delete i->second;
    i++;
  }
  mControllers.clear();

  delete [] mRawController;

  InterfaceDestroy();
  FrameworkDestroy();

  delete mpSceneControl;
  delete mpTitanApp;
  delete mpESFParser;
  delete mpOptions;

  sm_pSingleton = NULL;
}

static void WaitForDevice( const char* device )
{
  SyOutputString( "Waiting for device %s\n", device );
  int sleepCount = 0;
  while ( !SyDirectory::IsMounted( device ) )
  {
    SyPlatform::Sleep(200);
    if ( ++sleepCount % 5 == 0 )
    {
      SyOutputString( ".\n" );
    }
  }
  SyOutputString( "%s is mounted\n", device );
}

int TitanUI::Init()
{
#ifdef __CELLOS_LV2__
  //const char* root = SyDirectory::GetDVD();
  const char* root = SyDirectory::GetHost();
  //const char* root = SyDirectory::GetHDD();
  SyString rootParameter;
  if ( mpParameters->Found(OPTION_ROOT, &rootParameter ) )
  {
    if ( rootParameter.CompareWithoutCase( "dvd" ) == 0 )
    {
      root = SyDirectory::GetDVD();
    }
    else if ( rootParameter.CompareWithoutCase( "hdd" ) == 0 )
    {
      root = SyDirectory::GetHDD();
    }
    else if ( rootParameter.CompareWithoutCase( "host" ) == 0 )
    {
      root = SyDirectory::GetHost();
    }
    else
    {
      SyOutputString( "--%s: '%s' is not a valid option\n", OPTION_ROOT, rootParameter.AsChar() );
      return -1;
    }
  }

  WaitForDevice( root );
  SyDirectory::SetCWD( root );

  if ( mpParameters->Found(OPTION_INSTALL) )
  {
    WaitForDevice( SyDirectory::GetHDD() );
    if ( TiInstaller::Install( root, SyDirectory::GetHDD() ) == 0 )
    {
      SyDirectory::SetCWD( SyDirectory::GetHDD() );
    }
    TiInstaller::ListTree( SyDirectory::GetHDD() );
    return -1;
  }
  else if ( mpParameters->Found(OPTION_INSTALL_MAIN) )
  {
    WaitForDevice( SyDirectory::GetHDD() );
    if ( TiInstaller::CopyFile( "/app_home/main.elf", "/dev_hdd0/main.elf" ) == 0 )
    {
      SyDirectory::SetCWD( SyDirectory::GetHDD() );
    }
    TiInstaller::ListTree( SyDirectory::GetHDD() );
    return -1;
  }
  else if ( mpParameters->Found(OPTION_LIST) )
  {
    TiInstaller::ListTree( root );
    return -1;
  }

#endif // __CELLOS_LV2__

  mpSceneControl = SyNew TiSceneController();
  mpESFParser = SyNew SyESFParse();
  mpOptions = SyNew TitanOptions(this);

  mpTitanApp = SyNew TitanApp(this);

  CHECK_RESULT( mpParameters != NULL );
  if ( FrameworkCreate() < 0 )
  {
    return -1;
  }

  mpParameters->Found(OPTION_MOVIE, &mMovieFilename );

  mRawController = new RawController[7]; // 7 controller max on PS3
  GetController(0); // force a controller create

#ifdef WIN32
  SyString controllerName;
  if ( mpParameters->Found( OPTION_CONTROLLER, &controllerName ) )
  {
    if ( controllerName.CompareWithoutCase( "airflo" ) == 0 )
    {
      SetControllerMapping( CONTROLLER_MAPPING_AIRFLO );
    }
    else if ( controllerName.CompareWithoutCase( "ps2" ) == 0 )
    {
      SetControllerMapping( CONTROLLER_MAPPING_PS2 );
    }
    else if ( controllerName.CompareWithoutCase( "logitech" ) == 0 )
    {
      SetControllerMapping( CONTROLLER_MAPPING_LOGITECH );
    }
    else
    {
      SyOutputString( "--%s: '%s' is not a valid option\n", OPTION_CONTROLLER, controllerName.AsChar() );
      return -1;
    }
  }
#endif // WIN32

  CHECK_RESULT( mpTitan->Init( GetTime(), *mpParameters ) );

#if 0       // test async file io
  static char giantBuffer[1024 * 1024 * 10];
  SyFile test;
  test.Open("mesh.obj", SYFILE_RONLY | SYFILE_BINARY | SYFILE_ASYNC);
  test.ReadAsynch(0, giantBuffer, sizeof(giantBuffer));
  while (test.IsAsynchComplete() == 0)
  {
      printf("waiting for read\n");
      SyPlatform::Sleep(10);
  }
  printf("wait finished\n");
#endif


#if 0       // test http file download
  for (int jj = 0; jj < 20; jj++)
  {
    printf("Starting file download\n");
    HttpFileDownload df;
    // df.DownloadStart("http://64.37.156.32/screenshots/general/049.jpg", "download.jpg");
    // df.DownloadStart("http://69.93.231.164/PRODS/EOS1DS2/FULLRES/1DS2OUTK49P3.JPG", "download.jpg");
    df.DownloadStart("http://64.37.156.247:7000/patch/web/misc/VTS_11.sfd", "download.sfd");

    int ret = 0;
    for (;;)
    {
        SyPlatform::Sleep(25);
        uint64 recv, total;
        ret = df.DownloadStatus(&recv, &total);
        printf("%d of %d\n", (int)recv, (int)total);
        if (ret != 0)
        {
            break;
        }
    }

    printf("Ending file download (status=%d)\n", ret);
  }

#endif

  if ( mpParameters->Found(OPTION_NO_TITLE_SCREEN) )
  {
    SetGameMode(kGameModeGame);
  }
  else
  {
    SetGameMode(kGameModeFrontScreen);
  }
  return 0;
}

// Get a pointer to an interface that can be used to poll a controller state
TitanControllerI* TitanUI::GetController( int controllerId )
{
  std::map<int,TitanController*>::iterator i = mControllers.find(controllerId);
  if ( i == mControllers.end() )
  {
    TitanController* controller = new TitanController(&mRawController[controllerId]);
    mControllers[controllerId] = controller;
    return controller;
  }
  return i->second;
}

// Get the scene titan can use for drawing
SyScene* TitanUI::GetScene()
{
  return mpScene;
}

// Get the scene titan can use for drawing
SyPerformanceStats* TitanUI::GetPerformanceStats()
{
  return mpPerformanceStats;
}

SyInputConsole* TitanUI::GetInputConsole()
{
  return mpInputConsole;
}

int TitanUI::GetBloomEffectHandle()
{
  return mBloomEffectHandle;
}

// Use this method instead of Scene::Clear to give the interface an 
// opportunity to reload its assets after the clear. 
int TitanUI::ClearCommon()
{
  mFontHandle = -1;
  InterfaceDestroy();
  TiSpriteInfo::ClearAll();
  FrameworkReset();
  return 0;
}


struct ButtonMap
{
  int         mButtonIndex;
  TitanButton mTitanButton;
};

ButtonMap gTitanPS2ButtonMap[] =
{
  { 6,  ButtonAttackL },
  { 7,  ButtonAttackS },
  { 5,  ButtonJump },
  { 9,  ButtonDodge },
  { 4,  ButtonAction },
  { 10, ButtonMagic },
  { 8,  ButtonAttackRanged },
  { 11, ButtonBlock },
  { 14, ButtonCameraCenter },
  { 12, ButtonPause},
  { 0,  ButtonDPadUp},
  { 2,  ButtonDPadDown},
  { 3,  ButtonDPadLeft},
  { 1,  ButtonDPadRight},
  { 13, ButtonJoyLeft},
  { -1, ButtonMax} // terminator
};        

ButtonMap gTitanAirFloButtonMap[] =
{
#ifdef __CELLOS_LV2__
  { 4,  ButtonAttackL },
  { 6,  ButtonAttackS },
  { 5,  ButtonJump },
  { 11, ButtonDodge },
  { 7,  ButtonAction },
  { 8,  ButtonMagic },
  { 9,  ButtonAttackRanged },
  { 10, ButtonBlock },
  { 15, ButtonCameraCenter },
  { 12, ButtonPause},
  { 0,  ButtonDPadUp},
  { 2,  ButtonDPadDown},
  { 3,  ButtonDPadLeft},
  { 1,  ButtonDPadRight},
  { 14, ButtonJoyLeft},
  { -1, ButtonMax} // terminator
#else
  { 4,  ButtonAttackL },
  { 6,  ButtonAttackS },
  { 5,  ButtonJump },
  { 11, ButtonDodge },
  { 7,  ButtonAction },
  { 8,  ButtonMagic },
  { 10, ButtonAttackRanged },
  { 9,  ButtonBlock },
  { 15, ButtonCameraCenter },
  { 12, ButtonPause},
  { 0,  ButtonDPadUp},
  { 2,  ButtonDPadDown},
  { 3,  ButtonDPadLeft},
  { 1,  ButtonDPadRight},
  { 14, ButtonJoyLeft},
  { -1, ButtonMax} // terminator
#endif
};

ButtonMap gTitanLogitechButtonMap[] =
{
#ifdef __CELLOS_LV2__
  { 4,  ButtonAttackL },
  { 6,  ButtonAttackS },
  { 5,  ButtonJump },
  { 11, ButtonDodge },
  { 7,  ButtonAction },
  { 8,  ButtonMagic },
  { 9,  ButtonAttackRanged },
  { 10, ButtonBlock },
  { 14, ButtonCameraCenter },
  { 13, ButtonPause},
  { 0,  ButtonDPadUp},
  { 2,  ButtonDPadDown},
  { 3,  ButtonDPadLeft},
  { 1,  ButtonDPadRight},
  { 12, ButtonJoyLeft},
  { -1, ButtonMax} // terminator
#else
  { 5,  ButtonAttackL },
  { 4,  ButtonAttackS },
  { 6,  ButtonJump },
  { 11, ButtonDodge },
  { 7,  ButtonAction },
  { 8,  ButtonMagic },
  { 10, ButtonAttackRanged },
  { 9,  ButtonBlock },
  { 14, ButtonCameraCenter },
  { 12, ButtonPause },
  { 0,  ButtonDPadUp},
  { 2,  ButtonDPadDown},
  { 3,  ButtonDPadLeft},
  { 1,  ButtonDPadRight},
  { 13, ButtonJoyLeft},
  { -1, ButtonMax } // terminator
#endif
};

int gTitanAirFloAxisMap[] = 
{
  0,
  1,
  2,
  3
};


int gTitanPS2AxisMap[] = 
{
  0,
  1,
  2,
  3
};

int gTitanLogitechAxisMap[] = 
{
#ifdef __CELLOS_LV2__

  0,
  1,
  2,
  3
#else
  0,
  1,
  3,
  2
#endif
};
ButtonMap *gCurrentTitanButtonMap = gTitanAirFloButtonMap;
int *gCurrentTitanAxisMap = gTitanAirFloAxisMap;

void        
TitanUI::SetControllerMapping(eControllerMapping mapping)
{
  switch (mapping)
  {
  case CONTROLLER_MAPPING_AIRFLO:
    gCurrentTitanButtonMap = gTitanAirFloButtonMap;
    gCurrentTitanAxisMap = gTitanAirFloAxisMap;

    TiWindow::SetButtonMap( TiButtonMap::kAirflo );
    break;
  case CONTROLLER_MAPPING_PS2:
    gCurrentTitanButtonMap = gTitanPS2ButtonMap;
    gCurrentTitanAxisMap = gTitanPS2AxisMap;

    TiWindow::SetButtonMap( TiButtonMap::kPS2 );
    break;
  case CONTROLLER_MAPPING_LOGITECH:
    gCurrentTitanButtonMap = gTitanLogitechButtonMap;
    gCurrentTitanAxisMap = gTitanLogitechAxisMap;

    TiWindow::SetButtonMap( TiButtonMap::kLogitech );
    break;
  default:
    // unknown mapping SyAssertf(0,"Unknown Mapping");
    break;
  }
}

TitanButton TitanUI::GetTitanButton( int buttonIndex )
{
  for ( int i = 0; gCurrentTitanButtonMap[i].mButtonIndex!=-1;i++ )
  {
    if ( gCurrentTitanButtonMap[i].mButtonIndex == buttonIndex )
    {
      return gCurrentTitanButtonMap[i].mTitanButton;
    }
  }
  return ButtonMax;
}

int TitanUI::GetButtonIndex( TitanButton titanButton )
{
  for ( int i = 0; gCurrentTitanButtonMap[i].mButtonIndex!=-1;i++ )
  {
    if ( gCurrentTitanButtonMap[i].mTitanButton == titanButton )
    {
      return gCurrentTitanButtonMap[i].mButtonIndex;
    }
  }
  return -1;
}

int TitanUI::GetAxisIndex( int titanAxis)
{
  if (titanAxis < 4 && titanAxis >= 0)
  {
    return gCurrentTitanAxisMap[titanAxis];
  }
  return -1;
};


int 
TitanUI::PawnDebugUI(const char *src, int linenum, const char *variables)
{
  if( mMode == kGameModeGame )
  {
    return( mpGameWindow->PawnDebugUI( src, linenum, variables ) );
  }
  else
  {
    return( 0 );
  }
}

void
TitanUI::PawnDebugOutput(const char *output)
{
  // todo: also dump this to a file...
  if( mMode == kGameModeGame )
  {
    mpGameWindow->PawnDebugOutput( output );
  }
}

void TitanUI::FadeIn(float32 fTransition)
{
  m_fFadeTransition = fTransition;
  m_fFadeProgress = fTransition;
  m_eFade = FM_FadingIn;
}

void TitanUI::FadeOut(float32 fTransition)
{
  m_fFadeTransition = fTransition;
  m_fFadeProgress = 0.f;
  m_eFade = FM_FadingOut;
}

void TitanUI::ProcessFade(float32 fElapse)
{
  if(m_eFade == FM_Normal)
    return;

  if(m_eFade == FM_FadingIn)
  {
    m_fFadeProgress = SY_MAX(0.f, m_fFadeProgress - fElapse);
    if(m_fFadeProgress == 0.f)
    {
      m_eFade = FM_Normal;
      return;
    }
  }
  if(m_eFade == FM_FadingOut)
  {
    m_fFadeProgress = SY_MIN(m_fFadeTransition, m_fFadeProgress + fElapse);
    if(m_fFadeProgress == m_fFadeTransition)
      m_eFade = FM_Faded;
  }

  float fAlpha = 1.f;
  if(m_fFadeTransition > 0.f)
  {
    // a transition of 0 is valid... it means fade immediately
    fAlpha = m_fFadeProgress / m_fFadeTransition;
  }

  TiRect rect;
  TiSize size;
  TiUI::Instance()->GetDisplaySize(&size.cx, &size.cy);

  rect.SetRect(0, 0, size.cx, size.cy);
  TiUI::Instance()->FillRectangle(rect, SyColor32F(0.f, 0.f, 0.f, fAlpha));

}

const float32 c_fLetterboxTransition = .5f;
const float32 c_fLetterboxBarHeight = 128.f;

void TitanUI::BeginLetterbox(bool bInstant)
{
  m_eLetterbox = LM_Shrinking;
  m_fLetterboxProgress = 0.f;
  if(bInstant)
  {
    m_fLetterboxProgress = c_fLetterboxTransition;
  }
}

void TitanUI::EndLetterbox(bool bInstant /* = false */)
{
  m_eLetterbox = LM_Expanding;
  m_fLetterboxProgress = c_fLetterboxTransition;
  if(bInstant)
  {
    m_fLetterboxProgress = 0.f;
  }
}

void TitanUI::ProcessLetterbox(float32 fElapsed)
{
  if(m_eLetterbox == LM_Normal)
    return;

  if(m_eLetterbox == LM_Shrinking)
  {
    m_fLetterboxProgress = SY_MIN(c_fLetterboxTransition, m_fLetterboxProgress + fElapsed);
    if(m_fLetterboxProgress == c_fLetterboxTransition)
    {
      m_eLetterbox = LM_Letterbox;
    }
  }

  if(m_eLetterbox == LM_Expanding)
  {
    m_fLetterboxProgress = SY_MAX(0.f, m_fLetterboxProgress - fElapsed);
    if(m_fLetterboxProgress == 0.f)
    {
      m_eLetterbox = LM_Normal;
      return;
    }
  }

  TiRect rect;
  TiSize size;
  TiUI::Instance()->GetDisplaySize(&size.cx, &size.cy);

  int32 nHeight = (int32)(c_fLetterboxBarHeight * m_fLetterboxProgress / c_fLetterboxTransition);

  rect.SetRect(0, 0, size.cx, nHeight);
  TiUI::Instance()->FillRectangle(rect, c_crBlack);
  rect.SetRect(0, size.cy - nHeight, size.cx, size.cy);
  TiUI::Instance()->FillRectangle(rect, c_crBlack);
}

void TitanUI::FadeAndExit(float32 fDelayBeforeFading, float32 fFadeDuration)
{
  m_eFadeAndExit = FAE_WaitingToFade;
  m_fFAEWaitTime = fDelayBeforeFading;
  m_fFAEFadeTime = fFadeDuration;
  m_fFAEProgress = 0.f;
}

void TitanUI::ProcessFadeAndExit(float32 fElapsed)
{
  if(m_eFadeAndExit == FAE_Normal)
  {
    return;
  }

  m_fFAEProgress += fElapsed;
  if(m_eFadeAndExit == FAE_WaitingToFade)
  {
    if(m_fFAEProgress >= m_fFAEWaitTime)
    {
      m_eFadeAndExit = FAE_Fading;
      FadeOut(m_fFAEFadeTime);
    }
  }
  else if(m_eFadeAndExit == FAE_Fading)
  {
    if(m_fFAEProgress >= m_fFAEWaitTime + m_fFAEFadeTime)
    {
      m_eFadeAndExit = FAE_Exiting;
      SetGameMode(kGameModeFrontScreen);
      m_eFadeAndExit = FAE_Normal;
    }
  }
}

void TitanUI::OnFrame()
{
  SyTime time = mpInputConsole->GetTime();

  int32 w = mpRaster->GetScreenWidth();
  int32 h = mpRaster->GetScreenHeight();
  mpUI->SetDisplaySize( w, h );

  mpUI->UpdateFrameElapse(time);
  TiSprite::UpdateAnimationTime(time);

  mpTitan->AdvanceTime(time);
  mpRaster->SetTime(time);

  ////////////////
  // begin scene
  ////////////////
  mpPerformanceStats->BeginFrame();
  mpRaster->BeginScene();

  ////////////////
  // do frame
  ////////////////
  switch (mMode)
  {
    case kGameModeGame:
      OnFrameGame();
      break;
    case kGameModeFrontScreen:
      OnFrameFrontScreen();
      break;
    default:
      break;
  }

  ////////////////
  // end scene
  ////////////////
  ScreenCap();
  mpRaster->EndScene();
  mpPerformanceStats->EndFrame();

  ProcessFadeAndExit(mpUI->GetFrameElapse());

#ifdef SNTUNER
    snStartMarker(14, "ProcessInput()");
#endif
  ProcessInput();
#ifdef SNTUNER
    snStopMarker(14);
#endif


#ifdef SNTUNER
    snStartMarker(15, "ProcessUI()");
#endif
  ProcessUI();
#ifdef SNTUNER
    snStopMarker(15);
#endif

  // the mouse cursor should be visible if we've received an event in the last second
  mpInputConsole->SetCursorVisible( GetTime() - mLastMouseEvent  < 1000 );

  // are we between levels?
  if( mpTitan->IsTransitionLevelSet() )
  {
    mpESFParser->SetProgressCallback( ProgressCallback, (void*)this );
  }
  else
  {
    mpESFParser->SetProgressCallback( NULL, NULL );
  }
}

/**********************************************************
 * OnFrameFrontScreen
 **********************************************************/
void TitanUI::OnFrameFrontScreen()
{
  mpScene->Update(); // for sound system to be given time
  mpSceneControl->Render();
  
  mpRaster->Begin2D();
  mpStartWindow->ProcessFrame();
  mpStartWindow->Draw();
  if(m_bConsoleActive)
  {
    m_pConsoleWindow->ProcessFrame();
    m_pConsoleWindow->Draw();
  }
  DrawStats();
  DrawVersion();
  mpUI->FlushDeferred2D();
  mpRaster->End2D();
  mpRaster->Flush();
}


/**********************************************************
 * OnFrameGame
 **********************************************************/
void TitanUI::OnFrameGame()
{
#ifdef SNTUNER
    snStartMarker(11, "mpTitan->Render()");
#endif
    mpTitan->Render();
#ifdef SNTUNER
    snStopMarker(11);
#endif

#ifdef SNTUNER
    snStartMarker(12, "Titan 2D stuff");
#endif

    // predrawing allow windows to process frame (empty for now)

    // let the 2d windows draw themselves
    mpRaster->Begin2D();
    if(IsLetterboxMode())
    {
      ProcessLetterbox(mpUI->GetFrameElapse());
    }
    else
    {
      mpGameWindow->Draw();
    }
    ProcessFade(mpUI->GetFrameElapse());

    if(m_bConsoleActive)
    {
      m_pConsoleWindow->Draw();
    }

    DrawStats();
    DrawVersion();
    mpUI->FlushDeferred2D();
    mpRaster->End2D();

    // postdrawing allow windows to process frame
    mpGameWindow->ProcessFrame();
    if(m_bConsoleActive)
    {
      m_pConsoleWindow->ProcessFrame();
    }

#ifdef SNTUNER
    snStopMarker(12);
#endif

#ifdef SNTUNER
    snStartMarker(13, "mpTitan->RenderHUD()");
#endif
    mpTitan->RenderHUD();
#ifdef SNTUNER
    snStopMarker(13);
#endif

    mpRaster->Flush();
    SyTime time = mpScene->GetTime();

    if (!mbHardPause)
    {
#ifdef SNTUNER
    snStartMarker(10, "mpTitan->Update(time)");
#endif
      mpTitan->Update( time );
#ifdef SNTUNER
    snStopMarker(10);
#endif
    }
#ifdef HAVOK_ENABLED
    else
    {
      if (mbStabilizeHavokObjects)
      {
        if (mbStabilizeHavokObjects == 1)
        {
          mpTitan->NudgeProps();         // nudge the props
          mbStabilizeHavokObjects++;
        }
        mpTitan->UpdateJustProps( time ); //for use with havok stabilization
        
        if ( mbExitAfterStabilize )
        {
          static int countStabilizeFrames = 0;
          int i = SyHavok::GetCountOfActiveSimulationIslands();
          if (i == 0)
          {
            countStabilizeFrames++;
            if ( countStabilizeFrames == 500 )
            {
              mpTitan->SaveLevel("stable_");
              mpTitanApp->ExitMainLoop();
            }
          }
          else
          {
            countStabilizeFrames = 0;
          }
        }
      }
    }
#endif
}


struct VideoMode
{
  const char*            mpName;
  int                    mWidth;
  int                    mHeight;
};

// this table must be kept in sync with enum SyRasterTVStandard
// note: the width/height members are only used for the windows build.  The PS3 keys off the tvstandard alone. - JEFFP
static const VideoMode sTVStandards[SYRASTER_TV_STANDARD_MAX] = 
{
  { "auto",    1280,  720 },
  { "ntsc",     720,  480 },
  { "ntsc_j",   720,  480 },
  { "pal_m",    720,  576 },
  { "pal_b",    720,  576 },
  { "pal_d",    720,  576 },
  { "pal_g",    720,  576 },
  { "pal_h",    720,  576 },
  { "pal_i",    720,  576 },
  { "pal_n",    720,  576 },
  { "pal_nc",   720,  576 },
  { "480i",     720,  480 },
  { "480p",     720,  480 },
  { "576i",    1024,  576 },
  { "576p",    1024,  576 },
  { "720p",    1280,  720 },
  { "1080i",   1920, 1080 },
  { "1080p",   1920, 1080 },
  { "vga720",  1280,  720 },
  { "vga1080", 1920, 1080 }
};
#define ARRAYSIZEOF(__x) (sizeof(__x)/sizeof(__x[0]))

/* this is a global function in SyWaterSystem.cpp -PB */
void init_waterspu_elf();

void TitanUI::InputConsoleCreate(int width, int height)
{
  mpInputConsole = SyInputConsole::Create();
  mpInputConsole->Initialize( L"Virtual Desktop", width, height );
  mpInputConsole->SetCursorVisible(false);
  mLastMouseEvent = 0;
  int fixedFrameRate;
  if ( mpParameters->Found(OPTION_FRAMERATE, &fixedFrameRate ))
  {
    mpInputConsole->SetFixedFrameMode(fixedFrameRate);
  }

  SyString playbackFilename;
  if ( mpParameters->Found(OPTION_PLAYBACK, &playbackFilename ) )
  {
    SyAssertf( !mpParameters->Found(OPTION_RECORD), "You can't specify record and playback together" );
    mpInputConsole = new SyPlaybackInputConsole(mpInputConsole, playbackFilename.AsChar());
  }
  else 
  {
    SyString recordFilename;
    if ( mpParameters->Found(OPTION_RECORD, &recordFilename ) )
    {
      mpInputConsole = new SyRecordingInputConsole(mpInputConsole, recordFilename.AsChar());
    }
  }
}

int TitanUI::FrameworkCreate()
{
  CHECK_RESULT( mpParameters != NULL );
  SyRasterInit RasterInit;
  int width  = 1280;
  int height = 720;

#ifdef WIN32
  RasterInit.mFullScreen = mpParameters->Found(OPTION_FULLSCREEN);
#endif

  // OPTION_TVSTANDARD
  SyString tvstandardString;
  SyString resolution;
  if ( mpParameters->Found(OPTION_TVSTANDARD, &tvstandardString ))
  {
    tvstandardString.Lower();
    bool found = false;
    for ( size_t i = 0; i < ARRAYSIZEOF(sTVStandards); i++ )
    {
      if ( strcmp( tvstandardString.AsChar(), sTVStandards[i].mpName ) == 0 )
      {
        RasterInit.mTVStandard = (SyRasterTVStandard)i;
        if ( sTVStandards[i].mWidth != 0 && sTVStandards[i].mHeight != 0 )
        {
          width    = sTVStandards[i].mWidth;
          height   = sTVStandards[i].mHeight;
        }
        found = true;
        break;
      }
    }

    if ( !found )
    {
      // not found in the mode table, try parsing as a resolution ex. 1280x1024
      SyAssertf( false, "%s parameter is invalid", OPTION_TVSTANDARD );
      return -1;
    }
    SyOutputString( "--%s=%s\n", OPTION_TVSTANDARD, tvstandardString.AsChar() );
  }
#ifdef WIN32
  // OPTION_RESOLUTION
  else if ( mpParameters->Found(OPTION_RESOLUTION, &resolution ) )
  {
    // not found in the mode table, try parsing as a resolution ex. 1280x1024
    if ( 2 != sscanf( resolution.AsChar(), "%ix%i", &width, &height ) )
    {
      SyAssertf( false, "%s parameter is invalid", OPTION_RESOLUTION );
      return -1;
    }
    SyOutputString( "--%s=%ix%i\n", OPTION_RESOLUTION, width, height );
  }
#endif
  else
  {
    // OPTION_TVSTANDARD and OPTION_RESOLUTION were not specified, use default values
#ifdef WIN32
    if ( RasterInit.mFullScreen )
    {
      width  = GetSystemMetrics (SM_CXSCREEN); 
      height = GetSystemMetrics (SM_CYSCREEN);
    }
    else
#endif
    {
      RasterInit.mTVStandard = SYRASTER_TV_STANDARD_AUTO;
      width  = sTVStandards[RasterInit.mTVStandard].mWidth;
      height = sTVStandards[RasterInit.mTVStandard].mHeight;
    }
  }

  mpScene       = new SyScene();
  mpRaster      = new SyRaster(); 
  mpDictionary  = new SyDictionary();
  mpCollide     = new SyCollide();
  mpWaterSystem = new SyWaterSystem();

#ifdef HAVOK_ENABLED
  mpPhysics     = new SyHavok();
  mpCollide->SetHavok(mpPhysics);
#endif

  InputConsoleCreate(width, height);

#ifdef __CELLOS_LV2__
  RasterInit.mFullScreen = true;
  RasterInit.mWidth = 0;
  RasterInit.mHeight = 0;
  RasterInit.mWindowHandle = NULL;
  CHECK_RESULT( 0 == mpRaster->Init( RasterInit ) );
#else
  RasterInit.mWidth = width;
  RasterInit.mHeight = height;
  RasterInit.mWindowHandle = mpInputConsole->Context();
  CHECK_RESULT( 0 == mpRaster->Init( RasterInit ) );
#endif


#ifdef __CELLOS_LV2__
  init_waterspu_elf();
#endif

  mpSoundDevice = new SySoundDevice();

  CHECK_RESULT( 0 == mpCollide->Init() );

  if ( mpSoundDevice )
  {
      CHECK_RESULT( 0 == mpSoundDevice->Init(SySoundDevice::kOutputModeStereo, 32) );
  }
  CHECK_RESULT( 0 == mpDictionary->Init() );

  CHECK_RESULT( 0 == mpScene->Init( GetTime(), *mpDictionary, mpRaster, mpSoundDevice, *mpCollide, mpWaterSystem ) );
  mpScene->SetMultiPass(true);
  mBloomEffectHandle = mpScene->GetPostEffectSystem()->CreateBloomEffect();

  mpTitan->GetFXScriptDriver()->Init(*mpScene);
  mpScene->GetFXScriptSystem()->SetDriver(*mpTitan->GetFXScriptDriver());

  mpPerformanceStats = new SyPerformanceStats;
  CHECK_RESULT( mpPerformanceStats->Init( *mpScene ) == 0 );

  //CHECK_RESULT( 0 == LoadAssets() );

  return 0;
}

void TitanUI::FrameworkDestroy()
{
  if (mpScene != NULL)
  {
    mpScene->Clear();
  }

  if (mpDictionary != NULL)
  {
    mpDictionary->Clear();
  }

  if (mpSoundDevice != NULL)
  {
    mpSoundDevice->Close();
  }

  if (mpCollide != NULL)
  {
    mpCollide->Close();
  }

  if (mpRaster != NULL)
  {
    mpRaster->Close();
  }


#ifdef HAVOK_ENABLED
  delete mpPhysics;
#endif

  delete mpScene;
  delete mpWaterSystem;
  delete mpPerformanceStats;
  delete mpRaster;
  delete mpDictionary;
  delete mpCollide;
  delete mpSoundDevice;
  delete mpInputConsole;
}

int TitanUI::FrameworkReset()
{
  // clear resources
  CHECK_RESULT( 0 == mpScene->Clear() );
  CHECK_RESULT( 0 == mpDictionary->Clear() );

  // reset devices
  if ( mpSoundDevice )
  {
    CHECK_RESULT( 0 == mpSoundDevice->Reset() );
  }
  CHECK_RESULT( 0 == mpCollide->Reset() );
  CHECK_RESULT( 0 == mpRaster->Reset() );

#ifdef HAVOK_ENABLED
  CHECK_RESULT( 0 == mpPhysics->Reset() );
#endif

  // init resources
  CHECK_RESULT( 0 == mpDictionary->Init() );

  CHECK_RESULT( 0 == mpScene->Init( 0, *mpDictionary, mpRaster, mpSoundDevice, *mpCollide, mpWaterSystem ) );
  mpScene->SetMultiPass(true);
  mBloomEffectHandle = mpScene->GetPostEffectSystem()->CreateBloomEffect();
  
  mpTitan->GetFXScriptDriver()->Init(*mpScene);
  mpScene->GetFXScriptSystem()->SetDriver(*mpTitan->GetFXScriptDriver());

  return(0);
}

void TitanUI::InterfaceCreate()
{
  m_bConsoleActive = false;

    // create windows
  mpUI = SyNew TiUI( mpRaster, mpSoundDevice, mpDictionary, &mAtlasDirectory, mFontHandle );
  mpStartWindow = SyNew TiStartWindow( mpTitanApp, this );
  mpGameWindow = SyNew TiGameWindow( mpTitanApp, this, mpTitan );
  m_pConsoleWindow = new TiConsoleWindow(mpTitanApp, mpTitan);

    // hide windows
  mpStartWindow->Show( false );
  mpGameWindow->Show( false );
  m_pConsoleWindow->Show( false );

    // not sure what these do - JEFFP
  mpStats = SyNew TiUIControl();
  mpStats->Close( true );
  mpParameters->Found(OPTION_STATS, &mShowStats);
}

void TitanUI::InterfaceDestroy()
{
  delete m_pConsoleWindow;
  delete mpStartWindow;
  delete mpGameWindow;
  delete mpStats;
  delete mpUI;

  m_pConsoleWindow = NULL;
  mpStartWindow = NULL;
  mpGameWindow = NULL;
  mpUI = NULL;
  mpStats = NULL;
}

int TitanUI::LoadAtlasDirectory( const char8* pFilename )
{
  TiXmlDocument xmldoc( pFilename );

  // load the XML file
  if( !xmldoc.LoadFile() )
  {
    return -1;
  }

  const char* pDocumentElementName          = "TextureAtlasDirectory";
  const char* pSubImageElementName          = "SubImage";
  const char* pSubImageNameAttribute        = "name";
  const char* pSubImageTextureNameAttribute = "texture";
  const char* pTextureCoordinateElementName = "TextureCoordinate";

  // get the root node
  TiXmlHandle docHandle( &xmldoc );

  // read all sub-images
  TiXmlElement* subImage = docHandle.FirstChildElement( pDocumentElementName ).FirstChildElement( pSubImageElementName ).Element();
  for ( ; subImage; subImage = subImage->NextSiblingElement( pSubImageElementName ) )
  {
    const char* pSubImageName = subImage->Attribute( pSubImageNameAttribute );
    const char* pTextureName  = subImage->Attribute( pSubImageTextureNameAttribute );

    TiBitmapInfo bi;
    bi.mSurfaceResourceID = SyHashResourceID( pTextureName );

    // read coordinates
    TiXmlElement* textureCoordinate = subImage->FirstChildElement( pTextureCoordinateElementName );
    for( int i = 0; i < 4; i++ )
    {
      int u, v;
      textureCoordinate->QueryIntAttribute( "u", &u );
      textureCoordinate->QueryIntAttribute( "v", &v );
      bi.mUV[i].X = u;
      bi.mUV[i].Y = v;

      textureCoordinate = textureCoordinate->NextSiblingElement( pTextureCoordinateElementName );
    }

    // add to atlas
    SyResourceID resourceID = SyHashResourceID( pSubImageName );
    mAtlasDirectory[ resourceID ] = bi;
  }

  return( 0 );
};

void TitanUI::Main()
{
  mpTitanApp->RunMainLoop();
}

void TitanUI::ProcessInput()
{
  mpInputConsole->Update();

  for (;;)
  {
    SyInputEvent *event = mpInputConsole->PopEvent();
    if ( event == 0 )
    {
      break;
    }
    switch ( event->GetType() )
    {
    case SyInputEvent::EVENT_ACTIVATEAPP:
    case SyInputEvent::EVENT_SIZE:
      break;
    case SyInputEvent::EVENT_QUIT:
      mpTitanApp->ExitMainLoop();
      break;
    case SyInputEvent::EVENT_LBUTTONUP:
    case SyInputEvent::EVENT_MOUSEMOVE:
    case SyInputEvent::EVENT_LBUTTONDOWN:
    case SyInputEvent::EVENT_MBUTTONUP:
    case SyInputEvent::EVENT_MBUTTONDOWN:
    case SyInputEvent::EVENT_RBUTTONUP:
    case SyInputEvent::EVENT_RBUTTONDOWN:
      mLastMouseEvent = GetTime();
      break;
    case SyInputEvent::EVENT_KEYCHAR:
    case SyInputEvent::EVENT_KEYDOWN:
    case SyInputEvent::EVENT_KEYUP:
      {
        int  data        = event->GetParam(SyInputEvent::KEY_INDEX_KEY);
        int  x           = event->GetParam(SyInputEvent::KEY_INDEX_MOUSEX);
        int  y           = event->GetParam(SyInputEvent::KEY_INDEX_MOUSEY);
        bool shiftDown   = event->GetParam(SyInputEvent::KEY_INDEX_SHIFTKEY)!=0;
        bool controlDown = event->GetParam(SyInputEvent::KEY_INDEX_CTRLKEY)!=0;
        bool altDown     = event->GetParam(SyInputEvent::KEY_INDEX_ALTKEY)!=0;
        bool extendedKey = event->GetParam(SyInputEvent::KEY_INDEX_EXTENDEDKEY)!=0;
        //bool capsLock    = event->GetParam(SyInputEvent::KEY_INDEX_CAPSLOCK)!=0;
        //bool numLock     = event->GetParam(SyInputEvent::KEY_INDEX_NUMLOCK)!=0;

        switch ( event->GetType() )
        {
        case SyInputEvent::EVENT_KEYCHAR:
          OnChar( data, x, y, shiftDown, controlDown, altDown, extendedKey );
          break;
        case SyInputEvent::EVENT_KEYDOWN:
          OnKeyDown( (SyInputEvent::KeyCode)data, x, y, shiftDown, controlDown, altDown, extendedKey );
          break;
        case SyInputEvent::EVENT_KEYUP:
          OnKeyUp( (SyInputEvent::KeyCode)data, x, y, shiftDown, controlDown, altDown, extendedKey );
          break;
        default:
          break;
        }
      }
      break;
    case SyInputEvent::EVENT_PADSTATE:
      {
        int  deviceId      = event->GetParam(SyInputEvent::PADSTATE_INDEX_CONTROLLERID);
        RawController* pRawController = &mRawController[deviceId];

        // save old controller state
        RawController before = *pRawController;

        // update controller state
        pRawController->SetConnected( true );
        pRawController->SetAxis( 0, event->GetParam(SyInputEvent::PADSTATE_INDEX_JOY1X) );
        pRawController->SetAxis( 1, event->GetParam(SyInputEvent::PADSTATE_INDEX_JOY1Y) );
        pRawController->SetAxis( 2, event->GetParam(SyInputEvent::PADSTATE_INDEX_JOY2X) );
        pRawController->SetAxis( 3, event->GetParam(SyInputEvent::PADSTATE_INDEX_JOY2Y) );

        int dpadButtons[4];
        RawController::POVtoDPAD( event->GetParam(SyInputEvent::PADSTATE_INDEX_POV1), dpadButtons );
        for ( int i = 0; i < 4; i++ )
        {
          pRawController->SetButton( i, dpadButtons[i] );
        }

        for ( int i = 0; i < RawController::BUTTON_MAX-4; i++ )      // BUTTON_MAX better be less than PADSTATE_BUTTON_COUNT - JEFFP
        {
          pRawController->SetButton( i + 4, event->GetParam(SyInputEvent::PADSTATE_INDEX_BUTTON1 + i) );
        }

        // create a button state bit vector
        int buttonStates = pRawController->GetButtonStates();

        if ( pRawController->GetConnected() != before.GetConnected() )
        {
          if ( pRawController->GetConnected() )
          {
            OnControllerConnect( deviceId, pRawController->GetAxis(0), pRawController->GetAxis(1), buttonStates );
          }
          else
          {
            OnControllerDisconnect( deviceId, pRawController->GetAxis(0), pRawController->GetAxis(1), buttonStates );
          }
        }

        for ( int i = 0; i < RawController::AXIS_MAX; i++ )
        {
          if ( pRawController->GetAxis(i) != before.GetAxis(i) )
          {
            OnControllerAxisMove( deviceId, pRawController->GetAxis(0), pRawController->GetAxis(1), buttonStates );
          }
        }

        for ( int i = 0; i < RawController::BUTTON_MAX; i++ )
        {
          if ( pRawController->GetButton(i) != before.GetButton(i) )
          {
            // a button has changed state the last state event
            if ( pRawController->GetButton(i) )
            {
              OnControllerButtonDown( deviceId, i, pRawController->GetAxis(0), pRawController->GetAxis(1), buttonStates );
            }
            else
            {
              OnControllerButtonUp( deviceId, i, pRawController->GetAxis(0), pRawController->GetAxis(1), buttonStates );
            }
          }
        }
      }
      break;

    default:
      break;
    }

    delete event;
  }
}

void TitanUI::ProcessUI()
{
  if (mDesiredMode != mMode)
  {
    SetGameMode(mDesiredMode);
  }

  if( mMode == kGameModeGame )
  {
    // update game window(s) data
    // todo: networked players
    int32 localPlayers = mpTitan->GetNumLocalPlayers();
    mpGameWindow->SetPlayerCount( localPlayers );
    for( int32 i = 0; i < localPlayers; i++ )
    {
      mpGameWindow->SetHealthMax(     i, mpTitan->GetPlayerHealthMax(i) );
      mpGameWindow->SetHealth(        i, mpTitan->GetPlayerHealth(i) );
      mpGameWindow->SetManaMax(       i, mpTitan->GetPlayerManaMax(i) );
      mpGameWindow->SetMana(          i, mpTitan->GetPlayerMana(i) );
      mpGameWindow->SetExperienceMax( i, mpTitan->GetPlayerNextLevelExp(i) - mpTitan->GetPlayerPrevLevelExp(i) );
      mpGameWindow->SetExperience(    i, mpTitan->GetPlayerCurExp(i) - mpTitan->GetPlayerPrevLevelExp(i) );

      const int BUF_LEN = 128;
      char buf[BUF_LEN];
      bool activate = mpTitan->GetSubtitleText( buf, BUF_LEN );
      if( activate )
      {
        mpGameWindow->SetSubtitleText( buf );
      }
      else
      {
        mpGameWindow->SetSubtitleText( "" );
      }

      activate = mpTitan->GetActivateString( i, buf, BUF_LEN );
      if( activate )
      {
        mpGameWindow->SetActivateText( i, buf );
      }
      else
      {
        mpGameWindow->SetActivateText( i, "" );
      }
    }
  }
  else if( mMode == kGameModeFrontScreen )
  {
  }
}

void TitanUI::OnChar( int data, int mouseX, int mouseY, bool shiftDown, bool controlDown, bool altDown, bool extendedKey )
{
}

static bool smInputConsoleKeyCodeToTitanKeyCodeMapReady = false;
static uint8 smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_COUNT];

void InitInputConsoleKeyCodeToTitanKeyCodeMap()
{
  if ( smInputConsoleKeyCodeToTitanKeyCodeMapReady )
  {
    return;
  }
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_NONE] = (uint8)TitanI::KEYCODE_NONE;

  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F1] = (uint8)TitanI::KEYCODE_F1;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F2] = (uint8)TitanI::KEYCODE_F2;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F3] = (uint8)TitanI::KEYCODE_F3;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F4] = (uint8)TitanI::KEYCODE_F4;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F5] = (uint8)TitanI::KEYCODE_F5;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F6] = (uint8)TitanI::KEYCODE_F6;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F7] = (uint8)TitanI::KEYCODE_F7;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F8] = (uint8)TitanI::KEYCODE_F8;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F9] = (uint8)TitanI::KEYCODE_F9;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F10] = (uint8)TitanI::KEYCODE_F10;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F11] = (uint8)TitanI::KEYCODE_F11;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F12] = (uint8)TitanI::KEYCODE_F12;
                                                         
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_ESCAPE] = (uint8)TitanI::KEYCODE_ESCAPE;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_PRINT] = (uint8)TitanI::KEYCODE_PRINT;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_PAUSE] = (uint8)TitanI::KEYCODE_PAUSE;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_ACCENT] = (uint8)TitanI::KEYCODE_ACCENT;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_MINUS] = (uint8)TitanI::KEYCODE_MINUS;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_EQUAL] = (uint8)TitanI::KEYCODE_EQUAL;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_BACKSPACE] = (uint8)TitanI::KEYCODE_BACKSPACE;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_TAB] = (uint8)TitanI::KEYCODE_TAB;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_LEFT_BRACKET] = (uint8)TitanI::KEYCODE_LEFT_BRACKET;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_RIGHT_BRACKET] = (uint8)TitanI::KEYCODE_RIGHT_BRACKET;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_BACKSLASH] = (uint8)TitanI::KEYCODE_BACKSLASH;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_SEMICOLON] = (uint8)TitanI::KEYCODE_SEMICOLON;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_QUOTE] = (uint8)TitanI::KEYCODE_QUOTE;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_ENTER] = (uint8)TitanI::KEYCODE_ENTER;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_COMMA] = (uint8)TitanI::KEYCODE_COMMA;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_PERIOD] = (uint8)TitanI::KEYCODE_PERIOD;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_SLASH] = (uint8)TitanI::KEYCODE_SLASH;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_SPACE] = (uint8)TitanI::KEYCODE_SPACE;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_INSERT] = (uint8)TitanI::KEYCODE_INSERT;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_HOME] = (uint8)TitanI::KEYCODE_HOME;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_PAGE_UP] = (uint8)TitanI::KEYCODE_PAGE_UP;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_DELETE] = (uint8)TitanI::KEYCODE_DELETE;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_END] = (uint8)TitanI::KEYCODE_END;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_PAGE_DOWN] = (uint8)TitanI::KEYCODE_PAGE_DOWN;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_UP] = (uint8)TitanI::KEYCODE_UP;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_LEFT] = (uint8)TitanI::KEYCODE_LEFT;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_DOWN] = (uint8)TitanI::KEYCODE_DOWN;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_RIGHT] = (uint8)TitanI::KEYCODE_RIGHT;
                                                         
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_0] = (uint8)TitanI::KEYCODE_0;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_1] = (uint8)TitanI::KEYCODE_1;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_2] = (uint8)TitanI::KEYCODE_2;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_3] = (uint8)TitanI::KEYCODE_3;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_4] = (uint8)TitanI::KEYCODE_4;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_5] = (uint8)TitanI::KEYCODE_5;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_6] = (uint8)TitanI::KEYCODE_6;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_7] = (uint8)TitanI::KEYCODE_7;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_8] = (uint8)TitanI::KEYCODE_8;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_9] = (uint8)TitanI::KEYCODE_9;
                                                         
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_A] = (uint8)TitanI::KEYCODE_A;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_B] = (uint8)TitanI::KEYCODE_B;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_C] = (uint8)TitanI::KEYCODE_C;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_D] = (uint8)TitanI::KEYCODE_D;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_E] = (uint8)TitanI::KEYCODE_E;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_F] = (uint8)TitanI::KEYCODE_F;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_G] = (uint8)TitanI::KEYCODE_G;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_H] = (uint8)TitanI::KEYCODE_H;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_I] = (uint8)TitanI::KEYCODE_I;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_J] = (uint8)TitanI::KEYCODE_J;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_K] = (uint8)TitanI::KEYCODE_K;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_L] = (uint8)TitanI::KEYCODE_L;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_M] = (uint8)TitanI::KEYCODE_M;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_N] = (uint8)TitanI::KEYCODE_N;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_O] = (uint8)TitanI::KEYCODE_O;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_P] = (uint8)TitanI::KEYCODE_P;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_Q] = (uint8)TitanI::KEYCODE_Q;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_R] = (uint8)TitanI::KEYCODE_R;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_S] = (uint8)TitanI::KEYCODE_S;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_T] = (uint8)TitanI::KEYCODE_T;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_U] = (uint8)TitanI::KEYCODE_U;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_V] = (uint8)TitanI::KEYCODE_V;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_W] = (uint8)TitanI::KEYCODE_W;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_X] = (uint8)TitanI::KEYCODE_X;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_Y] = (uint8)TitanI::KEYCODE_Y;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_Z] = (uint8)TitanI::KEYCODE_Z;
                                                         
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_0] = (uint8)TitanI::KEYCODE_KEYPAD_0;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_1] = (uint8)TitanI::KEYCODE_KEYPAD_1;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_2] = (uint8)TitanI::KEYCODE_KEYPAD_2;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_3] = (uint8)TitanI::KEYCODE_KEYPAD_3;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_4] = (uint8)TitanI::KEYCODE_KEYPAD_4;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_5] = (uint8)TitanI::KEYCODE_KEYPAD_5;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_6] = (uint8)TitanI::KEYCODE_KEYPAD_6;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_7] = (uint8)TitanI::KEYCODE_KEYPAD_7;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_8] = (uint8)TitanI::KEYCODE_KEYPAD_8;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_9] = (uint8)TitanI::KEYCODE_KEYPAD_9;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_PERIOD] = (uint8)TitanI::KEYCODE_KEYPAD_PERIOD;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_DIVIDE] = (uint8)TitanI::KEYCODE_KEYPAD_DIVIDE;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_MULTIPLY] = (uint8)TitanI::KEYCODE_KEYPAD_MULTIPLY;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_SUBTRACT] = (uint8)TitanI::KEYCODE_KEYPAD_SUBTRACT;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_ADD] = (uint8)TitanI::KEYCODE_KEYPAD_ADD;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KEYPAD_ENTER] = (uint8)TitanI::KEYCODE_KEYPAD_ENTER;
                                                         
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_NUM_LOCK] = (uint8)TitanI::KEYCODE_NUM_LOCK;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_CAPS_LOCK] = (uint8)TitanI::KEYCODE_CAPS_LOCK;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_SCROLL_LOCK] = (uint8)TitanI::KEYCODE_SCROLL_LOCK;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_SHIFT] = (uint8)TitanI::KEYCODE_SHIFT;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_CTRL] = (uint8)TitanI::KEYCODE_CTRL;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_ALT] = (uint8)TitanI::KEYCODE_ALT;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_WIN] = (uint8)TitanI::KEYCODE_WIN;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_APPLICATION] = (uint8)TitanI::KEYCODE_APPLICATION;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_KANA] = (uint8)TitanI::KEYCODE_KANA;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_HENKAN] = (uint8)TitanI::KEYCODE_HENKAN;
  smInputConsoleKeyCodeToTitanKeyCodeMap[SyInputEvent::KEYCODE_MUHENKAN] = (uint8)TitanI::KEYCODE_MUHENKAN;

  smInputConsoleKeyCodeToTitanKeyCodeMapReady = true;
}

TitanI::KeyCode InputConsoleKeyCodeToTitanKeyCode( SyInputEvent::KeyCode key )
{
  InitInputConsoleKeyCodeToTitanKeyCodeMap();
  return (TitanI::KeyCode)smInputConsoleKeyCodeToTitanKeyCodeMap[key];
}

void TitanUI::OnKeyDown( SyInputEvent::KeyCode data, int mouseX, int mouseY, bool shiftDown, bool controlDown, bool altDown, bool extendedKey )
{
  if (data == SyInputEvent::KEYCODE_HOME)
  {
    SyMemory::Snapshot(false);
  }

  if(m_bConsoleActive)
  {
    if(data == SyInputEvent::KEYCODE_ESCAPE)
    {
      m_bConsoleActive = false;
      m_pConsoleWindow->Show(m_bConsoleActive);
    }
    else
    {
      m_pConsoleWindow->ProcessKeyDown(data);
    }
    return;
  }

  switch ( data )
  {
  case SyInputEvent::KEYCODE_F4:
    {
      static int cap_num = 0;
      char filename[512];
      sprintf(filename,"capture_%d.bmp",cap_num++);
      SyScreenCap cap;
      cap.Init(*mpRaster);
      cap.CaptureToBMPFile(filename);
      break;
    }

  case SyInputEvent::KEYCODE_W:
    mShowStats = !mShowStats;
    break;

  case SyInputEvent::KEYCODE_D:
    {
      static bool bToggleShowDmgFlash = true;
      bToggleShowDmgFlash = !bToggleShowDmgFlash;
      mpTitan->SetShowDamageFlash(bToggleShowDmgFlash);
    }
    break;

  case SyInputEvent::KEYCODE_X:
    mShowVersion = !mShowVersion;
    break;
    
  case SyInputEvent::KEYCODE_Y:
    {
      TiWindow* pFocus = mpTitanApp->GetFocus();
      if( pFocus )
      {
        pFocus->ReloadLayout();
      }
    }
    break;

  case SyInputEvent::KEYCODE_Z:
    mShowUI = !mShowUI;
    break;

  case SyInputEvent::KEYCODE_O:
    if( mMode == kGameModeGame )
    {
      mpGameWindow->TogglePawnOutput();
      break;
    }
    // else FALLTHROUGH to default

  case SyInputEvent::KEYCODE_ESCAPE:
    m_bConsoleActive = true;
    m_pConsoleWindow->Show(m_bConsoleActive);
    break;

  case SyInputEvent::KEYCODE_S:
    mpTitan->SaveLevel("stable_");
    break;

  case SyInputEvent::KEYCODE_H:
    mbStabilizeHavokObjects = 1;   // activate havok stabilization
    break;

  case SyInputEvent::KEYCODE_PAUSE:
    mbHardPause = !mbHardPause;
    if (mbHardPause)
    {
      mbStabilizeHavokObjects = 0;  // only deactivate havok stabilization when turning on pause
    }
    break;

  case SyInputEvent::KEYCODE_END:
    mShowPlayerPos = !mShowPlayerPos;
    if (mShowPlayerPos)
    {
      DEBUGOVERLAY_ENABLECHANNEL("playerPos", 1);
    }
    else
    {
      DEBUGOVERLAY_ENABLECHANNEL("playerPos", 0);
    }
    break;

  default:
    {
      // give whatever has focus first crack at it
      TiWindow* pFocus = mpTitanApp->GetFocus();
      if( !pFocus || !pFocus->ProcessKeyDown( data ) )
      {
        // no window handled the key event; pass to Titan
        TitanI::KeyCode titanKeyCode = InputConsoleKeyCodeToTitanKeyCode( data );
        mpTitan->CheatKey( titanKeyCode );
      }
    }
  }
}

//---------------------------------------------------------------------------------------------------------------------------------------------
// void TitanUI::SetHavokRagdoll( int i )
// related to OPTION_HAVOKNORAGDOLL - when this is set, SetHavokRagdoll is called with false to turn off ragdoll
//---------------------------------------------------------------------------------------------------------------------------------------------
void TitanUI::SetHavokRagdoll( int i )
{
#ifdef HAVOK_ENABLED
  SyHavok::SetEnableRagdoll( i );
#endif
}

void TitanUI::OnKeyUp( SyInputEvent::KeyCode data, int mouseX, int mouseY, bool shiftDown, bool controlDown, bool altDown, bool extendedKey )
{
  if(m_bConsoleActive)
  {
    m_pConsoleWindow->ProcessKeyUp(data);
    return;
  }
  TiWindow* pFocus = mpTitanApp->GetFocus();
  if( pFocus )
  {
    pFocus->ProcessKeyUp( data );
  }
}

void TitanUI::OnControllerAxisMove( int deviceId, int axisX, int axisY, int buttonStates )
{
  TiWindow* pFocus = mpTitanApp->GetFocus();
  if( !pFocus || !pFocus->ProcessAxisMove( deviceId, axisX, axisY, buttonStates) )
  {
  }
}

void TitanUI::OnControllerButtonDown( int deviceId, int buttonId, int axisX, int axisY, int buttonStates )
{
  // give active window first try at processing
  TiWindow* pFocus = mpTitanApp->GetFocus();
  if( !pFocus || !pFocus->ProcessButtonDown( deviceId, buttonId ) )
  {
    if( mMode == kGameModeGame )
    {
      // no window handled the button event; pass to Titan
      TitanButton tb = GetTitanButton( buttonId );
      TitanInputHandlerI* pInputHandler = mpTitan->GetInputHandler( deviceId );

      if( pInputHandler != NULL && tb < ButtonMax )
      {
        pInputHandler->OnButtonDown( tb );
      }
    }
  }
}

void TitanUI::OnControllerButtonUp( int deviceId, int buttonId, int axisX, int axisY, int buttonStates )
{
  // give active window first try at processing
  TiWindow* pFocus = mpTitanApp->GetFocus();
  if( !pFocus || !pFocus->ProcessButtonUp( deviceId, buttonId ) )
  {
    if( mMode == kGameModeGame )
    {
      // no window handled the button event; pass to Titan
      TitanButton tb = GetTitanButton( buttonId );
      TitanInputHandlerI* pInputHandler = mpTitan->GetInputHandler( deviceId );

      if( pInputHandler != NULL && tb < ButtonMax )
      {
        pInputHandler->OnButtonUp( tb );
      }
    }
  }
}

void TitanUI::OnControllerConnect( int deviceId, int axisX, int axisY, int buttonStates )
{
}

void TitanUI::OnControllerDisconnect( int deviceId, int axisX, int axisY, int buttonStates )
{
}

uint64 TitanUI::GetTime()
{
  return mpInputConsole->GetTime();
}

void TitanUI::ProcessCommandMessage( TiCommandMessage* pMessage )
{
  switch( pMessage->GetCommandId() )
  {
  case TI_CMD_GOD_MODE:
    mpTitan->SetGodMode( pMessage->IsChecked() );
    break;
  case TI_CMD_INVISIBLE:
    mpTitan->SetInvisibleMode( pMessage->IsChecked() );
    break;
  case TI_CMD_LOG:
    mpTitan->SetLogMode( pMessage->IsChecked() );
    break;
  case TI_CMD_DEBUG_LABEL:
    mpTitan->SetDebugLabel( pMessage->IsChecked() );
    break;
  case TI_CMD_RESTART:
    {
      bool bGodMode = mpTitan->GetGodMode();
      bool bInvisibleMode = mpTitan->GetInvisibleMode();
      mpTitan->Restart();

      // player gets recreated, so we need to restore these flags ourselves
      if (bGodMode)
      {
        mpTitan->SetGodMode(true);
      }

      if (bInvisibleMode)
      {
        mpTitan->SetInvisibleMode(true);
      }
    }
    break;
  case TI_CMD_BLOOM:
    mpTitan->SetBloom( pMessage->IsChecked() );
    break;
  //case TI_CMD_WATERONSPU:
    //mpTitan->SetEnableSPUWater( !mpTitan->GetEnableSPUWater() );
    //break;
  case TI_CMD_MULTI_PASS:
    mpTitan->SetMultiPass( pMessage->IsChecked() );
    break;
  case TI_CMD_DISPLAY_STATS:
    mShowStats = true;
    break;
  case TI_CMD_NORMAL:
    mpTitan->SetDrawMode( TitanI::DrawModeNormal );
    break;
  case TI_CMD_WIRE_FRAME:
    mpTitan->SetDrawMode( TitanI::DrawModeWire );
    break;
  case TI_CMD_SOLID_FILL:
    mpTitan->SetDrawMode( TitanI::DrawModeSolid );
    break;
  case TI_CMD_TOGGLE_SHADOW:
    mpScene->EnableShadows( mpScene->AreShadowsEnabled() ? 0 : 1 );
    break;
  case TI_CMD_TOGGLE_PORTALS:
    mpScene->EnablePortalDisplay( mpScene->IsPortalDisplayEnabled() ? 0 : 1 );
    break;
  case TI_CMD_TOGGLE_FLORA:
    mpScene->SetRadialFloraMode( mpScene->GetRadialFloraMode() ? SYRADIALFLORAMODE_OFF : SYRADIALFLORAMODE_ON );
    break;
  case TI_CMD_TOGGLE_PARTICLES:
    mpScene->EnableParticleSystem( mpScene->IsParticleSystemEnabled() ? 0 : 1 );
    break;
  case TI_CMD_VINCE:
    break;
  case TI_CMD_MONO:
    break;
  case TI_CMD_STEREO:
    break;
  case TI_CMD_5_1_SURROUND:
    break;
  case TI_CMD_7_1_SURROUND:
    break;
  case TI_CMD_START:
    ProcessStartMessage( pMessage );
    break;
  case TI_CMD_EXIT_GAME:
    SetDesiredGameMode(kGameModeFrontScreen);
    break;
  case TI_CMD_EXIT_TITAN:
    mpTitanApp->ExitMainLoop();
    break;
  case TI_CMD_GOTO_LEVEL:
    ProcessGotoLevelMessage( pMessage );
    break;
  }
}

// handle message from front screens
void TitanUI::ProcessStartMessage( TiCommandMessage* pMessage )
{
  TiStartMessage* pMsg = static_cast<TiStartMessage*>(pMessage);
  m_nGameToLoad = -1;

  switch( pMsg->GetStartMessageId() )
  {
  case TI_START_GO:
    SetDesiredGameMode(kGameModeGame);
    break;
  case TI_START_LOAD_GAME:
	  if( mMode == kGameModeGame )
	  {
		  mpTitan->SaveGameLoad( pMsg->GetLoadGame() );
	  }
	  else
	  {
		  m_nGameToLoad = pMsg->GetLoadGame();
		  SetDesiredGameMode(kGameModeGame);
	  }
	  break;
  case TI_START_NEW_GAME:
    SetDesiredGameMode(kGameModeGame);
    // mpTitan->SetPlayerName( 0, pMsg->GetName().AsChar() );
    break;
  }
}

void TitanUI::ProcessGotoLevelMessage( TiCommandMessage* pMessage )
{
  mCurrentLevelFilename = pMessage->GetCommandString();
  mpTitan->SetTransitionLevel( mCurrentLevelFilename.AsChar(), "playerSpawn" );
}

void TitanUI::SetDesiredGameMode(GameMode mode)
{
  mDesiredMode = mode;
}

void TitanUI::ClearCurrentGameMode()
{
  switch(mMode)
  {
    case kGameModeFrontScreen:
      ClearFrontScreen();
      break;
    case kGameModeGame:
      ClearGame();
      break;
    case kGameModeNone:
      break;
  }

  mMode = kGameModeNone;
  mDesiredMode = mMode;
}

void TitanUI::SetGameMode(GameMode mode)
{
  ClearCurrentGameMode();

  mMode = mode;
  mDesiredMode = mMode;

  switch(mMode)
  {
    case kGameModeFrontScreen:
      InitFrontScreen();
      break;
    case kGameModeGame:
      InitGame();
      break;
    case kGameModeNone:
      break;
  }
}

int TitanUI::InitFrontScreen()
{
  // load assets common to game & front-screen
  InitCommon();

  // load assets specific to front-screen
  int32 handle;
  SyESFParse& parser = GetESFParser();
  CHECK_RESULT( 0 == parser.Parse( "game_assets/art/ui/pregame.esf", *mpScene ) );
  CHECK_RESULT( 0 != mpDictionary->FindTyped( SyHashResourceID("title_menu.tga"), SYRESOURCETYPE_SURFACE, handle ) );
  CHECK_RESULT( 0 != mpDictionary->FindTyped( SyHashResourceID("soe_logo.tga"), SYRESOURCETYPE_SURFACE, handle ) );
  //CHECK_RESULT( 0 != mpDictionary->FindTyped( SyHashResourceID("pregame000.tga"), SYRESOURCETYPE_SURFACE, handle ) );
  //CHECK_RESULT( 0 == LoadAtlasDirectory("game_assets/art/ui/pregame.dir") );
  LoadStartScene();

  // switch interfaces
#if 1
  mpStartWindow->StartScreen();     // skip directly to menu for now - JEFFP
#endif
  mpStartWindow->Show( true );
  mpStartWindow->SetFocus();
  return( 0 );
}

int TitanUI::ClearFrontScreen()
{
  mpStartWindow->Show( false );

  // reset directory
  mAtlasDirectory.clear();

  ClearCommon();
  return( 0 );
}

int TitanUI::InitGame()
{
  // load common assets
  InitCommon();

  if ( mpParameters->Found(OPTION_NET) )
  {
        // multiplayer network startup requested
    SyString levelname = GetStartupLevel();
    const char* netRecordFilename = "";
    const char* netPlaybackFilename = "";
    mpTitan->HackStartupNetwork("Kaiser Sose", "Test Game", levelname.AsChar(), netRecordFilename, netPlaybackFilename);
  }
  else
  {
    // load game mode specific assets
    LoadLevel( GetStartupLevel() );
  }

  // if we're loading a saved game, do that now
  if( m_nGameToLoad >= 0 )
  {
	  mpTitan->SaveGameLoad( m_nGameToLoad );
	  m_nGameToLoad = -1;
  }

#if 0       // enable for a memory snapshot before first frame of level is rendered
  SyMemory::Snapshot(false);
#endif

  // switch interfaces
  mpGameWindow->Show( true );
  mpGameWindow->SetFocus();
  return( 0 );
}

int TitanUI::ClearGame()
{
  mpGameWindow->Show( false );

  // clear game resources
  mpTitan->Reset();

  // reset directory
  mAtlasDirectory.clear();

  ClearCommon();
  return( 0 );
}

int TitanUI::InitCommon()
{
  SyESFParse loading;
  CHECK_RESULT( 0 == loading.Parse( "game_assets/art/ui/loading_sewers_1.esf", *mpScene ) );

  int32 handle;
  SyESFParse& parser = GetESFParser();

  // load font, images
  CHECK_RESULT( 0 == parser.Parse( "programming/ui/albertus27.esf", *mpScene ) );
  CHECK_RESULT( 0 == parser.Parse( "game_assets/art/ui/ui.esf", *mpScene ) );

  CHECK_RESULT( 0 == parser.Parse( "programming/ui/sounds.esf", *mpScene ) );

  // make sure they're there
  CHECK_RESULT( 0 != mpDictionary->FindTyped( SyHashResourceID("albertus27"), SYRESOURCETYPE_FONT, mFontHandle ) );
  CHECK_RESULT( 0 != mpDictionary->FindTyped( SyHashResourceID("atlas000.tga"), SYRESOURCETYPE_SURFACE, handle ) );
  CHECK_RESULT( 0 != mpDictionary->FindTyped( SyHashResourceID("vTile000.tga"), SYRESOURCETYPE_SURFACE, handle ) );
  CHECK_RESULT( 0 != mpDictionary->FindTyped( SyHashResourceID("hTile000.tga"), SYRESOURCETYPE_SURFACE, handle ) );

  // load image directory
  CHECK_RESULT( 0 == LoadAtlasDirectory("game_assets/art/ui/atlas.dir") );
  CHECK_RESULT( 0 == LoadAtlasDirectory("game_assets/art/ui/vTile.dir") );
  CHECK_RESULT( 0 == LoadAtlasDirectory("game_assets/art/ui/hTile.dir") );

  // add standalone tiles that aren't atlas'd
  TiBitmapInfo bi;
  bi.mSurfaceResourceID = SyHashResourceID( "black.tga" );
  bi.mUV[0] = SyVect2I(0,0);
  bi.mUV[1] = SyVect2I(32,0);
  bi.mUV[2] = SyVect2I(32,32);
  bi.mUV[3] = SyVect2I(0,32);
  mAtlasDirectory[ bi.mSurfaceResourceID ] = bi;

  bi.mSurfaceResourceID = SyHashResourceID( "menu_dialog_scrollbar.tga" );
  bi.mUV[0] = SyVect2I(0,0);
  bi.mUV[1] = SyVect2I(16,0);
  bi.mUV[2] = SyVect2I(16,4);
  bi.mUV[3] = SyVect2I(0,4);
  mAtlasDirectory[ bi.mSurfaceResourceID ] = bi;

  
  bi.mSurfaceResourceID = SyHashResourceID( "menu_dialog_gradient.tga" );
  bi.mUV[0] = SyVect2I(0,0);
  bi.mUV[1] = SyVect2I(512,0);
  bi.mUV[2] = SyVect2I(512,512);
  bi.mUV[3] = SyVect2I(0,512);
  mAtlasDirectory[ bi.mSurfaceResourceID ] = bi;
  

  bi.mSurfaceResourceID = SyHashResourceID( "frontend_gamecontrols.tga" );
  bi.mUV[0] = SyVect2I(0,0);
  bi.mUV[1] = SyVect2I(960,0);
  bi.mUV[2] = SyVect2I(960,720);
  bi.mUV[3] = SyVect2I(0,720);
  mAtlasDirectory[ bi.mSurfaceResourceID ] = bi;

  bi.mSurfaceResourceID = SyHashResourceID( "title_menu.tga" );
  bi.mUV[0] = SyVect2I(0,0);
  bi.mUV[1] = SyVect2I(1280,0);
  bi.mUV[2] = SyVect2I(1280,720);
  bi.mUV[3] = SyVect2I(0,720);
  mAtlasDirectory[ bi.mSurfaceResourceID ] = bi;

  bi.mSurfaceResourceID = SyHashResourceID( "title_splash.tga" );
  bi.mUV[0] = SyVect2I(0,0);
  bi.mUV[1] = SyVect2I(1280,0);
  bi.mUV[2] = SyVect2I(1280,720);
  bi.mUV[3] = SyVect2I(0,720);
  mAtlasDirectory[ bi.mSurfaceResourceID ] = bi;

  bi.mSurfaceResourceID = SyHashResourceID( "downloads.tga" );
  bi.mUV[0] = SyVect2I(0,0);
  bi.mUV[1] = SyVect2I(1280,0);
  bi.mUV[2] = SyVect2I(1280,720);
  bi.mUV[3] = SyVect2I(0,720);
  mAtlasDirectory[ bi.mSurfaceResourceID ] = bi;

  bi.mSurfaceResourceID = SyHashResourceID( "soe_logo.tga" );
  bi.mUV[0] = SyVect2I(0,0);
  bi.mUV[1] = SyVect2I(884,0);
  bi.mUV[2] = SyVect2I(884,598);
  bi.mUV[3] = SyVect2I(0,598);
  mAtlasDirectory[ bi.mSurfaceResourceID ] = bi;

  // manually add minimap textures (again, this needs to be automated somehow)
  bi.mSurfaceResourceID = SyHashResourceID( "barbarian_lands_1_minimap512.tga" );
  bi.mUV[0] = SyVect2I(0,0);
  bi.mUV[1] = SyVect2I(512,0);
  bi.mUV[2] = SyVect2I(512,512);
  bi.mUV[3] = SyVect2I(0,512);
  mAtlasDirectory[ bi.mSurfaceResourceID ] = bi;

  TiSpriteInfo::CreateTextureSprites(mAtlasDirectory);
  TiSpriteInfo::ReadXML( "ul3sprites.xml" );

  InterfaceCreate();
  return( 0 );
}

void TitanUI::LoadLevel( const SyString& Filename )
{
  SyTime start = SyTimer::GetTime();
  SyAssert( mMode == kGameModeGame );
  mCurrentLevelFilename = Filename;
  mpESFParser->SetProgressCallback( ProgressCallback, (void*)this );
  mpTitan->LoadLevel( Filename.AsChar() );
  mpESFParser->SetProgressCallback( NULL, NULL );
  SyTime end = SyTimer::GetTime();
  SyTime elapsed = end - start;
  SyOutputString( "TitanUI::LoadLevel: %i seconds\n", (int)(elapsed/1000) );
  mpTitan->Update(0);
  FadeIn(2.0f);
}

SyString TitanUI::GetStartupLevel()
{
  SyAssert( mpParameters != NULL );
  SyString result;
  if( !mpParameters->Found( OPTION_LEVEL, &result ) )
  {
    result = "sewers_1.lvl";
  }

  return( result );
}

void TitanUI::ScreenCap()
{
  if (mMovieFilename.Length() != 0)
  {
    char useFilename[256];
    sprintf(useFilename, "%s_%06d.bmp", mMovieFilename.AsChar(), mMovieFrame);
    mMovieFrame++;

    SyScreenCap cap;
    cap.Init(*mpRaster);
    cap.CaptureToBMPFile(useFilename);
  }
}

void TitanUI::DrawStats()
{
  // this could be moved into its own drawing object...
  if( mpStats && mShowStats )
  {
    mpStats->Open( true );

    // window dimensions
    int32 w, h;
    mpUI->GetDisplaySize( &w, &h );

    int32 x0 = 0;
    int32 x1 = mpUI->GetStringWidth( "MemTotal:  " );
    int32 x2 = x1 + mpUI->GetStringWidth( "000000000 " );

    int32 rows = 10;
    int32 width = x2 + mpUI->GetStringWidth( "000000000 " ); //450;
    int32 height = mpUI->GetFontHeight() * rows;

    // position at upper right corner
    SyVect2I center( w-(width>>1)-75, (height>>1)+75 );
    mpStats->Init( center, SyVect2I(width,height), TiUIControl::kNone );
    mpStats->Draw();

    SyColor32F color( 1,1,1,1 );
    int32 fps = mpTitan->GetFPS();
    if( fps < 30 ) {
      color( 1,0,0,1 );
    } else if( fps < 60 ) {
      color( 1,1,0,1 );
    }

    // print labels
    mpStats->DrawTextBox( "FPS:",       x0, 1, x1, 1, color, TI_TF_SHADOW );
    mpStats->DrawTextBox( "Batches:",   x0, 2, x1, 1, color, TI_TF_SHADOW );
    mpStats->DrawTextBox( "Vertices:",  x0, 3, x1, 1, color, TI_TF_SHADOW );
    mpStats->DrawTextBox( "Tris:",      x0, 4, x1, 1, color, TI_TF_SHADOW );
    mpStats->DrawTextBox( "Deg Tris:",  x0, 5, x1, 1, color, TI_TF_SHADOW );
    mpStats->DrawTextBox( "Fill:",      x0, 6, x1, 1, color, TI_TF_SHADOW );

    // print stats
    char8 str[256];
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetFPS() );
    mpStats->DrawTextBox( str, x1, 1, x2-x1, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetBatches() );
    mpStats->DrawTextBox( str, x1, 2, x2-x1, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetVertexes() );
    mpStats->DrawTextBox( str, x1, 3, x2-x1, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetTriangles() );
    mpStats->DrawTextBox( str, x1, 4, x2-x1, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetDegenerateTriangles() );
    mpStats->DrawTextBox( str, x1, 5, x2-x1, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetPixels() );
    mpStats->DrawTextBox( str, x1, 6, x2-x1, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );

    // print average stats
    mpStats->DrawTextBox( "Avg", x2, 0, width-x2, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetAverageFPS() );
    mpStats->DrawTextBox( str, x2, 1, width-x2, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetAverageBatches() );
    mpStats->DrawTextBox( str, x2, 2, width-x2, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetAverageVertexes() );
    mpStats->DrawTextBox( str, x2, 3, width-x2, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetAverageTriangles() );
    mpStats->DrawTextBox( str, x2, 4, width-x2, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", mpTitan->GetAverageDegenerateTriangles() );
    mpStats->DrawTextBox( str, x2, 5, width-x2, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );

#ifdef HAVOK_ENABLED
    mpStats->DrawTextBox( "HkIslands:",      x0, 7, x1, 1, color, TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%i", SyHavok::GetCountOfActiveSimulationIslands() );
    mpStats->DrawTextBox( str, x1, 7, x2-x1, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
#endif

#ifdef DEBUG
    mpStats->DrawTextBox( "MemTotal:",      x0, 8, x1, 1, color, TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%u", SyMemory::GetTotalMemoryInUse());
    mpStats->DrawTextBox( str, x1, 8, x2-x1, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );

    mpStats->DrawTextBox( "MemPeak:",      x0, 9, x1, 1, color, TI_TF_SHADOW );
    SyStr::snprintf( str, sizeof(str), "%u", SyMemory::GetPeakMemoryInUse());
    mpStats->DrawTextBox( str, x1, 9, x2-x1, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );

    #if 0
        mpStats->DrawTextBox( "MemDebug:",      x0, 10, x1, 1, color, TI_TF_SHADOW );
        SyStr::snprintf( str, sizeof(str), "%u", SyMemory::GetDebugMemoryInUse());
        mpStats->DrawTextBox( str, x1, 10, x2-x1, 1, color, TI_TF_HALIGN_RIGHT|TI_TF_SHADOW );
    #endif
#endif
  }

  if (mShowPlayerPos)
  {
    SyVect3 pos;
    
    mpTitan->GetPlayerLocation(0, pos);

    DEBUGOVERLAY_DRAWSCREENTEXT(0,
                                "playerPos",
                                100,
                                600,
                                ("Player Position: (%f, %f)", pos(0), pos(2)),
                                cDebugOverlay::WHITE);
  }
}

void TitanUI::DrawVersion()
{
  if( mShowVersion )
  {
    int32 w, h;
    mpUI->GetDisplaySize( &w, &h );
    mpUI->DrawCenteredString( g_buildVersionString, SyVect2I(w>>1,75), SyColor32F(1,1,1,1), SYRASTER_CENTERFLAG_HCENTER, true );
  }
}

void TitanUI::LoadStartScene()
{
  // background scene
  int32 w = mpRaster->GetScreenWidth();
  int32 h = mpRaster->GetScreenHeight();
  mpSceneControl->Init( this, 55.f, (float32)w / (float32)h );

  // placeholder art
  mpESFParser->SetProgressCallback( ProgressCallback, (void*)this );
  //mpSceneControl->LoadScene( "game_assets\\art\\levels\\arena.esf" );
  mpESFParser->SetProgressCallback( NULL, NULL );
}

void TitanUI::UpdatePhysics( float deltatime )
{
#ifdef HAVOK_ENABLED
  mpPhysics->Update( deltatime );
#endif
}

void TitanUI::UpdateInputConsole()
{
  mpInputConsole->Update();
}

TiUII*      TitanUI::GetUII()
{
  return mpUI;
}

bool TitanUI::GetDisplayStats() const
{
  return( mShowStats );
}

void TitanUI::SetMinimap(const SyString&  textureName,
                         const SyVect2&   worldPos1,
                         const SyVect2&   worldPos2,
                         const SyVect2&   mapPos1,
                         const SyVect2&   mapPos2,
                         SyRaster*        raster,
                         SyDictionary*    dictionary)
{
  mpGameWindow->SetMinimap(textureName,
                           worldPos1,
                           worldPos2,
                           mapPos1,
                           mapPos2,
                           raster,
                           dictionary);
}

void TitanUI::UpdateCharacterData()
{
	if( mpGameWindow != NULL )
	{
		mpGameWindow->UpdateCharacterData();
	}
}
