2003-02-16 04:01:45 +00:00
# include "global.h"
2003-02-06 07:32:57 +00:00
# include "NoteSkinManager.h"
# include "RageLog.h"
# include "RageException.h"
# include "GameState.h"
# include "GameDef.h"
# include "StyleInput.h"
2004-06-28 07:26:00 +00:00
# include "Style.h"
2003-02-06 07:32:57 +00:00
# include "RageUtil.h"
# include "GameManager.h"
2003-07-22 07:47:27 +00:00
# include "arch/arch.h"
2003-09-03 04:30:29 +00:00
# include "RageDisplay.h"
2004-06-10 22:47:51 +00:00
# include "arch/Dialog/Dialog.h"
2004-03-01 02:45:29 +00:00
# include "PrefsManager.h"
2003-02-06 07:32:57 +00:00
NoteSkinManager * NOTESKIN = NULL ; // global object accessable from anywhere in the program
2003-12-10 09:26:05 +00:00
const CString NOTESKINS_DIR = " NoteSkins/ " ;
2003-08-15 03:14:53 +00:00
const CString GAME_BASE_NOTESKIN_NAME = " default " ;
2003-12-10 09:26:05 +00:00
const CString GLOBAL_BASE_NOTESKIN_DIR = NOTESKINS_DIR + " common/default/ " ;
2004-02-17 22:16:22 +00:00
static map < CString , CString > g_PathCache ;
2003-02-06 07:32:57 +00:00
NoteSkinManager : : NoteSkinManager ( )
{
2004-07-25 04:27:20 +00:00
m_pCurGame = NULL ;
2003-02-06 07:32:57 +00:00
}
NoteSkinManager : : ~ NoteSkinManager ( )
{
}
2004-07-25 04:27:20 +00:00
void NoteSkinManager : : RefreshNoteSkinData ( const GameDef * game )
2003-02-06 07:32:57 +00:00
{
2003-09-12 04:18:43 +00:00
/* Reload even if we don't need to, so exiting out of the menus refreshes the note
* skin list (so you don't have to restart to see new noteskins). */
2004-07-25 04:27:20 +00:00
m_pCurGame = GAMESTATE - > m_pCurGame ;
2003-09-12 04:18:43 +00:00
2004-07-25 04:27:20 +00:00
const GameDef * pGameDef = game ;
2003-02-06 07:32:57 +00:00
2004-02-17 22:16:22 +00:00
// clear path cache
g_PathCache . clear ( ) ;
2003-12-10 09:44:16 +00:00
CString sBaseSkinFolder = NOTESKINS_DIR + pGameDef - > m_szName + " / " ;
2003-04-22 04:54:04 +00:00
CStringArray asNoteSkinNames ;
GetDirListing ( sBaseSkinFolder + " * " , asNoteSkinNames , true ) ;
2003-02-06 07:32:57 +00:00
2003-04-22 04:54:04 +00:00
// strip out "CVS"
2003-04-23 02:45:51 +00:00
for ( int i = asNoteSkinNames . size ( ) - 1 ; i > = 0 ; i - - )
2003-04-22 04:54:04 +00:00
if ( 0 = = stricmp ( " cvs " , asNoteSkinNames [ i ] ) )
asNoteSkinNames . erase ( asNoteSkinNames . begin ( ) + i , asNoteSkinNames . begin ( ) + i + 1 ) ;
2003-02-06 07:32:57 +00:00
2003-04-22 04:54:04 +00:00
m_mapNameToData . clear ( ) ;
2003-04-23 02:45:51 +00:00
for ( unsigned j = 0 ; j < asNoteSkinNames . size ( ) ; j + + )
2003-02-06 07:32:57 +00:00
{
2003-04-23 02:45:51 +00:00
CString sName = asNoteSkinNames [ j ] ;
2003-04-22 04:54:04 +00:00
sName . MakeLower ( ) ;
m_mapNameToData [ sName ] = NoteSkinData ( ) ;
LoadNoteSkinData ( sName , m_mapNameToData [ sName ] ) ;
2003-02-06 07:32:57 +00:00
}
2003-04-22 04:54:04 +00:00
}
2003-02-06 07:32:57 +00:00
2003-04-22 04:54:04 +00:00
void NoteSkinManager : : LoadNoteSkinData ( CString sNoteSkinName , NoteSkinData & data_out )
{
data_out . sName = sNoteSkinName ;
data_out . metrics . Reset ( ) ;
2003-02-09 00:47:11 +00:00
2003-08-15 03:14:53 +00:00
/* Load global NoteSkin defaults */
2004-05-23 02:27:51 +00:00
data_out . metrics . ReadFile ( GLOBAL_BASE_NOTESKIN_DIR + " metrics.ini " ) ;
2003-08-15 03:14:53 +00:00
/* Load game NoteSkin defaults */
2004-05-23 02:27:51 +00:00
data_out . metrics . ReadFile ( GetNoteSkinDir ( GAME_BASE_NOTESKIN_NAME ) + " metrics.ini " ) ;
2003-08-15 03:14:53 +00:00
/* Read the active NoteSkin */
2004-05-23 02:27:51 +00:00
data_out . metrics . ReadFile ( GetNoteSkinDir ( sNoteSkinName ) + " metrics.ini " ) ;
2003-04-22 04:54:04 +00:00
}
void NoteSkinManager : : GetNoteSkinNames ( CStringArray & AddTo )
{
2003-09-12 04:18:43 +00:00
/* If the skin data for the current game isn't already load it, load it now. */
2004-07-25 04:27:20 +00:00
if ( m_pCurGame ! = GAMESTATE - > m_pCurGame )
RefreshNoteSkinData ( GAMESTATE - > m_pCurGame ) ;
2003-09-12 04:18:43 +00:00
/* Don't call GetNoteSkinNames below, since we don't want to call RefreshNoteSkinData; it's
* slow. */
for ( map < CString , NoteSkinData > : : const_iterator iter = m_mapNameToData . begin ( ) ;
iter ! = m_mapNameToData . end ( ) ; + + iter )
{
AddTo . push_back ( iter - > second . sName ) ;
}
2003-10-29 10:43:18 +00:00
2004-02-17 22:23:07 +00:00
/* Move "default" to the front if it exists. */
2003-10-29 10:43:18 +00:00
{
CStringArray : : iterator iter = find ( AddTo . begin ( ) , AddTo . end ( ) , " default " ) ;
if ( iter ! = AddTo . end ( ) )
{
AddTo . erase ( iter ) ;
2004-03-01 02:45:29 +00:00
if ( ! PREFSMAN - > m_bHideDefaultNoteSkin )
AddTo . insert ( AddTo . begin ( ) , " default " ) ;
2003-10-29 10:43:18 +00:00
}
}
2003-04-22 04:54:04 +00:00
}
2004-07-25 04:27:20 +00:00
void NoteSkinManager : : GetNoteSkinNames ( const GameDef * game , CStringArray & AddTo )
2003-04-22 04:54:04 +00:00
{
2003-06-04 20:06:10 +00:00
RefreshNoteSkinData ( game ) ;
2003-04-22 04:54:04 +00:00
for ( map < CString , NoteSkinData > : : const_iterator iter = m_mapNameToData . begin ( ) ;
2003-09-12 04:18:43 +00:00
iter ! = m_mapNameToData . end ( ) ; + + iter )
2003-04-22 04:54:04 +00:00
{
AddTo . push_back ( iter - > second . sName ) ;
}
2003-06-04 20:06:10 +00:00
/* Put the note skins back. */
2004-07-25 04:27:20 +00:00
RefreshNoteSkinData ( GAMESTATE - > m_pCurGame ) ;
2003-04-22 04:54:04 +00:00
}
bool NoteSkinManager : : DoesNoteSkinExist ( CString sSkinName )
{
CStringArray asSkinNames ;
GetNoteSkinNames ( asSkinNames ) ;
for ( unsigned i = 0 ; i < asSkinNames . size ( ) ; i + + )
if ( 0 = = stricmp ( sSkinName , asSkinNames [ i ] ) )
return true ;
return false ;
2003-02-06 07:32:57 +00:00
}
CString NoteSkinManager : : GetNoteSkinDir ( CString sSkinName )
{
2003-08-15 03:14:53 +00:00
CString sGame = GAMESTATE - > GetCurrentGameDef ( ) - > m_szName ;
2003-02-06 07:32:57 +00:00
2003-12-10 09:44:16 +00:00
return NOTESKINS_DIR + sGame + " / " + sSkinName + " / " ;
2003-02-06 07:32:57 +00:00
}
2003-09-12 04:08:03 +00:00
CString NoteSkinManager : : GetMetric ( CString sNoteSkinName , CString sButtonName , CString sValue )
2003-02-06 07:32:57 +00:00
{
2003-09-12 04:44:53 +00:00
sNoteSkinName . MakeLower ( ) ;
2004-05-23 22:17:26 +00:00
map < CString , NoteSkinData > : : const_iterator it = m_mapNameToData . find ( sNoteSkinName ) ;
ASSERT_M ( it ! = m_mapNameToData . end ( ) , sNoteSkinName ) ; // this NoteSkin doesn't exist!
const NoteSkinData & data = it - > second ;
2003-02-06 07:32:57 +00:00
CString sReturn ;
2003-04-22 04:54:04 +00:00
if ( data . metrics . GetValue ( sButtonName , sValue , sReturn ) )
2003-02-08 23:47:47 +00:00
return sReturn ;
2003-04-22 04:54:04 +00:00
if ( ! data . metrics . GetValue ( " NoteDisplay " , sValue , sReturn ) )
2003-08-10 08:58:11 +00:00
RageException : : Throw ( " Could not read metric '[%s] %s' or '[NoteDisplay] %s' in '%s' " ,
2003-07-20 21:23:20 +00:00
sButtonName . c_str ( ) , sValue . c_str ( ) , sValue . c_str ( ) , sNoteSkinName . c_str ( ) ) ;
2003-02-06 07:32:57 +00:00
return sReturn ;
}
2003-09-12 04:08:03 +00:00
int NoteSkinManager : : GetMetricI ( CString sNoteSkinName , CString sButtonName , CString sValueName )
{
return atoi ( GetMetric ( sNoteSkinName , sButtonName , sValueName ) ) ;
}
float NoteSkinManager : : GetMetricF ( CString sNoteSkinName , CString sButtonName , CString sValueName )
{
return ( float ) atof ( GetMetric ( sNoteSkinName , sButtonName , sValueName ) ) ;
}
bool NoteSkinManager : : GetMetricB ( CString sNoteSkinName , CString sButtonName , CString sValueName )
{
return atoi ( GetMetric ( sNoteSkinName , sButtonName , sValueName ) ) ! = 0 ;
}
RageColor NoteSkinManager : : GetMetricC ( CString sNoteSkinName , CString sButtonName , CString sValueName )
{
float r = 1 , b = 1 , g = 1 , a = 1 ; // initialize in case sscanf fails
CString sValue = GetMetric ( sNoteSkinName , sButtonName , sValueName ) ;
char szValue [ 40 ] ;
strncpy ( szValue , sValue , 39 ) ;
int result = sscanf ( szValue , " %f,%f,%f,%f " , & r , & g , & b , & a ) ;
if ( result ! = 4 )
{
LOG - > Warn ( " The color value '%s' for theme metric '%s : %s' is invalid. " , szValue , sButtonName . c_str ( ) , sValueName . c_str ( ) ) ;
ASSERT ( 0 ) ;
}
return RageColor ( r , g , b , a ) ;
}
2003-02-08 23:47:47 +00:00
CString NoteSkinManager : : ColToButtonName ( int col )
2003-02-06 07:32:57 +00:00
{
2004-06-28 07:26:00 +00:00
const Style * pStyle = GAMESTATE - > GetCurrentStyle ( ) ;
2003-02-06 07:32:57 +00:00
const GameDef * pGameDef = GAMESTATE - > GetCurrentGameDef ( ) ;
StyleInput SI ( PLAYER_1 , col ) ;
2004-06-28 07:26:00 +00:00
GameInput GI = pStyle - > StyleInputToGameInput ( SI ) ;
2003-02-08 23:47:47 +00:00
return pGameDef - > m_szButtonNames [ GI . button ] ;
}
2003-02-06 07:32:57 +00:00
2003-12-31 21:40:38 +00:00
CString NoteSkinManager : : GetPathToFromPlayerAndCol ( PlayerNumber pn , int col , CString sFileName , bool bOptional )
2003-02-08 23:47:47 +00:00
{
CString sButtonName = ColToButtonName ( col ) ;
2003-02-06 07:32:57 +00:00
2003-12-31 21:40:38 +00:00
return GetPathToFromPlayerAndButton ( pn , sButtonName , sFileName , bOptional ) ;
2003-04-17 21:45:37 +00:00
}
2003-09-12 04:08:03 +00:00
2003-12-31 21:40:38 +00:00
CString NoteSkinManager : : GetPathToFromPlayerAndButton ( PlayerNumber pn , CString sButtonName , CString sElement , bool bOptional ) // looks in GAMESTATE for the current Style
2003-04-17 21:45:37 +00:00
{
2003-08-15 03:14:53 +00:00
// search active NoteSkin
2003-04-22 04:54:04 +00:00
CString sNoteSkinName = GAMESTATE - > m_PlayerOptions [ pn ] . m_sNoteSkin ;
sNoteSkinName . MakeLower ( ) ;
2003-12-31 21:40:38 +00:00
return GetPathToFromNoteSkinAndButton ( sNoteSkinName , sButtonName , sElement , bOptional ) ;
2003-09-12 04:08:03 +00:00
}
2003-02-06 07:32:57 +00:00
2003-08-15 03:14:53 +00:00
2004-02-17 08:55:33 +00:00
CString NoteSkinManager : : GetPathToFromNoteSkinAndButton ( CString NoteSkin , CString sButtonName , CString sElement , bool bOptional )
{
2004-02-17 22:16:22 +00:00
const CString CacheString = NoteSkin + " / " + sButtonName + " / " + sElement ;
map < CString , CString > : : iterator it = g_PathCache . find ( CacheString ) ;
if ( it ! = g_PathCache . end ( ) )
return it - > second ;
2004-02-17 22:23:07 +00:00
CString sPath ;
if ( sPath . empty ( ) )
sPath = GetPathToFromDir ( GetNoteSkinDir ( NoteSkin ) , sButtonName + " " + sElement ) ;
if ( sPath . empty ( ) ) // Search game default NoteSkin
sPath = GetPathToFromDir ( GetNoteSkinDir ( GAME_BASE_NOTESKIN_NAME ) , sButtonName + " " + sElement ) ;
if ( sPath . empty ( ) ) // Search global default NoteSkin
sPath = GetPathToFromDir ( GLOBAL_BASE_NOTESKIN_DIR , " Fallback " + sElement ) ;
if ( sPath . empty ( ) ) // Search global default NoteSkin
2004-02-17 08:55:33 +00:00
{
if ( bOptional )
{
2004-02-17 22:16:22 +00:00
g_PathCache [ CacheString ] = sPath ;
2004-02-17 08:55:33 +00:00
return sPath ;
}
2003-08-15 03:14:53 +00:00
2003-12-31 21:40:38 +00:00
RageException : : Throw ( " The NoteSkin element '%s %s' could not be found in '%s', '%s', or '%s'. " ,
sButtonName . c_str ( ) , sElement . c_str ( ) ,
GetNoteSkinDir ( NoteSkin ) . c_str ( ) ,
GetNoteSkinDir ( GAME_BASE_NOTESKIN_NAME ) . c_str ( ) ,
GLOBAL_BASE_NOTESKIN_DIR . c_str ( ) ) ;
2004-02-17 08:55:33 +00:00
}
while ( GetExtension ( sPath ) = = " redir " )
{
CString sNewFileName = GetRedirContents ( sPath ) ;
CString sRealPath ;
if ( sRealPath = = " " )
sRealPath = GetPathToFromDir ( GetNoteSkinDir ( NoteSkin ) , sNewFileName ) ;
if ( sRealPath = = " " )
sRealPath = GetPathToFromDir ( GetNoteSkinDir ( GAME_BASE_NOTESKIN_NAME ) , sNewFileName ) ;
if ( sRealPath = = " " )
sRealPath = GetPathToFromDir ( GLOBAL_BASE_NOTESKIN_DIR , sNewFileName ) ;
if ( sRealPath = = " " )
{
CString message = ssprintf (
" NoteSkinManager: The redirect '%s' points to the file '%s', which does not exist. "
" Verify that this redirect is correct. " ,
sPath . c_str ( ) , sNewFileName . c_str ( ) ) ;
2004-06-10 22:47:51 +00:00
if ( Dialog : : AbortRetryIgnore ( message ) = = Dialog : : retry )
2004-02-17 08:55:33 +00:00
{
FlushDirCache ( ) ;
2004-02-17 22:16:22 +00:00
g_PathCache . clear ( ) ;
2004-02-17 08:55:33 +00:00
continue ;
}
RageException : : Throw ( " %s " , message . c_str ( ) ) ;
}
sPath = sRealPath ;
}
2003-02-06 07:32:57 +00:00
2004-02-17 22:16:22 +00:00
g_PathCache [ CacheString ] = sPath ;
2004-02-17 08:55:33 +00:00
return sPath ;
}
2004-02-17 08:25:32 +00:00
CString NoteSkinManager : : GetPathToFromDir ( CString sDir , CString sFileName )
2003-02-06 07:32:57 +00:00
{
2003-09-03 04:30:29 +00:00
CStringArray matches ; // fill this with the possible files
2003-02-06 07:32:57 +00:00
2003-09-03 04:30:29 +00:00
GetDirListing ( sDir + sFileName + " *.redir " , matches , false , true ) ;
2003-09-21 20:57:07 +00:00
GetDirListing ( sDir + sFileName + " *.actor " , matches , false , true ) ;
2004-02-08 11:17:03 +00:00
GetDirListing ( sDir + sFileName + " *.model " , matches , false , true ) ;
2003-09-03 04:30:29 +00:00
GetDirListing ( sDir + sFileName + " *.txt " , matches , false , true ) ;
GetDirListing ( sDir + sFileName + " *.sprite " , matches , false , true ) ;
GetDirListing ( sDir + sFileName + " *.png " , matches , false , true ) ;
GetDirListing ( sDir + sFileName + " *.jpg " , matches , false , true ) ;
GetDirListing ( sDir + sFileName + " *.bmp " , matches , false , true ) ;
GetDirListing ( sDir + sFileName + " *.gif " , matches , false , true ) ;
2004-03-01 05:58:19 +00:00
GetDirListing ( sDir + sFileName + " * " , matches , false , true ) ;
2003-02-06 07:32:57 +00:00
2003-09-03 04:30:29 +00:00
if ( matches . empty ( ) )
2003-02-06 07:32:57 +00:00
return " " ;
2003-09-03 04:30:29 +00:00
if ( matches . size ( ) > 1 )
{
CString sError = " Multiple files match ' " + sDir + sFileName + " '. Please remove all but one of these files. " ;
2004-06-10 22:47:51 +00:00
Dialog : : OK ( sError ) ;
2003-09-03 04:30:29 +00:00
}
2004-02-17 08:55:33 +00:00
return matches [ 0 ] ;
2003-02-06 07:32:57 +00:00
}
2004-06-08 01:24:17 +00:00
/*
* (c) 2003-2004 Chris Danford
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/