#include "global.h" /* ----------------------------------------------------------------------------- Class: NoteSkinManager Desc: See header. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford ----------------------------------------------------------------------------- */ #include "NoteSkinManager.h" #include "RageLog.h" #include "RageException.h" #include "GameState.h" #include "GameDef.h" #include "StyleInput.h" #include "StyleDef.h" #include "RageUtil.h" #include "GameManager.h" #include "arch/arch.h" #include "RageDisplay.h" #include "arch/ArchHooks/ArchHooks.h" NoteSkinManager* NOTESKIN = NULL; // global object accessable from anywhere in the program const CString NOTESKINS_DIR = BASE_PATH "NoteSkins" SLASH; const CString GAME_BASE_NOTESKIN_NAME = "default"; const CString GLOBAL_BASE_NOTESKIN_DIR = NOTESKINS_DIR + "common" SLASH "default" SLASH; NoteSkinManager::NoteSkinManager() { m_CurGame = GAME_INVALID; } NoteSkinManager::~NoteSkinManager() { } void NoteSkinManager::RefreshNoteSkinData( Game game ) { /* 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). */ m_CurGame = GAMESTATE->m_CurGame; GameDef* pGameDef = GAMEMAN->GetGameDefForGame( game ); CString sBaseSkinFolder = NOTESKINS_DIR + pGameDef->m_szName + SLASH; CStringArray asNoteSkinNames; GetDirListing( sBaseSkinFolder + "*", asNoteSkinNames, true ); // strip out "CVS" for( int i=asNoteSkinNames.size()-1; i>=0; i-- ) if( 0 == stricmp("cvs", asNoteSkinNames[i]) ) asNoteSkinNames.erase( asNoteSkinNames.begin()+i, asNoteSkinNames.begin()+i+1 ); m_mapNameToData.clear(); for( unsigned j=0; jm_CurGame ) RefreshNoteSkinData( GAMESTATE->m_CurGame ); /* Don't call GetNoteSkinNames below, since we don't want to call RefreshNoteSkinData; it's * slow. */ for( map::const_iterator iter = m_mapNameToData.begin(); iter != m_mapNameToData.end(); ++iter ) { AddTo.push_back( iter->second.sName ); } } void NoteSkinManager::GetNoteSkinNames( Game game, CStringArray &AddTo ) { RefreshNoteSkinData( game ); for( map::const_iterator iter = m_mapNameToData.begin(); iter != m_mapNameToData.end(); ++iter ) { AddTo.push_back( iter->second.sName ); } /* Put the note skins back. */ RefreshNoteSkinData( GAMESTATE->m_CurGame ); } bool NoteSkinManager::DoesNoteSkinExist( CString sSkinName ) { CStringArray asSkinNames; GetNoteSkinNames( asSkinNames ); for( unsigned i=0; iGetCurrentGameDef()->m_szName; return NOTESKINS_DIR + sGame + SLASH + sSkinName + SLASH; } CString NoteSkinManager::GetMetric( CString sNoteSkinName, CString sButtonName, CString sValue ) { sNoteSkinName.MakeLower(); CString sReturn; NoteSkinData& data = m_mapNameToData[sNoteSkinName]; if( data.metrics.GetValue( sButtonName, sValue, sReturn ) ) return sReturn; if( !data.metrics.GetValue( "NoteDisplay", sValue, sReturn ) ) RageException::Throw( "Could not read metric '[%s] %s' or '[NoteDisplay] %s' in '%s'", sButtonName.c_str(), sValue.c_str(), sValue.c_str(), sNoteSkinName.c_str() ); return sReturn; } 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); } CString NoteSkinManager::ColToButtonName(int col) { const StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); const GameDef* pGameDef = GAMESTATE->GetCurrentGameDef(); StyleInput SI( PLAYER_1, col ); GameInput GI = pStyleDef->StyleInputToGameInput( SI ); return pGameDef->m_szButtonNames[GI.button]; } CString NoteSkinManager::GetPathTo( PlayerNumber pn, int col, CString sFileName ) { CString sButtonName = ColToButtonName(col); return GetPathTo( pn, sButtonName, sFileName ); } CString NoteSkinManager::GetPathTo( PlayerNumber pn, CString sButtonName, CString sFileName ) // looks in GAMESTATE for the current Style { // search active NoteSkin CString sNoteSkinName = GAMESTATE->m_PlayerOptions[pn].m_sNoteSkin; sNoteSkinName.MakeLower(); return GetPathTo( sNoteSkinName, sButtonName, sFileName ); } CString NoteSkinManager::GetPathTo( CString NoteSkin, CString sButtonName, CString sFileName ) { CString ret = GetPathTo( GetNoteSkinDir(NoteSkin), sButtonName+" "+sFileName ); if( !ret.empty() ) // we found something return ret; // Search game default NoteSkin ret = GetPathTo( GetNoteSkinDir(GAME_BASE_NOTESKIN_NAME), sButtonName+" "+sFileName); if( !ret.empty() ) // we found something return ret; // Search global default NoteSkin ret = GetPathTo( GLOBAL_BASE_NOTESKIN_DIR, "Fallback "+sFileName ); if( !ret.empty() ) // we found something return ret; RageException::Throw( "The NoteSkin element '%s %s' could not be found in '%s', '%s', or '%s'.", sButtonName.c_str(), sFileName.c_str(), GetNoteSkinDir(NoteSkin).c_str(), GetNoteSkinDir(GAME_BASE_NOTESKIN_NAME).c_str(), GLOBAL_BASE_NOTESKIN_DIR.c_str() ); } CString NoteSkinManager::GetPathTo( CString sDir, CString sFileName ) { CStringArray matches; // fill this with the possible files GetDirListing( sDir+sFileName+"*.redir", matches, false, true ); GetDirListing( sDir+sFileName+"*.model", matches, false, true ); 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 ); if( matches.empty() ) return ""; if( matches.size() > 1 ) { CString sError = "Multiple files match '"+sDir+sFileName+"'. Please remove all but one of these files."; if( DISPLAY->IsWindowed() ) HOOKS->MessageBoxOK( sError ); } CString sPath = matches[0]; bool bIsARedirect = GetExtension(sPath).CompareNoCase("redir")==0; if( !bIsARedirect ) { return sPath; } else // bIsARedirect { CString sNewFileName = GetRedirContents(sPath); CString sNewPath = GetPathTo(sDir, sNewFileName); if( !sNewPath.empty() ) return sNewPath; else { CString message = ssprintf( "ThemeManager: The redirect '%s' points to the file '%s', which does not exist. " "Verify that this redirect is correct.", sPath.c_str(), sNewFileName.c_str()); RageException::Throw( "%s", message.c_str() ); } } }