2002-01-16 10:01:32 +00:00
# include "stdafx.h"
/*
-----------------------------------------------------------------------------
2002-05-19 01:59:48 +00:00
Class: ThemeManager
2002-01-16 10:01:32 +00:00
2002-02-28 19:40:40 +00:00
Desc: See header.
2002-01-16 10:01:32 +00:00
2002-05-19 01:59:48 +00:00
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
2002-02-28 19:40:40 +00:00
Chris Danford
2002-01-16 10:01:32 +00:00
-----------------------------------------------------------------------------
*/
# include "ThemeManager.h"
2002-05-01 19:14:55 +00:00
# include "RageLog.h"
2002-07-23 01:41:40 +00:00
# include "PrefsManager.h"
2002-07-27 19:29:51 +00:00
# include "RageException.h"
2002-08-31 10:33:13 +00:00
# include "RageTimer.h"
2002-07-31 19:40:40 +00:00
# include "GameState.h"
# include "GameDef.h"
2002-08-13 23:26:46 +00:00
# include "IniFile.h"
2002-10-28 19:05:05 +00:00
# include "RageTimer.h"
2002-01-16 10:01:32 +00:00
2002-10-31 03:54:50 +00:00
# include <fstream>
using namespace std ;
2002-01-16 10:01:32 +00:00
ThemeManager * THEME = NULL ; // global object accessable from anywhere in the program
2002-07-23 01:41:40 +00:00
const CString BASE_THEME_NAME = " default " ;
const CString THEMES_DIR = " Themes \\ " ;
2002-05-19 01:59:48 +00:00
2002-03-19 07:09:49 +00:00
ThemeManager : : ThemeManager ( )
{
2002-08-13 23:26:46 +00:00
m_pIniMetrics = new IniFile ;
2002-08-31 10:33:13 +00:00
/* Update the metric cache on the first call to GetMetric. */
2002-10-28 19:05:05 +00:00
m_fNextReloadTicks = 0 ;
2002-08-13 23:26:46 +00:00
2002-10-28 19:05:05 +00:00
m_sCurThemeName = BASE_THEME_NAME ; // Use the base theme for now. It's up to PrefsManager to change this.
2002-07-23 01:41:40 +00:00
2002-03-19 07:09:49 +00:00
CStringArray arrayThemeNames ;
2002-07-31 19:40:40 +00:00
GetAllThemeNames ( arrayThemeNames ) ;
2002-03-19 07:09:49 +00:00
}
2002-08-13 23:26:46 +00:00
ThemeManager : : ~ ThemeManager ( )
{
delete m_pIniMetrics ;
}
2002-07-31 19:40:40 +00:00
void ThemeManager : : GetAllThemeNames ( CStringArray & AddTo )
2002-03-19 07:09:49 +00:00
{
2002-07-23 01:41:40 +00:00
GetDirListing ( THEMES_DIR + " \\ * " , AddTo , true ) ;
2002-03-19 07:09:49 +00:00
// strip out the folder called "CVS"
2002-10-31 04:11:08 +00:00
for ( CStringArray : : iterator i = AddTo . begin ( ) ; i ! = AddTo . end ( ) ; + + i )
{
if ( ! stricmp ( * i , " cvs " ) ) {
AddTo . erase ( i , i + 1 ) ;
break ;
}
}
2002-03-19 07:09:49 +00:00
}
2002-07-31 19:40:40 +00:00
void ThemeManager : : GetThemeNamesForCurGame ( CStringArray & AddTo )
{
GetAllThemeNames ( AddTo ) ;
2002-08-27 16:53:25 +00:00
/*
2002-07-31 19:40:40 +00:00
// strip out announcers that don't have the current game name in them
CString sGameName = GAMESTATE->GetCurrentGameDef()->m_szName;
sGameName.MakeLower();
2002-10-31 02:12:14 +00:00
for( unsigned i=AddTo.size()-1; i>=0; i-- )
2002-07-31 19:40:40 +00:00
{
CString sLowercaseVer = AddTo[i];
sLowercaseVer.MakeLower();
if( sLowercaseVer.Find(sGameName)==-1 )
AddTo.RemoveAt(i);
}
2002-08-27 16:53:25 +00:00
*/
2002-07-31 19:40:40 +00:00
}
2002-07-23 01:41:40 +00:00
bool ThemeManager : : DoesThemeExist ( CString sThemeName )
2002-03-19 07:09:49 +00:00
{
2002-07-23 01:41:40 +00:00
CStringArray asThemeNames ;
2002-07-31 19:40:40 +00:00
GetAllThemeNames ( asThemeNames ) ;
2002-10-31 02:12:14 +00:00
for ( unsigned i = 0 ; i < asThemeNames . size ( ) ; i + + )
2002-07-27 19:29:51 +00:00
{
2002-07-23 01:41:40 +00:00
if ( 0 = = stricmp ( sThemeName , asThemeNames [ i ] ) )
return true ;
2002-07-27 19:29:51 +00:00
}
2002-07-23 01:41:40 +00:00
return false ;
2002-03-19 07:09:49 +00:00
}
2002-07-23 01:41:40 +00:00
void ThemeManager : : SwitchTheme ( CString sThemeName )
{
2002-09-29 17:38:07 +00:00
if ( ! DoesThemeExist ( sThemeName ) )
2002-07-23 01:41:40 +00:00
m_sCurThemeName = BASE_THEME_NAME ;
else
m_sCurThemeName = sThemeName ;
2002-08-13 23:26:46 +00:00
// update hashes for metrics files
2002-09-07 09:53:03 +00:00
m_uHashForCurThemeMetrics = GetHashForFile ( GetMetricsPathFromName ( m_sCurThemeName ) ) ;
m_uHashForBaseThemeMetrics = GetHashForFile ( GetMetricsPathFromName ( BASE_THEME_NAME ) ) ;
2002-08-13 23:26:46 +00:00
// read new metrics. First read base metrics, then read cur theme's metrics, overriding base theme
m_pIniMetrics - > Reset ( ) ;
m_pIniMetrics - > SetPath ( GetMetricsPathFromName ( BASE_THEME_NAME ) ) ;
m_pIniMetrics - > ReadFile ( ) ;
m_pIniMetrics - > SetPath ( GetMetricsPathFromName ( m_sCurThemeName ) ) ;
m_pIniMetrics - > ReadFile ( ) ;
2002-03-19 07:09:49 +00:00
}
2002-05-19 01:59:48 +00:00
CString ThemeManager : : GetThemeDirFromName ( CString sThemeName )
2002-03-19 07:09:49 +00:00
{
2002-07-23 01:41:40 +00:00
return THEMES_DIR + sThemeName + " \\ " ;
2002-03-19 07:09:49 +00:00
}
2002-08-13 23:26:46 +00:00
CString ThemeManager : : GetPathTo ( CString sAssetCategory , CString sFileName )
{
2002-08-26 19:30:58 +00:00
# ifdef _DEBUG
2002-08-22 09:31:32 +00:00
try_element_again :
2002-08-26 19:30:58 +00:00
# endif
2002-08-22 09:31:32 +00:00
2002-08-13 23:26:46 +00:00
sAssetCategory . MakeLower ( ) ;
sFileName . MakeLower ( ) ;
const CString sCurrentThemeDir = GetThemeDirFromName ( m_sCurThemeName ) ;
const CString sDefaultThemeDir = GetThemeDirFromName ( BASE_THEME_NAME ) ;
CStringArray asPossibleElementFilePaths ;
// look for a redirect
GetDirListing ( sCurrentThemeDir + sAssetCategory + " \\ " + sFileName + " *.redir " , asPossibleElementFilePaths , false , true ) ;
2002-10-31 02:12:14 +00:00
if ( ! asPossibleElementFilePaths . empty ( ) )
2002-08-13 23:26:46 +00:00
{
2002-10-31 03:54:50 +00:00
ifstream file ( asPossibleElementFilePaths [ 0 ] ) ;
2002-08-13 23:26:46 +00:00
CString sLine ;
2002-10-31 03:54:50 +00:00
getline ( file , sLine ) ;
2002-08-13 23:26:46 +00:00
}
///////////////////////////////////////
// Search both the current theme and the default theme dirs for this element
///////////////////////////////////////
2002-08-31 19:13:45 +00:00
static const char * graphic_masks [ ] = {
" *.sprite " , " *.png " , " *.jpg " , " *.bmp " , " *.gif " , " *.redir " ,
" *.avi " , " *.mpg " , " *.mpeg " , NULL
} ;
static const char * sound_masks [ ] = { " .set " , " .mp3 " , " .ogg " , " .wav " , " .redir " , NULL } ;
2002-09-03 22:31:06 +00:00
static const char * font_masks [ ] = { " 16x16.png " , " .redir " , NULL } ;
2002-09-22 18:18:50 +00:00
static const char * numbers_masks [ ] = { " 5x3.png " , " .redir " , NULL } ;
2002-09-23 07:35:47 +00:00
static const char * bganimations_masks [ ] = { " . " , " .redir " , NULL } ;
2002-08-31 19:13:45 +00:00
const char * * asset_masks = NULL ;
if ( sAssetCategory = = " graphics " ) asset_masks = graphic_masks ;
else if ( sAssetCategory = = " sounds " ) asset_masks = sound_masks ;
else if ( sAssetCategory = = " fonts " ) asset_masks = font_masks ;
2002-09-22 18:18:50 +00:00
else if ( sAssetCategory = = " numbers " ) asset_masks = numbers_masks ;
2002-09-23 07:35:47 +00:00
else if ( sAssetCategory = = " bganimations " ) asset_masks = bganimations_masks ;
2002-08-31 19:13:45 +00:00
else ASSERT ( 0 ) ; // Unknown theme asset category
int i ;
for ( i = 0 ; asset_masks [ i ] ; + + i )
GetDirListing ( sCurrentThemeDir + sAssetCategory + " \\ " + sFileName + asset_masks [ i ] ,
asPossibleElementFilePaths , false , true ) ;
for ( i = 0 ; asset_masks [ i ] ; + + i )
GetDirListing ( sDefaultThemeDir + sAssetCategory + " \\ " + sFileName + asset_masks [ i ] ,
asPossibleElementFilePaths , false , true ) ;
2002-08-13 23:26:46 +00:00
2002-10-31 02:12:14 +00:00
if ( asPossibleElementFilePaths . empty ( ) )
2002-08-13 23:26:46 +00:00
{
2002-08-22 09:31:32 +00:00
# ifdef _DEBUG
2002-11-11 04:53:31 +00:00
switch ( MessageBox ( NULL , " ThemeManager " , ssprintf ( " The theme element %s/%s is missing. " , sAssetCategory . GetString ( ) , sFileName . GetString ( ) ) , MB_ABORTRETRYIGNORE ) )
2002-09-30 06:32:56 +00:00
{
case IDRETRY :
2002-08-22 09:31:32 +00:00
goto try_element_again ;
2002-09-30 06:32:56 +00:00
break ;
case IDABORT :
# endif
throw RageException ( " Theme element '%s/%s' could not be found in '%s' or '%s'. " ,
2002-10-29 07:58:44 +00:00
sAssetCategory . GetString ( ) ,
sFileName . GetString ( ) ,
2002-09-30 06:32:56 +00:00
GetThemeDirFromName ( m_sCurThemeName ) ,
GetThemeDirFromName ( BASE_THEME_NAME ) ) ;
# ifdef _DEBUG
case IDIGNORE :
LOG - > Warn (
" Theme element '%s/%s' could not be found in '%s' or '%s'. " ,
2002-10-29 07:58:44 +00:00
sAssetCategory . GetString ( ) ,
sFileName . GetString ( ) ,
2002-09-30 06:32:56 +00:00
GetThemeDirFromName ( m_sCurThemeName ) ,
GetThemeDirFromName ( BASE_THEME_NAME ) ) ;
return GetPathTo ( sAssetCategory , " _missing " ) ;
break ;
}
2002-08-22 09:31:32 +00:00
# endif
2002-08-13 23:26:46 +00:00
}
2002-09-07 09:53:03 +00:00
asPossibleElementFilePaths [ 0 ] . MakeLower ( ) ;
if ( asPossibleElementFilePaths [ 0 ] . GetLength ( ) > 5 & & asPossibleElementFilePaths [ 0 ] . Right ( 5 ) = = " redir " ) // this is a redirect file
2002-08-13 23:26:46 +00:00
{
2002-09-07 09:53:03 +00:00
CString sRedirFilePath = asPossibleElementFilePaths [ 0 ] ;
CString sDir , sFName , sExt ;
splitrelpath ( sRedirFilePath , sDir , sFName , sExt ) ;
CString sNewFileName ;
2002-10-31 03:54:50 +00:00
{
ifstream file ( sRedirFilePath ) ;
getline ( file , sNewFileName ) ;
2002-09-05 19:03:33 +00:00
// CString sNewFilePath = sDir+"\\"+sNewFileName; // This is what it used to be, FONT redirs were getting extra slashes
2002-09-09 05:50:32 +00:00
// at the start of their file names, so I took out this extra slash - Andy.
2002-10-31 03:54:50 +00:00
}
2002-09-09 05:50:32 +00:00
CString sNewFilePath = sDir + sNewFileName ;
if ( sNewFileName = = " " | | ! DoesFileExist ( sNewFilePath ) )
{
2002-09-09 05:22:02 +00:00
# ifdef _DEBUG
2002-11-11 04:53:31 +00:00
if ( IDRETRY = = MessageBox ( NULL , " ThemeManager " , ssprintf ( " The redirect '%s' points to the file '%s', which does not exist. Verify that this redirect is correct. " , sRedirFilePath . GetString ( ) , sNewFilePath . GetString ( ) ) , MB_RETRYCANCEL ) )
2002-09-09 05:50:32 +00:00
goto try_element_again ;
2002-09-09 05:22:02 +00:00
# endif
2002-10-29 07:58:44 +00:00
throw RageException ( " The redirect '%s' points to the file '%s', which does not exist. Verify that this redirect is correct. " , sRedirFilePath . GetString ( ) , sNewFilePath . GetString ( ) ) ;
2002-09-09 05:22:02 +00:00
}
else
2002-09-09 05:50:32 +00:00
return sNewFilePath ;
2002-08-13 23:26:46 +00:00
}
2002-05-19 06:13:16 +00:00
2002-09-07 09:53:03 +00:00
return asPossibleElementFilePaths [ 0 ] ;
2002-02-09 04:30:27 +00:00
}
2002-08-13 23:26:46 +00:00
CString ThemeManager : : GetMetricsPathFromName ( CString sThemeName )
{
return GetThemeDirFromName ( sThemeName ) + " metrics.ini " ;
}
2002-09-17 23:02:37 +00:00
CString ThemeManager : : GetMetric ( CString sClassName , CString sValueName )
2002-08-13 23:26:46 +00:00
{
2002-08-26 19:30:58 +00:00
# ifdef _DEBUG
2002-08-22 09:31:32 +00:00
try_metric_again :
2002-08-26 19:30:58 +00:00
# endif
2002-08-13 23:26:46 +00:00
CString sCurMetricPath = GetMetricsPathFromName ( m_sCurThemeName ) ;
CString sDefaultMetricPath = GetMetricsPathFromName ( BASE_THEME_NAME ) ;
2002-08-31 10:33:13 +00:00
// Is our metric cache out of date?
2002-10-28 19:05:05 +00:00
// XXX: GTSS wraps every ~40 days. Need a better way to handler timers like this.
if ( TIMER - > GetTimeSinceStart ( ) > = m_fNextReloadTicks )
2002-08-13 23:26:46 +00:00
{
2002-10-28 19:05:05 +00:00
m_fNextReloadTicks = TIMER - > GetTimeSinceStart ( ) + 1.0f ;
2002-09-07 09:53:03 +00:00
if ( m_uHashForCurThemeMetrics ! = GetHashForFile ( sCurMetricPath ) | |
m_uHashForBaseThemeMetrics ! = GetHashForFile ( sDefaultMetricPath ) )
2002-08-31 10:33:13 +00:00
{
SwitchTheme ( m_sCurThemeName ) ; // force a reload of the metrics cache
}
2002-08-13 23:26:46 +00:00
}
CString sValue ;
2002-09-17 23:02:37 +00:00
if ( m_pIniMetrics - > GetValue ( sClassName , sValueName , sValue ) )
2002-09-03 22:31:06 +00:00
{
sValue . Replace ( " :: " , " \n " ) ; // "::" means newline since you can't use line breaks in an ini file.
2002-08-13 23:26:46 +00:00
return sValue ;
2002-09-03 22:31:06 +00:00
}
2002-08-13 23:26:46 +00:00
2002-08-22 09:31:32 +00:00
# ifdef _DEBUG
2002-11-11 04:53:31 +00:00
if ( IDRETRY = = MessageBox ( NULL , " ThemeManager " , ssprintf ( " The theme metric %s-%s is missing. Correct this and click Retry, or Cancel to break. " , sClassName . GetString ( ) , sValueName . GetString ( ) ) , MB_RETRYCANCEL ) )
2002-08-22 09:31:32 +00:00
goto try_metric_again ;
# endif
2002-08-13 23:26:46 +00:00
throw RageException ( " Theme metric '%s : %s' could not be found in '%s' or '%s'. " ,
2002-10-29 07:58:44 +00:00
sClassName . GetString ( ) ,
sValueName . GetString ( ) ,
sCurMetricPath . GetString ( ) ,
sDefaultMetricPath . GetString ( )
2002-08-13 23:26:46 +00:00
) ;
}
2002-09-17 23:02:37 +00:00
int ThemeManager : : GetMetricI ( CString sClassName , CString sValueName )
2002-08-13 23:26:46 +00:00
{
2002-09-17 23:02:37 +00:00
return atoi ( GetMetric ( sClassName , sValueName ) ) ;
2002-08-13 23:26:46 +00:00
}
2002-09-17 23:02:37 +00:00
float ThemeManager : : GetMetricF ( CString sClassName , CString sValueName )
2002-08-13 23:26:46 +00:00
{
2002-09-17 23:02:37 +00:00
return ( float ) atof ( GetMetric ( sClassName , sValueName ) ) ;
2002-08-13 23:26:46 +00:00
}
2002-09-17 23:02:37 +00:00
bool ThemeManager : : GetMetricB ( CString sClassName , CString sValueName )
2002-08-13 23:26:46 +00:00
{
2002-09-17 23:02:37 +00:00
return atoi ( GetMetric ( sClassName , sValueName ) ) ! = 0 ;
2002-08-13 23:26:46 +00:00
}
2002-10-28 05:30:45 +00:00
RageColor ThemeManager : : GetMetricC ( CString sClassName , CString sValueName )
2002-08-13 23:26:46 +00:00
{
float r = 1 , b = 1 , g = 1 , a = 1 ; // initialize in case sscanf fails
2002-09-17 23:02:37 +00:00
CString sValue = GetMetric ( sClassName , sValueName ) ;
2002-08-13 23:26:46 +00:00
char szValue [ 40 ] ;
2002-09-17 23:02:37 +00:00
strncpy ( szValue , sValue , 39 ) ;
2002-08-13 23:26:46 +00:00
int result = sscanf ( szValue , " %f,%f,%f,%f " , & r , & g , & b , & a ) ;
if ( result ! = 4 )
{
2002-10-29 07:58:44 +00:00
LOG - > Warn ( " The color value '%s' for NoteSkin metric '%s : %s' is invalid. " , szValue , sClassName . GetString ( ) , sValueName . GetString ( ) ) ;
2002-08-13 23:26:46 +00:00
ASSERT ( 0 ) ;
}
2002-10-28 05:30:45 +00:00
return RageColor ( r , g , b , a ) ;
2002-08-13 23:26:46 +00:00
}