added autogeneration of Notes for missing NotesTypes

This commit is contained in:
Chris Danford
2002-08-25 19:00:12 +00:00
parent 8d63a5f7e0
commit 1b3c62adb9
14 changed files with 145 additions and 79 deletions
+4
View File
@@ -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
+15 -19
View File
@@ -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; t<m_iNumTracks; t++ )
{
int iOriginalTrack = iNewToOriginalTrack[t];
int i;
const int iOriginalTrack = iOriginalTrackToTakeFrom[t];
ASSERT( iOriginalTrack < pOriginal->m_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; i<pOriginal->m_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 )
+1 -1
View File
@@ -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();
+2 -2
View File
@@ -566,10 +566,10 @@ void NoteDisplay::DrawHold( const HoldNote& hn, const bool bActive, const float
//
// Draw the body
//
for( fY=fYBodyTop; fY<fYTailTop; fY+=fYStep ) // top to bottom
for( fY=fYBodyTop; fY<fYTailTop+1; fY+=fYStep ) // top to bottom
{
const float fYTop = fY;
const float fYBottom = min( fY+fYStep, fYTailTop );
const float fYBottom = min( fY+fYStep, fYTailTop+1 );
const float fXTop = ArrowGetXPos2( m_PlayerNumber, iCol, fYTop );
const float fXBottom = ArrowGetXPos2( m_PlayerNumber, iCol, fYBottom );
const float fXTopLeft = fXTop - fFrameWidth/2;
+5 -5
View File
@@ -20,7 +20,7 @@ D3DXCOLOR NoteTypeToColor( NoteType nt )
case NOTE_TYPE_8TH: return D3DXCOLOR(0,0,1,1); // blue
case NOTE_TYPE_12TH: return D3DXCOLOR(1,0,1,1); // purple
case NOTE_TYPE_16TH: return D3DXCOLOR(1,1,0,1); // yellow
default: ASSERT( 0 );return D3DXCOLOR(0.5f,0.5f,0.5f,1);
default: ASSERT(0); return D3DXCOLOR(0.5f,0.5f,0.5f,1);
}
};
@@ -28,11 +28,11 @@ float NoteTypeToBeat( NoteType nt )
{
switch( nt )
{
case NOTE_TYPE_4TH: return 1.0f; // quarter notes
case NOTE_TYPE_8TH: return 1.0f/2; // eighth notes
case NOTE_TYPE_4TH: return 1.0f; // quarter notes
case NOTE_TYPE_8TH: return 1.0f/2; // eighth notes
case NOTE_TYPE_12TH: return 1.0f/3; // triplets
case NOTE_TYPE_16TH: return 1.0f/4; // sixteenth notes
default: ASSERT( false ); return 0;
default: ASSERT(0); return 0;
}
}
@@ -42,7 +42,7 @@ NoteType GetNoteType( int iNoteIndex )
else if( iNoteIndex % (ROWS_PER_MEASURE/8) == 0) return NOTE_TYPE_8TH;
else if( iNoteIndex % (ROWS_PER_MEASURE/12) == 0) return NOTE_TYPE_12TH;
else if( iNoteIndex % (ROWS_PER_MEASURE/16) == 0) return NOTE_TYPE_16TH;
else return NOTE_TYPE_INVALID;
else return NOTE_TYPE_INVALID;
};
bool IsNoteOfType( int iNoteIndex, NoteType t )
+1 -1
View File
@@ -52,7 +52,7 @@ ScreenCaution::ScreenCaution()
m_FadeWipe.SetOpened();
this->AddSubActor( &m_FadeWipe );
this->SendScreenMessage( SM_StartClosing, 1 );
this->SendScreenMessage( SM_StartClosing, 3 );
}
+2 -2
View File
@@ -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:
+2 -2
View File
@@ -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; i<GAMESTATE->m_pCurCourse->m_iStages; i++ )
{
Song* pSong = GAMESTATE->m_pCurCourse->m_apSongs[i];
pSong->SaveToSMFile();
pSong->SaveToSongFile();
}
}
break;
+1 -1
View File
@@ -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 );
}
}
+91 -34
View File
@@ -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<Notes*, Notes*>& 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; i<arrayOldFileNames.GetSize(); i++ )
{
CString sOldPath = m_sSongDir + arrayOldFileNames[i];
CString sNewPath = sOldPath + ".old";
MoveFile( sOldPath, sNewPath );
}
SaveToSMFile( GetSongFilePath(), false );
}
void Song::SaveToSMFile( CString sPath )
void Song::SaveToSMFile( CString sPath, bool bSavingCache )
{
if( sPath == "" )
{
sPath = GetSongFilePath();
//
// 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; i<arrayOldFileNames.GetSize(); i++ )
{
CString sOldPath = m_sSongDir + arrayOldFileNames[i];
CString sNewPath = sOldPath + ".old";
MoveFile( sOldPath, sNewPath );
}
}
LOG->Trace( "Song::SaveToSMDir('%s')", sPath );
int i;
@@ -1328,16 +1337,20 @@ void Song::SaveToSMFile( CString sPath )
// Save all Notes for this file
//
for( i=0; i<m_apNotes.GetSize(); i++ )
m_apNotes[i]->WriteSMNotesTag( 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; i<NUM_AUTOGEN_MAPPINGS; i++ )
{
const AutoGenMapping& mapping = AUTO_GEN_MAPPINGS[i];
if( !SongHasNotesType(mapping.ntMissing))
{
for( int i=0; i<m_apNotes.GetSize(); i++ )
{
Notes* pOriginalNotes = m_apNotes[i];
if( pOriginalNotes->m_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<Notes*, Notes*> aNotes;
+12 -6
View File
@@ -221,6 +221,12 @@
<File
RelativePath="ScreenGraphicOptions.h">
</File>
<File
RelativePath="ScreenHowToPlay.cpp">
</File>
<File
RelativePath="ScreenHowToPlay.h">
</File>
<File
RelativePath="ScreenManager.cpp">
</File>
@@ -628,18 +634,18 @@
<File
RelativePath="GrooveRadar.h">
</File>
<File
RelativePath="GroupList.cpp">
</File>
<File
RelativePath="GroupList.h">
</File>
<File
RelativePath="GroupInfoFrame.cpp">
</File>
<File
RelativePath="GroupInfoFrame.h">
</File>
<File
RelativePath="GroupList.cpp">
</File>
<File
RelativePath="GroupList.h">
</File>
<File
RelativePath="MenuElements.cpp">
</File>
+1 -1
View File
@@ -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_iColsPerPlayer; col++ )
+1 -1
View File
@@ -65,6 +65,6 @@ public:
GameInput StyleInputToGameInput( const StyleInput StyleI ) const;
StyleInput GameInputToStyleInput( const GameInput &GameI ) const;
void GetTransformedNoteDataForStyle( PlayerNumber p, const NoteData* pOriginal, NoteData* pNoteDataOut ) const;
void GetTransformedNoteDataForStyle( PlayerNumber p, NoteData* pOriginal, NoteData* pNoteDataOut ) const;
};
+7 -4
View File
@@ -59,14 +59,16 @@ public:
void TidyUpData(); // call after loading to clean up invalid data
void SaveToSMFile( CString sPath = "" ); // no path means save to SongFilePath
void SaveToSMAndDWIFile(); // saves SM, then saves DWI so that the SM is the master copy and NoteTypes not supported by DWI are not lost
void SaveToSMFile( CString sPath, bool bSavingCache );
void SaveToSongFileAndDWI(); // saves SM, then saves DWI so that the SM is the master copy and NoteTypes not supported by DWI are not lost
void SaveToCacheFile();
void SaveToSongFile(); // no path means save to SongFilePath
const CString &GetSongFilePath() const;
CString GetCacheFilePath() const;
public:
void AddAutoGenNotes();
/* Directory this song data came from: */
CString m_sSongDir;
@@ -167,7 +169,8 @@ public:
CArray<Notes*, Notes*> m_apNotes;
bool SongHasNoteType( NotesType nt ) const;
bool SongHasNotesType( NotesType nt ) const;
bool SongHasNotesTypeAndDifficulty( NotesType nt, DifficultyClass dc ) const;
void GetNotesThatMatch( NotesType nt, CArray<Notes*, Notes*>& arrayAddTo ) const;
int GetNumTimesPlayed() const
{