preparing for alternate song art files (e.g. album cover, piu-style disc)
This commit is contained in:
+47
-47
@@ -381,6 +381,8 @@ void Song::TidyUpData()
|
|||||||
if( !m_sInstrumentTrackFile[i].empty() )
|
if( !m_sInstrumentTrackFile[i].empty() )
|
||||||
FixupPath( m_sInstrumentTrackFile[i], m_sSongDir );
|
FixupPath( m_sInstrumentTrackFile[i], m_sSongDir );
|
||||||
FixupPath( m_sBannerFile, m_sSongDir );
|
FixupPath( m_sBannerFile, m_sSongDir );
|
||||||
|
//FixupPath( m_sAlbumArtFile, m_sSongDir );
|
||||||
|
//FixupPath( m_sDiscFile, m_sSongDir );
|
||||||
FixupPath( m_sLyricsFile, m_sSongDir );
|
FixupPath( m_sLyricsFile, m_sSongDir );
|
||||||
FixupPath( m_sBackgroundFile, m_sSongDir );
|
FixupPath( m_sBackgroundFile, m_sSongDir );
|
||||||
FixupPath( m_sCDTitleFile, m_sSongDir );
|
FixupPath( m_sCDTitleFile, m_sSongDir );
|
||||||
@@ -512,8 +514,8 @@ void Song::TidyUpData()
|
|||||||
vector<RString> arrayPossibleBanners;
|
vector<RString> arrayPossibleBanners;
|
||||||
GetImageDirListing( m_sSongDir + "*banner*", arrayPossibleBanners );
|
GetImageDirListing( m_sSongDir + "*banner*", arrayPossibleBanners );
|
||||||
|
|
||||||
/* Some people do things differently for the sake of being different. Don't
|
/* Some people do things differently for the sake of being different.
|
||||||
* match eg. abnormal, numbness. */
|
* Don't match eg. abnormal, numbness. */
|
||||||
GetImageDirListing( m_sSongDir + "* BN", arrayPossibleBanners );
|
GetImageDirListing( m_sSongDir + "* BN", arrayPossibleBanners );
|
||||||
|
|
||||||
if( !arrayPossibleBanners.empty() )
|
if( !arrayPossibleBanners.empty() )
|
||||||
@@ -557,7 +559,7 @@ void Song::TidyUpData()
|
|||||||
for( unsigned i=0; i<arrayImages.size(); i++ ) // foreach image
|
for( unsigned i=0; i<arrayImages.size(); i++ ) // foreach image
|
||||||
{
|
{
|
||||||
if( HasBanner() && HasCDTitle() && HasBackground() )
|
if( HasBanner() && HasCDTitle() && HasBackground() )
|
||||||
break; /* done */
|
break; // done
|
||||||
|
|
||||||
// ignore DWI "-char" graphics
|
// ignore DWI "-char" graphics
|
||||||
RString sLower = arrayImages[i];
|
RString sLower = arrayImages[i];
|
||||||
@@ -578,7 +580,7 @@ void Song::TidyUpData()
|
|||||||
|
|
||||||
RString sPath = m_sSongDir + arrayImages[i];
|
RString sPath = m_sSongDir + arrayImages[i];
|
||||||
|
|
||||||
/* We only care about the dimensions. */
|
// We only care about the dimensions.
|
||||||
RString error;
|
RString error;
|
||||||
RageSurface *img = RageSurfaceUtils::LoadFile( sPath, error, true );
|
RageSurface *img = RageSurfaceUtils::LoadFile( sPath, error, true );
|
||||||
if( !img )
|
if( !img )
|
||||||
@@ -609,22 +611,22 @@ void Song::TidyUpData()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some songs have overlarge banners. Check if the ratio is reasonable (over
|
/* Some songs have overlarge banners. Check if the ratio is reasonable
|
||||||
* 2:1; usually over 3:1), and large (not a cdtitle). */
|
* (over 2:1; usually over 3:1), and large (not a cdtitle). */
|
||||||
if( !HasBanner() && width > 200 && float(width) / height > 2.0f )
|
if( !HasBanner() && width > 200 && float(width) / height > 2.0f )
|
||||||
{
|
{
|
||||||
m_sBannerFile = arrayImages[i];
|
m_sBannerFile = arrayImages[i];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Agh. DWI's inline title images are triggering this, resulting in kanji,
|
/* Agh. DWI's inline title images are triggering this, resulting in
|
||||||
* etc., being used as a CDTitle for songs with none. Some sample data
|
* kanji, etc., being used as a CDTitle for songs with none. Some
|
||||||
* from random incarnations:
|
* sample data from random incarnations:
|
||||||
* 42x50 35x50 50x50 144x49
|
* 42x50 35x50 50x50 144x49
|
||||||
* It looks like ~50 height is what people use to align to DWI's font.
|
* It looks like ~50 height is what people use to align to DWI's font.
|
||||||
*
|
*
|
||||||
* My tallest CDTitle is 44. Let's cut off in the middle and hope for
|
* My tallest CDTitle is 44. Let's cut off in the middle and hope for
|
||||||
* the best. */
|
* the best. -(who? -aj) */
|
||||||
/* The proper size of a CDTitle is 64x48 or sometihng. Simfile artists
|
/* The proper size of a CDTitle is 64x48 or sometihng. Simfile artists
|
||||||
* typically don't give a shit about this (see Cetaka's fucking banner
|
* typically don't give a shit about this (see Cetaka's fucking banner
|
||||||
* -sized CDTitle). This is also subverted in certain designs (beta
|
* -sized CDTitle). This is also subverted in certain designs (beta
|
||||||
@@ -639,7 +641,7 @@ void Song::TidyUpData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These will be written to cache, for Song::LoadFromSongDir to use later. */
|
// These will be written to cache, for Song::LoadFromSongDir to use later.
|
||||||
m_bHasMusic = HasMusic();
|
m_bHasMusic = HasMusic();
|
||||||
m_bHasBanner = HasBanner();
|
m_bHasBanner = HasBanner();
|
||||||
m_bHasBackground = HasBackground();
|
m_bHasBackground = HasBackground();
|
||||||
@@ -667,8 +669,9 @@ void Song::TidyUpData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Don't allow multiple Steps of the same StepsType and Difficulty (except for edits).
|
/* Don't allow multiple Steps of the same StepsType and Difficulty (except
|
||||||
* We should be able to use difficulty names as unique identifiers for steps. */
|
* for edits). We should be able to use difficulty names as unique
|
||||||
|
* identifiers for steps. */
|
||||||
SongUtil::AdjustDuplicateSteps( this );
|
SongUtil::AdjustDuplicateSteps( this );
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -692,8 +695,7 @@ void Song::TidyUpData()
|
|||||||
* else; it's the filename in use.
|
* else; it's the filename in use.
|
||||||
* 2. If there's a .DWI, use it with a changed extension.
|
* 2. If there's a .DWI, use it with a changed extension.
|
||||||
* 3. Otherwise, use the name of the directory, since it's definitely a valid
|
* 3. Otherwise, use the name of the directory, since it's definitely a valid
|
||||||
* filename, and should always be the title of the song (unlike KSFs).
|
* filename, and should always be the title of the song (unlike KSFs). */
|
||||||
*/
|
|
||||||
m_sSongFileName = m_sSongDir;
|
m_sSongFileName = m_sSongDir;
|
||||||
vector<RString> asFileNames;
|
vector<RString> asFileNames;
|
||||||
GetDirListing( m_sSongDir+"*.sm", asFileNames );
|
GetDirListing( m_sSongDir+"*.sm", asFileNames );
|
||||||
@@ -710,7 +712,7 @@ void Song::TidyUpData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If no time signature specified, assume 4/4 time for the whole song. */
|
// If no time signature specified, assume 4/4 time for the whole song.
|
||||||
if( m_Timing.m_vTimeSignatureSegments.empty() )
|
if( m_Timing.m_vTimeSignatureSegments.empty() )
|
||||||
{
|
{
|
||||||
TimeSignatureSegment seg;
|
TimeSignatureSegment seg;
|
||||||
@@ -733,7 +735,7 @@ void Song::TranslateTitles()
|
|||||||
|
|
||||||
void Song::ReCalculateRadarValuesAndLastBeat()
|
void Song::ReCalculateRadarValuesAndLastBeat()
|
||||||
{
|
{
|
||||||
float fFirstBeat = FLT_MAX; /* inf */
|
float fFirstBeat = FLT_MAX; // inf
|
||||||
float fLastBeat = m_fSpecifiedLastBeat; // Make sure we're at least as long as the specified amount.
|
float fLastBeat = m_fSpecifiedLastBeat; // Make sure we're at least as long as the specified amount.
|
||||||
|
|
||||||
for( unsigned i=0; i<m_vpSteps.size(); i++ )
|
for( unsigned i=0; i<m_vpSteps.size(); i++ )
|
||||||
@@ -762,8 +764,8 @@ void Song::ReCalculateRadarValuesAndLastBeat()
|
|||||||
NoteData tempNoteData;
|
NoteData tempNoteData;
|
||||||
pSteps->GetNoteData( tempNoteData );
|
pSteps->GetNoteData( tempNoteData );
|
||||||
|
|
||||||
/* Many songs have stray, empty song patterns. Ignore them, so
|
/* Many songs have stray, empty song patterns. Ignore them, so they
|
||||||
* they don't force the first beat of the whole song to 0. */
|
* don't force the first beat of the whole song to 0. */
|
||||||
if( tempNoteData.GetLastRow() == 0 )
|
if( tempNoteData.GetLastRow() == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -775,7 +777,7 @@ void Song::ReCalculateRadarValuesAndLastBeat()
|
|||||||
m_fLastBeat = fLastBeat;
|
m_fLastBeat = fLastBeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return whether the song is playable in the given style. */
|
// Return whether the song is playable in the given style.
|
||||||
bool Song::SongCompleteForStyle( const Style *st ) const
|
bool Song::SongCompleteForStyle( const Style *st ) const
|
||||||
{
|
{
|
||||||
return HasStepsType( st->m_StepsType );
|
return HasStepsType( st->m_StepsType );
|
||||||
@@ -798,14 +800,14 @@ void Song::Save()
|
|||||||
ReCalculateRadarValuesAndLastBeat();
|
ReCalculateRadarValuesAndLastBeat();
|
||||||
TranslateTitles();
|
TranslateTitles();
|
||||||
|
|
||||||
/* Save the new files. These calls make backups on their own. */
|
// Save the new files. These calls make backups on their own.
|
||||||
if( !SaveToSMFile(GetSongFilePath(), false) )
|
if( !SaveToSMFile(GetSongFilePath(), false) )
|
||||||
return;
|
return;
|
||||||
SaveToDWIFile();
|
SaveToDWIFile();
|
||||||
SaveToCacheFile();
|
SaveToCacheFile();
|
||||||
|
|
||||||
/* We've safely written our files and created backups. Rename non-SM and non-DWI
|
/* We've safely written our files and created backups. Rename non-SM and
|
||||||
* files to avoid confusion. */
|
* non-DWI files to avoid confusion. */
|
||||||
vector<RString> arrayOldFileNames;
|
vector<RString> arrayOldFileNames;
|
||||||
GetDirListing( m_sSongDir + "*.bms", arrayOldFileNames );
|
GetDirListing( m_sSongDir + "*.bms", arrayOldFileNames );
|
||||||
GetDirListing( m_sSongDir + "*.pms", arrayOldFileNames );
|
GetDirListing( m_sSongDir + "*.pms", arrayOldFileNames );
|
||||||
@@ -819,7 +821,7 @@ void Song::Save()
|
|||||||
if( !FileCopy( sOldPath, sNewPath ) )
|
if( !FileCopy( sOldPath, sNewPath ) )
|
||||||
{
|
{
|
||||||
LOG->UserLog( "Song file", sOldPath, "couldn't be backed up." );
|
LOG->UserLog( "Song file", sOldPath, "couldn't be backed up." );
|
||||||
/* Don't remove. */
|
// Don't remove.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
FILEMAN->Remove( sOldPath );
|
FILEMAN->Remove( sOldPath );
|
||||||
@@ -831,7 +833,7 @@ bool Song::SaveToSMFile( RString sPath, bool bSavingCache )
|
|||||||
{
|
{
|
||||||
LOG->Trace( "Song::SaveToSMFile('%s')", sPath.c_str() );
|
LOG->Trace( "Song::SaveToSMFile('%s')", sPath.c_str() );
|
||||||
|
|
||||||
/* If the file exists, make a backup. */
|
// If the file exists, make a backup.
|
||||||
if( !bSavingCache && IsAFile(sPath) )
|
if( !bSavingCache && IsAFile(sPath) )
|
||||||
FileCopy( sPath, sPath + ".old" );
|
FileCopy( sPath, sPath + ".old" );
|
||||||
|
|
||||||
@@ -875,7 +877,7 @@ bool Song::SaveToSMFile( RString sPath, bool bSavingCache )
|
|||||||
|
|
||||||
if( !bSavingCache )
|
if( !bSavingCache )
|
||||||
{
|
{
|
||||||
/* Mark these steps saved to disk. */
|
// Mark these steps saved to disk.
|
||||||
FOREACH( Steps*, vpStepsToSave, s )
|
FOREACH( Steps*, vpStepsToSave, s )
|
||||||
(*s)->SetSavedToDisk( true );
|
(*s)->SetSavedToDisk( true );
|
||||||
}
|
}
|
||||||
@@ -901,7 +903,7 @@ bool Song::SaveToDWIFile()
|
|||||||
const RString sPath = SetExtension( GetSongFilePath(), "dwi" );
|
const RString sPath = SetExtension( GetSongFilePath(), "dwi" );
|
||||||
LOG->Trace( "Song::SaveToDWIFile(%s)", sPath.c_str() );
|
LOG->Trace( "Song::SaveToDWIFile(%s)", sPath.c_str() );
|
||||||
|
|
||||||
/* If the file exists, make a backup. */
|
// If the file exists, make a backup.
|
||||||
if( IsAFile(sPath) )
|
if( IsAFile(sPath) )
|
||||||
FileCopy( sPath, sPath + ".old" );
|
FileCopy( sPath, sPath + ".old" );
|
||||||
|
|
||||||
@@ -962,7 +964,7 @@ void Song::AddAutoGenNotes()
|
|||||||
|
|
||||||
void Song::AutoGen( StepsType ntTo, StepsType ntFrom )
|
void Song::AutoGen( StepsType ntTo, StepsType ntFrom )
|
||||||
{
|
{
|
||||||
// int iNumTracksOfTo = GAMEMAN->StepsTypeToNumTracks(ntTo);
|
// int iNumTracksOfTo = GAMEMAN->StepsTypeToNumTracks(ntTo);
|
||||||
|
|
||||||
for( unsigned int j=0; j<m_vpSteps.size(); j++ )
|
for( unsigned int j=0; j<m_vpSteps.size(); j++ )
|
||||||
{
|
{
|
||||||
@@ -1011,16 +1013,16 @@ void Song::RemoveAutoGenNotes()
|
|||||||
|
|
||||||
bool Song::IsEasy( StepsType st ) const
|
bool Song::IsEasy( StepsType st ) const
|
||||||
{
|
{
|
||||||
/* Very fast songs and songs with wide tempo changes are hard for new players,
|
/* Very fast songs and songs with wide tempo changes are hard for new
|
||||||
* even if they have beginner steps. */
|
* players, even if they have beginner steps. */
|
||||||
DisplayBpms bpms;
|
DisplayBpms bpms;
|
||||||
this->GetDisplayBpms(bpms);
|
this->GetDisplayBpms(bpms);
|
||||||
if( bpms.GetMax() >= 250 || bpms.GetMax() - bpms.GetMin() >= 75 )
|
if( bpms.GetMax() >= 250 || bpms.GetMax() - bpms.GetMin() >= 75 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* The easy marker indicates which songs a beginner, having selected "beginner",
|
/* The easy marker indicates which songs a beginner, having selected
|
||||||
* can play and actually get a very easy song: if there are actual beginner
|
* "beginner", can play and actually get a very easy song: if there are
|
||||||
* steps, or if the light steps are 1- or 2-foot. */
|
* actual beginner steps, or if the light steps are 1- or 2-foot. */
|
||||||
const Steps* pBeginnerNotes = SongUtil::GetStepsByDifficulty( this, st, Difficulty_Beginner );
|
const Steps* pBeginnerNotes = SongUtil::GetStepsByDifficulty( this, st, Difficulty_Beginner );
|
||||||
if( pBeginnerNotes )
|
if( pBeginnerNotes )
|
||||||
return true;
|
return true;
|
||||||
@@ -1034,7 +1036,7 @@ bool Song::IsEasy( StepsType st ) const
|
|||||||
|
|
||||||
bool Song::IsTutorial() const
|
bool Song::IsTutorial() const
|
||||||
{
|
{
|
||||||
// A Song is a tutorial song is it has only Beginner steps.
|
// A Song is considered a Tutorial if it has only Beginner steps.
|
||||||
FOREACH_CONST( Steps*, m_vpSteps, s )
|
FOREACH_CONST( Steps*, m_vpSteps, s )
|
||||||
{
|
{
|
||||||
if( (*s)->m_StepsType == StepsType_lights_cabinet )
|
if( (*s)->m_StepsType == StepsType_lights_cabinet )
|
||||||
@@ -1072,10 +1074,10 @@ bool Song::NormallyDisplayed() const
|
|||||||
bool Song::ShowInDemonstrationAndRanking() const { return !IsTutorial() && NormallyDisplayed(); }
|
bool Song::ShowInDemonstrationAndRanking() const { return !IsTutorial() && NormallyDisplayed(); }
|
||||||
|
|
||||||
|
|
||||||
/* Hack: see Song::TidyUpData comments. */
|
// Hack: see Song::TidyUpData comments.
|
||||||
bool Song::HasMusic() const
|
bool Song::HasMusic() const
|
||||||
{
|
{
|
||||||
/* If we have keys, we always have music. */
|
// If we have keys, we always have music.
|
||||||
if( m_vsKeysoundFile.size() != 0 )
|
if( m_vsKeysoundFile.size() != 0 )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -1124,15 +1126,15 @@ RString GetSongAssetPath( RString sPath, const RString &sSongPath )
|
|||||||
if( sPath == "" )
|
if( sPath == "" )
|
||||||
return RString();
|
return RString();
|
||||||
|
|
||||||
/* If there's no path in the file, the file is in the same directory
|
/* If there's no path in the file, the file is in the same directory as the
|
||||||
* as the song. (This is the preferred configuration.) */
|
* song. (This is the preferred configuration.) */
|
||||||
if( sPath.find('/') == string::npos )
|
if( sPath.find('/') == string::npos )
|
||||||
return sSongPath+sPath;
|
return sSongPath+sPath;
|
||||||
|
|
||||||
/* The song contains a path; treat it as relative to the top SM directory. */
|
// The song contains a path; treat it as relative to the top SM directory.
|
||||||
if( sPath.Left(3) == "../" )
|
if( sPath.Left(3) == "../" )
|
||||||
{
|
{
|
||||||
/* The path begins with "../". Resolve it wrt. the song directory. */
|
// The path begins with "../". Resolve it wrt. the song directory.
|
||||||
sPath = sSongPath + sPath;
|
sPath = sSongPath + sPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1146,9 +1148,8 @@ RString GetSongAssetPath( RString sPath, const RString &sSongPath )
|
|||||||
return sPath;
|
return sPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note that supplying a path relative to the top-level directory is only for
|
||||||
/* Note that supplying a path relative to the top-level directory is only for compatibility
|
* compatibility with DWI. We prefer paths relative to the song directory. */
|
||||||
* with DWI. We prefer paths relative to the song directory. */
|
|
||||||
RString Song::GetMusicPath() const
|
RString Song::GetMusicPath() const
|
||||||
{
|
{
|
||||||
return GetSongAssetPath( m_sMusicFile, m_sSongDir );
|
return GetSongAssetPath( m_sMusicFile, m_sSongDir );
|
||||||
@@ -1197,7 +1198,6 @@ RString Song::GetDisplayArtist() const
|
|||||||
return m_sArtist;
|
return m_sArtist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RString Song::GetDisplayFullTitle() const
|
RString Song::GetDisplayFullTitle() const
|
||||||
{
|
{
|
||||||
RString Title = GetDisplayMainTitle();
|
RString Title = GetDisplayMainTitle();
|
||||||
@@ -1267,7 +1267,7 @@ bool Song::Matches(RString sGroup, RString sSong) const
|
|||||||
sDir.Replace("\\","/");
|
sDir.Replace("\\","/");
|
||||||
vector<RString> bits;
|
vector<RString> bits;
|
||||||
split( sDir, "/", bits );
|
split( sDir, "/", bits );
|
||||||
ASSERT(bits.size() >= 2); /* should always have at least two parts */
|
ASSERT(bits.size() >= 2); // should always have at least two parts
|
||||||
const RString &sLastBit = bits[bits.size()-1];
|
const RString &sLastBit = bits[bits.size()-1];
|
||||||
|
|
||||||
// match on song dir or title (ala DWI)
|
// match on song dir or title (ala DWI)
|
||||||
@@ -1279,8 +1279,8 @@ bool Song::Matches(RString sGroup, RString sSong) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If apInUse is set, it contains a list of steps which are in use elsewhere, and
|
/* If apInUse is set, it contains a list of steps which are in use elsewhere,
|
||||||
* should not be deleted. */
|
* and should not be deleted. */
|
||||||
void Song::FreeAllLoadedFromProfile( ProfileSlot slot, const set<Steps*> *setInUse )
|
void Song::FreeAllLoadedFromProfile( ProfileSlot slot, const set<Steps*> *setInUse )
|
||||||
{
|
{
|
||||||
/* DeleteSteps will remove and recreate autogen notes, which may reorder
|
/* DeleteSteps will remove and recreate autogen notes, which may reorder
|
||||||
|
|||||||
+3
-1
@@ -141,7 +141,9 @@ public:
|
|||||||
float m_fSpecifiedBPMMin;
|
float m_fSpecifiedBPMMin;
|
||||||
float m_fSpecifiedBPMMax; // if a range, then Min != Max
|
float m_fSpecifiedBPMMax; // if a range, then Min != Max
|
||||||
|
|
||||||
RString m_sBannerFile;
|
RString m_sBannerFile; // typically a 16:5 ratio graphic (e.g. 256x80)
|
||||||
|
//RString m_sAlbumArtFile; // typically square (e.g. 256x256)
|
||||||
|
//RString m_sDiscFile; // typically rectangular (e.g. 256x192)
|
||||||
RString m_sLyricsFile;
|
RString m_sLyricsFile;
|
||||||
RString m_sBackgroundFile;
|
RString m_sBackgroundFile;
|
||||||
RString m_sCDTitleFile;
|
RString m_sCDTitleFile;
|
||||||
|
|||||||
Reference in New Issue
Block a user