From 1b3c62adb98d33df549c746652848b8dfc72f8da Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Sun, 25 Aug 2002 19:00:12 +0000 Subject: [PATCH] added autogeneration of Notes for missing NotesTypes --- stepmania/NEWS | 4 + stepmania/src/NoteData.cpp | 34 ++++---- stepmania/src/NoteData.h | 2 +- stepmania/src/NoteDisplay.cpp | 4 +- stepmania/src/NoteTypes.cpp | 10 +-- stepmania/src/ScreenCaution.cpp | 2 +- stepmania/src/ScreenEdit.cpp | 4 +- stepmania/src/ScreenGameplay.cpp | 4 +- stepmania/src/ScreenSelectGroup.cpp | 2 +- stepmania/src/Song.cpp | 125 ++++++++++++++++++++-------- stepmania/src/StepMania.vcproj | 18 ++-- stepmania/src/StyleDef.cpp | 2 +- stepmania/src/StyleDef.h | 2 +- stepmania/src/song.h | 11 ++- 14 files changed, 145 insertions(+), 79 deletions(-) diff --git a/stepmania/NEWS b/stepmania/NEWS index b9f293442e..8711ed0e76 100644 --- a/stepmania/NEWS +++ b/stepmania/NEWS @@ -1,4 +1,8 @@ ------------------------CVS after 3.00 beta 6---------------- +NEW FEATURE: If a song is missing Notes of a certain NotesType, Notes of + the missing type will be generated from the existing types. For + example, this will allow any pump song to be played in the dance + game mode, and vica-versa. NEW FEATURE: Package Exporter now can export Announcers, BGAnimations, Courses, NoteSkins, RandomMovies, Themes, and Visualizations. NEW FEATURE: Package Exporter now has two options: "Export As One", and diff --git a/stepmania/src/NoteData.cpp b/stepmania/src/NoteData.cpp index 3c05437ae7..f1b61cfa08 100644 --- a/stepmania/src/NoteData.cpp +++ b/stepmania/src/NoteData.cpp @@ -105,8 +105,11 @@ CString NoteData::GetSMNoteDataString() for( int m=0; m<=iLastMeasure; m++ ) // foreach measure { NoteType nt = GetSmallestNoteTypeForMeasure( m ); - float fBeatSpacing = NoteTypeToBeat( nt ); - int iRowSpacing = roundf( fBeatSpacing * ROWS_PER_BEAT ); + int iRowSpacing; + if( nt == NOTE_TYPE_INVALID ) + iRowSpacing = 1; + else + iRowSpacing = roundf( NoteTypeToBeat(nt) * ROWS_PER_BEAT ); CStringArray asMeasureLines; asMeasureLines.Add( ssprintf(" // measure %d", m+1) ); @@ -774,9 +777,12 @@ float NoteData::GetFreezeRadarValue( float fSongSeconds ) } -void NoteData::LoadTransformed( const NoteData* pOriginal, int iNewNumTracks, const int iNewToOriginalTrack[] ) +// -1 for iOriginalTracksToTakeFrom means no track +void NoteData::LoadTransformed( NoteData* pOriginal, int iNewNumTracks, const int iOriginalTrackToTakeFrom[] ) { - // init + pOriginal->ConvertHoldNotesTo4s(); + + // reset all notes Init(); m_iNumTracks = iNewNumTracks; @@ -784,24 +790,14 @@ void NoteData::LoadTransformed( const NoteData* pOriginal, int iNewNumTracks, co // copy tracks for( int t=0; tm_iNumTracks ); + if( iOriginalTrack == -1 ) + continue; memcpy( m_TapNotes[t], pOriginal->m_TapNotes[iOriginalTrack], MAX_TAP_NOTE_ROWS*sizeof(m_TapNotes[0][0]) ); - - for( i=0; im_iNumHoldNotes; i++ ) - { - HoldNote hn = pOriginal->m_HoldNotes[i]; - if( hn.m_iTrack == iOriginalTrack ) - { - hn.m_iTrack = t; - this->AddHoldNote( hn ); - } - } - } + pOriginal->Convert4sToHoldNotes(); } NoteType NoteData::GetSmallestNoteTypeForMeasure( int iMeasureIndex ) diff --git a/stepmania/src/NoteData.h b/stepmania/src/NoteData.h index 6d88825aac..0557fede11 100644 --- a/stepmania/src/NoteData.h +++ b/stepmania/src/NoteData.h @@ -88,7 +88,7 @@ public: float GetChaosRadarValue( float fSongSeconds ); // Transformations - void LoadTransformed( const NoteData* pOriginal, int iNewNumTracks, const int iNewToOriginalTrack[] ); + void LoadTransformed( NoteData* pOriginal, int iNewNumTracks, const int iOriginalTrackToTakeFrom[] ); // -1 for iOriginalTracksToTakeFrom means no track void CropToLeftSide(); void CropToRightSide(); diff --git a/stepmania/src/NoteDisplay.cpp b/stepmania/src/NoteDisplay.cpp index d46fa522b8..508f4583dd 100644 --- a/stepmania/src/NoteDisplay.cpp +++ b/stepmania/src/NoteDisplay.cpp @@ -566,10 +566,10 @@ void NoteDisplay::DrawHold( const HoldNote& hn, const bool bActive, const float // // Draw the body // - for( fY=fYBodyTop; fYAddSubActor( &m_FadeWipe ); - this->SendScreenMessage( SM_StartClosing, 1 ); + this->SendScreenMessage( SM_StartClosing, 3 ); } diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index 311932039a..86dfbbd583 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -598,11 +598,11 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ switch( DeviceI.button ) { case DIK_S: - GAMESTATE->m_pCurSong->SaveToSMFile(); + GAMESTATE->m_pCurSong->SaveToSongFile(); SCREENMAN->SystemMessage( "Saved as SM." ); break; case DIK_W: - GAMESTATE->m_pCurSong->SaveToSMAndDWIFile(); + GAMESTATE->m_pCurSong->SaveToSongFileAndDWI(); SCREENMAN->SystemMessage( "Saved as SM and DWI." ); break; default: diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index 32f203d4b4..d23205935f 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -1067,7 +1067,7 @@ void SaveChanges() switch( GAMESTATE->m_PlayMode ) { case PLAY_MODE_ARCADE: - GAMESTATE->m_pCurSong->SaveToSMFile(); + GAMESTATE->m_pCurSong->SaveToSongFile(); break; case PLAY_MODE_ONI: case PLAY_MODE_ENDLESS: @@ -1075,7 +1075,7 @@ void SaveChanges() for( int i=0; im_pCurCourse->m_iStages; i++ ) { Song* pSong = GAMESTATE->m_pCurCourse->m_apSongs[i]; - pSong->SaveToSMFile(); + pSong->SaveToSongFile(); } } break; diff --git a/stepmania/src/ScreenSelectGroup.cpp b/stepmania/src/ScreenSelectGroup.cpp index 1a45903b14..3583153154 100644 --- a/stepmania/src/ScreenSelectGroup.cpp +++ b/stepmania/src/ScreenSelectGroup.cpp @@ -75,7 +75,7 @@ ScreenSelectGroup::ScreenSelectGroup() NotesType nt = GAMESTATE->GetCurrentStyleDef()->m_NotesType; for( i=aAllSongs.GetSize()-1; i>=0; i-- ) // foreach Song, back to front { - if( !aAllSongs[i]->SongHasNoteType(nt) ) + if( !aAllSongs[i]->SongHasNotesType(nt) ) aAllSongs.RemoveAt( i ); } } diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index 1b0476d83a..df0acb0b41 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -21,9 +21,10 @@ #include "RageSoundStream.h" #include "RageException.h" #include "SongCacheIndex.h" +#include "GameManager.h" -const int FILE_CACHE_VERSION = 61; // increment this when Song or Notes changes to invalidate cache +const int FILE_CACHE_VERSION = 64; // increment this when Song or Notes changes to invalidate cache int CompareBPMSegments(const void *arg1, const void *arg2) @@ -217,8 +218,8 @@ void Song::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, fl } -// This is a super hack, but it's only called from ScreenEdit, so it's OK :-) -// Writing an inverse function of GetBeatAndBPSFromElapsedTime() is impossible, +// This is a super hack, but it's only called from ScreenEdit, so it's OK. +// Writing an inverse function of GetBeatAndBPSFromElapsedTime() uber difficult, // so do a binary search to get close to the correct elapsed time. float Song::GetElapsedTimeFromBeat( float fBeat ) const { @@ -260,7 +261,7 @@ void Song::GetMainAndSubTitlesFromFullTitle( const CString sFullTitle, CString & CString Song::GetCacheFilePath() const { - return ssprintf( "Cache\\%u", (UINT)GetHashForString(m_sSongDir) ); + return ssprintf( "Cache\\%u", GetHashForString(m_sSongDir) ); } /* Get a path to the SM containing data for this song. It might @@ -312,6 +313,8 @@ bool Song::LoadWithoutCache( CString sDir ) return false; } + AddAutoGenNotes(); + TidyUpData(); // save a cache file so we don't have to parse it all over again next time @@ -1223,14 +1226,19 @@ void Song::GetNotesThatMatch( NotesType nt, CArray& arrayAddTo ) arrayAddTo.Add( m_apNotes[i] ); } -bool Song::SongHasNoteType( NotesType nt ) const +bool Song::SongHasNotesType( NotesType nt ) const { for( int i=0; i < m_apNotes.GetSize(); i++ ) // foreach Notes - { if( m_apNotes[i]->m_NotesType == nt ) return true; - } + return false; +} +bool Song::SongHasNotesTypeAndDifficulty( NotesType nt, DifficultyClass dc ) const +{ + for( int i=0; i < m_apNotes.GetSize(); i++ ) // foreach Notes + if( m_apNotes[i]->m_NotesType == nt && m_apNotes[i]->m_DifficultyClass == dc ) + return true; return false; } @@ -1239,33 +1247,34 @@ void Song::SaveToCacheFile() LOG->Trace( "Song::SaveToCacheFile()" ); SONGINDEX->AddCacheIndex(m_sSongDir, GetHashForDirectory(m_sSongDir)); - SaveToSMFile( GetCacheFilePath() ); + SaveToSMFile( GetCacheFilePath(), true ); +} + +void Song::SaveToSongFile() +{ + LOG->Trace( "Song::SaveToSongFile()" ); + + // + // rename all old files to avoid confusion + // + CStringArray arrayOldFileNames; + GetDirListing( m_sSongDir + "*.bms", arrayOldFileNames ); + GetDirListing( m_sSongDir + "*.dwi", arrayOldFileNames ); + GetDirListing( m_sSongDir + "*.ksf", arrayOldFileNames ); + + for( int i=0; iTrace( "Song::SaveToSMDir('%s')", sPath ); int i; @@ -1328,16 +1337,20 @@ void Song::SaveToSMFile( CString sPath ) // Save all Notes for this file // for( i=0; iWriteSMNotesTag( fp ); + { + Notes* pNotes = m_apNotes[i]; + if( bSavingCache || pNotes->m_sDescription.Find("(autogen)") == -1 ) // If notes aren't autogen + m_apNotes[i]->WriteSMNotesTag( fp ); + } fclose( fp ); } -void Song::SaveToSMAndDWIFile() +void Song::SaveToSongFileAndDWI() { - LOG->Trace( "Song::SaveToSMAndDWIFile()" ); + LOG->Trace( "Song::SaveToSongFileAndDWI()" ); - SaveToSMFile(); + SaveToSongFile(); CString sPath = GetSongFilePath(); sPath.Replace( ".sm", ".dwi" ); @@ -1382,6 +1395,50 @@ void Song::SaveToSMAndDWIFile() fclose( fp ); } +struct AutoGenMapping +{ + NotesType ntMissing; + NotesType ntGenerateFrom; + int iOriginalTrackToTakeFrom[MAX_NOTE_TRACKS]; +}; +const AutoGenMapping AUTO_GEN_MAPPINGS[] = { + { NOTES_TYPE_PUMP_SINGLE, NOTES_TYPE_DANCE_SINGLE, { 0, 1, -1, 2, 3 } }, + { NOTES_TYPE_DANCE_SINGLE, NOTES_TYPE_PUMP_SINGLE, { 0, 1, 3, 4 } }, + { NOTES_TYPE_PUMP_DOUBLE, NOTES_TYPE_DANCE_DOUBLE, { 0, 1, -1, 2, 3, 4, 5, -1, 6, 7 } }, + { NOTES_TYPE_DANCE_DOUBLE, NOTES_TYPE_PUMP_DOUBLE, { 0, 1, 3, 4, 5, 6, 8, 9 } }, +}; +const NUM_AUTOGEN_MAPPINGS = sizeof(AUTO_GEN_MAPPINGS) / sizeof(AutoGenMapping); + +void Song::AddAutoGenNotes() +{ + for( int i=0; im_NotesType != mapping.ntGenerateFrom ) + continue; + + Notes* pNewNotes = new Notes; + pNewNotes->m_DifficultyClass = pOriginalNotes->m_DifficultyClass; + pNewNotes->m_iMeter = pOriginalNotes->m_iMeter; + pNewNotes->m_sDescription = pOriginalNotes->m_sDescription + " (autogen)"; + pNewNotes->m_NotesType = mapping.ntMissing; + + NoteData originalNoteData, newNoteData; + pOriginalNotes->GetNoteData( &originalNoteData ); + newNoteData.LoadTransformed( &originalNoteData, GAMEMAN->NotesTypeToNumTracks(mapping.ntMissing), mapping.iOriginalTrackToTakeFrom ); + pNewNotes->SetNoteData( &newNoteData ); + this->m_apNotes.Add( pNewNotes ); + } + } + } +} + Grade Song::GetGradeForDifficultyClass( NotesType nt, DifficultyClass dc ) const { CArray aNotes; diff --git a/stepmania/src/StepMania.vcproj b/stepmania/src/StepMania.vcproj index 71655ab2f3..7647b64724 100644 --- a/stepmania/src/StepMania.vcproj +++ b/stepmania/src/StepMania.vcproj @@ -221,6 +221,12 @@ + + + + @@ -628,18 +634,18 @@ - - - - + + + + diff --git a/stepmania/src/StyleDef.cpp b/stepmania/src/StyleDef.cpp index bbaff7e83e..2896d1a1ad 100644 --- a/stepmania/src/StyleDef.cpp +++ b/stepmania/src/StyleDef.cpp @@ -18,7 +18,7 @@ #include "GameState.h" -void StyleDef::GetTransformedNoteDataForStyle( PlayerNumber p, const NoteData* pOriginal, NoteData* pNoteDataOut ) const +void StyleDef::GetTransformedNoteDataForStyle( PlayerNumber p, NoteData* pOriginal, NoteData* pNoteDataOut ) const { int iNewToOriginalTrack[MAX_COLS_PER_PLAYER]; for( int col=0; col m_apNotes; - bool SongHasNoteType( NotesType nt ) const; + bool SongHasNotesType( NotesType nt ) const; + bool SongHasNotesTypeAndDifficulty( NotesType nt, DifficultyClass dc ) const; void GetNotesThatMatch( NotesType nt, CArray& arrayAddTo ) const; int GetNumTimesPlayed() const {