diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index 7a115f0617..288ed40617 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -540,9 +540,6 @@ ColorGoodEnd=0.3,0.8,1.0,0 // blue no alpha ColorBooStart=0.8,0.0,0.6,1 // purple ColorBooEnd=0.8,0.0,0.6,0 // purple no alpha -[NoteDisplay] -UseHoldHeadForTap=1 - [BitmapText] RainbowColor1=1.0,0.0,0.4,1 // red RainbowColor2=0.8,0.2,0.6,1 // pink diff --git a/stepmania/src/GameDef.cpp b/stepmania/src/GameDef.cpp index 08cf5e9ed1..c5443670d2 100644 --- a/stepmania/src/GameDef.cpp +++ b/stepmania/src/GameDef.cpp @@ -21,155 +21,6 @@ #include "PrefsManager.h" -const CString NOTESKIN_DIR = "NoteSkins\\"; - - -CString GameDef::ElementToGraphicSuffix( const SkinElement gbg ) const -{ - CString sAssetPath; // fill this in below - - switch( gbg ) - { - case GRAPHIC_TAP_PARTS: sAssetPath = "tap parts"; break; - case GRAPHIC_HOLD_PARTS: sAssetPath = "hold parts"; break; - case GRAPHIC_RECEPTOR: sAssetPath = "receptor"; break; - case GRAPHIC_HOLD_EXPLOSION: sAssetPath = "hold explosion"; break; - case GRAPHIC_TAP_EXPLOSION_BRIGHT: sAssetPath = "tap explosion bright"; break; - case GRAPHIC_TAP_EXPLOSION_DIM: sAssetPath = "tap explosion dim"; break; - - default: - ASSERT(0); // invalid SkinElement - } - - return sAssetPath; -} - -CString GameDef::GetPathToGraphic( const CString sSkinName, const CString sButtonName, const SkinElement gbg ) const -{ - const CString sSkinDir = NOTESKIN_DIR + ssprintf("%s\\%s\\", m_szName, sSkinName); - const CString sGraphicSuffix = ElementToGraphicSuffix( gbg ); - - CStringArray arrayPossibleFileNames; // fill this with the possible files - - GetDirListing( ssprintf("%s%s %s*.sprite", sSkinDir, sButtonName, sGraphicSuffix), arrayPossibleFileNames ); - GetDirListing( ssprintf("%s%s %s*.png", sSkinDir, sButtonName, sGraphicSuffix), arrayPossibleFileNames ); - GetDirListing( ssprintf("%s%s %s*.jpg", sSkinDir, sButtonName, sGraphicSuffix), arrayPossibleFileNames ); - GetDirListing( ssprintf("%s%s %s*.bmp", sSkinDir, sButtonName, sGraphicSuffix), arrayPossibleFileNames ); - - if( arrayPossibleFileNames.GetSize() > 0 ) - return sSkinDir + arrayPossibleFileNames[0]; - - ASSERT(0); - throw RageException( "The game button graphic '%s%s %s' is missing.", sSkinDir, sButtonName, sGraphicSuffix ); -} - -void GameDef::GetTapTweenColors( const CString sSkinName, const CString sButtonName, CArray &aTapColorsOut ) const -{ - const CString sSkinDir = NOTESKIN_DIR + ssprintf("%s\\%s\\", m_szName, sSkinName); - const CString sColorsFilePath = sSkinDir + sButtonName + " Tap.colors"; - - FILE* fp = fopen( sColorsFilePath, "r" ); - ASSERT( fp != NULL ); - if( fp == NULL ) - { - ASSERT(0); - aTapColorsOut.Add( D3DXCOLOR(1,1,1,1) ); - LOG->Warn( "Couldn't open .colors file '%s'", sColorsFilePath ); - return; - } - - bool bSuccess; - do - { - D3DXCOLOR color; - int retval = fscanf( fp, "%f,%f,%f,%f\n", &color.r, &color.g, &color.b, &color.a ); - bSuccess = retval == 4; - if( bSuccess ) - aTapColorsOut.Add( color ); - } while( bSuccess ); - - if( aTapColorsOut.GetSize() == 0 ) - aTapColorsOut.Add( D3DXCOLOR(1,1,1,1) ); - - fclose( fp ); - return; -} - -void GameDef::GetHoldTweenColors( const CString sSkinName, const CString sButtonName, CArray &aHoldColorsOut ) const -{ - const CString sSkinDir = NOTESKIN_DIR + ssprintf("%s\\%s\\", m_szName, sSkinName); - - const CString sColorsFilePath = sSkinDir + sButtonName + " Hold.colors"; - - FILE* fp = fopen( sColorsFilePath, "r" ); - ASSERT( fp != NULL ); - if( fp == NULL ) - { - ASSERT(0); - aHoldColorsOut.Add( D3DXCOLOR(1,1,1,1) ); - LOG->Warn( "Couldn't open .colors file '%s'", sColorsFilePath ); - return; - } - - bool bSuccess; - do - { - D3DXCOLOR color; - int retval = fscanf( fp, "%f,%f,%f,%f\n", &color.r, &color.g, &color.b, &color.a ); - bSuccess = retval == 4; - if( bSuccess ) - aHoldColorsOut.Add( color ); - } while( bSuccess ); - - fclose( fp ); - return; -} - -void GameDef::GetSkinNames( CStringArray &AddTo ) const -{ - CString sBaseSkinFolder = NOTESKIN_DIR + CString(m_szName) + "\\"; - GetDirListing( sBaseSkinFolder + "*.*", AddTo, true ); - - // strip out "CVS" - for( int i=AddTo.GetSize()-1; i>=0; i-- ) - if( 0 == stricmp("cvs", AddTo[i]) ) - AddTo.RemoveAt( i ); -} - -bool GameDef::HasASkinNamed( CString sSkin ) const -{ - CStringArray asSkinNames; - GetSkinNames( asSkinNames ); - - for( int i=0; i &aTapTweenColorsAddTo ) const; - void GetHoldTweenColors( const CString sSkinName, const CString sButtonName, CArray &aHoldTweenColorsAddTo ) const; - CString ElementToGraphicSuffix( const SkinElement gbg ) const; }; diff --git a/stepmania/src/GameManager.cpp b/stepmania/src/GameManager.cpp index 26c8e86140..08b7a88d6d 100644 --- a/stepmania/src/GameManager.cpp +++ b/stepmania/src/GameManager.cpp @@ -19,10 +19,16 @@ #define DIRECTINPUT_VERSION 0x0800 #endif #include // for DIK_* key codes +#include "IniFile.h" +#include "RageLog.h" + GameManager* GAMEMAN = NULL; // global and accessable from anywhere in our program +const CString NOTESKIN_DIR = "NoteSkins\\"; + + const int DANCE_COL_SPACING = 64; const int DANCE_6PANEL_VERSUS_COL_SPACING = 54; const int PUMP_COL_SPACING = 50; @@ -994,8 +1000,13 @@ StyleDef g_StyleDefs[NUM_STYLES] = GameManager::GameManager() { + m_pIniFile = new IniFile; } +GameManager::~GameManager() +{ + delete m_pIniFile; +} GameDef* GameManager::GetGameDefForGame( Game g ) { @@ -1045,17 +1056,7 @@ void GameManager::GetNotesTypesForGame( Game game, CArray& } } -void GameManager::GetNoteSkinNames( CStringArray &AddTo ) -{ - GAMESTATE->GetCurrentGameDef()->GetSkinNames( AddTo ); -} - -void GameManager::GetNoteSkinNames( Game game, CStringArray &AddTo ) -{ - GetGameDefForGame(game)->GetSkinNames( AddTo ); -} - -bool GameManager::DoesNoteSkinExist( CString sSkinName ) +bool GameManager::DoesNoteSkinExist( CString sSkinName ) const { CStringArray asSkinNames; GetNoteSkinNames( asSkinNames ); @@ -1071,13 +1072,67 @@ void GameManager::SwitchNoteSkin( CString sNewNoteSkin ) { CStringArray as; GetNoteSkinNames( as ); - m_sCurNoteSkin = as[0]; + SwitchNoteSkin( as[0] ); } else + { m_sCurNoteSkin = sNewNoteSkin; + m_pIniFile->Reset(); + CString sPath = GetCurNoteSkinDir() + "metrics.ini"; + m_pIniFile->SetPath(sPath); + if( !m_pIniFile->ReadFile() ) + throw RageException( "Could not read NoteSkin metrics file '%s'", sPath ); + } } -CString GameManager::GetPathTo( const int col, const SkinElement gbg ) // looks in GAMESTATE for the current Style +CString GameManager::GetCurNoteSkinDir() +{ + const GameDef* pGameDef = GAMESTATE->GetCurrentGameDef(); + + return NOTESKIN_DIR + ssprintf("%s\\%s\\", pGameDef->m_szName, m_sCurNoteSkin); +} + +CString GameManager::GetMetric( CString sClassName, CString sValue ) // looks in GAMESTATE for the current Style +{ + CString sReturn; + if( !m_pIniFile->GetValue( sClassName, sValue, sReturn ) ) + throw RageException( "Could not read metric '%s - %s' from '%s'", sClassName, sValue, GetCurNoteSkinDir() + "metrics.ini" ); + return sReturn; +} + +int GameManager::GetMetricI( CString sClassName, CString sValueName ) +{ + return atoi( GetMetric(sClassName,sValueName) ); +} + +float GameManager::GetMetricF( CString sClassName, CString sValueName ) +{ + return (float)atof( GetMetric(sClassName,sValueName) ); +} + +bool GameManager::GetMetricB( CString sClassName, CString sValueName ) +{ + return atoi( GetMetric(sClassName,sValueName) ) != 0; +} + +D3DXCOLOR GameManager::GetMetricC( CString sClassName, CString sValueName ) +{ + float r=1,b=1,g=1,a=1; // initialize in case sscanf fails + CString sValue = GetMetric(sClassName,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, sClassName, sValueName ); + ASSERT(0); + } + + return D3DXCOLOR(r,g,b,a); +} + + +CString GameManager::GetPathTo( const int col, CString sElementName ) // looks in GAMESTATE for the current Style { const StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); const GameDef* pGameDef = GAMESTATE->GetCurrentGameDef(); @@ -1085,33 +1140,22 @@ CString GameManager::GetPathTo( const int col, const SkinElement gbg ) // looks StyleInput SI( PLAYER_1, col ); GameInput GI = pStyleDef->StyleInputToGameInput( SI ); CString sButtonName = pGameDef->m_szButtonNames[GI.button]; - return pGameDef->GetPathToGraphic( m_sCurNoteSkin, sButtonName, gbg ); -} -void GameManager::GetTapTweenColors( const int col, CArray &aTapTweenColorsAddTo ) // looks in GAMESTATE for the current Style -{ - ASSERT( m_sCurNoteSkin != "" ); // if this == NULL, SwitchGame() was never called + const CString sDir = GetCurNoteSkinDir(); - const StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); - const GameDef* pGameDef = GAMESTATE->GetCurrentGameDef(); + CStringArray arrayPossibleFileNames; // fill this with the possible files - StyleInput SI( PLAYER_1, col ); - GameInput GI = pStyleDef->StyleInputToGameInput( SI ); - CString sButtonName = pGameDef->m_szButtonNames[GI.button]; - pGameDef->GetTapTweenColors( m_sCurNoteSkin, sButtonName, aTapTweenColorsAddTo ); -} + GetDirListing( ssprintf("%s%s %s*.sprite", sDir, sButtonName, sElementName), arrayPossibleFileNames, false, true ); + GetDirListing( ssprintf("%s%s %s*.png", sDir, sButtonName, sElementName), arrayPossibleFileNames, false, true ); + GetDirListing( ssprintf("%s%s %s*.jpg", sDir, sButtonName, sElementName), arrayPossibleFileNames, false, true ); + GetDirListing( ssprintf("%s%s %s*.bmp", sDir, sButtonName, sElementName), arrayPossibleFileNames, false, true ); + GetDirListing( ssprintf("%s%s %s*.gif", sDir, sButtonName, sElementName), arrayPossibleFileNames, false, true ); + GetDirListing( ssprintf("%s%s %s*", sDir, sButtonName, sElementName), arrayPossibleFileNames, false, true ); -void GameManager::GetHoldTweenColors( const int col, CArray &aHoldTweenColorsAddTo ) // looks in GAMESTATE for the current Style -{ - ASSERT( m_sCurNoteSkin != "" ); // if this == NULL, SwitchGame() was never called + if( arrayPossibleFileNames.GetSize() > 0 ) + return arrayPossibleFileNames[0]; - const StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); - const GameDef* pGameDef = GAMESTATE->GetCurrentGameDef(); - - StyleInput SI( PLAYER_1, col ); - GameInput GI = pStyleDef->StyleInputToGameInput( SI ); - CString sButtonName = pGameDef->m_szButtonNames[GI.button]; - pGameDef->GetHoldTweenColors( m_sCurNoteSkin, sButtonName, aHoldTweenColorsAddTo ); + throw RageException( "The NoteSkin element '%s %s' is missing from '%s'.", sButtonName, sElementName, sDir ); } void GameManager::GetEnabledGames( CArray& aGamesOut ) @@ -1126,6 +1170,24 @@ void GameManager::GetEnabledGames( CArray& aGamesOut ) } } +void GameManager::GetNoteSkinNames( Game game, CStringArray &AddTo ) const +{ + GameDef* pGameDef = GAMEMAN->GetGameDefForGame( game ); + + CString sBaseSkinFolder = NOTESKIN_DIR + pGameDef->m_szName + "\\"; + GetDirListing( sBaseSkinFolder + "*.*", AddTo, true ); + + // strip out "CVS" + for( int i=AddTo.GetSize()-1; i>=0; i-- ) + if( 0 == stricmp("cvs", AddTo[i]) ) + AddTo.RemoveAt( i ); +} + +void GameManager::GetNoteSkinNames( CStringArray &AddTo ) const +{ + GetNoteSkinNames( GAMESTATE->m_CurGame, AddTo ); +} + int GameManager::NotesTypeToNumTracks( NotesType nt ) { if(nt >= NUM_NOTES_TYPES) @@ -1161,69 +1223,3 @@ CString GameManager::NotesTypeToString( NotesType nt ) return NotesTypes[nt].name; } - -/* once we're sure the above lookups works, nuke this */ -/* -int NotesTypeToNumTracks( NotesType nt ) -{ - switch( nt ) - { - case NOTES_TYPE_DANCE_SINGLE: return 4; - case NOTES_TYPE_DANCE_DOUBLE: return 8; - case NOTES_TYPE_DANCE_COUPLE: return 8; - case NOTES_TYPE_DANCE_SOLO: return 6; - case NOTES_TYPE_PUMP_SINGLE: return 5; - case NOTES_TYPE_PUMP_DOUBLE: return 10; - case NOTES_TYPE_PUMP_COUPLE: return 10; - case NOTES_TYPE_EZ2_SINGLE: return 5; // Single: TL,LHH,D,RHH,TR - case NOTES_TYPE_EZ2_SINGLE_HARD: return 5; // Single: TL,LHH,D,RHH,TR - case NOTES_TYPE_EZ2_DOUBLE: return 10; // Double: Single x2 - case NOTES_TYPE_EZ2_REAL: return 7; // Real: TL,LHH,LHL,D,RHL,RHH,TR -// case NOTES_TYPE_EZ2_SINGLE_VERSUS: return 10; -// case NOTES_TYPE_EZ2_SINGLE_HARD_VERSUS: return 10; -// case NOTES_TYPE_EZ2_REAL_VERSUS: return 10; - default: ASSERT(0); return -1; // invalid NotesType - } -} - -NotesType StringToNotesType( CString sNotesType ) -{ - sNotesType.MakeLower(); - if ( sNotesType == "dance-single" ) return NOTES_TYPE_DANCE_SINGLE; - else if( sNotesType == "dance-double" ) return NOTES_TYPE_DANCE_DOUBLE; - else if( sNotesType == "dance-couple" ) return NOTES_TYPE_DANCE_COUPLE; - else if( sNotesType == "dance-solo" ) return NOTES_TYPE_DANCE_SOLO; - else if( sNotesType == "pump-single" ) return NOTES_TYPE_PUMP_SINGLE; - else if( sNotesType == "pump-double" ) return NOTES_TYPE_PUMP_DOUBLE; - else if( sNotesType == "pump-couple" ) return NOTES_TYPE_PUMP_COUPLE; - else if( sNotesType == "ez2-single" ) return NOTES_TYPE_EZ2_SINGLE; - else if( sNotesType == "ez2-single-hard" ) return NOTES_TYPE_EZ2_SINGLE_HARD; - else if( sNotesType == "ez2-double" ) return NOTES_TYPE_EZ2_DOUBLE; - else if( sNotesType == "ez2-real" ) return NOTES_TYPE_EZ2_REAL; -// else if( sNotesType == "ez2-real-versus" ) return NOTES_TYPE_EZ2_REAL_VERSUS; -// else if( sNotesType == "ez2-single-versus" ) return NOTES_TYPE_EZ2_SINGLE_VERSUS; - else ASSERT(0); return NOTES_TYPE_DANCE_SINGLE; // invalid NotesType -} - -CString NotesTypeToString( NotesType nt ) -{ - switch( nt ) - { - case NOTES_TYPE_DANCE_SINGLE: return "dance-single"; - case NOTES_TYPE_DANCE_DOUBLE: return "dance-double"; - case NOTES_TYPE_DANCE_COUPLE: return "dance-couple"; - case NOTES_TYPE_DANCE_SOLO: return "dance-solo"; - case NOTES_TYPE_PUMP_SINGLE: return "pump-single"; - case NOTES_TYPE_PUMP_DOUBLE: return "pump-double"; - case NOTES_TYPE_PUMP_COUPLE: return "pump-couple"; - case NOTES_TYPE_EZ2_SINGLE: return "ez2-single"; - case NOTES_TYPE_EZ2_SINGLE_HARD: return "ez2-single-hard"; - case NOTES_TYPE_EZ2_DOUBLE: return "ez2-double"; - case NOTES_TYPE_EZ2_REAL: return "ez2-real"; -// case NOTES_TYPE_EZ2_REAL_VERSUS: return "ez2-real-versus"; -// case NOTES_TYPE_EZ2_SINGLE_VERSUS: return "ez2-single-versus"; -// case NOTES_TYPE_EZ2_SINGLE_HARD_VERSUS: return "ez2-single-hard-versus"; - default: ASSERT(0); return ""; // invalid NotesType - } -} -*/ diff --git a/stepmania/src/GameManager.h b/stepmania/src/GameManager.h index 5c7b47f542..da47b7051c 100644 --- a/stepmania/src/GameManager.h +++ b/stepmania/src/GameManager.h @@ -14,6 +14,7 @@ #include "StyleDef.h" #include "Style.h" #include "Game.h" +class IniFile; class GameManager @@ -30,14 +31,22 @@ public: // void GetGameNames( CStringArray &AddTo ); // bool DoesGameExist( CString sGameName ); - void GetNoteSkinNames( CStringArray &AddTo ); // looks up current Game in GAMESTATE - bool DoesNoteSkinExist( CString sSkinName ); // looks up current Game in GAMESTATE + CString GetCurNoteSkinDir(); + + void GetNoteSkinNames( Game game, CStringArray &AddTo ) const; + void GetNoteSkinNames( CStringArray &AddTo ) const; // looks up current Game in GAMESTATE + bool DoesNoteSkinExist( CString sSkinName ) const; // looks up current Game in GAMESTATE void SwitchNoteSkin( CString sNewNoteSkin ); // looks up current Game in GAMESTATE - CString GetCurNoteSkin() { return m_sCurNoteSkin; }; + CString GetCurNoteSkin() const { return m_sCurNoteSkin; }; + + CString GetPathTo( const int col, CString sElementName ); + + CString GetMetric( CString sClassName, CString sValueName ); + int GetMetricI( CString sClassName, CString sValueName ); + float GetMetricF( CString sClassName, CString sValueName ); + bool GetMetricB( CString sClassName, CString sValueName ); + D3DXCOLOR GetMetricC( CString sClassName, CString sValueName ); - CString GetPathTo( const int col, const SkinElement gbg ); // looks in GAMESTATE for the current Style - void GetTapTweenColors( const int col, CArray &aTapTweenColorsAddTo ); // looks in GAMESTATE for the current Style - void GetHoldTweenColors( const int col, CArray &aHoldTweenColorsAddTo ); // looks in GAMESTATE for the current Style void GetEnabledGames( CArray& aGamesOut ); @@ -46,10 +55,9 @@ public: static CString NotesTypeToString( NotesType nt ); protected: - void GetNoteSkinNames( Game game, CStringArray &AddTo ); CString m_sCurNoteSkin; - + IniFile* m_pIniFile; }; extern GameManager* GAMEMAN; // global and accessable from anywhere in our program diff --git a/stepmania/src/GhostArrowRow.cpp b/stepmania/src/GhostArrowRow.cpp index 7f061b38d8..790dc303b9 100644 --- a/stepmania/src/GhostArrowRow.cpp +++ b/stepmania/src/GhostArrowRow.cpp @@ -36,9 +36,9 @@ void GhostArrowRow::Load( PlayerNumber pn ) // init arrows for( int c=0; cGetPathTo(c, GRAPHIC_TAP_EXPLOSION_DIM) ); - m_GhostArrowRowBright[c].Load( GAMEMAN->GetPathTo(c, GRAPHIC_TAP_EXPLOSION_BRIGHT) ); - m_HoldGhostArrowRow[c].Load( GAMEMAN->GetPathTo(c, GRAPHIC_HOLD_EXPLOSION) ); + m_GhostArrowRow[c].Load( GAMEMAN->GetPathTo(c, "tap explosion dim") ); + m_GhostArrowRowBright[c].Load( GAMEMAN->GetPathTo(c, "tap explosion bright") ); + m_HoldGhostArrowRow[c].Load( GAMEMAN->GetPathTo(c, "hold explosion") ); m_GhostArrowRow[c].SetX( pStyleDef->m_ColumnInfo[pn][c].fXOffset ); m_GhostArrowRowBright[c].SetX( pStyleDef->m_ColumnInfo[pn][c].fXOffset ); diff --git a/stepmania/src/GrayArrowRow.cpp b/stepmania/src/GrayArrowRow.cpp index a08ae0805d..23d631d2a6 100644 --- a/stepmania/src/GrayArrowRow.cpp +++ b/stepmania/src/GrayArrowRow.cpp @@ -35,10 +35,12 @@ void GrayArrowRow::Load( PlayerNumber pn ) for( int c=0; cGetPathTo(c, GRAPHIC_RECEPTOR) ); + CString sPath = GAMEMAN->GetPathTo(c, "receptor"); + m_GrayArrow[c].Load( sPath ); + if( m_GrayArrow[c].GetNumStates() != 2 ) + throw RageException( "'%s' must have two frames", sPath ); m_GrayArrow[c].SetX( pStyleDef->m_ColumnInfo[pn][c].fXOffset ); - } - + } } void GrayArrowRow::Update( float fDeltaTime ) diff --git a/stepmania/src/LifeMeterBattery.cpp b/stepmania/src/LifeMeterBattery.cpp index 844d1c1391..254a73b397 100644 --- a/stepmania/src/LifeMeterBattery.cpp +++ b/stepmania/src/LifeMeterBattery.cpp @@ -53,13 +53,13 @@ void LifeMeterBattery::Load( PlayerNumber pn ) if( bPlayerEnabled ) this->AddChild( &m_sprBattery ); - m_textNumLives.LoadFromTextureAndChars( THEME->GetPathTo("Graphics","gameplay battery life numbers 5x3"), "0123456789x " ); + m_textNumLives.LoadFromTextureAndChars( THEME->GetPathTo("Graphics","gameplay battery life numbers 5x3"), "0123456789%. :x" ); m_textNumLives.SetDiffuse( D3DXCOLOR(1,1,1,1) ); m_textNumLives.TurnShadowOff(); if( bPlayerEnabled ) this->AddChild( &m_textNumLives ); - m_textPercent.LoadFromTextureAndChars( THEME->GetPathTo("Graphics","gameplay battery percent numbers 7x2"), "01234 :56789%." ); + m_textPercent.LoadFromTextureAndChars( THEME->GetPathTo("Graphics","gameplay battery percent numbers 5x3"), "0123456789%. :x" ); m_textPercent.TurnShadowOff(); m_textPercent.SetZoom( 0.7f ); m_textPercent.SetText( "00.0" ); diff --git a/stepmania/src/NoteDisplay.cpp b/stepmania/src/NoteDisplay.cpp index 33eea56df4..68ec30f24b 100644 --- a/stepmania/src/NoteDisplay.cpp +++ b/stepmania/src/NoteDisplay.cpp @@ -23,20 +23,17 @@ #include "RageLog.h" -#define USE_HOLD_HEAD_FOR_TAP THEME->GetMetricB("NoteDisplay","UseHoldHeadForTap") - -bool g_bUseHoldHeadForTap; // cache - +bool g_bDrawHoldHeadForTapsOnSameRow, g_bDrawTapOnTopOfHoldHead, g_bDrawTapOnTopOfHoldTail; // cache NoteDisplay::NoteDisplay() { - g_bUseHoldHeadForTap = USE_HOLD_HEAD_FOR_TAP; // update cache + g_bDrawHoldHeadForTapsOnSameRow = GAMEMAN->GetMetricB( "NoteDisplay", "DrawHoldHeadForTapsOnSameRow" ); + g_bDrawTapOnTopOfHoldHead = GAMEMAN->GetMetricB( "NoteDisplay", "DrawTapOnTopOfHoldHead" ); + g_bDrawTapOnTopOfHoldTail = GAMEMAN->GetMetricB( "NoteDisplay", "DrawTapOnTopOfHoldTail" ); // the owner of the NoteDisplay must call load on the gray and color parts - // m_sprHoldParts.Load( THEME->GetPathTo(GRAPHIC_COLOR_ARROW_GRAY_PART) ); // m_sprTapParts.Load( THEME->GetPathTo(GRAPHIC_COLOR_ARROW_COLOR_PART) ); - } @@ -44,24 +41,42 @@ void NoteDisplay::Load( int iColNum, PlayerNumber pn ) { m_PlayerNumber = pn; - CString sPath; - - sPath = GAMEMAN->GetPathTo(iColNum, GRAPHIC_TAP_PARTS); - m_sprTapParts.Load( sPath ); + CString sTapPartsPath = GAMEMAN->GetPathTo(iColNum, "tap parts"); + m_sprTapParts.Load( sTapPartsPath ); if( m_sprTapParts.GetNumStates() % 2 != 0 ) - throw RageException( "Tap Parts '%s' must have an even number of frames.", sPath ); - - sPath = GAMEMAN->GetPathTo(iColNum, GRAPHIC_HOLD_PARTS); - m_sprHoldParts.Load( sPath ); - if( m_sprHoldParts.GetTexture()->GetFramesWide() != 4 || m_sprHoldParts.GetTexture()->GetFramesHigh() != 2 ) - throw RageException( "Hold Parts '%s' must have 4x2 frames.", sPath ); - + throw RageException( "Tap Parts '%s' must have an even number of frames.", sTapPartsPath ); m_sprTapParts.StopAnimating(); m_sprTapParts.TurnShadowOff(); + + CString sHoldPartsPath = GAMEMAN->GetPathTo(iColNum, "hold parts"); + m_sprHoldParts.Load( sHoldPartsPath ); + if( m_sprHoldParts.GetTexture()->GetFramesWide() != 4 || m_sprHoldParts.GetTexture()->GetFramesHigh() != 2 ) + throw RageException( "Hold Parts '%s' must have 4x2 frames.", sHoldPartsPath ); m_sprHoldParts.StopAnimating(); m_sprHoldParts.TurnShadowOff(); + + m_colorTapTweens.RemoveAll(); - GAMEMAN->GetTapTweenColors( iColNum, m_colorTapTweens ); + const CString sColorsFilePath = GAMEMAN->GetPathTo( iColNum, "Tap.colors" ); + FILE* fp = fopen( sColorsFilePath, "r" ); + if( fp == NULL ) + throw RageException( "Couldn't open .colors file '%s'", sColorsFilePath ); + + bool bSuccess; + do + { + D3DXCOLOR color; + int retval = fscanf( fp, "%f,%f,%f,%f\n", &color.r, &color.g, &color.b, &color.a ); + bSuccess = (retval == 4); + if( bSuccess ) + m_colorTapTweens.Add( color ); + } while( bSuccess ); + + if( m_colorTapTweens.GetSize() == 0 ) + m_colorTapTweens.Add( D3DXCOLOR(1,1,1,1) ); + + fclose( fp ); + return; } @@ -195,11 +210,14 @@ void NoteDisplay::DrawHold( const HoldNote& hn, const bool bActive, const float const float fYHead = bReverse ? fEndYPos : fStartYPos; // the center of the head const float fYTail = bReverse ? fStartYPos : fEndYPos; // the center the tail + const float fYHeadTop = fYHead-fFrameHeight/2; + const float fYHeadBottom = fYHead+fFrameHeight/2; + const float fYTailTop = fYTail-fFrameHeight/2; const float fYTailBottom = fYTail+fFrameHeight/2; - const float fYBodyTop = fYHead; // middle of head -// const float fYBodyBottom = fYTailTop; // top of tail + const float fYBodyTop = g_bDrawTapOnTopOfHoldHead ? fYHeadBottom : fYHead; // middle of head + const float fYBodyBottom = fYTailTop; // top of tail const int fYStep = 8; // draw a segment every 8 pixels // this requires that the texture dimensions be a multiple of 8 @@ -259,7 +277,7 @@ void NoteDisplay::DrawHold( const HoldNote& hn, const bool bActive, const float // // Draw the body // - for( fY=fYBodyTop; fYFlushQueue(); - - - // - // Draw head - // + if( g_bDrawTapOnTopOfHoldHead ) { - fY = fYHead; - const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fY ); - const float fAlpha = ArrowGetAlpha( m_PlayerNumber, fY, fPercentFadeToFail ); - const float fGlow = ArrowGetGlow( m_PlayerNumber, fY, fPercentFadeToFail ); - const float fColorScale = SCALE(fLife,0,1,0.2f,1); - const D3DXCOLOR colorDiffuse= D3DXCOLOR(fColorScale,fColorScale,fColorScale,fAlpha); - const D3DXCOLOR colorGlow = D3DXCOLOR(1,1,1,fGlow); + // + // Draw the head + // + float fY; + for( fY=fYHeadTop; fYAddQuad( + D3DXVECTOR3(fXTopLeft-0.5f, fYTop-0.5f, 0), bDrawGlowOnly ? colorGlowTop : colorDiffuseTop, D3DXVECTOR2(fTexCoordLeft, fTexCoordTop), // colorGlowTop, // top-left + D3DXVECTOR3(fXTopRight-0.5f, fYTop-0.5f, 0), bDrawGlowOnly ? colorGlowTop : colorDiffuseTop, D3DXVECTOR2(fTexCoordRight, fTexCoordTop), // colorGlowTop, // top-right + D3DXVECTOR3(fXBottomLeft-0.5f, fYBottom-0.5f,0), bDrawGlowOnly ? colorGlowBottom : colorDiffuseBottom, D3DXVECTOR2(fTexCoordLeft, fTexCoordBottom),// colorGlowBottom, // bottom-left + D3DXVECTOR3(fXBottomRight-0.5f,fYBottom-0.5f,0), bDrawGlowOnly ? colorGlowBottom : colorDiffuseBottom, D3DXVECTOR2(fTexCoordRight, fTexCoordBottom) );//, colorGlowBottom ); // bottom-right } - else - { - m_sprHoldParts.SetDiffuse( colorDiffuse ); - m_sprHoldParts.SetGlow( D3DXCOLOR(0,0,0,0) ); - } - m_sprHoldParts.Draw(); + + DISPLAY->FlushQueue(); } + else + { + // + // Draw head + // + { + fY = fYHead; + const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fY ); + const float fAlpha = ArrowGetAlpha( m_PlayerNumber, fY, fPercentFadeToFail ); + const float fGlow = ArrowGetGlow( m_PlayerNumber, fY, fPercentFadeToFail ); + const float fColorScale = SCALE(fLife,0,1,0.2f,1); + const D3DXCOLOR colorDiffuse= D3DXCOLOR(fColorScale,fColorScale,fColorScale,fAlpha); + const D3DXCOLOR colorGlow = D3DXCOLOR(1,1,1,fGlow); + + m_sprHoldParts.SetState( bActive?1:0 ); + m_sprHoldParts.SetXY( fX, fY ); + if( bDrawGlowOnly ) + { + m_sprHoldParts.SetDiffuse( D3DXCOLOR(1,1,1,0) ); + m_sprHoldParts.SetGlow( colorGlow ); + } + else + { + m_sprHoldParts.SetDiffuse( colorDiffuse ); + m_sprHoldParts.SetGlow( D3DXCOLOR(0,0,0,0) ); + } + m_sprHoldParts.Draw(); + } + } + + + if( g_bDrawTapOnTopOfHoldHead ) + DrawTap( hn.m_iTrack, hn.m_fStartBeat, false, fPercentFadeToFail, fLife ); + if( g_bDrawTapOnTopOfHoldTail ) + DrawTap( hn.m_iTrack, hn.m_fEndBeat, false, fPercentFadeToFail, fLife ); + // now, draw the glow pass if( !bDrawGlowOnly ) DrawHold( hn, bActive, fLife, fPercentFadeToFail, true ); } -void NoteDisplay::DrawTap( const int iCol, const float fBeat, const bool bOnSameRowAsHoldStart, const float fPercentFadeToFail ) +void NoteDisplay::DrawTap( const int iCol, const float fBeat, const bool bOnSameRowAsHoldStart, const float fPercentFadeToFail, const float fLife ) { const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fBeat ); const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset ); @@ -342,8 +416,9 @@ void NoteDisplay::DrawTap( const int iCol, const float fBeat, const bool bOnSame const float fGlow = ArrowGetGlow( m_PlayerNumber, fYPos, fPercentFadeToFail ); const int iGrayPartFrameNo = GetTapGrayFrameNo( fBeat ); const int iColorPartFrameNo = GetTapColorFrameNo( fBeat ); + const float fColorScale = SCALE(fLife,0,1,0.2f,1); - D3DXCOLOR colorGrayPart = D3DXCOLOR(1,1,1,1); + D3DXCOLOR colorGrayPart = D3DXCOLOR(fColorScale,fColorScale,fColorScale,1); D3DXCOLOR colorLeadingEdge; D3DXCOLOR colorTrailingEdge; GetTapEdgeColors( fBeat, colorLeadingEdge, colorTrailingEdge ); @@ -351,7 +426,14 @@ void NoteDisplay::DrawTap( const int iCol, const float fBeat, const bool bOnSame colorLeadingEdge.a *= fAlpha; colorTrailingEdge.a *= fAlpha; - if( bOnSameRowAsHoldStart && g_bUseHoldHeadForTap ) + colorLeadingEdge.r *= fColorScale; + colorLeadingEdge.g *= fColorScale; + colorLeadingEdge.b *= fColorScale; + colorTrailingEdge.r *= fColorScale; + colorTrailingEdge.g *= fColorScale; + colorTrailingEdge.b *= fColorScale; + + if( bOnSameRowAsHoldStart && g_bDrawHoldHeadForTapsOnSameRow ) { // // draw hold head diff --git a/stepmania/src/NoteDisplay.h b/stepmania/src/NoteDisplay.h index f511dbf47c..9699fcc421 100644 --- a/stepmania/src/NoteDisplay.h +++ b/stepmania/src/NoteDisplay.h @@ -23,7 +23,7 @@ public: void Load( int iColNum, PlayerNumber pn ); - void DrawTap( const int iCol, const float fBeat, const bool bOnSameRowAsHoldStart, const float fPercentFadeToFail ); + void DrawTap( const int iCol, const float fBeat, const bool bOnSameRowAsHoldStart, const float fPercentFadeToFail, const float fLife = 1 ); void DrawHold( const HoldNote& hn, const bool bActive, const float fLife, const float fPercentFadeToFail, bool bDrawGlowOnly = false ); protected: diff --git a/stepmania/src/NoteTypes.cpp b/stepmania/src/NoteTypes.cpp index efd0ad4660..e8e31b58dd 100644 --- a/stepmania/src/NoteTypes.cpp +++ b/stepmania/src/NoteTypes.cpp @@ -21,9 +21,9 @@ D3DXCOLOR NoteTypeToColor( NoteType nt ) case NOTE_TYPE_12TH: return D3DXCOLOR(1,0,1,1); // purple case NOTE_TYPE_16TH: return D3DXCOLOR(1,1,0,1); // yellow case NOTE_TYPE_24TH: return D3DXCOLOR(0,1,1,1); // light blue - case NOTE_TYPE_32ND: // fall through default: ASSERT(0); + case NOTE_TYPE_32ND: // fall through return D3DXCOLOR(0.5f,0.5f,0.5f,1); // gray } }; diff --git a/stepmania/src/ThemeManager.cpp b/stepmania/src/ThemeManager.cpp index 171e1ba30a..2fffdf02e6 100644 --- a/stepmania/src/ThemeManager.cpp +++ b/stepmania/src/ThemeManager.cpp @@ -206,7 +206,7 @@ CString ThemeManager::GetMetricsPathFromName( CString sThemeName ) return GetThemeDirFromName( sThemeName ) + "metrics.ini"; } -CString ThemeManager::GetMetric( CString sScreenName, CString sValueName ) +CString ThemeManager::GetMetric( CString sClassName, CString sValueName ) { #ifdef _DEBUG try_metric_again: @@ -226,50 +226,50 @@ try_metric_again: } CString sValue; - if( m_pIniMetrics->GetValue(sScreenName,sValueName,sValue) ) + if( m_pIniMetrics->GetValue(sClassName,sValueName,sValue) ) { sValue.Replace("::","\n"); // "::" means newline since you can't use line breaks in an ini file. return sValue; } #ifdef _DEBUG - if( IDRETRY == AfxMessageBox( ssprintf("The theme metric %s-%s is missing. Correct this and click Retry, or Cancel to break.",sScreenName,sValueName), MB_RETRYCANCEL ) ) + if( IDRETRY == AfxMessageBox( ssprintf("The theme metric %s-%s is missing. Correct this and click Retry, or Cancel to break.",sClassName,sValueName), MB_RETRYCANCEL ) ) goto try_metric_again; #endif throw RageException( "Theme metric '%s : %s' could not be found in '%s' or '%s'.", - sScreenName, + sClassName, sValueName, sCurMetricPath, sDefaultMetricPath ); } -int ThemeManager::GetMetricI( CString sScreenName, CString sValueName ) +int ThemeManager::GetMetricI( CString sClassName, CString sValueName ) { - return atoi( GetMetric(sScreenName,sValueName) ); + return atoi( GetMetric(sClassName,sValueName) ); } -float ThemeManager::GetMetricF( CString sScreenName, CString sValueName ) +float ThemeManager::GetMetricF( CString sClassName, CString sValueName ) { - return (float)atof( GetMetric(sScreenName,sValueName) ); + return (float)atof( GetMetric(sClassName,sValueName) ); } -bool ThemeManager::GetMetricB( CString sScreenName, CString sValueName ) +bool ThemeManager::GetMetricB( CString sClassName, CString sValueName ) { - return atoi( GetMetric(sScreenName,sValueName) ) != 0; + return atoi( GetMetric(sClassName,sValueName) ) != 0; } -D3DXCOLOR ThemeManager::GetMetricC( CString sScreenName, CString sValueName ) +D3DXCOLOR ThemeManager::GetMetricC( CString sClassName, CString sValueName ) { float r=1,b=1,g=1,a=1; // initialize in case sscanf fails - CString sValue = GetMetric(sScreenName,sValueName); + CString sValue = GetMetric(sClassName,sValueName); char szValue[40]; - strcpy( szValue, sValue ); + 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, sScreenName, sValueName ); + LOG->Warn( "The color value '%s' for NoteSkin metric '%s : %s' is invalid.", szValue, sClassName, sValueName ); ASSERT(0); } diff --git a/stepmania/src/ThemeManager.h b/stepmania/src/ThemeManager.h index 39e1b14c23..af791df2a4 100644 --- a/stepmania/src/ThemeManager.h +++ b/stepmania/src/ThemeManager.h @@ -29,11 +29,11 @@ public: CString GetPathTo( CString sAssetCategory, CString sFileName ); // looks up the current theme in PREFSMAN - CString GetMetric( CString sScreenName, CString sValueName ); - int GetMetricI( CString sScreenName, CString sValueName ); - float GetMetricF( CString sScreenName, CString sValueName ); - bool GetMetricB( CString sScreenName, CString sValueName ); - D3DXCOLOR GetMetricC( CString sScreenName, CString sValueName ); + CString GetMetric( CString sClassName, CString sValueName ); + int GetMetricI( CString sClassName, CString sValueName ); + float GetMetricF( CString sClassName, CString sValueName ); + bool GetMetricB( CString sClassName, CString sValueName ); + D3DXCOLOR GetMetricC( CString sClassName, CString sValueName ); protected: void GetAllThemeNames( CStringArray& AddTo );